ports/113293: [MAINTAINER] mail/spamd: update to 4.1.1
Alex Samorukov
samm at os2.kiev.ua
Sun Jun 3 16:00:14 UTC 2007
>Number: 113293
>Category: ports
>Synopsis: [MAINTAINER] mail/spamd: update to 4.1.1
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: maintainer-update
>Submitter-Id: current-users
>Arrival-Date: Sun Jun 03 16:00:13 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Alex Samorukov
>Release: FreeBSD 5.4-RELEASE-p22 i386
>Organization:
Shevchenko Didkovskiy and Partners
>Environment:
System: FreeBSD deepvision.tsua.net 5.4-RELEASE-p22 FreeBSD 5.4-RELEASE-p22 #6: Thu Feb 1 14:16:07 EET
>Description:
- Update to 4.1.1
- New IPFW support
- Many project home
Added file(s):
- files/obspamd.in
- files/obspamlogd.in
- files/pkg-deinstall.in
- files/pkg-install.in
- files/pkg-message.in
Removed file(s):
- files/patch-greyc
- files/patch-greyh
- files/patch-spamd
- files/patch-spamd-setup
- files/patch-spamdm
- files/pfspamd.sh.in
- pkg-install
- pkg-message
- pkg-plist
- work/.build_done.spamd._usr_local
- work/.configure_done.spamd._usr_local
- work/.extract_done.spamd._usr_local
- work/.patch_done.spamd._usr_local
- work/spamd_3.7/Makefile
- work/spamd_3.7/doc/spamd.conf
- work/spamd_3.7/doc/spamd.conf.5
- work/spamd_3.7/spamd/Makefile
- work/spamd_3.7/spamd/grey.c
- work/spamd_3.7/spamd/grey.c.orig
- work/spamd_3.7/spamd/grey.h
- work/spamd_3.7/spamd/grey.h.orig
- work/spamd_3.7/spamd/grey.o
- work/spamd_3.7/spamd/sdl.c
- work/spamd_3.7/spamd/sdl.h
- work/spamd_3.7/spamd/sdl.o
- work/spamd_3.7/spamd/spamd
- work/spamd_3.7/spamd/spamd.8
- work/spamd_3.7/spamd/spamd.8.bak
- work/spamd_3.7/spamd/spamd.8.gz
- work/spamd_3.7/spamd/spamd.8.orig
- work/spamd_3.7/spamd/spamd.c
- work/spamd_3.7/spamd/spamd.c.orig
- work/spamd_3.7/spamd/spamd.o
- work/spamd_3.7/spamd-setup/Makefile
- work/spamd_3.7/spamd-setup/spamd-setup
- work/spamd_3.7/spamd-setup/spamd-setup.8
- work/spamd_3.7/spamd-setup/spamd-setup.8.bak
- work/spamd_3.7/spamd-setup/spamd-setup.8.gz
- work/spamd_3.7/spamd-setup/spamd-setup.c
- work/spamd_3.7/spamd-setup/spamd-setup.c.bak
- work/spamd_3.7/spamd-setup/spamd-setup.c.orig
- work/spamd_3.7/spamd-setup/spamd-setup.o
- work/spamd_3.7/spamdb/Makefile
- work/spamd_3.7/spamdb/spamdb
- work/spamd_3.7/spamdb/spamdb.8
- work/spamd_3.7/spamdb/spamdb.8.gz
- work/spamd_3.7/spamdb/spamdb.c
- work/spamd_3.7/spamdb/spamdb.o
- work/spamd_3.7/spamlogd/Makefile
- work/spamd_3.7/spamlogd/spamlogd
- work/spamd_3.7/spamlogd/spamlogd.8
- work/spamd_3.7/spamlogd/spamlogd.8.gz
- work/spamd_3.7/spamlogd/spamlogd.c
- work/spamd_3.7/spamlogd/spamlogd.o
Generated with FreeBSD Port Tools 0.77
>How-To-Repeat:
>Fix:
--- spamd-4.1.1.patch begins here ---
diff -ruN --exclude=CVS /usr/ports/mail/spamd/Makefile /usr/home/samm/spamd/Makefile
--- /usr/ports/mail/spamd/Makefile Thu Apr 26 08:42:02 2007
+++ /usr/home/samm/spamd/Makefile Sun Jun 3 18:57:26 2007
@@ -1,75 +1,90 @@
-# New ports collection makefile for: spamd
-# Date created: 23 June 2003
+# New ports collection makefile for: spamd
+# Date created: 04 April 2007
# Whom: Max Laier <max at love2party.net>
#
-# $FreeBSD: ports/mail/spamd/Makefile,v 1.12 2007/03/20 15:16:44 delphij Exp $
+# $FreeBSD$
#
PORTNAME= spamd
-PORTVERSION= 3.7
-PORTREVISION= 3
+PORTVERSION= 4.1.1
CATEGORIES= mail
-MASTER_SITES= ${MASTER_SITE_LOCAL}
-MASTER_SITE_SUBDIR= delphij
-DISTNAME= ${PORTNAME}_${PORTVERSION}
+MASTER_SITES= BERLIOS
+MASTER_SITE_SUBDIR=freebsdspamd
+DISTNAME= ${PORTNAME}-${PORTVERSION}
MAINTAINER= samm at os2.kiev.ua
COMMENT= Traps spammers with a very slow smtp-login and return 4xx error
-USE_BZIP2= yes
-
.include <bsd.port.pre.mk>
-.if defined(WITH_IPFW)
-CFLAGS+= -DIPFW
-.if ${OSVERSION} < 490000
-BROKEN= IPFW with Tables is required for this port to function properly
-.endif
-.else
.if ${OSVERSION} < 502117
BROKEN= OpenBSD 3.5 pf/pfctl is necessary for this port to function properly.
.else
LOCAL_PFCTL= /sbin/pfctl
.endif
-.endif
-USE_RC_SUBR= pfspamd.sh
+USE_RC_SUBR?= obspamd obspamlogd
-.if !defined(BATCH) && !defined(PACKAGE_BUILDING)
-IS_INTERACTIVE= yes
-.endif
+SPAMDUSER?= _spamd
+SPAMDGROUP?= _spamd
+SPAMDDIR?= /var/empty
+
+SPAMDUID= 132
+SPAMDGID= ${SPAMDUID}
MAN5= spamd.conf.5
MAN8= spamd.8 spamd-setup.8 spamdb.8 spamlogd.8
+PORTDOCS= ipfw-spamd.txt
-SAMPLE_SPAMD_CONF= ${PREFIX}/etc/spamd.conf.sample
+PLIST_DIRS= etc/spamd
+PLIST_FILES= libexec/spamd libexec/spamlogd \
+ sbin/spamd-setup sbin/spamdb \
+ etc/spamd/spamd.conf.sample
+
+CONFIG_DIR= ${PREFIX}/etc/spamd
+SAMPLE_SPAMD_CONF= ${CONFIG_DIR}/spamd.conf.sample
+
+PLIST_SUB= SPAMDDIR=${SPAMDDIR} \
+ SPAMDUSER=${SPAMDUSER} \
+ SPAMDGROUP=${SPAMDGROUP} \
+ SPAMDUID=${SPAMDUID} \
+ SPAMDGID=${SPAMDGID}
+
+SUB_FILES= pkg-install \
+ pkg-deinstall \
+ pkg-message
-post-patch:
- @${REINPLACE_CMD} -e 's|%%LOCAL_PFCTL%%|${LOCAL_PFCTL}|; \
- s|%%LOCAL_SPAMD_CONF%%|${PREFIX}/etc/spamd.conf|' \
- ${WRKSRC}/spamd-setup/spamd-setup.c
- @${REINPLACE_CMD} -e 's|/etc/spamd.conf|${PREFIX}/etc/spamd.conf|' \
- ${WRKSRC}/spamd/spamd.8 ${WRKSRC}/spamd-setup/spamd-setup.8
-
-pre-su-install:
-.if !defined(BATCH) && !defined(PACKAGE_BUILDING)
- @${SETENV} PKG_PREFIX=${PREFIX} ${SH} ${PKGINSTALL} ${PKGNAME} PRE-INSTALL
-.endif
+SUB_LIST= PREFIX=${PREFIX} \
+ ${PLIST_SUB}
+
+pre-install:
+ @${SH} ${PKGINSTALL} ${DISTNAME} PRE-INSTALL
+
+post-install:
+ @${CAT} ${PKGMESSAGE}
do-install:
${INSTALL_PROGRAM} ${WRKSRC}/spamd/spamd ${PREFIX}/libexec
${INSTALL_PROGRAM} ${WRKSRC}/spamlogd/spamlogd ${PREFIX}/libexec
${INSTALL_PROGRAM} ${WRKSRC}/spamd-setup/spamd-setup ${PREFIX}/sbin
${INSTALL_PROGRAM} ${WRKSRC}/spamdb/spamdb ${PREFIX}/sbin
- ${INSTALL_MAN} ${WRKSRC}/doc/spamd.conf.5 ${PREFIX}/man/man5
+ ${INSTALL_MAN} ${WRKSRC}/etc/spamd.conf.5 ${PREFIX}/man/man5
${INSTALL_MAN} ${WRKSRC}/spamd/spamd.8 ${PREFIX}/man/man8
${INSTALL_MAN} ${WRKSRC}/spamd-setup/spamd-setup.8 ${PREFIX}/man/man8
${INSTALL_MAN} ${WRKSRC}/spamdb/spamdb.8 ${PREFIX}/man/man8
${INSTALL_MAN} ${WRKSRC}/spamlogd/spamlogd.8 ${PREFIX}/man/man8
- @if [ ! -f ${SAMPLE_SPAMD_CONF} ]; then \
+ @if [ ! -d ${CONFIG_DIR} ]; then \
+ ${MKDIR} ${CONFIG_DIR}; \
+ fi
+ @if [ ! -f ${SAMPLE_SPAMD_CONF} ]; then \
${ECHO_MSG} "Installing ${SAMPLE_SPAMD_CONF} file."; \
- ${INSTALL_DATA} ${WRKSRC}/doc/spamd.conf \
- ${SAMPLE_SPAMD_CONF}; \
+ ${ECHO_MSG} "${INSTALL_DATA} -v -p ${WRKSRC}/etc/spamd.conf ${SAMPLE_SPAMD_CONF}"; \
+ ${INSTALL_DATA} -v -p ${WRKSRC}/etc/spamd.conf \
+ ${SAMPLE_SPAMD_CONF}; \
fi
+.if !defined(NOPORTDOCS)
+ @${MKDIR} ${DOCSDIR}
+ @${INSTALL_DATA} ${WRKSRC}/doc/ipfw-spamd.txt ${DOCSDIR}/
+.endif
.include <bsd.port.post.mk>
diff -ruN --exclude=CVS /usr/ports/mail/spamd/distinfo /usr/home/samm/spamd/distinfo
--- /usr/ports/mail/spamd/distinfo Thu Jan 26 21:27:27 2006
+++ /usr/home/samm/spamd/distinfo Sun Jun 3 18:49:28 2007
@@ -1,3 +1,3 @@
-MD5 (spamd_3.7.tar.bz2) = e1d96b9d7b1d4189dca510ff0000383f
-SHA256 (spamd_3.7.tar.bz2) = a06ad07ead38240f13ea01c5d0315179e7089ed8fb8fe6544b1860bd8cfdc355
-SIZE (spamd_3.7.tar.bz2) = 28066
+MD5 (spamd-4.1.1.tar.gz) = 6cf6a92b709e1907162fd1c59af7943a
+SHA256 (spamd-4.1.1.tar.gz) = b6e8b00ec0b3ff5ff3e73de2fab3f3bbbd3d95807ef1a946a6302666d17c503a
+SIZE (spamd-4.1.1.tar.gz) = 50179
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/obspamd.in /usr/home/samm/spamd/files/obspamd.in
--- /usr/ports/mail/spamd/files/obspamd.in Thu Jan 1 03:00:00 1970
+++ /usr/home/samm/spamd/files/obspamd.in Mon Apr 23 18:33:35 2007
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: obspamd
+# REQUIRE: NETWORKING SERVERS
+# BEFORE: DAEMON
+# KEYWORD: shutdown
+
+#
+# Define these spamd_* variables in one of these files:
+# /etc/rc.conf
+# /etc/rc.conf.local
+#
+# obspamd_enable="YES" # Run the spamd(8) daemon (YES/NO).
+# obspamd_flags="" # Extra flags for spamd(8) (if enabled).
+#
+# DO NOT CHANGE THESE DEFAULT VALUES HERE
+#
+obspamd_enable=${obspamd_enable:-"NO"}
+obspamd_flags=${obspamd_flags:-""}
+
+. %%RC_SUBR%%
+
+name="obspamd"
+rcvar=`set_rcvar`
+
+command="%%PREFIX%%/libexec/spamd"
+start_precmd="obspamd_precmd"
+start_postcmd="obspamd_postcmd"
+restart_postcmd="obspamd_postcmd"
+stop_postcmd="obspamd_cleanup"
+pidfile="/var/run/spamd.pid"
+
+obspamd_precmd()
+{
+ _rc=0
+ echo "${obspamd_flags}" | grep "\-b" 2>&1 > /dev/null
+ if [ $? -eq 1 ]; then
+ /sbin/mount -p | grep 'fdescfs.*/dev/fd.*fdescfs.*rw' 2>&1 > /dev/null
+ _rc=${?}
+ if [ ${_rc} -ne 0 ]; then
+ echo "Unable to start spamd in greylisting mode"
+ echo ""
+ echo "Please mount fdescfs with the following line in /etc/fstab"
+ echo ""
+ echo " fdescfs /dev/fd fdescfs rw 0 0"
+ echo ""
+ fi
+ return ${_rc}
+ fi
+}
+
+obspamd_postcmd()
+{
+ if [ -x %%PREFIX%%/sbin/spamd-setup ]; then
+ if [ -r %%PREFIX%%/etc/spamd/spamd.conf ]; then
+ %%PREFIX%%/sbin/spamd-setup &
+ fi
+ fi
+}
+
+obspamd_cleanup()
+{
+ /bin/rm -f ${pidfile}
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/obspamlogd.in /usr/home/samm/spamd/files/obspamlogd.in
--- /usr/ports/mail/spamd/files/obspamlogd.in Thu Jan 1 03:00:00 1970
+++ /usr/home/samm/spamd/files/obspamlogd.in Mon Apr 23 18:33:35 2007
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: obspamlogd
+# REQUIRE: NETWORKING SERVERS obspamd
+# BEFORE: DAEMON
+# KEYWORD: shutdown
+
+#
+# Define these obspamlogd_* variables in one of these files:
+# /etc/rc.conf
+# /etc/rc.conf.local
+#
+# obspamlogd_enable="YES" # Run the spamlogd(8) daemon (YES/NO).
+# obspamlogd_flags="" # Extra flags for spamlogd(8) (if enabled).
+#
+# DO NOT CHANGE THESE DEFAULT VALUES HERE
+#
+obspamlogd_enable=${obspamlogd_enable:-"NO"}
+obspamlogd_flags=${obspamlogd_flags:-""}
+
+. %%RC_SUBR%%
+
+name="obspamlogd"
+rcvar=`set_rcvar`
+
+command="%%PREFIX%%/libexec/spamlogd"
+start_precmd="obspamlogd_precmd"
+stop_postcmd="obspamlogd_cleanup"
+pidfile="/var/run/spamlogd.pid"
+
+obspamlogd_precmd()
+{
+ _rc=0
+ /sbin/mount -p | grep 'fdescfs.*/dev/fd.*fdescfs.*rw' 2>&1 > /dev/null
+ _rc=${?}
+ if [ ${_rc} -ne 0 ]; then
+ echo "Unable to start ${name}"
+ echo ""
+ echo "Please mount fdescfs with the following line in /etc/fstab"
+ echo ""
+ echo " fdescfs /dev/fd fdescfs rw 0 0"
+ echo ""
+ fi
+ return ${_rc}
+}
+
+obspamlogd_cleanup()
+{
+ /bin/rm -f ${pidfile}
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/patch-greyc /usr/home/samm/spamd/files/patch-greyc
--- /usr/ports/mail/spamd/files/patch-greyc Tue May 2 11:54:50 2006
+++ /usr/home/samm/spamd/files/patch-greyc Thu Jan 1 03:00:00 1970
@@ -1,131 +0,0 @@
---- spamd/grey.c Wed Apr 13 03:22:17 2005
-+++ spamd/grey.c Mon Mar 20 15:26:18 2006
-@@ -39,6 +39,10 @@
- #include <unistd.h>
- #include <netdb.h>
-
-+#ifdef IPFW
-+#include <netinet/ip_fw.h>
-+#endif
-+
- #include "grey.h"
-
- extern time_t passtime, greyexp, whiteexp, trapexp;
-@@ -65,13 +69,17 @@
- char *traplist_msg = "\"Your address %A has mailed to spamtraps here\\n\"";
-
- pid_t db_pid = -1;
--int pfdev;
- int spamdconf;
-
-+#ifdef IPFW
-+extern int tabno;
-+#else
-+int pfdev;
- static char *pargv[11]= {
- "pfctl", "-p", "/dev/pf", "-q", "-t",
- "spamd-white", "-T", "replace", "-f" "-", NULL
- };
-+#endif
-
- /* If the parent gets a signal, kill off the children and exit */
- /* ARGSUSED */
-@@ -104,6 +112,7 @@
- return(0);
- }
-
-+#ifndef IPFW
- int
- configure_pf(char **addrs, int count)
- {
-@@ -166,11 +175,54 @@
- for (i = 0; i < count; i++)
- if (addrs[i] != NULL)
- fprintf(pf, "%s/32\n", addrs[i]);
-+
- fclose(pf);
- waitpid(pid, NULL, 0);
- sigaction(SIGCHLD, &sa, NULL);
- return(0);
- }
-+#else
-+int
-+configure_pf(char **addrs, int count)
-+{
-+ static int s = -1;
-+ ipfw_table_entry ent;
-+ int i;
-+
-+ if (s == -1)
-+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-+ if (s < 0)
-+ {
-+ syslog_r(LOG_INFO, &sdata, "IPFW socket unavailable (%m)");
-+ return(-1);
-+ }
-+
-+ /* flush the table */
-+ ent.tbl = tabno;
-+ if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
-+ {
-+ syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_FLUSH) (%m)");
-+ return(-1);
-+ }
-+
-+ for (i = 0; i < count; i++)
-+ if (addrs[i] != NULL)
-+ {
-+ /* add addrs[i] to tabno */
-+ ent.tbl = tabno;
-+ ent.masklen = 32;
-+ ent.value = 0;
-+ inet_aton(addrs[i], (struct in_addr *)&ent.addr);
-+ if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD, &ent, sizeof(ent)) < 0)
-+ {
-+ syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_ADD) (%m)");
-+ return(-1);
-+ }
-+ }
-+
-+ return(0);
-+}
-+#endif
-
- void
- freeaddrlists(void)
-@@ -590,11 +642,13 @@
- int i;
- struct sigaction sa;
-
-+#ifndef IPFW
- pfdev = open("/dev/pf", O_RDWR);
- if (pfdev == -1) {
- syslog_r(LOG_ERR, &sdata, "open of /dev/pf failed (%m)");
- exit(1);
- }
-+#endif
-
- /* check to see if /var/db/spamd exists, if not, create it */
- if ((i = open(PATH_SPAMD_DB, O_RDWR, 0)) == -1 && errno == ENOENT) {
-@@ -636,7 +690,9 @@
- * child, talks to jailed spamd over greypipe,
- * updates db. has no access to pf.
- */
-+#ifndef IPFW
- close(pfdev);
-+#endif
- setproctitle("(%s update)", PATH_SPAMD_DB);
- greyreader();
- /* NOTREACHED */
-@@ -655,7 +711,11 @@
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
-+#ifndef IPFW
- setproctitle("(pf <spamd-white> update)");
-+#else
-+ setproctitle("(ipfw white table update)");
-+#endif
- greyscanner();
- /* NOTREACHED */
- exit(1);
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/patch-greyh /usr/home/samm/spamd/files/patch-greyh
--- /usr/ports/mail/spamd/files/patch-greyh Tue May 2 11:54:50 2006
+++ /usr/home/samm/spamd/files/patch-greyh Thu Jan 1 03:00:00 1970
@@ -1,10 +0,0 @@
---- spamd/grey.h Thu Mar 16 19:55:33 2006
-+++ spamd/grey.h Thu Mar 16 19:55:56 2006
-@@ -22,6 +22,7 @@
- #define WHITEEXP (60 * 60 * 24 * 36) /* remove white entries after 36 days */
- #define TRAPEXP (60 * 60 * 24) /* hitting a spamtrap blacklists for a day */
- #define PATH_PFCTL "/sbin/pfctl"
-+#define PATH_IPFW "/sbin/ipfw"
- #define DB_SCAN_INTERVAL 60
- #define PATH_SPAMD_DB "/var/db/spamd"
-
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/patch-spamd /usr/home/samm/spamd/files/patch-spamd
--- /usr/ports/mail/spamd/files/patch-spamd Tue May 2 11:54:50 2006
+++ /usr/home/samm/spamd/files/patch-spamd Thu Jan 1 03:00:00 1970
@@ -1,48 +0,0 @@
---- spamd/spamd.c Thu Mar 16 20:56:45 2006
-+++ spamd/spamd.c Thu Mar 16 21:07:11 2006
-@@ -123,6 +123,10 @@
- pid_t jail_pid = -1;
- u_short cfg_port;
-
-+#ifdef IPFW
-+int tabno=1;
-+#endif
-+
- extern struct sdlist *blacklists;
-
- int conffd = -1;
-@@ -153,6 +157,10 @@
- " [-G mins:hours:hours] [-n name] [-p port]\n");
- fprintf(stderr,
- " [-r reply] [-s secs] [-w window]\n");
-+#ifdef IPFW
-+ fprintf(stderr,
-+ " [-t table_no]\n");
-+#endif
- exit(1);
- }
-
-@@ -958,7 +966,11 @@
- if (gethostname(hostname, sizeof hostname) == -1)
- err(1, "gethostname");
-
-+#ifdef IPFW
-+ while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:t:")) != -1) {
-+#else
- while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:")) != -1) {
-+#endif
- switch (ch) {
- case '4':
- nreply = "450";
-@@ -1015,6 +1027,11 @@
- case 'v':
- verbose = 1;
- break;
-+#ifdef IPFW
-+ case 't':
-+ tabno = atoi(optarg);
-+ break;
-+#endif
- case 'w':
- window = atoi(optarg);
- if (window <= 0)
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/patch-spamd-setup /usr/home/samm/spamd/files/patch-spamd-setup
--- /usr/ports/mail/spamd/files/patch-spamd-setup Thu Apr 26 08:42:02 2007
+++ /usr/home/samm/spamd/files/patch-spamd-setup Thu Jan 1 03:00:00 1970
@@ -1,110 +0,0 @@
---- spamd-setup/spamd-setup.c.orig Wed Apr 13 01:18:59 2005
-+++ spamd-setup/spamd-setup.c Wed May 10 01:55:13 2006
-@@ -41,6 +41,11 @@
- #include <netdb.h>
- #include <zlib.h>
-
-+#ifdef IPFW
-+#include <net/if.h>
-+#include <netinet/ip_fw.h>
-+#endif
-+
- #define PATH_FTP "/usr/bin/ftp"
- #define PATH_PFCTL "%%LOCAL_PFCTL%%"
- #define PATH_SPAMD_CONF "%%LOCAL_SPAMD_CONF%%"
-@@ -93,6 +98,11 @@
- int debug;
- int dryrun;
-
-+#ifdef IPFW
-+int tabno=2;
-+#endif
-+
-+
- u_int32_t
- imask(u_int8_t b)
- {
-@@ -630,6 +640,7 @@
- }
-
-
-+#ifndef IPFW
- int
- configure_pf(struct cidr **blacklists)
- {
-@@ -676,6 +687,51 @@
- }
- return(0);
- }
-+#else
-+int
-+configure_pf(struct cidr **blacklists)
-+{
-+ static int s = -1;
-+ ipfw_table_entry ent;
-+
-+ if (s == -1)
-+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-+ if (s < 0)
-+ {
-+ err(1, "IPFW socket unavailable");
-+ return(-1);
-+ }
-+
-+ /* flush the table */
-+ ent.tbl = tabno;
-+ if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
-+ {
-+ err(1, "IPFW setsockopt(IP_FW_TABLE_FLUSH)");
-+ return(-1);
-+ }
-+
-+ while (*blacklists != NULL) {
-+ struct cidr *b = *blacklists;
-+
-+ while (b->addr != 0) {
-+ /* add b to tabno */
-+ ent.tbl = tabno;
-+ ent.masklen = b->bits;
-+ ent.value = 0;
-+ inet_aton(atop(b->addr), (struct in_addr *)&ent.addr);
-+ if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD, &ent, sizeof(ent)) < 0)
-+ {
-+ err(1, "IPFW setsockopt(IP_FW_TABLE_ADD)");
-+ return(-1);
-+ }
-+ b++;
-+ }
-+ blacklists++;
-+ }
-+
-+ return(0);
-+}
-+#endif
-
- int
- getlist(char ** db_array, char *name, struct blacklist *blist,
-@@ -773,7 +829,11 @@
- struct servent *ent;
- int i, ch;
-
-+#ifndef IPFW
- while ((ch = getopt(argc, argv, "nd")) != -1) {
-+#else
-+ while ((ch = getopt(argc, argv, "ndt:")) != -1) {
-+#endif
- switch (ch) {
- case 'n':
- dryrun = 1;
-@@ -781,6 +841,11 @@
- case 'd':
- debug = 1;
- break;
-+#ifdef IPFW
-+ case 't':
-+ tabno = atoi(optarg);
-+ break;
-+#endif
- default:
- break;
- }
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/patch-spamdm /usr/home/samm/spamd/files/patch-spamdm
--- /usr/ports/mail/spamd/files/patch-spamdm Tue May 2 11:54:50 2006
+++ /usr/home/samm/spamd/files/patch-spamdm Thu Jan 1 03:00:00 1970
@@ -1,89 +0,0 @@
---- spamd/spamd.8 Wed Apr 13 03:21:48 2005
-+++ spamd/spamd.8 Mon Mar 20 15:12:10 2006
-@@ -49,6 +49,8 @@
- daemon which rejects false mail.
- If the
- .Xr pf 4
-+or
-+.Xr ipfw 4
- packet filter is configured to redirect port 25 (SMTP) to this daemon,
- it will attempt to waste the time and resources of the spam sender.
- .Pp
-@@ -151,11 +153,15 @@
- which processes a list of spammers' addresses, and applies appropriate
- .Xr pfctl 8
- .Em rdr
-+or
-+.Xr ipfw 8
-+.Em fwd
- rules.
- .Xr spamd-setup 8
- is run from
- .Xr cron 8 .
- .Sh REDIRECTING SMTP CONNECTIONS
-+.Ss "When using PF"
- With
- .Xr pf 4 ,
- connections to port 25 (SMTP) can be redirected to another host or port,
-@@ -189,6 +195,8 @@
- can also be used to load addresses into the
- .Em <spamd>
- table.
-+
-+
- .Xr spamd-setup 8
- also has the added benefit of being able to remove addresses from
- blacklists, and will connect to
-@@ -203,6 +211,52 @@
- This is important as it allows legitimate mail
- senders to pressure spam sources into behaving properly so that they
- may be removed from the relevant blacklists.
-+
-+.Ss "If compiled with IPFW"
-+With
-+.Xr ipfw 4 ,
-+the syntax for redirection of TCP sessions is quite different
-+from that of
-+.Xr pf 4 .
-+The
-+.Em fwd
-+rule used for this purpose are described in
-+.Xr ipfw 8 .
-+The rules should be added to the ruleset called by /etc/rc.firewall
-+to be present at boot time.
-+.Bd -literal -offset 4n
-+fwd 127.0.0.1,8025 tcp from table(2) to me 25 in
-+allow tcp from table(1) to me 25 in
-+fwd 127.0.0.1,8025 tcp from any to me 25 in
-+.Ed
-+.Pp
-+Any addresses in the blacklist table
-+.Em 2
-+and not in the whitelist table
-+.Em 1
-+are then redirected to
-+.Nm
-+running on port 8025.
-+Addresses can be loaded into the blacklist
-+.Em table ,
-+like:
-+.Bd -literal -offset 4n
-+# ipfw table 1 add a.b.c.d/x
-+.Ed
-+.Pp
-+.Xr spamd-setup 8
-+can also be used to load addresses into the blacklist table
-+.Em 2 .
-+.Pp
-+The
-+.Op Fl t Ar table_no
-+option to
-+.Em spamd
-+and
-+.Em spamd-setup
-+can be used to change the default table
-+numbers.
-+
- .Sh CONFIGURATION CONNECTIONS
- .Nm
- listens for configuration connections on the port identified by the
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/pfspamd.sh.in /usr/home/samm/spamd/files/pfspamd.sh.in
--- /usr/ports/mail/spamd/files/pfspamd.sh.in Thu Apr 26 08:42:02 2007
+++ /usr/home/samm/spamd/files/pfspamd.sh.in Thu Jan 1 03:00:00 1970
@@ -1,49 +0,0 @@
-#!/bin/sh
-#
-# $FreeBSD: ports/mail/spamd/files/pfspamd.sh.in,v 1.2 2007/03/20 15:16:44 delphij Exp $
-#
-
-# PROVIDE: pfspamd
-# REQUIRE: NETWORKING
-# BEFORE: mail
-# KEYWORD: shutdown
-
-#
-# Add the following lines to /etc/rc.conf to enable spamd:
-# pfspamd_enable (bool): Set to "NO" by default.
-# Set it to "YES" to enable spamd
-# pfspamd_flags (str): Set to "" by default.
-# Extra flags passed to start command.
-# pfspamd_setup_flags (str): Set to "" by default.
-# Extra flags passed to spamd-setup command.
-
-. %%RC_SUBR%%
-
-name="pfspamd"
-rcvar=`set_rcvar`
-
-command="%%PREFIX%%/libexec/spamd"
-start_postcmd="pfspamd_postcmd"
-restart_postcmd="pfspamd_postcmd"
-
-[ -z "$pfspamd_enable" ] && pfspamd_enable="NO"
-[ -z "$pfspamd_flags" ] && pfspamd_flags=""
-[ -z "$pfspamd_setup_flags" ] && pfspamd_setup_flags=""
-
-load_rc_config $name
-
-# we override check_process to avoid conflict with the spamd from sa-spamd
-check_process()
-{
- ps ax -o pid,command | grep "libexec/spamd" | grep -v grep | awk '{print $1}'
-}
-
-
-pfspamd_postcmd()
-{
- if [ -x %%PREFIX%%/sbin/spamd-setup ]; then
- %%PREFIX%%/sbin/spamd-setup $pfspamd_setup_flags
- fi
-}
-
-run_rc_command "$1"
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/pkg-deinstall.in /usr/home/samm/spamd/files/pkg-deinstall.in
--- /usr/ports/mail/spamd/files/pkg-deinstall.in Thu Jan 1 03:00:00 1970
+++ /usr/home/samm/spamd/files/pkg-deinstall.in Tue Apr 10 18:49:02 2007
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+#
+
+SPAMDDIR=%%SPAMDDIR%%
+SPAMDUSER=%%SPAMDUSER%%
+SPAMDGROUP=%%SPAMDGROUP%%
+
+if [ "$2" = "POST-DEINSTALL" ]; then
+ if /usr/sbin/pw group show "${SPAMDGROUP}" 2>&1 >/dev/null; then
+ echo "You should manually remove the \"${SPAMDGROUP}\" group."
+ fi
+
+ if /usr/sbin/pw user show "${SPAMDUSER}" 2>&1 >/dev/null; then
+ echo "You should manually remove the \"${SPAMDUSER}\" user."
+ fi
+
+ if [ -e "${SPAMDDIR}" ]; then
+ echo "You should manually remove the \"${SPAMDDIR}\" directory."
+ fi
+fi
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/pkg-install.in /usr/home/samm/spamd/files/pkg-install.in
--- /usr/ports/mail/spamd/files/pkg-install.in Thu Jan 1 03:00:00 1970
+++ /usr/home/samm/spamd/files/pkg-install.in Wed Apr 18 15:58:31 2007
@@ -0,0 +1,148 @@
+#!/bin/sh
+#
+#
+
+SPAMDDIR=%%SPAMDDIR%%
+SPAMDUSER=%%SPAMDUSER%%
+SPAMDGROUP=%%SPAMDGROUP%%
+SPAMDUID=%%SPAMDUID%%
+SPAMDGID=%%SPAMDGID%%
+
+ask() {
+ local question default answer
+
+ question=$1
+ default=$2
+ if [ -z "${PACKAGE_BUILDING}" ]; then
+ read -p "${question} [${default}]? " answer
+ fi
+ if [ "x${answer}" = "x" ]; then
+ answer=${default}
+ fi
+ echo ${answer}
+}
+
+yesno() {
+ local default question answer
+
+ question=$1
+ default=$2
+ while :; do
+ answer=$(ask "${question}" "${default}")
+ case "${answer}" in
+ [Yy][Ee][Ss]|[Yy])
+ return 0
+ ;;
+ [Nn][Oo]|[Nn])
+ return 1
+ ;;
+ esac
+ echo "Please answer yes or no."
+ done
+}
+
+check_db() {
+ DB=/var/db/spamd
+ if [ -f ${DB} ]; then
+ OWN=`ls -l ${DB} | awk '{print $3}'`
+ GRP=`ls -l ${DB} | awk '{print $4}'`
+ fi
+ if [ "x${OWN}" != "x${SPAMDUSER}" ]; then
+ echo "change ${BD} owner to ${SPAMDUSER}:"
+ /usr/sbin/chown ${SPAMDUSER} ${DB}
+ fi
+ if [ "x${GRP}" != "x${SPAMDGROUP}" ]; then
+ echo "change ${BD} owner to :${SPAMDUSER}"
+ /usr/sbin/chown :${SPAMDGROUP} ${DB}
+ fi
+}
+
+check_service() {
+ local name number type comment
+
+ name=$1
+ number=$2
+ type=$3
+ comment=$4
+
+ FILE="/etc/services"
+ # check
+ OK=no
+ HAS_SERVICE=no
+ COUNT=1
+ for i in `grep $name $FILE `; do
+ if [ $COUNT = 1 ] && [ X"$i" = X"$name" ]; then
+ HAS_SERVICE=yes
+ elif [ $COUNT = 2 ] && [ $HAS_SERVICE = yes ] && \
+ [ X"$i" = X"$number/$type" ]; then
+ OK=yes
+ break
+ fi
+ COUNT=`expr ${COUNT} + 1`
+ done
+ # add an entry for SERVICE to /etc/services
+ if [ $OK = no ]; then
+ echo "This system has no entry for $name in ${FILE}"
+ if yesno "Would you like to add it automatically?" y; then
+ mv ${FILE} ${FILE}.bak
+ (grep -v $name ${FILE}.bak ; \
+ echo "$name $number/$type # $comment") \
+ >> ${FILE}
+ rm ${FILE}.bak
+ else
+ echo "Please add '$name $number/$type' into ${FILE}, and try again."
+ return 1
+ fi
+ fi
+ return 0
+}
+
+
+if [ "$2" = "PRE-INSTALL" ]; then
+ check_dbown=0
+ if /usr/sbin/pw group show "${SPAMDGROUP}" 2>&1 >/dev/null; then
+ echo "You already have a \"${SPAMDGROUP}\" group, so I will use it."
+ else
+ echo "You need a \"${SPAMDGROUP}\" group."
+ if yesno "Would you like me to create it" "YES"; then
+ /usr/sbin/pw groupadd "${SPAMDGROUP}" -g "${SPAMDGID}" -h - || \
+ /usr/sbin/pw groupadd "${SPAMDGROUP}" -h - || exit
+ echo "Done."
+ check_dbown=1
+ else
+ echo "Please create the \"${SPAMDGROUP}\" group manually and try again."
+ exit 1
+ fi
+ fi
+
+ if /usr/sbin/pw user show "${SPAMDUSER}" 2>&1 >/dev/null; then
+ echo "You already have a \"${SPAMDUSER}\" user, so I will use it."
+ else
+ echo "You need a \"${SPAMDUSER}\" user."
+ if yesno "Would you like me to create it" "YES"; then
+ /usr/sbin/pw useradd "${SPAMDUSER}" -u "${SPAMDUID}" -g "${SPAMDGROUP}" -h - -d "${SPAMDDIR}" \
+ -s /sbin/nologin -c "spamd pseudo-user" || \
+ /usr/sbin/pw useradd "${SPAMDUSER}" -g "${SPAMDGROUP}" -h - -d "${SPAMDDIR}" \
+ -s /sbin/nologin -c "spamd pseudo-user" || exit
+ check_dbown=1
+ else
+ echo "Please create the \"${SPAMDUSER}\" user manually and try again."
+ exit 1
+ fi
+ fi
+
+ if [ ${check_dbown} -eq 1 ]; then
+ check_db
+ fi
+
+ if ! check_service spamd 8025 tcp "spamd(8)"; then
+ exit 1
+ fi
+ if ! check_service spamd-cfg 8026 tcp "spamd(8) configuration"; then
+ exit 1
+ fi
+ if ! check_service spamd-sync 8025 udp "spamd(8) synchronisation"; then
+ exit 1
+ fi
+
+fi
diff -ruN --exclude=CVS /usr/ports/mail/spamd/files/pkg-message.in /usr/home/samm/spamd/files/pkg-message.in
--- /usr/ports/mail/spamd/files/pkg-message.in Thu Jan 1 03:00:00 1970
+++ /usr/home/samm/spamd/files/pkg-message.in Sun Jun 3 18:49:28 2007
@@ -0,0 +1,42 @@
+**********************************************************************
+To enable spamd you need:
+
+1) Enable spamd in /etc/rc.conf with the following line:
+ obspamd_enable="YES"
+ obspamlogd_enable="YES"
+
+2) Configuration template is available in %%PREFIX%%/etc/spamd as
+ spamd.conf.sample file. Copy then to spamd.conf file and
+ edit to suit your needs.
+
+3) mount fdescfs to /dev/fd with the following line in /etc/fstab
+ fdescfs /dev/fd fdescfs rw 0 0
+
+4) Add following lines to the pf.conf(5)
+
+ table <spamd-white> persist
+ no rdr inet proto tcp from <spamd-white> to any \
+ port smtp
+ rdr pass inet proto tcp from any to any \
+ port smtp -> 127.0.0.1 port spamd
+
+ !!!!!!!!!!!! -- I M P O T A N T - N O T E S -- !!!!!!!!!!!!!!!!!
+ !
+ ! changes in Ver. 4.1.x:
+ ! - UID/GID is reserved to: _spamd:_spamd
+ ! check the owner of /var/db/spamd
+ ! - greylisting is now the default
+ ! - paramer: -b is now blacklist (Ver. < 4.1.x it is bind address)
+ ! - paramer: -l is now listen address
+ ! - spamdb: format is now HASH, helo/ehlo is also stored in db
+ ! convert will be done at the first start of spamd
+ ! if you have scripts that use spamdb review this scripts
+ ! - config files: new location is %%PREFIX%%/etc/spamd
+ ! - spamtrapp addresses: remove the surrounding '< >' signs
+ ! - pfspamd.sh was renamed to the obspamd
+ ! - IPFW support (beta) added to the sources.
+ ! See %%PREFIX%%/%%DOCSDIR%%/spamd-ipfw.txt for usage manual.
+ !
+ !!!!!!!!!!!! -- I M P O T A N T - N O T E S -- !!!!!!!!!!!!!!!!!
+
+**********************************************************************
diff -ruN --exclude=CVS /usr/ports/mail/spamd/pkg-descr /usr/home/samm/spamd/pkg-descr
--- /usr/ports/mail/spamd/pkg-descr Wed Nov 8 22:37:58 2006
+++ /usr/home/samm/spamd/pkg-descr Tue Apr 10 11:41:43 2007
@@ -1,17 +1,21 @@
-Tarpits like spamd are fake SMTP servers, which accept connections but don't
-deliver mail. Instead, they keep the connections open and reply very slowly.
-If the peer is patient enough to actually complete the SMTP dialogue (which
-will take ten minutes or more), the tarpit returns a 'temporary error' code
-(4xx), which indicates that the mail could not be delivered successfully and
-that the sender should keep the mail in his queue and retry again later. If
-he does, the same procedure repeats. Until, after several attempts, wasting
-both his queue space and socket handles for several days, he gives up. The
-resources I have to waste to do this are minimal.
+Spamd is a fake sendmail(8)-like daemon which rejects false mail. It is
+designed to be very efficient so that it does not slow down the receiving
+machine.
-If the sender is badly configured, an uncooperative recipient might actually
-delay his entire queue handling for several minutes each time he connects to
-the tarpit. And many spammers use badly configured open relays
+spamd considers sending hosts to be of three types:
-WWW: http://www.OpenBSD.org/spamd/
+ blacklisted hosts are redirected to spamd and tarpitted i.e. they are
+ communicated with very slowly to consume the sender's resources. Mail is
+ rejected with either a 450 or 550 error message. A blacklisted host will not
+ be allowed to talk to a real mail server.
+
+ whitelisted hosts do not talk to spamd. Their connections are instead sent to
+ a real mail server, such as sendmail(8).
+
+ greylisted hosts are redirected to spamd, but spamd has not yet decided if
+ they are likely spammers. They are given a temporary failure message by spamd
+ when they try to deliver mail.
+
+WWW: http://freebsdspamd.berlios.de/
-Max <max at love2party.net>
diff -ruN --exclude=CVS /usr/ports/mail/spamd/pkg-install /usr/home/samm/spamd/pkg-install
--- /usr/ports/mail/spamd/pkg-install Tue Sep 30 02:01:21 2003
+++ /usr/home/samm/spamd/pkg-install Thu Jan 1 03:00:00 1970
@@ -1,84 +0,0 @@
-#!/bin/sh
-# an installation script for spamd copied from pf_freebsd
-
-ask() {
- local question default answer
-
- question=$1
- default=$2
- if [ -z "${PACKAGE_BUILDING}" ]; then
- read -p "${question} (y/n) [${default}]? " answer
- fi
- if [ x${answer} = x ]; then
- answer=${default}
- fi
- echo ${answer}
-}
-
-yesno() {
- local dflt question answer
-
- question=$1
- dflt=$2
- while :; do
- answer=$(ask "${question}" "${dflt}")
- case "${answer}" in
- [Yy]*) return 0;;
- [Nn]*) return 1;;
- esac
- echo "Please answer yes or no."
- done
-}
-
-check_service() {
- local name number type comment
-
- name=$1
- number=$2
- type=$3
- comment=$4
-
- FILE="/etc/services"
- # check
- OK=no
- HAS_SERVICE=no
- COUNT=1
- for i in `grep $name $FILE `; do
- if [ $COUNT = 1 ] && [ X"$i" = X"$name" ]; then
- HAS_SERVICE=yes
- elif [ $COUNT = 2 ] && [ $HAS_SERVICE = yes ] && \
- [ X"$i" = X"$number/$type" ]; then
- OK=yes
- break
- fi
- COUNT=`expr ${COUNT} + 1`
- done
- # add an entry for SERVICE to /etc/services
- if [ $OK = no ]; then
- echo "This system has no entry for $name in ${FILE}"
- if yesno "Would you like to add it automatically?" y; then
- mv ${FILE} ${FILE}.bak
- (grep -v $name ${FILE}.bak ; \
- echo "$name $number/$type # $comment") \
- >> ${FILE}
- rm ${FILE}.bak
- else
- echo "Please add '$name $number/$type' into ${FILE}, and try again."
- return 1
- fi
- fi
- return 0
-}
-
-case $2 in
-PRE-INSTALL)
-
- if ! check_service spamd 8025 tcp "# spamd(8)"; then
- exit 1
- fi
- if ! check_service spamd-cfg 8026 tcp "# spamd(8) configuration"; then
- exit 1
- fi
- ;;
-
-esac
diff -ruN --exclude=CVS /usr/ports/mail/spamd/pkg-message /usr/home/samm/spamd/pkg-message
--- /usr/ports/mail/spamd/pkg-message Thu Jan 13 04:54:46 2005
+++ /usr/home/samm/spamd/pkg-message Thu Jan 1 03:00:00 1970
@@ -1,9 +0,0 @@
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-In order to use spamd greylisting feature you have to have a mounted fdescfs(5)
-at /dev/fd. This is done by adding:
-
- fdescfs /dev/fd fdescfs rw 0 0
-
-to /etc/fstab. You may need either a customised kernel, or kldload the fdescfs
-kernel module.
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff -ruN --exclude=CVS /usr/ports/mail/spamd/pkg-plist /usr/home/samm/spamd/pkg-plist
--- /usr/ports/mail/spamd/pkg-plist Tue May 23 14:17:08 2006
+++ /usr/home/samm/spamd/pkg-plist Thu Jan 1 03:00:00 1970
@@ -1,5 +0,0 @@
-libexec/spamd
-libexec/spamlogd
-sbin/spamd-setup
-sbin/spamdb
-etc/spamd.conf.sample
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/Makefile /usr/home/samm/spamd/work/spamd_3.7/Makefile
--- /usr/ports/mail/spamd/work/spamd_3.7/Makefile Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/Makefile Thu Jan 1 03:00:00 1970
@@ -1,7 +0,0 @@
-#
-# Makefile for OpenBSD spamd
-#
-
-SUBDIR+= spamd spamd-setup spamdb spamlogd
-
-.include <bsd.subdir.mk>
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/doc/spamd.conf /usr/home/samm/spamd/work/spamd_3.7/doc/spamd.conf
--- /usr/ports/mail/spamd/work/spamd_3.7/doc/spamd.conf Sun Jan 16 19:16:44 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/doc/spamd.conf Thu Jan 1 03:00:00 1970
@@ -1,86 +0,0 @@
-# $OpenBSD: spamd.conf,v 1.12 2005/01/16 17:16:44 deraadt Exp $
-#
-# spamd config file, read by spamd-setup(8) for spamd(8)
-#
-# See spamd.conf(5)
-#
-# Configures whitelists and blacklists for spamd
-#
-# Strings follow getcap(3) convention escapes, other than you
-# can have a bare colon (:) inside a quoted string and it
-# will deal with it. See spamd-setup(8) for more details.
-#
-# "all" must be here, and defines the order in which lists are applied
-# whitelists apply to the previous blacklist. more than one whitelist
-# may be applied to each blacklist
-#
-# As of November 2004, a place to search for black lists is
-# http://spamlinks.net/filter-bl.htm
-#
-# Some of the URLs below point to www.openbsd.org locations. Those
-# files are likely to be mirrored to other OpenBSD www mirrors located
-# around the world. Hence, it is possible to edit this file and rewrite
-# www.openbsd.org with, for instance, to www.de.openbsd.org
-
-all:\
- :spamhaus:china:korea:
-
-# Mirrored from http://spfilter.openrbl.org/data/sbl/SBL.cidr.bz2
-spamhaus:\
- :black:\
- :msg="SPAM. Your address %A is in the Spamhaus Block List\n\
- See http://www.spamhaus.org/sbl and\
- http://www.abuse.net/sbl.phtml?IP=%A for more details":\
- :method=http:\
- :file=www.openbsd.org/spamd/SBL.cidr.gz:
-
-# Mirrored from http://www.spews.org/spews_list_level1.txt
-spews1:\
- :black:\
- :msg="SPAM. Your address %A is in the spews level 1 database\n\
- See http://www.spews.org/ask.cgi?x=%A for more details":\
- :method=http:\
- :file=www.openbsd.org/spamd/spews_list_level1.txt.gz:
-
-# Mirrored from http://www.spews.org/spews_list_level2.txt
-spews2:\
- :black:\
- :msg="SPAM. Your address %A is in the spews level 2 database\n\
- See http://www.spews.org/ask.cgi?x=%A for more details":\
- :method=http:\
- :file=www.openbsd.org/spamd/spews_list_level2.txt.gz:
-
-# Mirrored from http://www.okean.com/chinacidr.txt
-china:\
- :black:\
- :msg="SPAM. Your address %A appears to be from China\n\
- See http://www.okean.com/asianspamblocks.html for more details":\
- :method=http:\
- :file=www.openbsd.org/spamd/chinacidr.txt.gz:
-
-# Mirrored from http://www.okean.com/koreacidr.txt
-korea:\
- :black:\
- :msg="SPAM. Your address %A appears to be from Korea\n\
- See http://www.okean.com/asianspamblocks.html for more details":\
- :method=http:\
- :file=www.openbsd.org/spamd/koreacidr.txt.gz:
-
-
-# Whitelists are done like this, and must be added to "all" after each
-# blacklist from which you want the addresses in the whitelist removed.
-#
-#whitelist:\
-# :white:\
-# :file=/var/mail/whitelist.txt:
-
-relaydb-black:\
- :black:\
- :msg="SPAM. Your address %A is in my relaydb list.":\
- :method=exec:\
- :file=relaydb -4lb:
-
-relaydb-white:\
- :white:\
- :method=exec:\
- :file=relaydb -4lw:
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/doc/spamd.conf.5 /usr/home/samm/spamd/work/spamd_3.7/doc/spamd.conf.5
--- /usr/ports/mail/spamd/work/spamd_3.7/doc/spamd.conf.5 Thu Jan 29 19:44:29 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/doc/spamd.conf.5 Thu Jan 1 03:00:00 1970
@@ -1,190 +0,0 @@
-.\" $OpenBSD: spamd.conf.5,v 1.12 2004/01/29 17:44:29 jmc Exp $
-.\"
-.\" Copyright (c) 2003 Jason L. Wright (jason at thought.net)
-.\" Copyright (c) 2003 Bob Beck
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd March 8, 2003
-.Dt SPAMD.CONF 5
-.Os
-.Sh NAME
-.Nm spamd.conf
-.Nd configuration file read by
-.Xr spamd-setup 8
-for
-.Xr spamd 8
-.Sh SYNOPSIS
-.Nm spamd.conf
-.Sh DESCRIPTION
-The
-.Nm
-file is read by
-.Xr spamd-setup 8
-to configure blacklists and whitelists with corresponding
-.Xr pf 4
-table entries for
-.Xr spamd 8 .
-.Nm
-follows the syntax of configuration databases as documented in
-.Xr getcap 3 .
-Example:
-.Bd -literal -offset indent
-all:\e
- :spews1:white:myblack:
-
-spews1:\e
- :black:\e
- :msg="SPAM. Your address \&%A is in the spews\e
- level 1 database\ensee http://www.spews.org/ask.cgi?x=\&%A\en":\e
- :method=http:\e
- :file=www.spews.org/spews_list_level1.txt:
-
-white:\e
- :white:\e
- :method=file:\e
- :file=/var/mail/mywhite.txt:
-
-myblack:\e
- :black:\e
- :msg=/var/mail/myblackmsg.txt:\e
- :method=file:\e
- :file=/var/mail/myblack.txt:
-.Ed
-.Pp
-The default configuration file must include the entry
-.Ar all
-which specifies the order in which named blacklists and whitelists
-are to be applied.
-The addresses in a whitelist are removed from the preceding blacklist.
-In the above example, if the address was present in all three lists, blacklists
-.Ar spews1
-and
-.Ar myblack ,
-as well as whitelist
-.Ar white ,
-the address would be removed from blacklist
-.Ar spews1
-by the subsequent
-.Ar white
-whitelist.
-However, the address would not be removed from the
-.Ar myblack
-blacklist.
-To remove all the addresses in
-.Ar white
-from
-.Ar myblack ,
-the configuration
-.Bd -literal -offset indent
-all:\e
- :spews1:white:myblack:white:
-.Ed
-.Pp
-would be used instead.
-.Pp
-Blacklists and whitelists are then constructed by name;
-blacklists are identified by the capability
-.Ar black ,
-and whitelists by the capability
-.Ar white .
-.Pp
-The source of the addresses for blacklists and whitelists is
-specified using the
-.Ar method
-and
-.Ar file
-capability entries.
-.Pp
-.Ar method
-specifies the method by which to retrieve a file containing a list of
-addresses that consist of the blacklist or whitelist, and may be
-.Ar http ,
-.Ar ftp ,
-.Ar file
-or
-.Ar exec .
-The methods
-.Ar http ,
-.Ar ftp
-and
-.Ar file
-capabilities will make
-.Nm
-retrieve a list of addresses specified in the location in the
-.Ar file
-capability for the list.
-The
-.Ar exec
-capability will make
-.Nm
-spawn the program with arguments indicated in the
-.Ar file
-capability for the list, and reads a list of addresses
-from the output of the program.
-.Pp
-The format of the list of addresses is expected to consist of one
-network block or address per line (optionally followed by a space and
-text that is ignored).
-Comment lines beginning with
-.Ar #
-are ignored.
-Network blocks may be specified in any of the formats as in
-the following example:
-.Bd -literal -offset indent
-# CIDR format
-192.168.20.0/24
-# A start - end range
-192.168.21.0 - 192.168.21.255
-# As a single IP address
-192.168.23.1
-.Ed
-.Pp
-Each blacklist must include a message, specified in the
-.Ar msg
-capability as a string.
-If the
-.Ar msg
-string is enclosed in double quotes, the characters in the quoted string
-are escaped as specified in
-.Xr getcap 3
-with the exception that a colon (:) is allowed in the quoted string.
-The resulting string is used as the message.
-Alternatively, if the
-.Ar msg
-string is not specified in quotes, it is assumed to be a local filename
-from which the message text may be read.
-.Pp
-The message is configured in
-.Xr spamd 8
-to be displayed in the SMTP dialogue to any connections that match
-addresses in the blacklist.
-The sequence \e" in the message will produce a double quote in the output.
-The sequence %% will produce a single % in the output,
-and the sequence \&%A will be expanded in the message by
-.Xr spamd 8
-to display the connecting IP address in the output.
-.Sh SEE ALSO
-.Xr ftp 1 ,
-.Xr pf 4 ,
-.Xr spamd 8 ,
-.Xr spamd-setup 8
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/Makefile /usr/home/samm/spamd/work/spamd_3.7/spamd/Makefile
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/Makefile Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/Makefile Thu Jan 1 03:00:00 1970
@@ -1,9 +0,0 @@
-# $OpenBSD: Makefile,v 1.7 2004/02/26 07:28:55 beck Exp $
-
-PROG= spamd
-SRCS= spamd.c sdl.c grey.c
-MAN= spamd.8
-
-CFLAGS+= -Wall -Wstrict-prototypes -ansi
-
-.include <bsd.prog.mk>
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.c /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.c Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.c Thu Jan 1 03:00:00 1970
@@ -1,722 +0,0 @@
-/* $OpenBSD: grey.c,v 1.21 2005/03/12 00:02:07 beck Exp $ */
-
-/*
- * Copyright (c) 2004,2005 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/fcntl.h>
-#include <sys/wait.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <db.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-#include <netdb.h>
-
-#ifdef IPFW
-#include <netinet/ip_fw.h>
-#endif
-
-#include "grey.h"
-
-extern time_t passtime, greyexp, whiteexp, trapexp;
-#ifdef __OpenBSD__
-extern struct syslog_data sdata;
-#else
-#define syslog_r(l, s, args...) syslog(l,args)
-#define openlog_r(i, l, f, s) openlog(i, l, f)
-extern int sdata; /* dummy */
-#endif
-extern struct passwd *pw;
-extern u_short cfg_port;
-extern pid_t jail_pid;
-extern FILE * trapcfg;
-extern FILE * grey;
-extern int debug;
-
-size_t whitecount, whitealloc;
-size_t trapcount, trapalloc;
-char **whitelist;
-char **traplist;
-
-char *traplist_name = "spamd-greytrap";
-char *traplist_msg = "\"Your address %A has mailed to spamtraps here\\n\"";
-
-pid_t db_pid = -1;
-int spamdconf;
-
-#ifdef IPFW
-extern int tabno;
-#else
-int pfdev;
-static char *pargv[11]= {
- "pfctl", "-p", "/dev/pf", "-q", "-t",
- "spamd-white", "-T", "replace", "-f" "-", NULL
-};
-#endif
-
-/* If the parent gets a signal, kill off the children and exit */
-/* ARGSUSED */
-static void
-sig_term_chld(int sig)
-{
- if (db_pid != -1)
- kill(db_pid, SIGTERM);
- if (jail_pid != -1)
- kill(jail_pid, SIGTERM);
- _exit(1);
-}
-
-/*
- * Greatly simplified version from spamd_setup.c - only
- * sends one blacklist to an already open stream. Has no need
- * to collapse cidr ranges since these are only ever single
- * host hits.
- */
-int
-configure_spamd(char **addrs, int count, FILE *sdc)
-{
- int i;
-
- fprintf(sdc, "%s;%s;", traplist_name, traplist_msg);
- for (i = 0; i < count; i++)
- fprintf(sdc, "%s/32;", addrs[i]);
- fprintf(sdc, "\n");
- fflush(sdc);
- return(0);
-}
-
-#ifndef IPFW
-int
-configure_pf(char **addrs, int count)
-{
- FILE *pf = NULL;
- int i, pdes[2];
- pid_t pid;
- char *fdpath;
- struct sigaction sa;
-
- sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = sig_term_chld;
-
- if (debug)
- fprintf(stderr, "configure_pf - device on fd %d\n", pfdev);
- if (pfdev < 1 || pfdev > 63)
- return(-1);
- if (asprintf(&fdpath, "/dev/fd/%d", pfdev) == -1)
- return(-1);
- pargv[2] = fdpath;
- if (pipe(pdes) != 0) {
- syslog_r(LOG_INFO, &sdata, "pipe failed (%m)");
- free(fdpath);
- fdpath = NULL;
- return(-1);
- }
- signal(SIGCHLD, SIG_DFL);
- switch (pid = fork()) {
- case -1:
- syslog_r(LOG_INFO, &sdata, "fork failed (%m)");
- free(fdpath);
- fdpath = NULL;
- close(pdes[0]);
- close(pdes[1]);
- sigaction(SIGCHLD, &sa, NULL);
- return(-1);
- case 0:
- /* child */
- close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- dup2(pdes[0], STDIN_FILENO);
- close(pdes[0]);
- }
- execvp(PATH_PFCTL, pargv);
- syslog_r(LOG_ERR, &sdata, "can't exec %s:%m", PATH_PFCTL);
- _exit(1);
- }
-
- /* parent */
- free(fdpath);
- fdpath = NULL;
- close(pdes[0]);
- pf = fdopen(pdes[1], "w");
- if (pf == NULL) {
- syslog_r(LOG_INFO, &sdata, "fdopen failed (%m)");
- close(pdes[1]);
- sigaction(SIGCHLD, &sa, NULL);
- return(-1);
- }
- for (i = 0; i < count; i++)
- if (addrs[i] != NULL)
- fprintf(pf, "%s/32\n", addrs[i]);
-
- fclose(pf);
- waitpid(pid, NULL, 0);
- sigaction(SIGCHLD, &sa, NULL);
- return(0);
-}
-#else
-int
-configure_pf(char **addrs, int count)
-{
- static int s = -1;
- ipfw_table_entry ent;
- int i;
-
- if (s == -1)
- s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- if (s < 0)
- {
- syslog_r(LOG_INFO, &sdata, "IPFW socket unavailable (%m)");
- return(-1);
- }
-
- /* flush the table */
- ent.tbl = tabno;
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
- {
- syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_FLUSH) (%m)");
- return(-1);
- }
-
- for (i = 0; i < count; i++)
- if (addrs[i] != NULL)
- {
- /* add addrs[i] to tabno */
- ent.tbl = tabno;
- ent.masklen = 32;
- ent.value = 0;
- inet_aton(addrs[i], (struct in_addr *)&ent.addr);
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD, &ent, sizeof(ent)) < 0)
- {
- syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_ADD) (%m)");
- return(-1);
- }
- }
-
- return(0);
-}
-#endif
-
-void
-freeaddrlists(void)
-{
- int i;
-
- if (whitelist != NULL)
- for (i = 0; i < whitecount; i++) {
- free(whitelist[i]);
- whitelist[i] = NULL;
- }
- whitecount = 0;
- if (traplist != NULL) {
- for (i = 0; i < trapcount; i++) {
- free(traplist[i]);
- traplist[i] = NULL;
- }
- }
- trapcount = 0;
-}
-
-/* validate, then add to list of addrs to whitelist */
-int
-addwhiteaddr(char *addr)
-{
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
- if (whitecount == whitealloc) {
- char **tmp;
-
- tmp = realloc(whitelist,
- (whitealloc + 1024) * sizeof(char *));
- if (tmp == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- whitelist = tmp;
- whitealloc += 1024;
- }
- whitelist[whitecount] = strdup(addr);
- if (whitelist[whitecount] == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- whitecount++;
- freeaddrinfo(res);
- } else
- return(-1);
- return(0);
-}
-
-/* validate, then add to list of addrs to traplist */
-int
-addtrapaddr(char *addr)
-{
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
- if (trapcount == trapalloc) {
- char **tmp;
-
- tmp = realloc(traplist,
- (trapalloc + 1024) * sizeof(char *));
- if (tmp == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- traplist = tmp;
- trapalloc += 1024;
- }
- traplist[trapcount] = strdup(addr);
- if (traplist[trapcount] == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- trapcount++;
- freeaddrinfo(res);
- } else
- return(-1);
- return(0);
-}
-
-
-int
-greyscan(char *dbname)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- struct gdata gd;
- int r;
- char *a = NULL;
- size_t asiz = 0;
- time_t now = time(NULL);
-
- /* walk db, expire, and whitelist */
-
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL) {
- syslog_r(LOG_INFO, &sdata, "dbopen failed (%m)");
- return(-1);
- }
- memset(&dbk, 0, sizeof(dbk));
- memset(&dbd, 0, sizeof(dbd));
- for (r = db->seq(db, &dbk, &dbd, R_FIRST); !r;
- r = db->seq(db, &dbk, &dbd, R_NEXT)) {
- if ((dbk.size < 1) || dbd.size != sizeof(struct gdata)) {
- goto bad;
- }
- if (asiz < dbk.size + 1) {
- char *tmp;
-
- tmp = realloc(a, dbk.size * 2);
- if (tmp == NULL)
- goto bad;
- a = tmp;
- asiz = dbk.size * 2;
- }
- memset(a, 0, asiz);
- memcpy(a, dbk.data, dbk.size);
- memcpy(&gd, dbd.data, sizeof(gd));
- if (gd.expire <= now && gd.pcount != -2) {
- /* get rid of entry */
- if (debug)
- fprintf(stderr, "deleting %s\n", a);
- if (db->del(db, &dbk, 0)) {
- goto bad;
- }
- db->sync(db, 0);
- } else if (gd.pcount == -1) {
- /* this is a greytrap hit */
- if ((addtrapaddr(a) == -1) &&
- db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- if (debug)
- fprintf(stderr, "trapped %s\n", a);
- } else if (gd.pcount >= 0 && gd.pass <= now) {
- int tuple = 0;
- char *cp;
-
- /*
- * remove this tuple-keyed entry from db
- * add address to whitelist
- * add an address-keyed entry to db
- */
- cp = strchr(a, '\n');
- if (cp != NULL) {
- tuple = 1;
- *cp = '\0';
- }
- if ((addwhiteaddr(a) == -1) && db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- if (tuple) {
- if (db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- /* re-add entry, keyed only by ip */
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(a);
- dbk.data = a;
- memset(&dbd, 0, sizeof(dbd));
- gd.expire = now + whiteexp;
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- if (db->put(db, &dbk, &dbd, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- db->sync(db, 0);
- syslog_r(LOG_DEBUG, &sdata,
- "whitelisting %s in %s", a, dbname);
-
- }
- if (debug)
- fprintf(stderr, "whitelisted %s\n", a);
- }
- }
- configure_pf(whitelist, whitecount);
- if (configure_spamd(traplist, trapcount, trapcfg) == -1)
- syslog_r(LOG_DEBUG, &sdata, "configure_spamd failed");
-
- db->close(db);
- db = NULL;
- freeaddrlists();
- free(a);
- a = NULL;
- asiz = 0;
- return(0);
- bad:
- db->close(db);
- db = NULL;
- freeaddrlists();
- free(a);
- a = NULL;
- asiz = 0;
- return(-1);
-}
-
-int
-greyupdate(char *dbname, char *ip, char *from, char *to)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- char *key = NULL;
- char *trap = NULL;
- char *lookup;
- struct gdata gd;
- time_t now, expire;
- int i, r, spamtrap;
-
- now = time(NULL);
-
- /* open with lock, find record, update, close, unlock */
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL)
- return(-1);
- if (asprintf(&key, "%s\n%s\n%s", ip, from, to) == -1)
- goto bad;
- if ((trap = strdup(to)) == NULL)
- goto bad;
- for (i = 0; trap[i] != '\0'; i++)
- if (isupper(trap[i]))
- trap[i] = tolower(trap[i]);
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(trap);
- dbk.data = trap;
- memset(&dbd, 0, sizeof(dbd));
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1)
- goto bad;
- if (r) {
- /* didn't exist - so this doesn't match a known spamtrap */
- spamtrap = 0;
- lookup = key;
- expire = greyexp;
- } else {
- /* To: address is a spamtrap, so add as a greytrap entry */
- spamtrap = 1;
- lookup = ip;
- expire = trapexp;
- }
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1)
- goto bad;
- if (r) {
- /* new entry */
- memset(&gd, 0, sizeof(gd));
- gd.first = now;
- gd.bcount = 1;
- gd.pcount = spamtrap ? -1 : 0;
- gd.pass = now + expire;
- gd.expire = now + expire;
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- r = db->put(db, &dbk, &dbd, 0);
- db->sync(db, 0);
- if (r)
- goto bad;
- if (debug)
- fprintf(stderr, "added %s %s\n",
- spamtrap ? "greytrap entry for" : "", lookup);
- } else {
- /* existing entry */
- if (dbd.size != sizeof(gd)) {
- /* whatever this is, it doesn't belong */
- db->del(db, &dbk, 0);
- db->sync(db, 0);
- goto bad;
- }
- memcpy(&gd, dbd.data, sizeof(gd));
- gd.bcount++;
- gd.pcount = spamtrap ? -1 : 0;
- if (gd.first + passtime < now)
- gd.pass = now;
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- r = db->put(db, &dbk, &dbd, 0);
- db->sync(db, 0);
- if (r)
- goto bad;
- if (debug)
- fprintf(stderr, "updated %s\n", lookup);
- }
- free(key);
- key = NULL;
- free(trap);
- trap = NULL;
- db->close(db);
- db = NULL;
- return(0);
- bad:
- free(key);
- key = NULL;
- free(trap);
- trap = NULL;
- db->close(db);
- db = NULL;
- return(-1);
-}
-
-int
-greyreader(void)
-{
- char ip[32], from[MAX_MAIL], to[MAX_MAIL], *buf;
- size_t len;
- int state;
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- state = 0;
- if (grey == NULL) {
- syslog_r(LOG_ERR, &sdata, "No greylist pipe stream!\n");
- exit(1);
- }
- while ((buf = fgetln(grey, &len))) {
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- else
- /* all valid lines end in \n */
- continue;
- if (strlen(buf) < 4)
- continue;
-
- switch (state) {
- case 0:
- if (strncmp(buf, "IP:", 3) != 0)
- break;
- strlcpy(ip, buf+3, sizeof(ip));
- if (getaddrinfo(ip, NULL, &hints, &res) == 0) {
- freeaddrinfo(res);
- state = 1;
- } else
- state = 0;
- break;
- case 1:
- if (strncmp(buf, "FR:", 3) != 0) {
- state = 0;
- break;
- }
- strlcpy(from, buf+3, sizeof(from));
- state = 2;
- break;
- case 2:
- if (strncmp(buf, "TO:", 3) != 0) {
- state = 0;
- break;
- }
- strlcpy(to, buf+3, sizeof(to));
- if (debug)
- fprintf(stderr,
- "Got Grey IP %s from %s to %s\n",
- ip, from, to);
- greyupdate(PATH_SPAMD_DB, ip, from, to);
- state = 0;
- break;
- }
- }
- return (0);
-}
-
-void
-greyscanner(void)
-{
- int i;
-
- for (;;) {
- sleep(DB_SCAN_INTERVAL);
- i = greyscan(PATH_SPAMD_DB);
- if (i == -1)
- syslog_r(LOG_NOTICE, &sdata, "scan of %s failed",
- PATH_SPAMD_DB);
- }
- /* NOTREACHED */
-}
-
-int
-greywatcher(void)
-{
- int i;
- struct sigaction sa;
-
-#ifndef IPFW
- pfdev = open("/dev/pf", O_RDWR);
- if (pfdev == -1) {
- syslog_r(LOG_ERR, &sdata, "open of /dev/pf failed (%m)");
- exit(1);
- }
-#endif
-
- /* check to see if /var/db/spamd exists, if not, create it */
- if ((i = open(PATH_SPAMD_DB, O_RDWR, 0)) == -1 && errno == ENOENT) {
- i = open(PATH_SPAMD_DB, O_RDWR|O_CREAT, 0644);
- if (i == -1) {
- syslog_r(LOG_ERR, &sdata, "create %s failed (%m)",
- PATH_SPAMD_DB);
- exit(1);
- }
- /* if we are dropping privs, chown to that user */
- if (pw && (fchown(i, pw->pw_uid, pw->pw_gid) == -1)) {
- syslog_r(LOG_ERR, &sdata, "chown %s failed (%m)",
- PATH_SPAMD_DB);
- exit(1);
- }
- }
- if (i != -1)
- close(i);
-
- /*
- * lose root, continue as non-root user
- * XXX Should not be _spamd - as it currently is.
- */
- if (pw) {
- setgroups(1, &pw->pw_gid);
- setegid(pw->pw_gid);
- setgid(pw->pw_gid);
- seteuid(pw->pw_uid);
- setuid(pw->pw_uid);
- }
-
- db_pid = fork();
- switch(db_pid) {
- case -1:
- syslog_r(LOG_ERR, &sdata, "fork failed (%m)");
- exit(1);
- case 0:
- /*
- * child, talks to jailed spamd over greypipe,
- * updates db. has no access to pf.
- */
-#ifndef IPFW
- close(pfdev);
-#endif
- setproctitle("(%s update)", PATH_SPAMD_DB);
- greyreader();
- /* NOTREACHED */
- _exit(1);
- }
- /*
- * parent, scans db periodically for changes and updates
- * pf whitelist table accordingly.
- */
- fclose(grey);
- sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = sig_term_chld;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
-#ifndef IPFW
- setproctitle("(pf <spamd-white> update)");
-#else
- setproctitle("(ipfw white table update)");
-#endif
- greyscanner();
- /* NOTREACHED */
- exit(1);
-}
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.c.orig /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.c.orig
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.c.orig Tue Apr 12 20:22:17 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.c.orig Thu Jan 1 03:00:00 1970
@@ -1,662 +0,0 @@
-/* $OpenBSD: grey.c,v 1.21 2005/03/12 00:02:07 beck Exp $ */
-
-/*
- * Copyright (c) 2004,2005 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/fcntl.h>
-#include <sys/wait.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <db.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-#include <netdb.h>
-
-#include "grey.h"
-
-extern time_t passtime, greyexp, whiteexp, trapexp;
-#ifdef __OpenBSD__
-extern struct syslog_data sdata;
-#else
-#define syslog_r(l, s, args...) syslog(l,args)
-#define openlog_r(i, l, f, s) openlog(i, l, f)
-extern int sdata; /* dummy */
-#endif
-extern struct passwd *pw;
-extern u_short cfg_port;
-extern pid_t jail_pid;
-extern FILE * trapcfg;
-extern FILE * grey;
-extern int debug;
-
-size_t whitecount, whitealloc;
-size_t trapcount, trapalloc;
-char **whitelist;
-char **traplist;
-
-char *traplist_name = "spamd-greytrap";
-char *traplist_msg = "\"Your address %A has mailed to spamtraps here\\n\"";
-
-pid_t db_pid = -1;
-int pfdev;
-int spamdconf;
-
-static char *pargv[11]= {
- "pfctl", "-p", "/dev/pf", "-q", "-t",
- "spamd-white", "-T", "replace", "-f" "-", NULL
-};
-
-/* If the parent gets a signal, kill off the children and exit */
-/* ARGSUSED */
-static void
-sig_term_chld(int sig)
-{
- if (db_pid != -1)
- kill(db_pid, SIGTERM);
- if (jail_pid != -1)
- kill(jail_pid, SIGTERM);
- _exit(1);
-}
-
-/*
- * Greatly simplified version from spamd_setup.c - only
- * sends one blacklist to an already open stream. Has no need
- * to collapse cidr ranges since these are only ever single
- * host hits.
- */
-int
-configure_spamd(char **addrs, int count, FILE *sdc)
-{
- int i;
-
- fprintf(sdc, "%s;%s;", traplist_name, traplist_msg);
- for (i = 0; i < count; i++)
- fprintf(sdc, "%s/32;", addrs[i]);
- fprintf(sdc, "\n");
- fflush(sdc);
- return(0);
-}
-
-int
-configure_pf(char **addrs, int count)
-{
- FILE *pf = NULL;
- int i, pdes[2];
- pid_t pid;
- char *fdpath;
- struct sigaction sa;
-
- sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = sig_term_chld;
-
- if (debug)
- fprintf(stderr, "configure_pf - device on fd %d\n", pfdev);
- if (pfdev < 1 || pfdev > 63)
- return(-1);
- if (asprintf(&fdpath, "/dev/fd/%d", pfdev) == -1)
- return(-1);
- pargv[2] = fdpath;
- if (pipe(pdes) != 0) {
- syslog_r(LOG_INFO, &sdata, "pipe failed (%m)");
- free(fdpath);
- fdpath = NULL;
- return(-1);
- }
- signal(SIGCHLD, SIG_DFL);
- switch (pid = fork()) {
- case -1:
- syslog_r(LOG_INFO, &sdata, "fork failed (%m)");
- free(fdpath);
- fdpath = NULL;
- close(pdes[0]);
- close(pdes[1]);
- sigaction(SIGCHLD, &sa, NULL);
- return(-1);
- case 0:
- /* child */
- close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- dup2(pdes[0], STDIN_FILENO);
- close(pdes[0]);
- }
- execvp(PATH_PFCTL, pargv);
- syslog_r(LOG_ERR, &sdata, "can't exec %s:%m", PATH_PFCTL);
- _exit(1);
- }
-
- /* parent */
- free(fdpath);
- fdpath = NULL;
- close(pdes[0]);
- pf = fdopen(pdes[1], "w");
- if (pf == NULL) {
- syslog_r(LOG_INFO, &sdata, "fdopen failed (%m)");
- close(pdes[1]);
- sigaction(SIGCHLD, &sa, NULL);
- return(-1);
- }
- for (i = 0; i < count; i++)
- if (addrs[i] != NULL)
- fprintf(pf, "%s/32\n", addrs[i]);
- fclose(pf);
- waitpid(pid, NULL, 0);
- sigaction(SIGCHLD, &sa, NULL);
- return(0);
-}
-
-void
-freeaddrlists(void)
-{
- int i;
-
- if (whitelist != NULL)
- for (i = 0; i < whitecount; i++) {
- free(whitelist[i]);
- whitelist[i] = NULL;
- }
- whitecount = 0;
- if (traplist != NULL) {
- for (i = 0; i < trapcount; i++) {
- free(traplist[i]);
- traplist[i] = NULL;
- }
- }
- trapcount = 0;
-}
-
-/* validate, then add to list of addrs to whitelist */
-int
-addwhiteaddr(char *addr)
-{
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
- if (whitecount == whitealloc) {
- char **tmp;
-
- tmp = realloc(whitelist,
- (whitealloc + 1024) * sizeof(char *));
- if (tmp == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- whitelist = tmp;
- whitealloc += 1024;
- }
- whitelist[whitecount] = strdup(addr);
- if (whitelist[whitecount] == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- whitecount++;
- freeaddrinfo(res);
- } else
- return(-1);
- return(0);
-}
-
-/* validate, then add to list of addrs to traplist */
-int
-addtrapaddr(char *addr)
-{
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
- if (trapcount == trapalloc) {
- char **tmp;
-
- tmp = realloc(traplist,
- (trapalloc + 1024) * sizeof(char *));
- if (tmp == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- traplist = tmp;
- trapalloc += 1024;
- }
- traplist[trapcount] = strdup(addr);
- if (traplist[trapcount] == NULL) {
- freeaddrinfo(res);
- return(-1);
- }
- trapcount++;
- freeaddrinfo(res);
- } else
- return(-1);
- return(0);
-}
-
-
-int
-greyscan(char *dbname)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- struct gdata gd;
- int r;
- char *a = NULL;
- size_t asiz = 0;
- time_t now = time(NULL);
-
- /* walk db, expire, and whitelist */
-
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL) {
- syslog_r(LOG_INFO, &sdata, "dbopen failed (%m)");
- return(-1);
- }
- memset(&dbk, 0, sizeof(dbk));
- memset(&dbd, 0, sizeof(dbd));
- for (r = db->seq(db, &dbk, &dbd, R_FIRST); !r;
- r = db->seq(db, &dbk, &dbd, R_NEXT)) {
- if ((dbk.size < 1) || dbd.size != sizeof(struct gdata)) {
- goto bad;
- }
- if (asiz < dbk.size + 1) {
- char *tmp;
-
- tmp = realloc(a, dbk.size * 2);
- if (tmp == NULL)
- goto bad;
- a = tmp;
- asiz = dbk.size * 2;
- }
- memset(a, 0, asiz);
- memcpy(a, dbk.data, dbk.size);
- memcpy(&gd, dbd.data, sizeof(gd));
- if (gd.expire <= now && gd.pcount != -2) {
- /* get rid of entry */
- if (debug)
- fprintf(stderr, "deleting %s\n", a);
- if (db->del(db, &dbk, 0)) {
- goto bad;
- }
- db->sync(db, 0);
- } else if (gd.pcount == -1) {
- /* this is a greytrap hit */
- if ((addtrapaddr(a) == -1) &&
- db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- if (debug)
- fprintf(stderr, "trapped %s\n", a);
- } else if (gd.pcount >= 0 && gd.pass <= now) {
- int tuple = 0;
- char *cp;
-
- /*
- * remove this tuple-keyed entry from db
- * add address to whitelist
- * add an address-keyed entry to db
- */
- cp = strchr(a, '\n');
- if (cp != NULL) {
- tuple = 1;
- *cp = '\0';
- }
- if ((addwhiteaddr(a) == -1) && db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- if (tuple) {
- if (db->del(db, &dbk, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- /* re-add entry, keyed only by ip */
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(a);
- dbk.data = a;
- memset(&dbd, 0, sizeof(dbd));
- gd.expire = now + whiteexp;
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- if (db->put(db, &dbk, &dbd, 0)) {
- db->sync(db, 0);
- goto bad;
- }
- db->sync(db, 0);
- syslog_r(LOG_DEBUG, &sdata,
- "whitelisting %s in %s", a, dbname);
-
- }
- if (debug)
- fprintf(stderr, "whitelisted %s\n", a);
- }
- }
- configure_pf(whitelist, whitecount);
- if (configure_spamd(traplist, trapcount, trapcfg) == -1)
- syslog_r(LOG_DEBUG, &sdata, "configure_spamd failed");
-
- db->close(db);
- db = NULL;
- freeaddrlists();
- free(a);
- a = NULL;
- asiz = 0;
- return(0);
- bad:
- db->close(db);
- db = NULL;
- freeaddrlists();
- free(a);
- a = NULL;
- asiz = 0;
- return(-1);
-}
-
-int
-greyupdate(char *dbname, char *ip, char *from, char *to)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- char *key = NULL;
- char *trap = NULL;
- char *lookup;
- struct gdata gd;
- time_t now, expire;
- int i, r, spamtrap;
-
- now = time(NULL);
-
- /* open with lock, find record, update, close, unlock */
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL)
- return(-1);
- if (asprintf(&key, "%s\n%s\n%s", ip, from, to) == -1)
- goto bad;
- if ((trap = strdup(to)) == NULL)
- goto bad;
- for (i = 0; trap[i] != '\0'; i++)
- if (isupper(trap[i]))
- trap[i] = tolower(trap[i]);
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(trap);
- dbk.data = trap;
- memset(&dbd, 0, sizeof(dbd));
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1)
- goto bad;
- if (r) {
- /* didn't exist - so this doesn't match a known spamtrap */
- spamtrap = 0;
- lookup = key;
- expire = greyexp;
- } else {
- /* To: address is a spamtrap, so add as a greytrap entry */
- spamtrap = 1;
- lookup = ip;
- expire = trapexp;
- }
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1)
- goto bad;
- if (r) {
- /* new entry */
- memset(&gd, 0, sizeof(gd));
- gd.first = now;
- gd.bcount = 1;
- gd.pcount = spamtrap ? -1 : 0;
- gd.pass = now + expire;
- gd.expire = now + expire;
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- r = db->put(db, &dbk, &dbd, 0);
- db->sync(db, 0);
- if (r)
- goto bad;
- if (debug)
- fprintf(stderr, "added %s %s\n",
- spamtrap ? "greytrap entry for" : "", lookup);
- } else {
- /* existing entry */
- if (dbd.size != sizeof(gd)) {
- /* whatever this is, it doesn't belong */
- db->del(db, &dbk, 0);
- db->sync(db, 0);
- goto bad;
- }
- memcpy(&gd, dbd.data, sizeof(gd));
- gd.bcount++;
- gd.pcount = spamtrap ? -1 : 0;
- if (gd.first + passtime < now)
- gd.pass = now;
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(lookup);
- dbk.data = lookup;
- memset(&dbd, 0, sizeof(dbd));
- dbd.size = sizeof(gd);
- dbd.data = &gd;
- r = db->put(db, &dbk, &dbd, 0);
- db->sync(db, 0);
- if (r)
- goto bad;
- if (debug)
- fprintf(stderr, "updated %s\n", lookup);
- }
- free(key);
- key = NULL;
- free(trap);
- trap = NULL;
- db->close(db);
- db = NULL;
- return(0);
- bad:
- free(key);
- key = NULL;
- free(trap);
- trap = NULL;
- db->close(db);
- db = NULL;
- return(-1);
-}
-
-int
-greyreader(void)
-{
- char ip[32], from[MAX_MAIL], to[MAX_MAIL], *buf;
- size_t len;
- int state;
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; /*for now*/
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_protocol = IPPROTO_UDP; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
-
- state = 0;
- if (grey == NULL) {
- syslog_r(LOG_ERR, &sdata, "No greylist pipe stream!\n");
- exit(1);
- }
- while ((buf = fgetln(grey, &len))) {
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- else
- /* all valid lines end in \n */
- continue;
- if (strlen(buf) < 4)
- continue;
-
- switch (state) {
- case 0:
- if (strncmp(buf, "IP:", 3) != 0)
- break;
- strlcpy(ip, buf+3, sizeof(ip));
- if (getaddrinfo(ip, NULL, &hints, &res) == 0) {
- freeaddrinfo(res);
- state = 1;
- } else
- state = 0;
- break;
- case 1:
- if (strncmp(buf, "FR:", 3) != 0) {
- state = 0;
- break;
- }
- strlcpy(from, buf+3, sizeof(from));
- state = 2;
- break;
- case 2:
- if (strncmp(buf, "TO:", 3) != 0) {
- state = 0;
- break;
- }
- strlcpy(to, buf+3, sizeof(to));
- if (debug)
- fprintf(stderr,
- "Got Grey IP %s from %s to %s\n",
- ip, from, to);
- greyupdate(PATH_SPAMD_DB, ip, from, to);
- state = 0;
- break;
- }
- }
- return (0);
-}
-
-void
-greyscanner(void)
-{
- int i;
-
- for (;;) {
- sleep(DB_SCAN_INTERVAL);
- i = greyscan(PATH_SPAMD_DB);
- if (i == -1)
- syslog_r(LOG_NOTICE, &sdata, "scan of %s failed",
- PATH_SPAMD_DB);
- }
- /* NOTREACHED */
-}
-
-int
-greywatcher(void)
-{
- int i;
- struct sigaction sa;
-
- pfdev = open("/dev/pf", O_RDWR);
- if (pfdev == -1) {
- syslog_r(LOG_ERR, &sdata, "open of /dev/pf failed (%m)");
- exit(1);
- }
-
- /* check to see if /var/db/spamd exists, if not, create it */
- if ((i = open(PATH_SPAMD_DB, O_RDWR, 0)) == -1 && errno == ENOENT) {
- i = open(PATH_SPAMD_DB, O_RDWR|O_CREAT, 0644);
- if (i == -1) {
- syslog_r(LOG_ERR, &sdata, "create %s failed (%m)",
- PATH_SPAMD_DB);
- exit(1);
- }
- /* if we are dropping privs, chown to that user */
- if (pw && (fchown(i, pw->pw_uid, pw->pw_gid) == -1)) {
- syslog_r(LOG_ERR, &sdata, "chown %s failed (%m)",
- PATH_SPAMD_DB);
- exit(1);
- }
- }
- if (i != -1)
- close(i);
-
- /*
- * lose root, continue as non-root user
- * XXX Should not be _spamd - as it currently is.
- */
- if (pw) {
- setgroups(1, &pw->pw_gid);
- setegid(pw->pw_gid);
- setgid(pw->pw_gid);
- seteuid(pw->pw_uid);
- setuid(pw->pw_uid);
- }
-
- db_pid = fork();
- switch(db_pid) {
- case -1:
- syslog_r(LOG_ERR, &sdata, "fork failed (%m)");
- exit(1);
- case 0:
- /*
- * child, talks to jailed spamd over greypipe,
- * updates db. has no access to pf.
- */
- close(pfdev);
- setproctitle("(%s update)", PATH_SPAMD_DB);
- greyreader();
- /* NOTREACHED */
- _exit(1);
- }
- /*
- * parent, scans db periodically for changes and updates
- * pf whitelist table accordingly.
- */
- fclose(grey);
- sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = sig_term_chld;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
- setproctitle("(pf <spamd-white> update)");
- greyscanner();
- /* NOTREACHED */
- exit(1);
-}
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.h /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.h
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.h Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.h Thu Jan 1 03:00:00 1970
@@ -1,37 +0,0 @@
-/* $OpenBSD: grey.h,v 1.5 2005/03/11 23:09:53 beck Exp $ */
-
-/*
- * Copyright (c) 2004 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define MAX_MAIL 1024 /* how big an email address will we consider */
-#define PASSTIME (60 * 25) /* pass after first retry seen after 25 mins */
-#define GREYEXP (60 * 60 * 4) /* remove grey entries after 4 hours */
-#define WHITEEXP (60 * 60 * 24 * 36) /* remove white entries after 36 days */
-#define TRAPEXP (60 * 60 * 24) /* hitting a spamtrap blacklists for a day */
-#define PATH_PFCTL "/sbin/pfctl"
-#define PATH_IPFW "/sbin/ipfw"
-#define DB_SCAN_INTERVAL 60
-#define PATH_SPAMD_DB "/var/db/spamd"
-
-struct gdata {
- time_t first; /* when did we see it first */
- time_t pass; /* when was it whitelisted */
- time_t expire; /* when will we get rid of this entry */
- int bcount; /* how many times have we blocked it */
- int pcount; /* how many times passed, or -1 for spamtrap */
-};
-
-extern int greywatcher(void);
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.h.orig /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.h.orig
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.h.orig Tue Apr 12 20:21:48 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.h.orig Thu Jan 1 03:00:00 1970
@@ -1,36 +0,0 @@
-/* $OpenBSD: grey.h,v 1.5 2005/03/11 23:09:53 beck Exp $ */
-
-/*
- * Copyright (c) 2004 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define MAX_MAIL 1024 /* how big an email address will we consider */
-#define PASSTIME (60 * 25) /* pass after first retry seen after 25 mins */
-#define GREYEXP (60 * 60 * 4) /* remove grey entries after 4 hours */
-#define WHITEEXP (60 * 60 * 24 * 36) /* remove white entries after 36 days */
-#define TRAPEXP (60 * 60 * 24) /* hitting a spamtrap blacklists for a day */
-#define PATH_PFCTL "/sbin/pfctl"
-#define DB_SCAN_INTERVAL 60
-#define PATH_SPAMD_DB "/var/db/spamd"
-
-struct gdata {
- time_t first; /* when did we see it first */
- time_t pass; /* when was it whitelisted */
- time_t expire; /* when will we get rid of this entry */
- int bcount; /* how many times have we blocked it */
- int pcount; /* how many times passed, or -1 for spamtrap */
-};
-
-extern int greywatcher(void);
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd/grey.o and /usr/home/samm/spamd/work/spamd_3.7/spamd/grey.o differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/sdl.c /usr/home/samm/spamd/work/spamd_3.7/spamd/sdl.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/sdl.c Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/sdl.c Thu Jan 1 03:00:00 1970
@@ -1,271 +0,0 @@
-/* $OpenBSD: sdl.c,v 1.12 2004/02/26 08:18:56 deraadt Exp $ */
-
-/*
- * Copyright (c) 2003 Bob Beck. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * sdl.c - Implement spamd source lists
- *
- * This consists of everything we need to do to determine which lists
- * someone is on. Spamd gets the connecting address, and looks it up
- * against all lists to determine what deferral messages to feed back
- * to the connecting machine. - The redirection to spamd will happen
- * from pf in the kernel, first macth will rdr to us. Spamd (along with
- * setup) must keep track of *all* matches, so as to tell someone all the
- * lists that they are on.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sdl.h"
-
-static void sdl_free(struct sdlist *);
-static void sdl_clear(struct sdlist *);
-int match_addr(struct sdaddr *a, struct sdaddr *m, struct sdaddr *b,
- sa_family_t af);
-
-extern int debug;
-struct sdlist *blacklists = NULL;
-int blc = 0, blu = 0;
-
-int
-sdl_add(char *sdname, char *sdstring, char ** addrs, int addrc)
-{
- int i, index = -1;
- char astring[40];
- unsigned int maskbits;
- struct sdaddr *m, *n;
-
- /*
- * if a blacklist of same tag name is already there, replace it,
- * otherwise append.
- */
- for (i = 0; i < blu; i++) {
- if (strcmp(blacklists[i].tag, sdname) == 0) {
- index = i;
- break;
- }
- }
- if (index != -1) {
- if (debug > 0)
- printf("replacing list %s\n", blacklists[index].tag);
- sdl_free(&blacklists[index]);
- } else {
- if (debug > 0)
- printf("adding list %s\n", sdname);
- index = blu;
- }
- if (index == blu && blu == blc) {
- struct sdlist *tmp;
-
- tmp = realloc(blacklists, (blc + 128) *
- sizeof(struct sdlist));
- if (tmp == NULL)
- return (-1);
- blacklists = tmp;
- blc += 128;
- sdl_clear(&blacklists[index]);
- }
-
- if ((blacklists[index].tag = strdup(sdname)) == NULL)
- goto misc_error;
- if ((blacklists[index].string = strdup(sdstring)) == NULL)
- goto misc_error;
-
- blacklists[index].naddrs = addrc;
-
- /*
- * Cycle through addrs, converting. We assume they are correctly
- * formatted v4 and v6 addrs, if they don't all convert correctly, the
- * add fails. Each address should be address/maskbits
- */
- blacklists[index].addrs = malloc(addrc * sizeof(struct sdentry));
- if (blacklists[index].addrs == NULL)
- goto misc_error;
-
- for(i = 0; i < addrc; i++) {
- int j, k, af;
-
- n = &blacklists[index].addrs[i].sda;
- m = &blacklists[index].addrs[i].sdm;
-
- j = sscanf(addrs[i], "%39[^/]/%u", astring, &maskbits);
- if (j != 2)
- goto parse_error;
- if (maskbits > 128)
- goto parse_error;
- /*
- * sanity check! we don't allow a 0 mask -
- * don't blacklist the entire net.
- */
- if (maskbits == 0)
- goto parse_error;
- if (strchr(astring, ':') != NULL)
- af = AF_INET6;
- else
- af = AF_INET;
- if (af == AF_INET && maskbits > 32)
- goto parse_error;
- j = inet_pton(af, astring, n);
- if (j != 1)
- goto parse_error;
- if (debug > 0)
- printf("added %s/%u\n", astring, maskbits);
-
- /* set mask, borrowed from pf */
- k = 0;
- for (j = 0; j < 4; j++)
- m->addr32[j] = 0;
- while (maskbits >= 32) {
- m->addr32[k++] = 0xffffffff;
- maskbits -= 32;
- }
- for (j = 31; j > 31 - maskbits; --j)
- m->addr32[k] |= (1 << j);
- if (maskbits)
- m->addr32[k] = htonl(m->addr32[k]);
-
- /* mask off address bits that won't ever be used */
- for (j = 0; j < 4; j++)
- n->addr32[j] = n->addr32[j] & m->addr32[j];
- }
- if (index == blu) {
- blu++;
- blacklists[blu].tag = NULL;
- }
- return (0);
- parse_error:
- if (debug > 0)
- printf("sdl_add: parse error, \"%s\"\n", addrs[i]);
- misc_error:
- sdl_free(&blacklists[index]);
- return (-1);
-}
-
-
-/*
- * Return 1 if the addresses a (with mask m) matches address b
- * otherwise return 0. It is assumed that address a has been
- * pre-masked out, we only need to mask b.
- */
-int
-match_addr(struct sdaddr *a, struct sdaddr *m, struct sdaddr *b,
- sa_family_t af)
-{
- int match = 0;
-
- switch (af) {
- case AF_INET:
- if ((a->addr32[0]) ==
- (b->addr32[0] & m->addr32[0]))
- match++;
- break;
- case AF_INET6:
- if (((a->addr32[0]) ==
- (b->addr32[0] & m->addr32[0])) &&
- ((a->addr32[1]) ==
- (b->addr32[1] & m->addr32[1])) &&
- ((a->addr32[2]) ==
- (b->addr32[2] & m->addr32[2])) &&
- ((a->addr32[3]) ==
- (b->addr32[3] & m->addr32[3])))
- match++;
- break;
- }
- return (match);
-}
-
-
-/*
- * Given an address and address family
- * return list of pointers to matching nodes. or NULL if none.
- */
-struct sdlist **
-sdl_lookup(struct sdlist *head, int af, void * src)
-{
- int i, matches = 0;
- struct sdlist *sdl;
- struct sdentry *sda;
- struct sdaddr *source = (struct sdaddr *) src;
- int sdnewlen = 0;
- struct sdlist **sdnew = NULL;
-
- if (head == NULL)
- return (NULL);
- else
- sdl = head;
- while (sdl->tag != NULL) {
- for (i = 0; i < sdl->naddrs; i++) {
- sda = sdl->addrs + i;
- if (match_addr(&sda->sda, &sda->sdm, source, af)) {
- if (matches == sdnewlen) {
- struct sdlist **tmp;
-
- tmp = realloc(sdnew,
- (sdnewlen + 128) *
- sizeof(struct sdlist *));
- if (tmp == NULL)
- /*
- * XXX out of memory -
- * return what we have
- */
- return (sdnew);
- sdnew = tmp;
- sdnewlen += 128;
- }
- sdnew[matches]= sdl;
- matches++;
- sdnew[matches]=NULL;
- break;
- }
- }
- sdl++;
- }
- return (sdnew);
-}
-
-static void
-sdl_free(struct sdlist *sdl)
-{
- free(sdl->tag);
- free(sdl->string);
- free(sdl->addrs);
- sdl_clear(sdl);
-}
-
-static void
-sdl_clear(struct sdlist *sdl)
-{
- sdl->tag = NULL;
- sdl->string = NULL;
- sdl->addrs = NULL;
- sdl->naddrs = 0;
-}
-
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/sdl.h /usr/home/samm/spamd/work/spamd_3.7/spamd/sdl.h
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/sdl.h Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/sdl.h Thu Jan 1 03:00:00 1970
@@ -1,71 +0,0 @@
-/* $OpenBSD: sdl.h,v 1.2 2004/02/26 08:18:56 deraadt Exp $ */
-
-/*
- * Copyright (c) 2003 Bob Beck, Kjell Wooding. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _SDL_H_
-#define _SDL_H_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#ifdef __OpenBSD__
-#include <netinet/ip_ipsp.h>
-#endif
-
-/* spamd source list */
-struct sdlist {
- char *tag; /* sdlist source name */
- char *string; /* Format (451) string with no smtp code or \r\n */
- struct sdentry *addrs;
- size_t naddrs;
-};
-
-/* yeah. Stolen from pf */
-struct sdaddr {
- union {
- struct in_addr v4;
- struct in6_addr v6;
- u_int8_t addr8[16];
- u_int16_t addr16[8];
- u_int32_t addr32[4];
- } _sda; /* 128-bit address */
-#define v4 _sda.v4
-#define v6 _sda.v6
-#define addr8 _sda.addr8
-#define addr16 _sda.addr16
-#define addr32 _sda.addr32
-};
-
-/* spamd netblock (black) list */
-struct sdentry {
- struct sdaddr sda;
- struct sdaddr sdm;
-};
-
-
-extern int sdl_add(char *, char *, char **, int);
-extern struct sdlist **sdl_lookup(struct sdlist *head,
- int af, void * src);
-
-#endif /* _SDL_H_ */
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd/sdl.o and /usr/home/samm/spamd/work/spamd_3.7/spamd/sdl.o differ
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd and /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8 /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8 Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8 Thu Jan 1 03:00:00 1970
@@ -1,473 +0,0 @@
-.\" $OpenBSD: spamd.8,v 1.53 2005/03/11 23:09:53 beck Exp $
-.\"
-.\" Copyright (c) 2002 Theo de Raadt. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd December 18, 2002
-.Dt SPAMD 8
-.Os
-.Sh NAME
-.Nm spamd
-.Nd spam deferral daemon
-.Sh SYNOPSIS
-.Nm spamd
-.Bk -words
-.Op Fl 45dgv
-.Op Fl B Ar maxblack
-.Op Fl b Ar address
-.Op Fl c Ar maxcon
-.Op Fl G Ar passtime:greyexp:whiteexp
-.Op Fl n Ar name
-.Op Fl p Ar port
-.Op Fl r Ar reply
-.Op Fl s Ar secs
-.Op Fl w Ar window
-.Ek
-.Sh DESCRIPTION
-.Nm
-is a fake
-.Xr sendmail 8 Ns -like
-daemon which rejects false mail.
-If the
-.Xr pf 4
-or
-.Xr ipfw 4
-packet filter is configured to redirect port 25 (SMTP) to this daemon,
-it will attempt to waste the time and resources of the spam sender.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl 4
-For black listed entries, return error code 450 to the spammer (default).
-.It Fl 5
-For black-listed entries, return error code 550 to the spammer.
-.It Fl B Ar maxblack
-The maximum number of concurrent blacklisted connections to allow in
-greylisting mode.
-This value may not be greater than maxcon (see below).
-The default is maxcon \- 100
-.It Fl b Ar address
-Specify the local address to which
-.Nm
-is to
-.Xr bind 2 .
-By default
-.Nm
-listens on all local addresses.
-.It Fl c Ar maxcon
-The maximum number of concurrent connections to allow.
-The default is 800.
-.It Fl d
-Debug mode.
-.Nm
-does not
-.Xr fork 2
-into the background.
-.It Fl G Ar passtime:greyexp:whiteexp
-Adjust the three time parameters for greylisting; see
-.Sx GREYLISTING
-below.
-.Ar passtime
-defaults to 25 (minutes),
-.Ar greyexp
-to 4 (hours),
-and
-.Ar whiteexp
-to 864 (hours, approximately 36 days).
-.It Fl g
-Greylisting mode; see
-.Sx GREYLISTING
-below.
-.It Fl n Ar name
-The SMTP version banner that is reported upon initial connection.
-.It Fl p Ar port
-Specify a different port number from the default port that
-.Nm
-should listen for redirected SMTP connections on.
-The default port is found by looking for the named service
-.Em spamd
-using
-.Xr getservbyname 3 .
-.It Fl r Ar reply
-The SMTP error to return to the spammer, i.e. 450, 451, 550.
-This defaults to 450.
-.It Fl s Ar secs
-Delay each character sent to the client by the specified
-amount of seconds.
-Defaults to 1.
-.It Fl v
-Enable verbose logging.
-By default
-.Nm
-logs connections, disconnections and blacklist matches to
-.Xr syslogd 8
-at
-.Dv LOG_INFO
-level.
-With verbose logging enabled, message detail
-including subject and recipient information is logged at
-.Dv LOG_INFO ,
-along with the message body and SMTP dialogue being logged at
-.Dv LOG_DEBUG
-level.
-.It Fl w Ar window
-Set the socket receive buffer to this many bytes, adjusting the window size.
-.El
-.Pp
-.Nm
-is designed to be very efficient so that it does not slow down the
-receiving machine.
-Spam is never accepted, but always rejected with either a 450 or 550
-error message.
-The normal way that spam has been dealt with in the past is to either
-accept and drop, or outright block.
-When configured to use 450 responses,
-.Nm
-takes neither of these actions: it rejects the mail back to the senders'
-queue.
-.Pp
-.Nm
-is best started from
-.Xr rc 8
-in conjunction with the
-.Xr spamd-setup 8
-which processes a list of spammers' addresses, and applies appropriate
-.Xr pfctl 8
-.Em rdr
-or
-.Xr ipfw 8
-.Em fwd
-rules.
-.Xr spamd-setup 8
-is run from
-.Xr cron 8 .
-.Sh REDIRECTING SMTP CONNECTIONS
-.Ss "When using PF"
-With
-.Xr pf 4 ,
-connections to port 25 (SMTP) can be redirected to another host or port,
-based on the source address of the sender.
-The
-.Em rdr
-rules used for this purpose are described in
-.Xr pf.conf 5 .
-The rules can be loaded into a
-.Em table
-to simplify handling.
-.Bd -literal -offset 4n
-table <spamd> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-.Ed
-.Pp
-Any addresses in table
-.Em <spamd>
-are then redirected to
-.Nm
-running on port 8025.
-Addresses can be loaded into the
-.Em table ,
-like:
-.Bd -literal -offset 4n
-# pfctl -q -t spamd -T replace -f /usr/local/share/spammers
-.Ed
-.Pp
-.Xr spamd-setup 8
-can also be used to load addresses into the
-.Em <spamd>
-table.
-
-
-.Xr spamd-setup 8
-also has the added benefit of being able to remove addresses from
-blacklists, and will connect to
-.Nm
-over a localhost socket, giving
-.Nm
-information about each source of blacklist addresses, as well as custom
-rejection messages for each blacklist source
-that can be used to let any real person whose mail
-is deferred by spamd know why their address has been listed
-from sending mail.
-This is important as it allows legitimate mail
-senders to pressure spam sources into behaving properly so that they
-may be removed from the relevant blacklists.
-
-.Ss "If compiled with IPFW"
-With
-.Xr ipfw 4 ,
-the syntax for redirection of TCP sessions is quite different
-from that of
-.Xr pf 4 .
-The
-.Em fwd
-rule used for this purpose are described in
-.Xr ipfw 8 .
-The rules should be added to the ruleset called by /etc/rc.firewall
-to be present at boot time.
-.Bd -literal -offset 4n
-fwd 127.0.0.1,8025 tcp from table(2) to me 25 in
-allow tcp from table(1) to me 25 in
-fwd 127.0.0.1,8025 tcp from any to me 25 in
-.Ed
-.Pp
-Any addresses in the blacklist table
-.Em 2
-and not in the whitelist table
-.Em 1
-are then redirected to
-.Nm
-running on port 8025.
-Addresses can be loaded into the blacklist
-.Em table ,
-like:
-.Bd -literal -offset 4n
-# ipfw table 1 add a.b.c.d/x
-.Ed
-.Pp
-.Xr spamd-setup 8
-can also be used to load addresses into the blacklist table
-.Em 2 .
-.Pp
-The
-.Op Fl t Ar table_no
-option to
-.Em spamd
-and
-.Em spamd-setup
-can be used to change the default table
-numbers.
-
-.Sh CONFIGURATION CONNECTIONS
-.Nm
-listens for configuration connections on the port identified by the
-named service
-.Em spamd-cfg
-(see
-.Xr services 5 ) .
-The configuration socket listens only on the INADDR_LOOPBACK
-address.
-Configuration of spamd is done by connecting to the configuration
-socket, and sending blacklist information, one blacklist per line.
-Each blacklist consists of a name, a message to reject mail
-with, and addresses in CIDR format, all separated by semicolons (;):
-.Bd -literal -offset indent
-tag;"rejection message";aaa.bbb.ccc.ddd/mm;aaa.bbb.ccc.ddd/mm
-.Ed
-.Pp
-The rejection message must be inside double quotes.
-A \e" will produce a double quote in the output.
-\en will produce a newline.
-%A will expand to the connecting IP address in dotted quad format.
-%% may be used to produce a single % in the output.
-\e\e will produce a single \e.
-.Nm
-will reject mail by displaying all the messages from all blacklists in which
-a connecting address is matched.
-.Xr spamd-setup 8
-is normally used to configure this information.
-.Sh GREYLISTING
-When run in greylisting mode,
-.Nm
-will run in the normal mode for any addresses blacklisted by
-.Xr spamd-setup 8 .
-Connections from addresses not blacklisted by
-.Xr spamd-setup 8
-will be considered for greylisting.
-Such connections will not be stuttered at or delayed,
-and will receive the pleasantly innocuous temporary failure of:
-.Bd -literal -offset 4n
-451 Temporary failure, please try again later.
-.Ed
-.Pp
-in the SMTP dialogue immediately after the recipient is specified.
-.Nm
-will use the db file in
-.Pa /var/db/spamd
-to track these non-blacklisted connections to
-.Nm
-by connecting IP address, envelope-from, and envelope-to, or "tuple" for
-short.
-.Pp
-A previously unseen tuple is added to the
-.Pa /var/db/spamd
-database, recording the time an initial connection attempt was seen.
-After
-.Em passtime
-minutes if
-.Nm
-sees a retried attempt to deliver mail for the same tuple,
-.Nm
-will whitelist the connecting address by adding it as a
-whitelist entry to
-.Pa /var/db/spamd .
-.Pp
-.Nm
-regularly scans the
-.Pa /var/db/spamd
-database and configures all whitelist addresses as the
-.Em spamd-white
-.Xr pf 4
-table.
-The
-.Em spamd-white
-table must be used to allow connections to pass to the
-real MTA as in the following
-.Xr pf.conf 5
-example:
-.Bd -literal -offset 4n
-table <spamd> persist
-table <spamd-white> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-rdr pass inet proto tcp from !<spamd-white> to any port smtp \e
- -> 127.0.0.1 port 8025
-.Ed
-.Pp
-With this configuration,
-.Xr spamd-setup 8
-should be used to configure blacklists in
-.Nm
-and add them to the
-.Em spamd
-.Xr pf 4
-table.
-These connections will be stuttered at by
-.Nm .
-All other connections not in the
-.Em spamd-white
-table are redirected to
-.Nm
-but will not be stuttered at.
-Such connections will be
-considered for greylisting and eventual whitelisting (by addition
-to the
-.Em spamd-white
-table so they are not redirected) if they retry mail delivery.
-.Pp
-.Nm
-removes tuple entries from the
-.Pa /var/db/spamd
-database if delivery has not been retried within
-.Em greyexp
-hours from the initial time a connection is seen.
-The default is 4 hours as this is the most common setting after which
-MTA's will give up attempting to retry delivery of a message.
-.Pp
-.Nm
-removes whitelist entries from the
-.Pa /var/db/spamd
-database if no mail delivery activity has been seen from the
-whitelisted address by
-.Xr spamlogd 8
-within
-.Em whiteexp
-hours from the initial time an address
-is whitelisted.
-The default is 36 days to allow for the delivery of
-monthly mailing list digests without greylist delays every time.
-.Xr spamlogd 8
-should be used to update the whitelist entries in
-.Pa /var/db/spamd
-when connections are seen to pass to the real MTA on the
-.Em smtp
-port.
-.Sh GREYTRAPPING
-When greylisting with
-.Nm
-it may be useful to define
-.Em spamtrap
-destination addresses to catch spammers as they send mail from greylisted
-hosts.
-Such
-.Em spamtrap
-addresses affect only greylisted connections to
-.Nm
-and are used to temporarily blacklist a host that is obviously sending spam.
-Unused email addresses or email addresses on spammers' lists are very
-useful for this.
-When a host that is currently greylisted attempts to send mail to a
-.Em spamtrap
-address, it is blacklisted for 24 hours by adding the host to the
-.Nm
-blacklist
-.Em spamd-greytrap .
-Spamtrap addresses are added to the
-.Pa /var/db/spamd
-database with the following
-.Xr spamdb 8
-command:
-.Pp
-.Dl spamdb -T -a \&"<spamtrap at mydomain.org>\&"
-.Pp
-It should be entered exactly as the address will be used in the SMTP dialogue.
-See
-.Xr spamdb 8
-for further details.
-.Sh LOGGING
-.Nm
-sends log messages to
-.Xr syslogd 8
-using
-.Em facility
-daemon and, with increasing verbosity,
-.Em level
-err, warn, info and debug.
-The following
-.Xr syslog.conf 5
-section can be used to log connection details to a dedicated file:
-.Bd -literal -offset indent
-!spamd
-daemon.err;daemon.warn;daemon.info /var/log/spamd
-.Ed
-.Sh FILES
-/usr/local/etc/spamd.conf
-.Sh SEE ALSO
-.Xr pf.conf 5 ,
-.Xr services 5 ,
-.Xr spamd.conf 5 ,
-.Xr syslog.conf 5 ,
-.Xr pfctl 8 ,
-.Xr spamd-setup 8 ,
-.Xr spamdb 8 ,
-.Xr spamlogd 8 ,
-.Xr syslogd 8
-.Sh HISTORY
-The
-.Nm
-command
-appeared in
-.Ox 3.3 .
-.Sh BUGS
-.Nm
-currently uses the user
-.Dq _spamd
-outside a chroot jail when running in greylisting mode, and requires
-the greylisting database in
-.Pa /var/db/spamd
-to be owned by the
-.Dq _spamd
-user.
-This is wrong and should change to a distinct user from the
-one used by the chrooted
-.Nm
-process.
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8.bak /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8.bak
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8.bak Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8.bak Thu Jan 1 03:00:00 1970
@@ -1,473 +0,0 @@
-.\" $OpenBSD: spamd.8,v 1.53 2005/03/11 23:09:53 beck Exp $
-.\"
-.\" Copyright (c) 2002 Theo de Raadt. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd December 18, 2002
-.Dt SPAMD 8
-.Os
-.Sh NAME
-.Nm spamd
-.Nd spam deferral daemon
-.Sh SYNOPSIS
-.Nm spamd
-.Bk -words
-.Op Fl 45dgv
-.Op Fl B Ar maxblack
-.Op Fl b Ar address
-.Op Fl c Ar maxcon
-.Op Fl G Ar passtime:greyexp:whiteexp
-.Op Fl n Ar name
-.Op Fl p Ar port
-.Op Fl r Ar reply
-.Op Fl s Ar secs
-.Op Fl w Ar window
-.Ek
-.Sh DESCRIPTION
-.Nm
-is a fake
-.Xr sendmail 8 Ns -like
-daemon which rejects false mail.
-If the
-.Xr pf 4
-or
-.Xr ipfw 4
-packet filter is configured to redirect port 25 (SMTP) to this daemon,
-it will attempt to waste the time and resources of the spam sender.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl 4
-For black listed entries, return error code 450 to the spammer (default).
-.It Fl 5
-For black-listed entries, return error code 550 to the spammer.
-.It Fl B Ar maxblack
-The maximum number of concurrent blacklisted connections to allow in
-greylisting mode.
-This value may not be greater than maxcon (see below).
-The default is maxcon \- 100
-.It Fl b Ar address
-Specify the local address to which
-.Nm
-is to
-.Xr bind 2 .
-By default
-.Nm
-listens on all local addresses.
-.It Fl c Ar maxcon
-The maximum number of concurrent connections to allow.
-The default is 800.
-.It Fl d
-Debug mode.
-.Nm
-does not
-.Xr fork 2
-into the background.
-.It Fl G Ar passtime:greyexp:whiteexp
-Adjust the three time parameters for greylisting; see
-.Sx GREYLISTING
-below.
-.Ar passtime
-defaults to 25 (minutes),
-.Ar greyexp
-to 4 (hours),
-and
-.Ar whiteexp
-to 864 (hours, approximately 36 days).
-.It Fl g
-Greylisting mode; see
-.Sx GREYLISTING
-below.
-.It Fl n Ar name
-The SMTP version banner that is reported upon initial connection.
-.It Fl p Ar port
-Specify a different port number from the default port that
-.Nm
-should listen for redirected SMTP connections on.
-The default port is found by looking for the named service
-.Em spamd
-using
-.Xr getservbyname 3 .
-.It Fl r Ar reply
-The SMTP error to return to the spammer, i.e. 450, 451, 550.
-This defaults to 450.
-.It Fl s Ar secs
-Delay each character sent to the client by the specified
-amount of seconds.
-Defaults to 1.
-.It Fl v
-Enable verbose logging.
-By default
-.Nm
-logs connections, disconnections and blacklist matches to
-.Xr syslogd 8
-at
-.Dv LOG_INFO
-level.
-With verbose logging enabled, message detail
-including subject and recipient information is logged at
-.Dv LOG_INFO ,
-along with the message body and SMTP dialogue being logged at
-.Dv LOG_DEBUG
-level.
-.It Fl w Ar window
-Set the socket receive buffer to this many bytes, adjusting the window size.
-.El
-.Pp
-.Nm
-is designed to be very efficient so that it does not slow down the
-receiving machine.
-Spam is never accepted, but always rejected with either a 450 or 550
-error message.
-The normal way that spam has been dealt with in the past is to either
-accept and drop, or outright block.
-When configured to use 450 responses,
-.Nm
-takes neither of these actions: it rejects the mail back to the senders'
-queue.
-.Pp
-.Nm
-is best started from
-.Xr rc 8
-in conjunction with the
-.Xr spamd-setup 8
-which processes a list of spammers' addresses, and applies appropriate
-.Xr pfctl 8
-.Em rdr
-or
-.Xr ipfw 8
-.Em fwd
-rules.
-.Xr spamd-setup 8
-is run from
-.Xr cron 8 .
-.Sh REDIRECTING SMTP CONNECTIONS
-.Ss "When using PF"
-With
-.Xr pf 4 ,
-connections to port 25 (SMTP) can be redirected to another host or port,
-based on the source address of the sender.
-The
-.Em rdr
-rules used for this purpose are described in
-.Xr pf.conf 5 .
-The rules can be loaded into a
-.Em table
-to simplify handling.
-.Bd -literal -offset 4n
-table <spamd> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-.Ed
-.Pp
-Any addresses in table
-.Em <spamd>
-are then redirected to
-.Nm
-running on port 8025.
-Addresses can be loaded into the
-.Em table ,
-like:
-.Bd -literal -offset 4n
-# pfctl -q -t spamd -T replace -f /usr/local/share/spammers
-.Ed
-.Pp
-.Xr spamd-setup 8
-can also be used to load addresses into the
-.Em <spamd>
-table.
-
-
-.Xr spamd-setup 8
-also has the added benefit of being able to remove addresses from
-blacklists, and will connect to
-.Nm
-over a localhost socket, giving
-.Nm
-information about each source of blacklist addresses, as well as custom
-rejection messages for each blacklist source
-that can be used to let any real person whose mail
-is deferred by spamd know why their address has been listed
-from sending mail.
-This is important as it allows legitimate mail
-senders to pressure spam sources into behaving properly so that they
-may be removed from the relevant blacklists.
-
-.Ss "If compiled with IPFW"
-With
-.Xr ipfw 4 ,
-the syntax for redirection of TCP sessions is quite different
-from that of
-.Xr pf 4 .
-The
-.Em fwd
-rule used for this purpose are described in
-.Xr ipfw 8 .
-The rules should be added to the ruleset called by /etc/rc.firewall
-to be present at boot time.
-.Bd -literal -offset 4n
-fwd 127.0.0.1,8025 tcp from table(2) to me 25 in
-allow tcp from table(1) to me 25 in
-fwd 127.0.0.1,8025 tcp from any to me 25 in
-.Ed
-.Pp
-Any addresses in the blacklist table
-.Em 2
-and not in the whitelist table
-.Em 1
-are then redirected to
-.Nm
-running on port 8025.
-Addresses can be loaded into the blacklist
-.Em table ,
-like:
-.Bd -literal -offset 4n
-# ipfw table 1 add a.b.c.d/x
-.Ed
-.Pp
-.Xr spamd-setup 8
-can also be used to load addresses into the blacklist table
-.Em 2 .
-.Pp
-The
-.Op Fl t Ar table_no
-option to
-.Em spamd
-and
-.Em spamd-setup
-can be used to change the default table
-numbers.
-
-.Sh CONFIGURATION CONNECTIONS
-.Nm
-listens for configuration connections on the port identified by the
-named service
-.Em spamd-cfg
-(see
-.Xr services 5 ) .
-The configuration socket listens only on the INADDR_LOOPBACK
-address.
-Configuration of spamd is done by connecting to the configuration
-socket, and sending blacklist information, one blacklist per line.
-Each blacklist consists of a name, a message to reject mail
-with, and addresses in CIDR format, all separated by semicolons (;):
-.Bd -literal -offset indent
-tag;"rejection message";aaa.bbb.ccc.ddd/mm;aaa.bbb.ccc.ddd/mm
-.Ed
-.Pp
-The rejection message must be inside double quotes.
-A \e" will produce a double quote in the output.
-\en will produce a newline.
-%A will expand to the connecting IP address in dotted quad format.
-%% may be used to produce a single % in the output.
-\e\e will produce a single \e.
-.Nm
-will reject mail by displaying all the messages from all blacklists in which
-a connecting address is matched.
-.Xr spamd-setup 8
-is normally used to configure this information.
-.Sh GREYLISTING
-When run in greylisting mode,
-.Nm
-will run in the normal mode for any addresses blacklisted by
-.Xr spamd-setup 8 .
-Connections from addresses not blacklisted by
-.Xr spamd-setup 8
-will be considered for greylisting.
-Such connections will not be stuttered at or delayed,
-and will receive the pleasantly innocuous temporary failure of:
-.Bd -literal -offset 4n
-451 Temporary failure, please try again later.
-.Ed
-.Pp
-in the SMTP dialogue immediately after the recipient is specified.
-.Nm
-will use the db file in
-.Pa /var/db/spamd
-to track these non-blacklisted connections to
-.Nm
-by connecting IP address, envelope-from, and envelope-to, or "tuple" for
-short.
-.Pp
-A previously unseen tuple is added to the
-.Pa /var/db/spamd
-database, recording the time an initial connection attempt was seen.
-After
-.Em passtime
-minutes if
-.Nm
-sees a retried attempt to deliver mail for the same tuple,
-.Nm
-will whitelist the connecting address by adding it as a
-whitelist entry to
-.Pa /var/db/spamd .
-.Pp
-.Nm
-regularly scans the
-.Pa /var/db/spamd
-database and configures all whitelist addresses as the
-.Em spamd-white
-.Xr pf 4
-table.
-The
-.Em spamd-white
-table must be used to allow connections to pass to the
-real MTA as in the following
-.Xr pf.conf 5
-example:
-.Bd -literal -offset 4n
-table <spamd> persist
-table <spamd-white> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-rdr pass inet proto tcp from !<spamd-white> to any port smtp \e
- -> 127.0.0.1 port 8025
-.Ed
-.Pp
-With this configuration,
-.Xr spamd-setup 8
-should be used to configure blacklists in
-.Nm
-and add them to the
-.Em spamd
-.Xr pf 4
-table.
-These connections will be stuttered at by
-.Nm .
-All other connections not in the
-.Em spamd-white
-table are redirected to
-.Nm
-but will not be stuttered at.
-Such connections will be
-considered for greylisting and eventual whitelisting (by addition
-to the
-.Em spamd-white
-table so they are not redirected) if they retry mail delivery.
-.Pp
-.Nm
-removes tuple entries from the
-.Pa /var/db/spamd
-database if delivery has not been retried within
-.Em greyexp
-hours from the initial time a connection is seen.
-The default is 4 hours as this is the most common setting after which
-MTA's will give up attempting to retry delivery of a message.
-.Pp
-.Nm
-removes whitelist entries from the
-.Pa /var/db/spamd
-database if no mail delivery activity has been seen from the
-whitelisted address by
-.Xr spamlogd 8
-within
-.Em whiteexp
-hours from the initial time an address
-is whitelisted.
-The default is 36 days to allow for the delivery of
-monthly mailing list digests without greylist delays every time.
-.Xr spamlogd 8
-should be used to update the whitelist entries in
-.Pa /var/db/spamd
-when connections are seen to pass to the real MTA on the
-.Em smtp
-port.
-.Sh GREYTRAPPING
-When greylisting with
-.Nm
-it may be useful to define
-.Em spamtrap
-destination addresses to catch spammers as they send mail from greylisted
-hosts.
-Such
-.Em spamtrap
-addresses affect only greylisted connections to
-.Nm
-and are used to temporarily blacklist a host that is obviously sending spam.
-Unused email addresses or email addresses on spammers' lists are very
-useful for this.
-When a host that is currently greylisted attempts to send mail to a
-.Em spamtrap
-address, it is blacklisted for 24 hours by adding the host to the
-.Nm
-blacklist
-.Em spamd-greytrap .
-Spamtrap addresses are added to the
-.Pa /var/db/spamd
-database with the following
-.Xr spamdb 8
-command:
-.Pp
-.Dl spamdb -T -a \&"<spamtrap at mydomain.org>\&"
-.Pp
-It should be entered exactly as the address will be used in the SMTP dialogue.
-See
-.Xr spamdb 8
-for further details.
-.Sh LOGGING
-.Nm
-sends log messages to
-.Xr syslogd 8
-using
-.Em facility
-daemon and, with increasing verbosity,
-.Em level
-err, warn, info and debug.
-The following
-.Xr syslog.conf 5
-section can be used to log connection details to a dedicated file:
-.Bd -literal -offset indent
-!spamd
-daemon.err;daemon.warn;daemon.info /var/log/spamd
-.Ed
-.Sh FILES
-/etc/spamd.conf
-.Sh SEE ALSO
-.Xr pf.conf 5 ,
-.Xr services 5 ,
-.Xr spamd.conf 5 ,
-.Xr syslog.conf 5 ,
-.Xr pfctl 8 ,
-.Xr spamd-setup 8 ,
-.Xr spamdb 8 ,
-.Xr spamlogd 8 ,
-.Xr syslogd 8
-.Sh HISTORY
-The
-.Nm
-command
-appeared in
-.Ox 3.3 .
-.Sh BUGS
-.Nm
-currently uses the user
-.Dq _spamd
-outside a chroot jail when running in greylisting mode, and requires
-the greylisting database in
-.Pa /var/db/spamd
-to be owned by the
-.Dq _spamd
-user.
-This is wrong and should change to a distinct user from the
-one used by the chrooted
-.Nm
-process.
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8.gz and /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8.gz differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8.orig /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8.orig
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.8.orig Tue Apr 12 20:21:48 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.8.orig Thu Jan 1 03:00:00 1970
@@ -1,419 +0,0 @@
-.\" $OpenBSD: spamd.8,v 1.53 2005/03/11 23:09:53 beck Exp $
-.\"
-.\" Copyright (c) 2002 Theo de Raadt. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd December 18, 2002
-.Dt SPAMD 8
-.Os
-.Sh NAME
-.Nm spamd
-.Nd spam deferral daemon
-.Sh SYNOPSIS
-.Nm spamd
-.Bk -words
-.Op Fl 45dgv
-.Op Fl B Ar maxblack
-.Op Fl b Ar address
-.Op Fl c Ar maxcon
-.Op Fl G Ar passtime:greyexp:whiteexp
-.Op Fl n Ar name
-.Op Fl p Ar port
-.Op Fl r Ar reply
-.Op Fl s Ar secs
-.Op Fl w Ar window
-.Ek
-.Sh DESCRIPTION
-.Nm
-is a fake
-.Xr sendmail 8 Ns -like
-daemon which rejects false mail.
-If the
-.Xr pf 4
-packet filter is configured to redirect port 25 (SMTP) to this daemon,
-it will attempt to waste the time and resources of the spam sender.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl 4
-For black listed entries, return error code 450 to the spammer (default).
-.It Fl 5
-For black-listed entries, return error code 550 to the spammer.
-.It Fl B Ar maxblack
-The maximum number of concurrent blacklisted connections to allow in
-greylisting mode.
-This value may not be greater than maxcon (see below).
-The default is maxcon \- 100
-.It Fl b Ar address
-Specify the local address to which
-.Nm
-is to
-.Xr bind 2 .
-By default
-.Nm
-listens on all local addresses.
-.It Fl c Ar maxcon
-The maximum number of concurrent connections to allow.
-The default is 800.
-.It Fl d
-Debug mode.
-.Nm
-does not
-.Xr fork 2
-into the background.
-.It Fl G Ar passtime:greyexp:whiteexp
-Adjust the three time parameters for greylisting; see
-.Sx GREYLISTING
-below.
-.Ar passtime
-defaults to 25 (minutes),
-.Ar greyexp
-to 4 (hours),
-and
-.Ar whiteexp
-to 864 (hours, approximately 36 days).
-.It Fl g
-Greylisting mode; see
-.Sx GREYLISTING
-below.
-.It Fl n Ar name
-The SMTP version banner that is reported upon initial connection.
-.It Fl p Ar port
-Specify a different port number from the default port that
-.Nm
-should listen for redirected SMTP connections on.
-The default port is found by looking for the named service
-.Em spamd
-using
-.Xr getservbyname 3 .
-.It Fl r Ar reply
-The SMTP error to return to the spammer, i.e. 450, 451, 550.
-This defaults to 450.
-.It Fl s Ar secs
-Delay each character sent to the client by the specified
-amount of seconds.
-Defaults to 1.
-.It Fl v
-Enable verbose logging.
-By default
-.Nm
-logs connections, disconnections and blacklist matches to
-.Xr syslogd 8
-at
-.Dv LOG_INFO
-level.
-With verbose logging enabled, message detail
-including subject and recipient information is logged at
-.Dv LOG_INFO ,
-along with the message body and SMTP dialogue being logged at
-.Dv LOG_DEBUG
-level.
-.It Fl w Ar window
-Set the socket receive buffer to this many bytes, adjusting the window size.
-.El
-.Pp
-.Nm
-is designed to be very efficient so that it does not slow down the
-receiving machine.
-Spam is never accepted, but always rejected with either a 450 or 550
-error message.
-The normal way that spam has been dealt with in the past is to either
-accept and drop, or outright block.
-When configured to use 450 responses,
-.Nm
-takes neither of these actions: it rejects the mail back to the senders'
-queue.
-.Pp
-.Nm
-is best started from
-.Xr rc 8
-in conjunction with the
-.Xr spamd-setup 8
-which processes a list of spammers' addresses, and applies appropriate
-.Xr pfctl 8
-.Em rdr
-rules.
-.Xr spamd-setup 8
-is run from
-.Xr cron 8 .
-.Sh REDIRECTING SMTP CONNECTIONS
-With
-.Xr pf 4 ,
-connections to port 25 (SMTP) can be redirected to another host or port,
-based on the source address of the sender.
-The
-.Em rdr
-rules used for this purpose are described in
-.Xr pf.conf 5 .
-The rules can be loaded into a
-.Em table
-to simplify handling.
-.Bd -literal -offset 4n
-table <spamd> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-.Ed
-.Pp
-Any addresses in table
-.Em <spamd>
-are then redirected to
-.Nm
-running on port 8025.
-Addresses can be loaded into the
-.Em table ,
-like:
-.Bd -literal -offset 4n
-# pfctl -q -t spamd -T replace -f /usr/local/share/spammers
-.Ed
-.Pp
-.Xr spamd-setup 8
-can also be used to load addresses into the
-.Em <spamd>
-table.
-.Xr spamd-setup 8
-also has the added benefit of being able to remove addresses from
-blacklists, and will connect to
-.Nm
-over a localhost socket, giving
-.Nm
-information about each source of blacklist addresses, as well as custom
-rejection messages for each blacklist source
-that can be used to let any real person whose mail
-is deferred by spamd know why their address has been listed
-from sending mail.
-This is important as it allows legitimate mail
-senders to pressure spam sources into behaving properly so that they
-may be removed from the relevant blacklists.
-.Sh CONFIGURATION CONNECTIONS
-.Nm
-listens for configuration connections on the port identified by the
-named service
-.Em spamd-cfg
-(see
-.Xr services 5 ) .
-The configuration socket listens only on the INADDR_LOOPBACK
-address.
-Configuration of spamd is done by connecting to the configuration
-socket, and sending blacklist information, one blacklist per line.
-Each blacklist consists of a name, a message to reject mail
-with, and addresses in CIDR format, all separated by semicolons (;):
-.Bd -literal -offset indent
-tag;"rejection message";aaa.bbb.ccc.ddd/mm;aaa.bbb.ccc.ddd/mm
-.Ed
-.Pp
-The rejection message must be inside double quotes.
-A \e" will produce a double quote in the output.
-\en will produce a newline.
-%A will expand to the connecting IP address in dotted quad format.
-%% may be used to produce a single % in the output.
-\e\e will produce a single \e.
-.Nm
-will reject mail by displaying all the messages from all blacklists in which
-a connecting address is matched.
-.Xr spamd-setup 8
-is normally used to configure this information.
-.Sh GREYLISTING
-When run in greylisting mode,
-.Nm
-will run in the normal mode for any addresses blacklisted by
-.Xr spamd-setup 8 .
-Connections from addresses not blacklisted by
-.Xr spamd-setup 8
-will be considered for greylisting.
-Such connections will not be stuttered at or delayed,
-and will receive the pleasantly innocuous temporary failure of:
-.Bd -literal -offset 4n
-451 Temporary failure, please try again later.
-.Ed
-.Pp
-in the SMTP dialogue immediately after the recipient is specified.
-.Nm
-will use the db file in
-.Pa /var/db/spamd
-to track these non-blacklisted connections to
-.Nm
-by connecting IP address, envelope-from, and envelope-to, or "tuple" for
-short.
-.Pp
-A previously unseen tuple is added to the
-.Pa /var/db/spamd
-database, recording the time an initial connection attempt was seen.
-After
-.Em passtime
-minutes if
-.Nm
-sees a retried attempt to deliver mail for the same tuple,
-.Nm
-will whitelist the connecting address by adding it as a
-whitelist entry to
-.Pa /var/db/spamd .
-.Pp
-.Nm
-regularly scans the
-.Pa /var/db/spamd
-database and configures all whitelist addresses as the
-.Em spamd-white
-.Xr pf 4
-table.
-The
-.Em spamd-white
-table must be used to allow connections to pass to the
-real MTA as in the following
-.Xr pf.conf 5
-example:
-.Bd -literal -offset 4n
-table <spamd> persist
-table <spamd-white> persist
-rdr pass inet proto tcp from <spamd> to any \e
- port smtp -> 127.0.0.1 port 8025
-rdr pass inet proto tcp from !<spamd-white> to any port smtp \e
- -> 127.0.0.1 port 8025
-.Ed
-.Pp
-With this configuration,
-.Xr spamd-setup 8
-should be used to configure blacklists in
-.Nm
-and add them to the
-.Em spamd
-.Xr pf 4
-table.
-These connections will be stuttered at by
-.Nm .
-All other connections not in the
-.Em spamd-white
-table are redirected to
-.Nm
-but will not be stuttered at.
-Such connections will be
-considered for greylisting and eventual whitelisting (by addition
-to the
-.Em spamd-white
-table so they are not redirected) if they retry mail delivery.
-.Pp
-.Nm
-removes tuple entries from the
-.Pa /var/db/spamd
-database if delivery has not been retried within
-.Em greyexp
-hours from the initial time a connection is seen.
-The default is 4 hours as this is the most common setting after which
-MTA's will give up attempting to retry delivery of a message.
-.Pp
-.Nm
-removes whitelist entries from the
-.Pa /var/db/spamd
-database if no mail delivery activity has been seen from the
-whitelisted address by
-.Xr spamlogd 8
-within
-.Em whiteexp
-hours from the initial time an address
-is whitelisted.
-The default is 36 days to allow for the delivery of
-monthly mailing list digests without greylist delays every time.
-.Xr spamlogd 8
-should be used to update the whitelist entries in
-.Pa /var/db/spamd
-when connections are seen to pass to the real MTA on the
-.Em smtp
-port.
-.Sh GREYTRAPPING
-When greylisting with
-.Nm
-it may be useful to define
-.Em spamtrap
-destination addresses to catch spammers as they send mail from greylisted
-hosts.
-Such
-.Em spamtrap
-addresses affect only greylisted connections to
-.Nm
-and are used to temporarily blacklist a host that is obviously sending spam.
-Unused email addresses or email addresses on spammers' lists are very
-useful for this.
-When a host that is currently greylisted attempts to send mail to a
-.Em spamtrap
-address, it is blacklisted for 24 hours by adding the host to the
-.Nm
-blacklist
-.Em spamd-greytrap .
-Spamtrap addresses are added to the
-.Pa /var/db/spamd
-database with the following
-.Xr spamdb 8
-command:
-.Pp
-.Dl spamdb -T -a \&"<spamtrap at mydomain.org>\&"
-.Pp
-It should be entered exactly as the address will be used in the SMTP dialogue.
-See
-.Xr spamdb 8
-for further details.
-.Sh LOGGING
-.Nm
-sends log messages to
-.Xr syslogd 8
-using
-.Em facility
-daemon and, with increasing verbosity,
-.Em level
-err, warn, info and debug.
-The following
-.Xr syslog.conf 5
-section can be used to log connection details to a dedicated file:
-.Bd -literal -offset indent
-!spamd
-daemon.err;daemon.warn;daemon.info /var/log/spamd
-.Ed
-.Sh FILES
-/etc/spamd.conf
-.Sh SEE ALSO
-.Xr pf.conf 5 ,
-.Xr services 5 ,
-.Xr spamd.conf 5 ,
-.Xr syslog.conf 5 ,
-.Xr pfctl 8 ,
-.Xr spamd-setup 8 ,
-.Xr spamdb 8 ,
-.Xr spamlogd 8 ,
-.Xr syslogd 8
-.Sh HISTORY
-The
-.Nm
-command
-appeared in
-.Ox 3.3 .
-.Sh BUGS
-.Nm
-currently uses the user
-.Dq _spamd
-outside a chroot jail when running in greylisting mode, and requires
-the greylisting database in
-.Pa /var/db/spamd
-to be owned by the
-.Dq _spamd
-user.
-This is wrong and should change to a distinct user from the
-one used by the chrooted
-.Nm
-process.
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.c /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.c Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.c Thu Jan 1 03:00:00 1970
@@ -1,1322 +0,0 @@
-/* $OpenBSD: spamd.c,v 1.75 2005/03/11 23:09:53 beck Exp $ */
-
-/*
- * Copyright (c) 2002 Theo de Raadt. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <netdb.h>
-
-#include "sdl.h"
-#include "grey.h"
-
-struct con {
- int fd;
- int state;
- int laststate;
- int af;
- struct sockaddr_storage ss;
- void *ia;
- char addr[32];
- char mail[MAX_MAIL], rcpt[MAX_MAIL];
- struct sdlist **blacklists;
-
- /*
- * we will do stuttering by changing these to time_t's of
- * now + n, and only advancing when the time is in the past/now
- */
- time_t r;
- time_t w;
- time_t s;
-
- char ibuf[8192];
- char *ip;
- int il;
- char rend[5]; /* any chars in here causes input termination */
-
- char *obuf;
- char *lists;
- size_t osize;
- char *op;
- int ol;
- int data_lines;
- int data_body;
- int stutter;
- int sr;
-} *con;
-
-void usage(void);
-char *grow_obuf(struct con *, int);
-int parse_configline(char *);
-void parse_configs(void);
-void do_config(void);
-int append_error_string (struct con *, size_t, char *, int, void *);
-void build_reply(struct con *);
-void doreply(struct con *);
-void setlog(char *, size_t, char *);
-void initcon(struct con *, int, struct sockaddr *);
-void closecon(struct con *);
-int match(const char *, const char *);
-void nextstate(struct con *);
-void handler(struct con *);
-void handlew(struct con *, int one);
-
-char hostname[MAXHOSTNAMELEN];
-#ifdef __OpenBSD__
-struct syslog_data sdata = SYSLOG_DATA_INIT;
-#else
-#define syslog_r(l, s, args...) syslog(l,args)
-#define openlog_r(i, l, f, s) openlog(i, l, f)
-int sdata = 0; /* dummy */
-#endif
-char *reply = NULL;
-char *nreply = "450";
-char *spamd = "spamd IP-based SPAM blocker";
-int greypipe[2];
-int trappipe[2];
-FILE *grey;
-FILE *trapcfg;
-time_t passtime = PASSTIME;
-time_t greyexp = GREYEXP;
-time_t whiteexp = WHITEEXP;
-time_t trapexp = TRAPEXP;
-struct passwd *pw;
-pid_t jail_pid = -1;
-u_short cfg_port;
-
-#ifdef IPFW
-int tabno=1;
-#endif
-
-extern struct sdlist *blacklists;
-
-int conffd = -1;
-int trapfd = -1;
-char *cb;
-size_t cbs, cbu;
-
-time_t t;
-
-#define MAXCON 800
-int maxcon = MAXCON;
-int maxblack = MAXCON;
-int blackcount;
-int clients;
-int debug;
-int greylist;
-int verbose;
-int stutter = 1;
-int window;
-#define MAXTIME 400
-
-void
-usage(void)
-{
- fprintf(stderr,
- "usage: spamd [-45dgv] [-B maxblack] [-b address] [-c maxcon]\n");
- fprintf(stderr,
- " [-G mins:hours:hours] [-n name] [-p port]\n");
- fprintf(stderr,
- " [-r reply] [-s secs] [-w window]\n");
-#ifdef IPFW
- fprintf(stderr,
- " [-t table_no]\n");
-#endif
- exit(1);
-}
-
-char *
-grow_obuf(struct con *cp, int off)
-{
- char *tmp;
-
- tmp = realloc(cp->obuf, cp->osize + 8192);
- if (tmp == NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- return (NULL);
- } else {
- cp->osize += 8192;
- cp->obuf = tmp;
- return (cp->obuf + off);
- }
-}
-
-int
-parse_configline(char *line)
-{
- char *cp, prev, *name, *msg;
- static char **av = NULL;
- static size_t ac = 0;
- size_t au = 0;
- int mdone = 0;
-
- name = line;
-
- for (cp = name; *cp && *cp != ';'; cp++)
- ;
- if (*cp != ';')
- goto parse_error;
- *cp++ = '\0';
- msg = cp;
- if (*cp++ != '"')
- goto parse_error;
- prev = '\0';
- for (; !mdone; cp++) {
- switch (*cp) {
- case '\\':
- if (!prev)
- prev = *cp;
- else
- prev = '\0';
- break;
- case '"':
- if (prev != '\\') {
- cp++;
- if (*cp == ';') {
- mdone = 1;
- *cp = '\0';
- } else
- goto parse_error;
- }
- break;
- case '\0':
- goto parse_error;
- default:
- prev = '\0';
- break;
- }
- }
-
- do {
- if (ac == au) {
- char **tmp;
-
- tmp = realloc(av, (ac + 2048) * sizeof(char *));
- if (tmp == NULL) {
- free(av);
- av = NULL;
- ac = 0;
- return (-1);
- }
- av = tmp;
- ac += 2048;
- }
- } while ((av[au++] = strsep(&cp, ";")) != NULL);
-
- /* toss empty last entry to allow for trailing ; */
- if (av[au - 1][0] == '\0');
- au--;
-
- if (au < 1)
- goto parse_error;
- else
- sdl_add(name, msg, av, au - 1);
- return (0);
-
-parse_error:
- if (debug > 0)
- printf("bogus config line - need 'tag;message;a/m;a/m;a/m...'\n");
- return (-1);
-}
-
-void
-parse_configs(void)
-{
- char *start, *end;
- int i;
-
- if (cbu == cbs) {
- char *tmp;
-
- tmp = realloc(cb, cbs + 8192);
- if (tmp == NULL) {
- if (debug > 0)
- perror("malloc()");
- free(cb);
- cb = NULL;
- cbs = cbu = 0;
- return;
- }
- cbs += 8192;
- cb = tmp;
- }
- cb[cbu++] = '\0';
-
- start = cb;
- end = start;
- for (i = 0; i < cbu; i++) {
- if (*end == '\n') {
- *end = '\0';
- if (end > start + 1)
- parse_configline(start);
- start = ++end;
- } else
- ++end;
- }
- if (end > start + 1)
- parse_configline(start);
-}
-
-void
-do_config(void)
-{
- int n;
-
- if (debug > 0)
- printf("got configuration connection\n");
-
- if (cbu == cbs) {
- char *tmp;
-
- tmp = realloc(cb, cbs + 8192);
- if (tmp == NULL) {
- if (debug > 0)
- perror("malloc()");
- free(cb);
- cb = NULL;
- cbs = 0;
- goto configdone;
- }
- cbs += 8192;
- cb = tmp;
- }
-
- n = read(conffd, cb + cbu, cbs - cbu);
- if (debug > 0)
- printf("read %d config bytes\n", n);
- if (n == 0) {
- parse_configs();
- goto configdone;
- } else if (n == -1) {
- if (debug > 0)
- perror("read()");
- goto configdone;
- } else
- cbu += n;
- return;
-
-configdone:
- cbu = 0;
- close(conffd);
- conffd = -1;
-}
-
-
-int
-read_configline(FILE *config)
-{
- char *buf;
- size_t len;
-
- if ((buf = fgetln(config, &len))) {
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- else
- return(-1); /* all valid lines end in \n */
- parse_configline(buf);
- } else {
- syslog_r(LOG_DEBUG, &sdata, "read_configline: fgetln (%m)");
- return(-1);
- }
- return(0);
-}
-
-int
-append_error_string(struct con *cp, size_t off, char *fmt, int af, void *ia)
-{
- char sav = '\0';
- static int lastcont = 0;
- char *c = cp->obuf + off;
- char *s = fmt;
- size_t len = cp->osize - off;
- int i = 0;
-
- if (off == 0)
- lastcont = 0;
-
- if (lastcont != 0)
- cp->obuf[lastcont] = '-';
- snprintf(c, len, "%s ", nreply);
- i += strlen(c);
- lastcont = off + i - 1;
- if (*s == '"')
- s++;
- while (*s) {
- /*
- * Make sure we at minimum, have room to add a
- * format code (4 bytes), and a v6 address(39 bytes)
- * and a byte saved in sav.
- */
- if (i >= len - 46) {
- c = grow_obuf(cp, off);
- if (c == NULL)
- return (-1);
- len = cp->osize - (off + i);
- }
-
- if (c[i-1] == '\n') {
- if (lastcont != 0)
- cp->obuf[lastcont] = '-';
- snprintf(c + i, len, "%s ", nreply);
- i += strlen(c);
- lastcont = off + i - 1;
- }
-
- switch (*s) {
- case '\\':
- case '%':
- if (!sav)
- sav = *s;
- else {
- c[i++] = sav;
- sav = '\0';
- c[i] = '\0';
- }
- break;
- case '"':
- case 'A':
- case 'n':
- if (*(s+1) == '\0') {
- break;
- }
- if (sav == '\\' && *s == 'n') {
- c[i++] = '\n';
- sav = '\0';
- c[i] = '\0';
- break;
- } else if (sav == '\\' && *s == '"') {
- c[i++] = '"';
- sav = '\0';
- c[i] = '\0';
- break;
- } else if (sav == '%' && *s == 'A') {
- inet_ntop(af, ia, c + i, (len - i));
- i += strlen(c + i);
- sav = '\0';
- break;
- }
- /* fallthrough */
- default:
- if (sav)
- c[i++] = sav;
- c[i++] = *s;
- sav = '\0';
- c[i] = '\0';
- break;
- }
- s++;
- }
- return (i);
-}
-
-char *
-loglists(struct con *cp)
-{
- static char matchlists[80];
- struct sdlist **matches;
- int s = sizeof(matchlists) - 4;
-
- matchlists[0] = '\0';
- matches = cp->blacklists;
- if (matches == NULL)
- return(NULL);
- for (; *matches; matches++) {
-
- /* don't report an insane amount of lists in the logs.
- * just truncate and indicate with ...
- */
- if (strlen(matchlists) + strlen(matches[0]->tag) + 1
- >= s)
- strlcat(matchlists, " ...", sizeof(matchlists));
- else {
- strlcat(matchlists, " ", s);
- strlcat(matchlists, matches[0]->tag, s);
- }
- }
- return matchlists;
-}
-
-void
-build_reply(struct con *cp)
-{
- struct sdlist **matches;
- int off = 0;
-
- matches = cp->blacklists;
- if (matches == NULL)
- goto nomatch;
- for (; *matches; matches++) {
- int used = 0;
- char *c = cp->obuf + off;
- int left = cp->osize - off;
-
- used = append_error_string(cp, off, matches[0]->string,
- cp->af, cp->ia);
- if (used == -1)
- goto bad;
- off += used;
- left -= used;
- if (cp->obuf[off - 1] != '\n') {
- if (left < 1) {
- c = grow_obuf(cp, off);
- if (c == NULL)
- goto bad;
- }
- cp->obuf[off++] = '\n';
- cp->obuf[off] = '\0';
- }
- }
- return;
-nomatch:
- /* No match. give generic reply */
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- if (cp->blacklists != NULL)
- asprintf(&cp->obuf,
- "%s-Sorry %s\n"
- "%s-You are trying to send mail from an address "
- "listed by one\n"
- "%s or more IP-based registries as being a SPAM source.\n",
- nreply, cp->addr, nreply, nreply);
- else
- asprintf(&cp->obuf,
- "451 Temporary failure, please try again later.\r\n");
- if (cp->obuf != NULL)
- cp->osize = strlen(cp->obuf) + 1;
- else
- cp->osize = 0;
- return;
-bad:
- if (cp->obuf != NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- }
-}
-
-void
-doreply(struct con *cp)
-{
- if (reply)
- snprintf(cp->obuf, cp->osize, "%s %s\n", nreply, reply);
- build_reply(cp);
-}
-
-void
-setlog(char *p, size_t len, char *f)
-{
- char *s;
-
- s = strsep(&f, ":");
- if (!f)
- return;
- while (*f == ' ' || *f == '\t')
- f++;
- s = strsep(&f, " \t");
- if (s == NULL)
- return;
- strlcpy(p, s, len);
- s = strsep(&p, " \t\n\r");
- if (s == NULL)
- return;
- s = strsep(&p, " \t\n\r");
- if (s)
- *s = '\0';
-}
-
-void
-initcon(struct con *cp, int fd, struct sockaddr *sa)
-{
- time_t t;
- char *tmp;
- int error;
-
- time(&t);
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- free(cp->blacklists);
- cp->blacklists = NULL;
- free(cp->lists);
- cp->lists = NULL;
- bzero(cp, sizeof(struct con));
- if (grow_obuf(cp, 0) == NULL)
- err(1, "malloc");
- cp->fd = fd;
- if (sa->sa_len > sizeof(cp->ss))
- errx(1, "sockaddr size");
- if (sa->sa_family != AF_INET)
- errx(1, "not supported yet");
- memcpy(&cp->ss, sa, sa->sa_len);
- cp->af = sa->sa_family;
- cp->ia = &((struct sockaddr_in *)sa)->sin_addr;
- cp->blacklists = sdl_lookup(blacklists, cp->af, cp->ia);
- cp->stutter = (greylist && cp->blacklists == NULL) ? 0 : stutter;
- error = getnameinfo(sa, sa->sa_len, cp->addr, sizeof(cp->addr), NULL, 0,
- NI_NUMERICHOST);
- if (error)
- errx(1, "%s", gai_strerror(error));
- tmp = strdup(ctime(&t));
- if (tmp == NULL)
- err(1, "malloc");
- tmp[strlen(tmp) - 1] = '\0'; /* nuke newline */
- snprintf(cp->obuf, cp->osize,
- "220 %s ESMTP %s; %s\r\n",
- hostname, spamd, tmp);
- free(tmp);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->s = t;
- strlcpy(cp->rend, "\n", sizeof cp->rend);
- clients++;
- if (cp->blacklists != NULL) {
- blackcount++;
- if (greylist && blackcount > maxblack) {
- closecon(cp); /* close and free */
- return;
- }
- cp->lists = strdup(loglists(cp));
- }
- else
- cp->lists = NULL;
-}
-
-void
-closecon(struct con *cp)
-{
- time_t t;
-
- time(&t);
- syslog_r(LOG_INFO, &sdata, "%s: disconnected after %ld seconds.%s%s",
- cp->addr, (long)(t - cp->s),
- ((cp->lists == NULL) ? "" : " lists:"),
- ((cp->lists == NULL) ? "": cp->lists));
- if (debug > 0)
- printf("%s connected for %ld seconds.\n", cp->addr,
- (long)(t - cp->s));
- if (cp->lists != NULL) {
- free(cp->lists);
- cp->lists = NULL;
- }
- if (cp->blacklists != NULL) {
- blackcount--;
- free(cp->blacklists);
- cp->blacklists = NULL;
- }
- if (cp->obuf != NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- }
- close(cp->fd);
- clients--;
- cp->fd = -1;
-}
-
-int
-match(const char *s1, const char *s2)
-{
- return (strncasecmp(s1, s2, strlen(s2)) == 0);
-}
-
-void
-nextstate(struct con *cp)
-{
- if (match(cp->ibuf, "QUIT") && cp->state < 99) {
- snprintf(cp->obuf, cp->osize, "221 %s\r\n", hostname);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 99;
- return;
- }
-
- if (match(cp->ibuf, "RSET") && cp->state > 2 && cp->state < 50) {
- snprintf(cp->obuf, cp->osize,
- "250 Ok to start over.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 2;
- return;
- }
- switch (cp->state) {
- case 0:
- /* banner sent; wait for input */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 1;
- cp->r = t;
- break;
- case 1:
- /* received input: parse, and select next state */
- if (match(cp->ibuf, "HELO") ||
- match(cp->ibuf, "EHLO")) {
- snprintf(cp->obuf, cp->osize,
- "250 Hello, spam sender. "
- "Pleased to be wasting your time.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 2;
- cp->w = t + cp->stutter;
- break;
- }
- goto mail;
- case 2:
- /* sent 250 Hello, wait for input */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 3;
- cp->r = t;
- break;
- mail:
- case 3:
- if (match(cp->ibuf, "MAIL")) {
- setlog(cp->mail, sizeof cp->mail, cp->ibuf);
- snprintf(cp->obuf, cp->osize,
- "250 You are about to try to deliver spam. "
- "Your time will be spent, for nothing.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 4;
- cp->w = t + cp->stutter;
- break;
- }
- goto rcpt;
- case 4:
- /* sent 250 Sender ok */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 5;
- cp->r = t;
- break;
- rcpt:
- case 5:
- if (match(cp->ibuf, "RCPT")) {
- setlog(cp->rcpt, sizeof(cp->rcpt), cp->ibuf);
- snprintf(cp->obuf, cp->osize,
- "250 This is hurting you more than it is "
- "hurting me.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 6;
- cp->w = t + cp->stutter;
- if (cp->mail[0] && cp->rcpt[0]) {
- if (verbose)
- syslog_r(LOG_INFO, &sdata,
- "(%s) %s: %s -> %s",
- cp->blacklists ? "BLACK" : "GREY",
- cp->addr, cp->mail,
- cp->rcpt);
- if (debug)
- fprintf(stderr, "(%s) %s: %s -> %s\n",
- cp->blacklists ? "BLACK" : "GREY",
- cp->addr, cp->mail, cp->rcpt);
- if (greylist && cp->blacklists == NULL) {
- /* send this info to the greylister */
- fprintf(grey, "IP:%s\nFR:%s\nTO:%s\n",
- cp->addr, cp->mail, cp->rcpt);
- fflush(grey);
- cp->laststate = cp->state;
- cp->state = 98;
- goto done;
- }
- }
- break;
- }
- goto spam;
- case 6:
- /* sent 250 blah */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 5;
- cp->r = t;
- break;
-
- spam:
- case 50:
- if (match(cp->ibuf, "DATA")) {
- snprintf(cp->obuf, cp->osize,
- "354 Enter spam, end with \".\" on a line by "
- "itself\r\n");
- cp->state = 60;
- if (window && setsockopt(cp->fd, SOL_SOCKET, SO_RCVBUF,
- &window, sizeof(window)) == -1) {
- syslog_r(LOG_DEBUG, &sdata,"setsockopt: %m");
- /* don't fail if this doesn't work. */
- }
- } else {
- snprintf(cp->obuf, cp->osize,
- "500 5.5.1 Command unrecognized\r\n");
- cp->state = cp->laststate;
- }
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- break;
- case 60:
- /* sent 354 blah */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 70;
- cp->r = t;
- break;
- case 70: {
- char *p, *q;
-
- for (p = q = cp->ibuf; q <= cp->ip; ++q)
- if (*q == '\n' || q == cp->ip) {
- *q = 0;
- if (q > p && q[-1] == '\r')
- q[-1] = 0;
- if (!strcmp(p, ".") ||
- (cp->data_body && ++cp->data_lines >= 10)) {
- cp->laststate = cp->state;
- cp->state = 98;
- goto done;
- }
- if (!cp->data_body && !*p)
- cp->data_body = 1;
- if (verbose && cp->data_body && *p)
- syslog_r(LOG_DEBUG, &sdata, "%s: "
- "Body: %s", cp->addr, p);
- else if (verbose && (match(p, "FROM:") ||
- match(p, "TO:") || match(p, "SUBJECT:")))
- syslog_r(LOG_INFO, &sdata, "%s: %s",
- cp->addr, p);
- p = ++q;
- }
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->r = t;
- break;
- }
- done:
- case 98:
- doreply(cp);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 99;
- break;
- case 99:
- closecon(cp);
- break;
- default:
- errx(1, "illegal state %d", cp->state);
- break;
- }
-}
-
-void
-handler(struct con *cp)
-{
- int end = 0;
- int n;
-
- if (cp->r) {
- n = read(cp->fd, cp->ip, cp->il);
- if (n == 0)
- closecon(cp);
- else if (n == -1) {
- if (debug > 0)
- perror("read()");
- closecon(cp);
- } else {
- cp->ip[n] = '\0';
- if (cp->rend[0])
- if (strpbrk(cp->ip, cp->rend))
- end = 1;
- cp->ip += n;
- cp->il -= n;
- }
- }
- if (end || cp->il == 0) {
- while (cp->ip > cp->ibuf &&
- (cp->ip[-1] == '\r' || cp->ip[-1] == '\n'))
- cp->ip--;
- *cp->ip = '\0';
- cp->r = 0;
- nextstate(cp);
- }
-}
-
-void
-handlew(struct con *cp, int one)
-{
- int n;
-
- if (cp->w) {
- if (*cp->op == '\n' && !cp->sr) {
- /* insert \r before \n */
- n = write(cp->fd, "\r", 1);
- if (n == 0) {
- closecon(cp);
- goto handled;
- } else if (n == -1) {
- if (debug > 0 && errno != EPIPE)
- perror("write()");
- closecon(cp);
- goto handled;
- }
- }
- if (*cp->op == '\r')
- cp->sr = 1;
- else
- cp->sr = 0;
- n = write(cp->fd, cp->op, (one && cp->stutter) ? 1 : cp->ol);
- if (n == 0)
- closecon(cp);
- else if (n == -1) {
- if (debug > 0 && errno != EPIPE)
- perror("write()");
- closecon(cp);
- } else {
- cp->op += n;
- cp->ol -= n;
- }
- }
-handled:
- cp->w = t + cp->stutter;
- if (cp->ol == 0) {
- cp->w = 0;
- nextstate(cp);
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- fd_set *fdsr = NULL, *fdsw = NULL;
- struct sockaddr_in sin;
- struct sockaddr_in lin;
- int ch, s, s2, conflisten = 0, i, omax = 0, one = 1;
- socklen_t sinlen;
- u_short port;
- struct servent *ent;
- struct rlimit rlp;
- char *bind_address = NULL;
-
- tzset();
- openlog_r("spamd", LOG_PID | LOG_NDELAY, LOG_DAEMON, &sdata);
-
- if ((ent = getservbyname("spamd", "tcp")) == NULL)
- errx(1, "Can't find service \"spamd\" in /etc/services");
- port = ntohs(ent->s_port);
- if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
- errx(1, "Can't find service \"spamd-cfg\" in /etc/services");
- cfg_port = ntohs(ent->s_port);
-
- if (gethostname(hostname, sizeof hostname) == -1)
- err(1, "gethostname");
-
-#ifdef IPFW
- while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:t:")) != -1) {
-#else
- while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:")) != -1) {
-#endif
- switch (ch) {
- case '4':
- nreply = "450";
- break;
- case '5':
- nreply = "550";
- break;
- case 'b':
- bind_address = optarg;
- break;
- case 'B':
- i = atoi(optarg);
- maxblack = i;
- break;
- case 'c':
- i = atoi(optarg);
- if (i > MAXCON)
- usage();
- maxcon = i;
- break;
- case 'p':
- i = atoi(optarg);
- port = i;
- break;
- case 'd':
- debug = 1;
- break;
- case 'g':
- greylist = 1;
- break;
- case 'G':
- if (sscanf(optarg, "%d:%d:%d", &passtime, &greyexp,
- &whiteexp) != 3)
- usage();
- /* convert to seconds from minutes */
- passtime *= 60;
- /* convert to seconds from hours */
- whiteexp *= (60 * 60);
- /* convert to seconds from hours */
- greyexp *= (60 * 60);
- break;
- case 'r':
- reply = optarg;
- break;
- case 's':
- i = atoi(optarg);
- if (i < 0 || i > 10)
- usage();
- stutter = i;
- break;
- case 'n':
- spamd = optarg;
- break;
- case 'v':
- verbose = 1;
- break;
-#ifdef IPFW
- case 't':
- tabno = atoi(optarg);
- break;
-#endif
- case 'w':
- window = atoi(optarg);
- if (window <= 0)
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- if (!greylist)
- maxblack = maxcon;
- else if (maxblack > maxcon)
- usage();
-
- rlp.rlim_cur = rlp.rlim_max = maxcon + 15;
- if (setrlimit(RLIMIT_NOFILE, &rlp) == -1)
- err(1, "setrlimit");
-
- con = calloc(maxcon, sizeof(*con));
- if (con == NULL)
- err(1, "calloc");
-
- con->obuf = malloc(8192);
-
- if (con->obuf == NULL)
- err(1, "malloc");
- con->osize = 8192;
-
- for (i = 0; i < maxcon; i++)
- con[i].fd = -1;
-
- signal(SIGPIPE, SIG_IGN);
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == -1)
- err(1, "socket");
-
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one,
- sizeof(one)) == -1)
- return (-1);
-
- conflisten = socket(AF_INET, SOCK_STREAM, 0);
- if (conflisten == -1)
- err(1, "socket");
-
- if (setsockopt(conflisten, SOL_SOCKET, SO_REUSEADDR, &one,
- sizeof(one)) == -1)
- return (-1);
-
- memset(&sin, 0, sizeof sin);
- sin.sin_len = sizeof(sin);
- if (bind_address) {
- if (inet_pton(AF_INET, bind_address, &sin.sin_addr) != 1)
- err(1, "inet_pton");
- } else
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
-
- if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1)
- err(1, "bind");
-
- memset(&lin, 0, sizeof sin);
- lin.sin_len = sizeof(sin);
- lin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- lin.sin_family = AF_INET;
- lin.sin_port = htons(cfg_port);
-
- if (bind(conflisten, (struct sockaddr *)&lin, sizeof lin) == -1)
- err(1, "bind local");
-
- pw = getpwnam("_spamd");
- if (!pw)
- pw = getpwnam("nobody");
-
- if (debug == 0) {
- if (daemon(1, 1) == -1)
- err(1, "daemon");
- }
-
- if (greylist) {
- maxblack = (maxblack >= maxcon) ? maxcon - 100 : maxblack;
- if (maxblack < 0)
- maxblack = 0;
-
- /* open pipe to talk to greylister */
- if (pipe(greypipe) == -1) {
- syslog(LOG_ERR, "pipe (%m)");
- exit(1);
- }
- /* open pipe to recieve spamtrap configs */
- if (pipe(trappipe) == -1) {
- syslog(LOG_ERR, "pipe (%m)");
- exit(1);
- }
- jail_pid = fork();
- switch(jail_pid) {
- case -1:
- syslog(LOG_ERR, "fork (%m)");
- exit(1);
- case 0:
- /* child - continue */
- grey = fdopen(greypipe[1], "w");
- if (grey == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- _exit(1);
- }
- close(greypipe[0]);
- trapfd = trappipe[0];
- trapcfg = fdopen(trappipe[0], "r");
- if (trapcfg == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- _exit(1);
- }
- close(trappipe[1]);
- goto jail;
- }
- /* parent - run greylister */
- grey = fdopen(greypipe[0], "r");
- if (grey == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- exit(1);
- }
- close(greypipe[1]);
- trapcfg = fdopen(trappipe[1], "w");
- if (trapcfg == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- exit(1);
- }
- close(trappipe[0]);
- return(greywatcher());
- /* NOTREACHED */
- }
-
-jail:
- if (chroot("/var/empty") == -1 || chdir("/") == -1) {
- syslog(LOG_ERR, "cannot chdir to /var/empty.");
- exit(1);
- }
-
- if (pw) {
- setgroups(1, &pw->pw_gid);
- setegid(pw->pw_gid);
- setgid(pw->pw_gid);
- seteuid(pw->pw_uid);
- setuid(pw->pw_uid);
- }
-
- if (listen(s, 10) == -1)
- err(1, "listen");
-
- if (listen(conflisten, 10) == -1)
- err(1, "listen");
-
- if (debug != 0)
- printf("listening for incoming connections.\n");
- syslog_r(LOG_WARNING, &sdata, "listening for incoming connections.");
-
- while (1) {
- struct timeval tv, *tvp;
- int max, i, n;
- int writers;
-
- max = MAX(s, conflisten);
- max = MAX(max, conffd);
- max = MAX(max, trapfd);
-
- time(&t);
- for (i = 0; i < maxcon; i++)
- if (con[i].fd != -1)
- max = MAX(max, con[i].fd);
-
- if (max > omax) {
- free(fdsr);
- fdsr = NULL;
- free(fdsw);
- fdsw = NULL;
- fdsr = (fd_set *)calloc(howmany(max+1, NFDBITS),
- sizeof(fd_mask));
- if (fdsr == NULL)
- err(1, "calloc");
- fdsw = (fd_set *)calloc(howmany(max+1, NFDBITS),
- sizeof(fd_mask));
- if (fdsw == NULL)
- err(1, "calloc");
- omax = max;
- } else {
- memset(fdsr, 0, howmany(max+1, NFDBITS) *
- sizeof(fd_mask));
- memset(fdsw, 0, howmany(max+1, NFDBITS) *
- sizeof(fd_mask));
- }
-
- writers = 0;
- for (i = 0; i < maxcon; i++) {
- if (con[i].fd != -1 && con[i].r) {
- if (con[i].r + MAXTIME <= t) {
- closecon(&con[i]);
- continue;
- }
- FD_SET(con[i].fd, fdsr);
- }
- if (con[i].fd != -1 && con[i].w) {
- if (con[i].w + MAXTIME <= t) {
- closecon(&con[i]);
- continue;
- }
- if (con[i].w <= t)
- FD_SET(con[i].fd, fdsw);
- writers = 1;
- }
- }
- FD_SET(s, fdsr);
-
- /* only one active config conn at a time */
- if (conffd == -1)
- FD_SET(conflisten, fdsr);
- else
- FD_SET(conffd, fdsr);
- if (trapfd != -1)
- FD_SET(trapfd, fdsr);
-
- if (writers == 0) {
- tvp = NULL;
- } else {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- tvp = &tv;
- }
-
- n = select(max+1, fdsr, fdsw, NULL, tvp);
- if (n == -1) {
- if (errno != EINTR)
- err(1, "select");
- continue;
- }
- if (n == 0)
- continue;
-
- for (i = 0; i < maxcon; i++) {
- if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsr))
- handler(&con[i]);
- if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsw))
- handlew(&con[i], clients + 5 < maxcon);
- }
- if (FD_ISSET(s, fdsr)) {
- sinlen = sizeof(sin);
- s2 = accept(s, (struct sockaddr *)&sin, &sinlen);
- if (s2 == -1)
- /* accept failed, they may try again */
- continue;
- for (i = 0; i < maxcon; i++)
- if (con[i].fd == -1)
- break;
- if (i == maxcon)
- close(s2);
- else {
- initcon(&con[i], s2, (struct sockaddr *)&sin);
- syslog_r(LOG_INFO, &sdata,
- "%s: connected (%d/%d)%s%s",
- con[i].addr, clients, blackcount,
- ((con[i].lists == NULL) ? "" :
- ", lists:"),
- ((con[i].lists == NULL) ? "":
- con[i].lists));
- }
- }
- if (FD_ISSET(conflisten, fdsr)) {
- sinlen = sizeof(lin);
- conffd = accept(conflisten, (struct sockaddr *)&lin,
- &sinlen);
- if (conffd == -1)
- /* accept failed, they may try again */
- continue;
- else if (ntohs(lin.sin_port) >= IPPORT_RESERVED) {
- close(conffd);
- conffd = -1;
- }
- }
- if (conffd != -1 && FD_ISSET(conffd, fdsr))
- do_config();
- if (trapfd != -1 && FD_ISSET(trapfd, fdsr))
- read_configline(trapcfg);
- }
- exit(1);
-}
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.c.orig /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.c.orig
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.c.orig Tue Apr 12 20:21:48 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.c.orig Thu Jan 1 03:00:00 1970
@@ -1,1305 +0,0 @@
-/* $OpenBSD: spamd.c,v 1.75 2005/03/11 23:09:53 beck Exp $ */
-
-/*
- * Copyright (c) 2002 Theo de Raadt. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <netdb.h>
-
-#include "sdl.h"
-#include "grey.h"
-
-struct con {
- int fd;
- int state;
- int laststate;
- int af;
- struct sockaddr_storage ss;
- void *ia;
- char addr[32];
- char mail[MAX_MAIL], rcpt[MAX_MAIL];
- struct sdlist **blacklists;
-
- /*
- * we will do stuttering by changing these to time_t's of
- * now + n, and only advancing when the time is in the past/now
- */
- time_t r;
- time_t w;
- time_t s;
-
- char ibuf[8192];
- char *ip;
- int il;
- char rend[5]; /* any chars in here causes input termination */
-
- char *obuf;
- char *lists;
- size_t osize;
- char *op;
- int ol;
- int data_lines;
- int data_body;
- int stutter;
- int sr;
-} *con;
-
-void usage(void);
-char *grow_obuf(struct con *, int);
-int parse_configline(char *);
-void parse_configs(void);
-void do_config(void);
-int append_error_string (struct con *, size_t, char *, int, void *);
-void build_reply(struct con *);
-void doreply(struct con *);
-void setlog(char *, size_t, char *);
-void initcon(struct con *, int, struct sockaddr *);
-void closecon(struct con *);
-int match(const char *, const char *);
-void nextstate(struct con *);
-void handler(struct con *);
-void handlew(struct con *, int one);
-
-char hostname[MAXHOSTNAMELEN];
-#ifdef __OpenBSD__
-struct syslog_data sdata = SYSLOG_DATA_INIT;
-#else
-#define syslog_r(l, s, args...) syslog(l,args)
-#define openlog_r(i, l, f, s) openlog(i, l, f)
-int sdata = 0; /* dummy */
-#endif
-char *reply = NULL;
-char *nreply = "450";
-char *spamd = "spamd IP-based SPAM blocker";
-int greypipe[2];
-int trappipe[2];
-FILE *grey;
-FILE *trapcfg;
-time_t passtime = PASSTIME;
-time_t greyexp = GREYEXP;
-time_t whiteexp = WHITEEXP;
-time_t trapexp = TRAPEXP;
-struct passwd *pw;
-pid_t jail_pid = -1;
-u_short cfg_port;
-
-extern struct sdlist *blacklists;
-
-int conffd = -1;
-int trapfd = -1;
-char *cb;
-size_t cbs, cbu;
-
-time_t t;
-
-#define MAXCON 800
-int maxcon = MAXCON;
-int maxblack = MAXCON;
-int blackcount;
-int clients;
-int debug;
-int greylist;
-int verbose;
-int stutter = 1;
-int window;
-#define MAXTIME 400
-
-void
-usage(void)
-{
- fprintf(stderr,
- "usage: spamd [-45dgv] [-B maxblack] [-b address] [-c maxcon]\n");
- fprintf(stderr,
- " [-G mins:hours:hours] [-n name] [-p port]\n");
- fprintf(stderr,
- " [-r reply] [-s secs] [-w window]\n");
- exit(1);
-}
-
-char *
-grow_obuf(struct con *cp, int off)
-{
- char *tmp;
-
- tmp = realloc(cp->obuf, cp->osize + 8192);
- if (tmp == NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- return (NULL);
- } else {
- cp->osize += 8192;
- cp->obuf = tmp;
- return (cp->obuf + off);
- }
-}
-
-int
-parse_configline(char *line)
-{
- char *cp, prev, *name, *msg;
- static char **av = NULL;
- static size_t ac = 0;
- size_t au = 0;
- int mdone = 0;
-
- name = line;
-
- for (cp = name; *cp && *cp != ';'; cp++)
- ;
- if (*cp != ';')
- goto parse_error;
- *cp++ = '\0';
- msg = cp;
- if (*cp++ != '"')
- goto parse_error;
- prev = '\0';
- for (; !mdone; cp++) {
- switch (*cp) {
- case '\\':
- if (!prev)
- prev = *cp;
- else
- prev = '\0';
- break;
- case '"':
- if (prev != '\\') {
- cp++;
- if (*cp == ';') {
- mdone = 1;
- *cp = '\0';
- } else
- goto parse_error;
- }
- break;
- case '\0':
- goto parse_error;
- default:
- prev = '\0';
- break;
- }
- }
-
- do {
- if (ac == au) {
- char **tmp;
-
- tmp = realloc(av, (ac + 2048) * sizeof(char *));
- if (tmp == NULL) {
- free(av);
- av = NULL;
- ac = 0;
- return (-1);
- }
- av = tmp;
- ac += 2048;
- }
- } while ((av[au++] = strsep(&cp, ";")) != NULL);
-
- /* toss empty last entry to allow for trailing ; */
- if (av[au - 1][0] == '\0');
- au--;
-
- if (au < 1)
- goto parse_error;
- else
- sdl_add(name, msg, av, au - 1);
- return (0);
-
-parse_error:
- if (debug > 0)
- printf("bogus config line - need 'tag;message;a/m;a/m;a/m...'\n");
- return (-1);
-}
-
-void
-parse_configs(void)
-{
- char *start, *end;
- int i;
-
- if (cbu == cbs) {
- char *tmp;
-
- tmp = realloc(cb, cbs + 8192);
- if (tmp == NULL) {
- if (debug > 0)
- perror("malloc()");
- free(cb);
- cb = NULL;
- cbs = cbu = 0;
- return;
- }
- cbs += 8192;
- cb = tmp;
- }
- cb[cbu++] = '\0';
-
- start = cb;
- end = start;
- for (i = 0; i < cbu; i++) {
- if (*end == '\n') {
- *end = '\0';
- if (end > start + 1)
- parse_configline(start);
- start = ++end;
- } else
- ++end;
- }
- if (end > start + 1)
- parse_configline(start);
-}
-
-void
-do_config(void)
-{
- int n;
-
- if (debug > 0)
- printf("got configuration connection\n");
-
- if (cbu == cbs) {
- char *tmp;
-
- tmp = realloc(cb, cbs + 8192);
- if (tmp == NULL) {
- if (debug > 0)
- perror("malloc()");
- free(cb);
- cb = NULL;
- cbs = 0;
- goto configdone;
- }
- cbs += 8192;
- cb = tmp;
- }
-
- n = read(conffd, cb + cbu, cbs - cbu);
- if (debug > 0)
- printf("read %d config bytes\n", n);
- if (n == 0) {
- parse_configs();
- goto configdone;
- } else if (n == -1) {
- if (debug > 0)
- perror("read()");
- goto configdone;
- } else
- cbu += n;
- return;
-
-configdone:
- cbu = 0;
- close(conffd);
- conffd = -1;
-}
-
-
-int
-read_configline(FILE *config)
-{
- char *buf;
- size_t len;
-
- if ((buf = fgetln(config, &len))) {
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- else
- return(-1); /* all valid lines end in \n */
- parse_configline(buf);
- } else {
- syslog_r(LOG_DEBUG, &sdata, "read_configline: fgetln (%m)");
- return(-1);
- }
- return(0);
-}
-
-int
-append_error_string(struct con *cp, size_t off, char *fmt, int af, void *ia)
-{
- char sav = '\0';
- static int lastcont = 0;
- char *c = cp->obuf + off;
- char *s = fmt;
- size_t len = cp->osize - off;
- int i = 0;
-
- if (off == 0)
- lastcont = 0;
-
- if (lastcont != 0)
- cp->obuf[lastcont] = '-';
- snprintf(c, len, "%s ", nreply);
- i += strlen(c);
- lastcont = off + i - 1;
- if (*s == '"')
- s++;
- while (*s) {
- /*
- * Make sure we at minimum, have room to add a
- * format code (4 bytes), and a v6 address(39 bytes)
- * and a byte saved in sav.
- */
- if (i >= len - 46) {
- c = grow_obuf(cp, off);
- if (c == NULL)
- return (-1);
- len = cp->osize - (off + i);
- }
-
- if (c[i-1] == '\n') {
- if (lastcont != 0)
- cp->obuf[lastcont] = '-';
- snprintf(c + i, len, "%s ", nreply);
- i += strlen(c);
- lastcont = off + i - 1;
- }
-
- switch (*s) {
- case '\\':
- case '%':
- if (!sav)
- sav = *s;
- else {
- c[i++] = sav;
- sav = '\0';
- c[i] = '\0';
- }
- break;
- case '"':
- case 'A':
- case 'n':
- if (*(s+1) == '\0') {
- break;
- }
- if (sav == '\\' && *s == 'n') {
- c[i++] = '\n';
- sav = '\0';
- c[i] = '\0';
- break;
- } else if (sav == '\\' && *s == '"') {
- c[i++] = '"';
- sav = '\0';
- c[i] = '\0';
- break;
- } else if (sav == '%' && *s == 'A') {
- inet_ntop(af, ia, c + i, (len - i));
- i += strlen(c + i);
- sav = '\0';
- break;
- }
- /* fallthrough */
- default:
- if (sav)
- c[i++] = sav;
- c[i++] = *s;
- sav = '\0';
- c[i] = '\0';
- break;
- }
- s++;
- }
- return (i);
-}
-
-char *
-loglists(struct con *cp)
-{
- static char matchlists[80];
- struct sdlist **matches;
- int s = sizeof(matchlists) - 4;
-
- matchlists[0] = '\0';
- matches = cp->blacklists;
- if (matches == NULL)
- return(NULL);
- for (; *matches; matches++) {
-
- /* don't report an insane amount of lists in the logs.
- * just truncate and indicate with ...
- */
- if (strlen(matchlists) + strlen(matches[0]->tag) + 1
- >= s)
- strlcat(matchlists, " ...", sizeof(matchlists));
- else {
- strlcat(matchlists, " ", s);
- strlcat(matchlists, matches[0]->tag, s);
- }
- }
- return matchlists;
-}
-
-void
-build_reply(struct con *cp)
-{
- struct sdlist **matches;
- int off = 0;
-
- matches = cp->blacklists;
- if (matches == NULL)
- goto nomatch;
- for (; *matches; matches++) {
- int used = 0;
- char *c = cp->obuf + off;
- int left = cp->osize - off;
-
- used = append_error_string(cp, off, matches[0]->string,
- cp->af, cp->ia);
- if (used == -1)
- goto bad;
- off += used;
- left -= used;
- if (cp->obuf[off - 1] != '\n') {
- if (left < 1) {
- c = grow_obuf(cp, off);
- if (c == NULL)
- goto bad;
- }
- cp->obuf[off++] = '\n';
- cp->obuf[off] = '\0';
- }
- }
- return;
-nomatch:
- /* No match. give generic reply */
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- if (cp->blacklists != NULL)
- asprintf(&cp->obuf,
- "%s-Sorry %s\n"
- "%s-You are trying to send mail from an address "
- "listed by one\n"
- "%s or more IP-based registries as being a SPAM source.\n",
- nreply, cp->addr, nreply, nreply);
- else
- asprintf(&cp->obuf,
- "451 Temporary failure, please try again later.\r\n");
- if (cp->obuf != NULL)
- cp->osize = strlen(cp->obuf) + 1;
- else
- cp->osize = 0;
- return;
-bad:
- if (cp->obuf != NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- }
-}
-
-void
-doreply(struct con *cp)
-{
- if (reply)
- snprintf(cp->obuf, cp->osize, "%s %s\n", nreply, reply);
- build_reply(cp);
-}
-
-void
-setlog(char *p, size_t len, char *f)
-{
- char *s;
-
- s = strsep(&f, ":");
- if (!f)
- return;
- while (*f == ' ' || *f == '\t')
- f++;
- s = strsep(&f, " \t");
- if (s == NULL)
- return;
- strlcpy(p, s, len);
- s = strsep(&p, " \t\n\r");
- if (s == NULL)
- return;
- s = strsep(&p, " \t\n\r");
- if (s)
- *s = '\0';
-}
-
-void
-initcon(struct con *cp, int fd, struct sockaddr *sa)
-{
- time_t t;
- char *tmp;
- int error;
-
- time(&t);
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- free(cp->blacklists);
- cp->blacklists = NULL;
- free(cp->lists);
- cp->lists = NULL;
- bzero(cp, sizeof(struct con));
- if (grow_obuf(cp, 0) == NULL)
- err(1, "malloc");
- cp->fd = fd;
- if (sa->sa_len > sizeof(cp->ss))
- errx(1, "sockaddr size");
- if (sa->sa_family != AF_INET)
- errx(1, "not supported yet");
- memcpy(&cp->ss, sa, sa->sa_len);
- cp->af = sa->sa_family;
- cp->ia = &((struct sockaddr_in *)sa)->sin_addr;
- cp->blacklists = sdl_lookup(blacklists, cp->af, cp->ia);
- cp->stutter = (greylist && cp->blacklists == NULL) ? 0 : stutter;
- error = getnameinfo(sa, sa->sa_len, cp->addr, sizeof(cp->addr), NULL, 0,
- NI_NUMERICHOST);
- if (error)
- errx(1, "%s", gai_strerror(error));
- tmp = strdup(ctime(&t));
- if (tmp == NULL)
- err(1, "malloc");
- tmp[strlen(tmp) - 1] = '\0'; /* nuke newline */
- snprintf(cp->obuf, cp->osize,
- "220 %s ESMTP %s; %s\r\n",
- hostname, spamd, tmp);
- free(tmp);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->s = t;
- strlcpy(cp->rend, "\n", sizeof cp->rend);
- clients++;
- if (cp->blacklists != NULL) {
- blackcount++;
- if (greylist && blackcount > maxblack) {
- closecon(cp); /* close and free */
- return;
- }
- cp->lists = strdup(loglists(cp));
- }
- else
- cp->lists = NULL;
-}
-
-void
-closecon(struct con *cp)
-{
- time_t t;
-
- time(&t);
- syslog_r(LOG_INFO, &sdata, "%s: disconnected after %ld seconds.%s%s",
- cp->addr, (long)(t - cp->s),
- ((cp->lists == NULL) ? "" : " lists:"),
- ((cp->lists == NULL) ? "": cp->lists));
- if (debug > 0)
- printf("%s connected for %ld seconds.\n", cp->addr,
- (long)(t - cp->s));
- if (cp->lists != NULL) {
- free(cp->lists);
- cp->lists = NULL;
- }
- if (cp->blacklists != NULL) {
- blackcount--;
- free(cp->blacklists);
- cp->blacklists = NULL;
- }
- if (cp->obuf != NULL) {
- free(cp->obuf);
- cp->obuf = NULL;
- cp->osize = 0;
- }
- close(cp->fd);
- clients--;
- cp->fd = -1;
-}
-
-int
-match(const char *s1, const char *s2)
-{
- return (strncasecmp(s1, s2, strlen(s2)) == 0);
-}
-
-void
-nextstate(struct con *cp)
-{
- if (match(cp->ibuf, "QUIT") && cp->state < 99) {
- snprintf(cp->obuf, cp->osize, "221 %s\r\n", hostname);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 99;
- return;
- }
-
- if (match(cp->ibuf, "RSET") && cp->state > 2 && cp->state < 50) {
- snprintf(cp->obuf, cp->osize,
- "250 Ok to start over.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 2;
- return;
- }
- switch (cp->state) {
- case 0:
- /* banner sent; wait for input */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 1;
- cp->r = t;
- break;
- case 1:
- /* received input: parse, and select next state */
- if (match(cp->ibuf, "HELO") ||
- match(cp->ibuf, "EHLO")) {
- snprintf(cp->obuf, cp->osize,
- "250 Hello, spam sender. "
- "Pleased to be wasting your time.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 2;
- cp->w = t + cp->stutter;
- break;
- }
- goto mail;
- case 2:
- /* sent 250 Hello, wait for input */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 3;
- cp->r = t;
- break;
- mail:
- case 3:
- if (match(cp->ibuf, "MAIL")) {
- setlog(cp->mail, sizeof cp->mail, cp->ibuf);
- snprintf(cp->obuf, cp->osize,
- "250 You are about to try to deliver spam. "
- "Your time will be spent, for nothing.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 4;
- cp->w = t + cp->stutter;
- break;
- }
- goto rcpt;
- case 4:
- /* sent 250 Sender ok */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 5;
- cp->r = t;
- break;
- rcpt:
- case 5:
- if (match(cp->ibuf, "RCPT")) {
- setlog(cp->rcpt, sizeof(cp->rcpt), cp->ibuf);
- snprintf(cp->obuf, cp->osize,
- "250 This is hurting you more than it is "
- "hurting me.\r\n");
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->laststate = cp->state;
- cp->state = 6;
- cp->w = t + cp->stutter;
- if (cp->mail[0] && cp->rcpt[0]) {
- if (verbose)
- syslog_r(LOG_INFO, &sdata,
- "(%s) %s: %s -> %s",
- cp->blacklists ? "BLACK" : "GREY",
- cp->addr, cp->mail,
- cp->rcpt);
- if (debug)
- fprintf(stderr, "(%s) %s: %s -> %s\n",
- cp->blacklists ? "BLACK" : "GREY",
- cp->addr, cp->mail, cp->rcpt);
- if (greylist && cp->blacklists == NULL) {
- /* send this info to the greylister */
- fprintf(grey, "IP:%s\nFR:%s\nTO:%s\n",
- cp->addr, cp->mail, cp->rcpt);
- fflush(grey);
- cp->laststate = cp->state;
- cp->state = 98;
- goto done;
- }
- }
- break;
- }
- goto spam;
- case 6:
- /* sent 250 blah */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 5;
- cp->r = t;
- break;
-
- spam:
- case 50:
- if (match(cp->ibuf, "DATA")) {
- snprintf(cp->obuf, cp->osize,
- "354 Enter spam, end with \".\" on a line by "
- "itself\r\n");
- cp->state = 60;
- if (window && setsockopt(cp->fd, SOL_SOCKET, SO_RCVBUF,
- &window, sizeof(window)) == -1) {
- syslog_r(LOG_DEBUG, &sdata,"setsockopt: %m");
- /* don't fail if this doesn't work. */
- }
- } else {
- snprintf(cp->obuf, cp->osize,
- "500 5.5.1 Command unrecognized\r\n");
- cp->state = cp->laststate;
- }
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- break;
- case 60:
- /* sent 354 blah */
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->laststate = cp->state;
- cp->state = 70;
- cp->r = t;
- break;
- case 70: {
- char *p, *q;
-
- for (p = q = cp->ibuf; q <= cp->ip; ++q)
- if (*q == '\n' || q == cp->ip) {
- *q = 0;
- if (q > p && q[-1] == '\r')
- q[-1] = 0;
- if (!strcmp(p, ".") ||
- (cp->data_body && ++cp->data_lines >= 10)) {
- cp->laststate = cp->state;
- cp->state = 98;
- goto done;
- }
- if (!cp->data_body && !*p)
- cp->data_body = 1;
- if (verbose && cp->data_body && *p)
- syslog_r(LOG_DEBUG, &sdata, "%s: "
- "Body: %s", cp->addr, p);
- else if (verbose && (match(p, "FROM:") ||
- match(p, "TO:") || match(p, "SUBJECT:")))
- syslog_r(LOG_INFO, &sdata, "%s: %s",
- cp->addr, p);
- p = ++q;
- }
- cp->ip = cp->ibuf;
- cp->il = sizeof(cp->ibuf) - 1;
- cp->r = t;
- break;
- }
- done:
- case 98:
- doreply(cp);
- cp->op = cp->obuf;
- cp->ol = strlen(cp->op);
- cp->w = t + cp->stutter;
- cp->laststate = cp->state;
- cp->state = 99;
- break;
- case 99:
- closecon(cp);
- break;
- default:
- errx(1, "illegal state %d", cp->state);
- break;
- }
-}
-
-void
-handler(struct con *cp)
-{
- int end = 0;
- int n;
-
- if (cp->r) {
- n = read(cp->fd, cp->ip, cp->il);
- if (n == 0)
- closecon(cp);
- else if (n == -1) {
- if (debug > 0)
- perror("read()");
- closecon(cp);
- } else {
- cp->ip[n] = '\0';
- if (cp->rend[0])
- if (strpbrk(cp->ip, cp->rend))
- end = 1;
- cp->ip += n;
- cp->il -= n;
- }
- }
- if (end || cp->il == 0) {
- while (cp->ip > cp->ibuf &&
- (cp->ip[-1] == '\r' || cp->ip[-1] == '\n'))
- cp->ip--;
- *cp->ip = '\0';
- cp->r = 0;
- nextstate(cp);
- }
-}
-
-void
-handlew(struct con *cp, int one)
-{
- int n;
-
- if (cp->w) {
- if (*cp->op == '\n' && !cp->sr) {
- /* insert \r before \n */
- n = write(cp->fd, "\r", 1);
- if (n == 0) {
- closecon(cp);
- goto handled;
- } else if (n == -1) {
- if (debug > 0 && errno != EPIPE)
- perror("write()");
- closecon(cp);
- goto handled;
- }
- }
- if (*cp->op == '\r')
- cp->sr = 1;
- else
- cp->sr = 0;
- n = write(cp->fd, cp->op, (one && cp->stutter) ? 1 : cp->ol);
- if (n == 0)
- closecon(cp);
- else if (n == -1) {
- if (debug > 0 && errno != EPIPE)
- perror("write()");
- closecon(cp);
- } else {
- cp->op += n;
- cp->ol -= n;
- }
- }
-handled:
- cp->w = t + cp->stutter;
- if (cp->ol == 0) {
- cp->w = 0;
- nextstate(cp);
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- fd_set *fdsr = NULL, *fdsw = NULL;
- struct sockaddr_in sin;
- struct sockaddr_in lin;
- int ch, s, s2, conflisten = 0, i, omax = 0, one = 1;
- socklen_t sinlen;
- u_short port;
- struct servent *ent;
- struct rlimit rlp;
- char *bind_address = NULL;
-
- tzset();
- openlog_r("spamd", LOG_PID | LOG_NDELAY, LOG_DAEMON, &sdata);
-
- if ((ent = getservbyname("spamd", "tcp")) == NULL)
- errx(1, "Can't find service \"spamd\" in /etc/services");
- port = ntohs(ent->s_port);
- if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
- errx(1, "Can't find service \"spamd-cfg\" in /etc/services");
- cfg_port = ntohs(ent->s_port);
-
- if (gethostname(hostname, sizeof hostname) == -1)
- err(1, "gethostname");
-
- while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:")) != -1) {
- switch (ch) {
- case '4':
- nreply = "450";
- break;
- case '5':
- nreply = "550";
- break;
- case 'b':
- bind_address = optarg;
- break;
- case 'B':
- i = atoi(optarg);
- maxblack = i;
- break;
- case 'c':
- i = atoi(optarg);
- if (i > MAXCON)
- usage();
- maxcon = i;
- break;
- case 'p':
- i = atoi(optarg);
- port = i;
- break;
- case 'd':
- debug = 1;
- break;
- case 'g':
- greylist = 1;
- break;
- case 'G':
- if (sscanf(optarg, "%d:%d:%d", &passtime, &greyexp,
- &whiteexp) != 3)
- usage();
- /* convert to seconds from minutes */
- passtime *= 60;
- /* convert to seconds from hours */
- whiteexp *= (60 * 60);
- /* convert to seconds from hours */
- greyexp *= (60 * 60);
- break;
- case 'r':
- reply = optarg;
- break;
- case 's':
- i = atoi(optarg);
- if (i < 0 || i > 10)
- usage();
- stutter = i;
- break;
- case 'n':
- spamd = optarg;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'w':
- window = atoi(optarg);
- if (window <= 0)
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- if (!greylist)
- maxblack = maxcon;
- else if (maxblack > maxcon)
- usage();
-
- rlp.rlim_cur = rlp.rlim_max = maxcon + 15;
- if (setrlimit(RLIMIT_NOFILE, &rlp) == -1)
- err(1, "setrlimit");
-
- con = calloc(maxcon, sizeof(*con));
- if (con == NULL)
- err(1, "calloc");
-
- con->obuf = malloc(8192);
-
- if (con->obuf == NULL)
- err(1, "malloc");
- con->osize = 8192;
-
- for (i = 0; i < maxcon; i++)
- con[i].fd = -1;
-
- signal(SIGPIPE, SIG_IGN);
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == -1)
- err(1, "socket");
-
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one,
- sizeof(one)) == -1)
- return (-1);
-
- conflisten = socket(AF_INET, SOCK_STREAM, 0);
- if (conflisten == -1)
- err(1, "socket");
-
- if (setsockopt(conflisten, SOL_SOCKET, SO_REUSEADDR, &one,
- sizeof(one)) == -1)
- return (-1);
-
- memset(&sin, 0, sizeof sin);
- sin.sin_len = sizeof(sin);
- if (bind_address) {
- if (inet_pton(AF_INET, bind_address, &sin.sin_addr) != 1)
- err(1, "inet_pton");
- } else
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
-
- if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1)
- err(1, "bind");
-
- memset(&lin, 0, sizeof sin);
- lin.sin_len = sizeof(sin);
- lin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- lin.sin_family = AF_INET;
- lin.sin_port = htons(cfg_port);
-
- if (bind(conflisten, (struct sockaddr *)&lin, sizeof lin) == -1)
- err(1, "bind local");
-
- pw = getpwnam("_spamd");
- if (!pw)
- pw = getpwnam("nobody");
-
- if (debug == 0) {
- if (daemon(1, 1) == -1)
- err(1, "daemon");
- }
-
- if (greylist) {
- maxblack = (maxblack >= maxcon) ? maxcon - 100 : maxblack;
- if (maxblack < 0)
- maxblack = 0;
-
- /* open pipe to talk to greylister */
- if (pipe(greypipe) == -1) {
- syslog(LOG_ERR, "pipe (%m)");
- exit(1);
- }
- /* open pipe to recieve spamtrap configs */
- if (pipe(trappipe) == -1) {
- syslog(LOG_ERR, "pipe (%m)");
- exit(1);
- }
- jail_pid = fork();
- switch(jail_pid) {
- case -1:
- syslog(LOG_ERR, "fork (%m)");
- exit(1);
- case 0:
- /* child - continue */
- grey = fdopen(greypipe[1], "w");
- if (grey == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- _exit(1);
- }
- close(greypipe[0]);
- trapfd = trappipe[0];
- trapcfg = fdopen(trappipe[0], "r");
- if (trapcfg == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- _exit(1);
- }
- close(trappipe[1]);
- goto jail;
- }
- /* parent - run greylister */
- grey = fdopen(greypipe[0], "r");
- if (grey == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- exit(1);
- }
- close(greypipe[1]);
- trapcfg = fdopen(trappipe[1], "w");
- if (trapcfg == NULL) {
- syslog(LOG_ERR, "fdopen (%m)");
- exit(1);
- }
- close(trappipe[0]);
- return(greywatcher());
- /* NOTREACHED */
- }
-
-jail:
- if (chroot("/var/empty") == -1 || chdir("/") == -1) {
- syslog(LOG_ERR, "cannot chdir to /var/empty.");
- exit(1);
- }
-
- if (pw) {
- setgroups(1, &pw->pw_gid);
- setegid(pw->pw_gid);
- setgid(pw->pw_gid);
- seteuid(pw->pw_uid);
- setuid(pw->pw_uid);
- }
-
- if (listen(s, 10) == -1)
- err(1, "listen");
-
- if (listen(conflisten, 10) == -1)
- err(1, "listen");
-
- if (debug != 0)
- printf("listening for incoming connections.\n");
- syslog_r(LOG_WARNING, &sdata, "listening for incoming connections.");
-
- while (1) {
- struct timeval tv, *tvp;
- int max, i, n;
- int writers;
-
- max = MAX(s, conflisten);
- max = MAX(max, conffd);
- max = MAX(max, trapfd);
-
- time(&t);
- for (i = 0; i < maxcon; i++)
- if (con[i].fd != -1)
- max = MAX(max, con[i].fd);
-
- if (max > omax) {
- free(fdsr);
- fdsr = NULL;
- free(fdsw);
- fdsw = NULL;
- fdsr = (fd_set *)calloc(howmany(max+1, NFDBITS),
- sizeof(fd_mask));
- if (fdsr == NULL)
- err(1, "calloc");
- fdsw = (fd_set *)calloc(howmany(max+1, NFDBITS),
- sizeof(fd_mask));
- if (fdsw == NULL)
- err(1, "calloc");
- omax = max;
- } else {
- memset(fdsr, 0, howmany(max+1, NFDBITS) *
- sizeof(fd_mask));
- memset(fdsw, 0, howmany(max+1, NFDBITS) *
- sizeof(fd_mask));
- }
-
- writers = 0;
- for (i = 0; i < maxcon; i++) {
- if (con[i].fd != -1 && con[i].r) {
- if (con[i].r + MAXTIME <= t) {
- closecon(&con[i]);
- continue;
- }
- FD_SET(con[i].fd, fdsr);
- }
- if (con[i].fd != -1 && con[i].w) {
- if (con[i].w + MAXTIME <= t) {
- closecon(&con[i]);
- continue;
- }
- if (con[i].w <= t)
- FD_SET(con[i].fd, fdsw);
- writers = 1;
- }
- }
- FD_SET(s, fdsr);
-
- /* only one active config conn at a time */
- if (conffd == -1)
- FD_SET(conflisten, fdsr);
- else
- FD_SET(conffd, fdsr);
- if (trapfd != -1)
- FD_SET(trapfd, fdsr);
-
- if (writers == 0) {
- tvp = NULL;
- } else {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- tvp = &tv;
- }
-
- n = select(max+1, fdsr, fdsw, NULL, tvp);
- if (n == -1) {
- if (errno != EINTR)
- err(1, "select");
- continue;
- }
- if (n == 0)
- continue;
-
- for (i = 0; i < maxcon; i++) {
- if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsr))
- handler(&con[i]);
- if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsw))
- handlew(&con[i], clients + 5 < maxcon);
- }
- if (FD_ISSET(s, fdsr)) {
- sinlen = sizeof(sin);
- s2 = accept(s, (struct sockaddr *)&sin, &sinlen);
- if (s2 == -1)
- /* accept failed, they may try again */
- continue;
- for (i = 0; i < maxcon; i++)
- if (con[i].fd == -1)
- break;
- if (i == maxcon)
- close(s2);
- else {
- initcon(&con[i], s2, (struct sockaddr *)&sin);
- syslog_r(LOG_INFO, &sdata,
- "%s: connected (%d/%d)%s%s",
- con[i].addr, clients, blackcount,
- ((con[i].lists == NULL) ? "" :
- ", lists:"),
- ((con[i].lists == NULL) ? "":
- con[i].lists));
- }
- }
- if (FD_ISSET(conflisten, fdsr)) {
- sinlen = sizeof(lin);
- conffd = accept(conflisten, (struct sockaddr *)&lin,
- &sinlen);
- if (conffd == -1)
- /* accept failed, they may try again */
- continue;
- else if (ntohs(lin.sin_port) >= IPPORT_RESERVED) {
- close(conffd);
- conffd = -1;
- }
- }
- if (conffd != -1 && FD_ISSET(conffd, fdsr))
- do_config();
- if (trapfd != -1 && FD_ISSET(trapfd, fdsr))
- read_configline(trapcfg);
- }
- exit(1);
-}
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd/spamd.o and /usr/home/samm/spamd/work/spamd_3.7/spamd/spamd.o differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/Makefile /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/Makefile
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/Makefile Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/Makefile Thu Jan 1 03:00:00 1970
@@ -1,12 +0,0 @@
-# $OpenBSD: Makefile,v 1.3 2004/01/21 08:07:41 deraadt Exp $
-
-PROG= spamd-setup
-SRCS= spamd-setup.c
-MAN= spamd-setup.8
-
-LDADD= -lz
-DPADD= ${LIBZ}
-
-CFLAGS+= -Wall -Wstrict-prototypes -ansi -D_NO_NAMESPACE_POLLUTION
-
-.include <bsd.prog.mk>
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup and /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8 /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8 Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8 Thu Jan 1 03:00:00 1970
@@ -1,95 +0,0 @@
-.\" $OpenBSD: spamd-setup.8,v 1.9 2004/01/29 17:41:00 jmc Exp $
-.\"
-.\" Copyright (c) 2003 Jason L. Wright (jason at thought.net)
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd February 14, 2003
-.Dt SPAMD-SETUP 8
-.Os
-.Sh NAME
-.Nm spamd-setup
-.Nd parse and load file of spammer addresses
-.Sh SYNOPSIS
-.Nm spamd-setup
-.Op Fl dn
-.Sh DESCRIPTION
-The
-.Nm
-utility adds blacklists by adding addresses to the
-.Xr pf 4
-table
-.Em <spamd> ,
-as well as configuring mail rejection messages for
-the added list of addresses in
-.Xr spamd 8 .
-The
-.Em spamd
-table is used in conjunction with a
-.Xr pf 4
-redirection rule to selectively redirect mail connections
-to the
-.Xr spamd 8
-daemon.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl d
-Debug mode reports a few pieces of information.
-.It Fl n
-Dry-run mode.
-No data is shipped to
-.Xr pf 4 .
-.El
-.Pp
-Blacklists and whitelists are specified in the configuration file
-.Pa /usr/local/etc/spamd.conf
-and are processed in the order specified in the
-.Ar all
-tag.
-Output is concatenated to build up a table for
-.Xr pf 4 .
-Then the blacklist addresses are sent to a running
-.Xr spamd 8
-along with the message spamd will give on mail rejection when a
-matching client connects.
-The configuration port for
-.Xr spamd 8
-is found from
-.Xr services 5 ,
-by looking for the named service
-.Em spamd-cfg .
-.Pp
-.Nm
-reads all configuration information from a
-.Xr spamd.conf 5
-file.
-.Sh FILES
-.Bd -literal
-/usr/local/etc/spamd.conf
-.Ed
-.Sh SEE ALSO
-.Xr ftp 1 ,
-.Xr pf 4 ,
-.Xr services 5 ,
-.Xr spamd.conf 5 ,
-.Xr spamd 8
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.bak /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.bak
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.bak Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.bak Thu Jan 1 03:00:00 1970
@@ -1,95 +0,0 @@
-.\" $OpenBSD: spamd-setup.8,v 1.9 2004/01/29 17:41:00 jmc Exp $
-.\"
-.\" Copyright (c) 2003 Jason L. Wright (jason at thought.net)
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd February 14, 2003
-.Dt SPAMD-SETUP 8
-.Os
-.Sh NAME
-.Nm spamd-setup
-.Nd parse and load file of spammer addresses
-.Sh SYNOPSIS
-.Nm spamd-setup
-.Op Fl dn
-.Sh DESCRIPTION
-The
-.Nm
-utility adds blacklists by adding addresses to the
-.Xr pf 4
-table
-.Em <spamd> ,
-as well as configuring mail rejection messages for
-the added list of addresses in
-.Xr spamd 8 .
-The
-.Em spamd
-table is used in conjunction with a
-.Xr pf 4
-redirection rule to selectively redirect mail connections
-to the
-.Xr spamd 8
-daemon.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl d
-Debug mode reports a few pieces of information.
-.It Fl n
-Dry-run mode.
-No data is shipped to
-.Xr pf 4 .
-.El
-.Pp
-Blacklists and whitelists are specified in the configuration file
-.Pa /etc/spamd.conf
-and are processed in the order specified in the
-.Ar all
-tag.
-Output is concatenated to build up a table for
-.Xr pf 4 .
-Then the blacklist addresses are sent to a running
-.Xr spamd 8
-along with the message spamd will give on mail rejection when a
-matching client connects.
-The configuration port for
-.Xr spamd 8
-is found from
-.Xr services 5 ,
-by looking for the named service
-.Em spamd-cfg .
-.Pp
-.Nm
-reads all configuration information from a
-.Xr spamd.conf 5
-file.
-.Sh FILES
-.Bd -literal
-/etc/spamd.conf
-.Ed
-.Sh SEE ALSO
-.Xr ftp 1 ,
-.Xr pf 4 ,
-.Xr services 5 ,
-.Xr spamd.conf 5 ,
-.Xr spamd 8
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.gz and /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.8.gz differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c Thu Jan 1 03:00:00 1970
@@ -1,924 +0,0 @@
-/* $OpenBSD: spamd-setup.c,v 1.21 2005/03/02 16:45:30 dhartmei Exp $ */
-
-/*
- * Copyright (c) 2003 Bob Beck. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <err.h>
-#ifdef __OpenBSD__
-#include <netinet/ip_ipsp.h>
-#endif
-#include <netdb.h>
-#include <zlib.h>
-
-#ifdef IPFW
-#include <net/if.h>
-#include <netinet/ip_fw.h>
-#endif
-
-#define PATH_FTP "/usr/bin/ftp"
-#define PATH_PFCTL ""
-#define PATH_SPAMD_CONF "/usr/local/etc/spamd.conf"
-#define SPAMD_ARG_MAX 256 /* max # of args to an exec */
-
-struct cidr {
- u_int32_t addr;
- u_int8_t bits;
-};
-
-struct bl {
- u_int32_t addr;
- int8_t b;
- int8_t w;
-};
-
-struct blacklist {
- char *name;
- char *message;
- struct bl *bl;
- size_t blc, bls;
- u_int8_t black;
- int count;
-};
-
-u_int32_t imask(u_int8_t b);
-u_int8_t maxblock(u_int32_t addr, u_int8_t bits);
-u_int8_t maxdiff(u_int32_t a, u_int32_t b);
-struct cidr *range2cidrlist(u_int32_t start, u_int32_t end);
-void cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end);
-char *atop(u_int32_t addr);
-u_int32_t ptoa(char *cp);
-int parse_netblock(char *buf, struct bl *start, struct bl *end,
- int white);
-int open_child(char *file, char **argv);
-int fileget(char *url);
-int open_file(char *method, char *file);
-char *fix_quoted_colons(char *buf);
-void do_message(FILE *sdc, char *msg);
-struct bl *add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf,
- int white);
-int cmpbl(const void *a, const void *b);
-struct cidr **collapse_blacklist(struct bl *bl, int blc);
-int configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists);
-int configure_pf(struct cidr **blacklists);
-int getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew);
-
-int debug;
-int dryrun;
-
-#ifdef IPFW
-int tabno=2;
-#endif
-
-
-u_int32_t
-imask(u_int8_t b)
-{
- u_int32_t j = 0;
- int i;
-
- for (i = 31; i > 31 - b; --i)
- j |= (1 << i);
- return(j);
-}
-
-u_int8_t
-maxblock(u_int32_t addr, u_int8_t bits)
-{
- while (bits > 0) {
- u_int32_t m = imask(bits - 1);
-
- if ((addr & m) != addr)
- return (bits);
- bits--;
- }
- return(bits);
-}
-
-u_int8_t
-maxdiff(u_int32_t a, u_int32_t b)
-{
- u_int8_t bits = 0;
-
- b++;
- while (bits < 32) {
- u_int32_t m = imask(bits);
-
- if ((a & m) != (b & m))
- return (bits);
- bits++;
- }
- return(bits);
-}
-
-struct cidr *
-range2cidrlist(u_int32_t start, u_int32_t end)
-{
- struct cidr *list = NULL;
- size_t cs = 0, cu = 0;
-
- while (end >= start) {
- u_int8_t maxsize = maxblock(start, 32);
- u_int8_t diff = maxdiff(start, end);
-
- maxsize = MAX(maxsize, diff);
- if (cs == cu) {
- struct cidr *tmp;
-
- tmp = realloc(list, (cs + 32) * sizeof(struct cidr));
- if (tmp == NULL)
- errx(1, "malloc failed");
- list = tmp;
- cs += 32;
- }
- list[cu].addr = start;
- list[cu].bits = maxsize;
- cu++;
- list[cu].addr = 0;
- list[cu].bits = 0;
- start = start + (1 << (32 - maxsize));
- }
- return(list);
-}
-
-void
-cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end)
-{
- *start = cidr.addr;
- *end = cidr.addr + (1 << (32 - cidr.bits)) - 1;
-}
-
-char *
-atop(u_int32_t addr)
-{
- struct in_addr in;
-
- memset(&in, 0, sizeof(in));
- in.s_addr = htonl(addr);
- return(inet_ntoa(in));
-}
-
-int
-parse_netblock(char *buf, struct bl *start, struct bl *end, int white)
-{
- char astring[16], astring2[16];
- unsigned maskbits;
-
- /* skip leading spaces */
- while (*buf == ' ')
- buf++;
- /* bail if it's a comment */
- if (*buf == '#')
- return(0);
- /* otherwise, look for a netblock of some sort */
- if (sscanf(buf, "%15[^/]/%u", astring, &maskbits) == 2) {
- /* looks like a cidr */
- struct cidr c;
-
- memset(&c.addr, 0, sizeof(c.addr));
- if (inet_net_pton(AF_INET, astring, &c.addr, sizeof(c.addr))
- == -1)
- return(0);
- c.addr = ntohl(c.addr);
- if (maskbits > 32)
- return(0);
- c.bits = maskbits;
- cidr2range(c, &start->addr, &end->addr);
- end->addr += 1;
- } else if (sscanf(buf, "%15[0123456789.]%*[ -]%15[0123456789.]",
- astring, astring2) == 2) {
- /* looks like start - end */
- memset(&start->addr, 0, sizeof(start->addr));
- memset(&end->addr, 0, sizeof(end->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- if (inet_net_pton(AF_INET, astring2, &end->addr,
- sizeof(end->addr)) == -1)
- return(0);
- end->addr = ntohl(end->addr) + 1;
- if (start > end)
- return(0);
- } else if (sscanf(buf, "%15[0123456789.]", astring) == 1) {
- /* just a single address */
- memset(&start->addr, 0, sizeof(start->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- end->addr = start->addr + 1;
- } else
- return(0);
-
- if (white) {
- start->b = 0;
- start->w = 1;
- end->b = 0;
- end->w = -1;
- } else {
- start->b = 1;
- start->w = 0;
- end->b = -1;
- end->w = 0;
- }
- return(1);
-}
-
-int
-open_child(char *file, char **argv)
-{
- int pdes[2];
-
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[0]);
- if (pdes[1] != STDOUT_FILENO) {
- dup2(pdes[1], STDOUT_FILENO);
- close(pdes[1]);
- }
- execvp(file, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[1]);
- return(pdes[0]);
-}
-
-int
-fileget(char *url)
-{
- char *argv[6];
-
- argv[0] = "ftp";
- argv[1] = "-V";
- argv[2] = "-o";
- argv[3] = "-";
- argv[4] = url;
- argv[5] = NULL;
-
- if (debug)
- fprintf(stderr, "Getting %s\n", url);
-
- return open_child(PATH_FTP, argv);
-}
-
-int
-open_file(char *method, char *file)
-{
- char *url;
-
- if ((method == NULL) || (strcmp(method, "file") == 0))
- return(open(file, O_RDONLY));
- if ((strcmp(method, "http") == 0) ||
- strcmp(method, "ftp") == 0) {
- int i;
-
- asprintf(&url, "%s://%s", method, file);
- if (url == NULL)
- return(-1);
- i = fileget(url);
- free(url);
- return(i);
- } else if (strcmp(method, "exec") == 0) {
- char **ap, **argv;
- int len, i, oerrno;
-
- len = strlen(file);
- argv = malloc(len * sizeof(char *));
- if (argv == NULL)
- errx(1, "malloc failed");
- for (ap = argv; ap < &argv[len - 1] &&
- (*ap = strsep(&file, " \t")) != NULL;) {
- if (**ap != '\0')
- ap++;
- }
- *ap = NULL;
- i = open_child(argv[0], argv);
- oerrno = errno;
- free(argv);
- errno = oerrno;
- return(i);
- }
- errx(1, "Unknown method %s", method);
- return(-1); /* NOTREACHED */
-}
-
-/*
- * fix_quoted_colons walks through a buffer returned by cgetent. We
- * look for quoted strings, to escape colons (:) in quoted strings for
- * getcap by replacing them with \C so cgetstr() deals with it correctly
- * without having to see the \C bletchery in a configuration file that
- * needs to have urls in it. Frees the buffer passed to it, passes back
- * another larger one, with can be used with cgetxxx(), like the original
- * buffer, it must be freed by the caller.
- * This should really be a temporary fix until there is a sanctioned
- * way to make getcap(3) handle quoted strings like this in a nicer
- * way.
- */
-char *
-fix_quoted_colons(char *buf)
-{
- int nbs = 0, i = 0, j = 0, in = 0;
- char *newbuf, last;
-
- nbs = strlen(buf) + 128;
- newbuf = malloc(nbs);
- if (newbuf == NULL)
- return NULL;
- last = '\0';
- for (i = 0; i < strlen(buf); i++) {
- switch (buf[i]) {
- case ':':
- if (in) {
- newbuf[j++] = '\\';
- newbuf[j++] = 'C';
- } else
- newbuf[j++] = buf[i];
- break;
- case '"':
- if (last != '\\')
- in = !in;
- newbuf[j++] = buf[i];
- break;
- default:
- newbuf[j++] = buf[i];
- }
- if (j == nbs) {
- char *tmp;
-
- nbs += 128;
- tmp = realloc(newbuf, nbs);
- if (tmp == NULL)
- errx(1, "malloc failed");
- newbuf = tmp;
- }
- }
- free(buf);
- newbuf[j] = '\0';
- return(newbuf);
-}
-
-void
-do_message(FILE *sdc, char *msg)
-{
- int i, n, bu = 0, bs = 0, len;
- char *buf = NULL, last;
-
- len = strlen(msg);
- if (msg[0] == '"' && msg[len - 1] == '"') {
- /* quoted msg, escape newlines and send it out */
- msg[len - 1] = '\0';
- buf = msg+1;
- bu = len - 2;
- goto sendit;
- } else {
- int fd;
-
- /*
- * message isn't quoted - try to open a local
- * file and read the message from it.
- */
- fd = open(msg, O_RDONLY);
- if (fd == -1)
- err(1, "Can't open message from %s", msg);
- for (;;) {
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192);
- if (tmp == NULL)
- errx(1, "malloc failed");
- bs += 8192;
- buf = tmp;
- }
-
- n = read(fd, buf + bu, bs - bu);
- if (n == 0) {
- goto sendit;
- } else if (n == -1) {
- err(1, "Can't read from %s", msg);
- } else
- bu += n;
- }
- buf[bu]='\0';
- }
- sendit:
- fprintf(sdc, ";\"");
- last = '\0';
- for (i = 0; i < bu; i++) {
- /* handle escaping the things spamd wants */
- switch (buf[i]) {
- case 'n':
- if (last == '\\')
- fprintf(sdc, "\\\\n");
- else
- fputc('n', sdc);
- last = '\0';
- break;
- case '\n':
- fprintf(sdc, "\\n");
- last = '\0';
- break;
- case '"':
- fputc('\\', sdc);
- /* fall through */
- default:
- fputc(buf[i], sdc);
- last = '\0';
- }
- }
- fputc('"', sdc);
- if (bs != 0)
- free(buf);
-}
-
-/* retrieve a list from fd. add to blacklist bl */
-struct bl *
-add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf, int white)
-{
- int i, n, start, bu = 0, bs = 0, serrno = 0;
- char *buf = NULL;
-
- for (;;) {
- /* read in gzf, then parse */
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192 + 1);
- if (tmp == NULL) {
- free(buf);
- buf = NULL;
- bs = 0;
- serrno = errno;
- goto bldone;
- }
- bs += 8192;
- buf = tmp;
- }
-
- n = gzread(gzf, buf + bu, bs - bu);
- if (n == 0)
- goto parse;
- else if (n == -1) {
- serrno = errno;
- goto bldone;
- } else
- bu += n;
- }
- parse:
- start = 0;
- for (i = 0; i <= bu; i++) {
- if (*blc == *bls) {
- struct bl *tmp;
-
- *bls += 1024;
- tmp = realloc(bl, *bls * sizeof(struct bl));
- if (tmp == NULL) {
- *bls -= 1024;
- serrno = errno;
- goto bldone;
- }
- bl = tmp;
- }
- if (i == bu || buf[i] == '\n') {
- buf[i] = '\0';
- if (parse_netblock(buf + start,
- bl + *blc, bl + *blc + 1, white))
- *blc+=2;
- start = i+1;
- }
- }
- if (bu == 0)
- errno = EIO;
- bldone:
- if (buf)
- free(buf);
- if (serrno)
- errno = serrno;
- return (bl);
-}
-
-int
-cmpbl(const void *a, const void *b)
-{
- if (((struct bl *)a)->addr > ((struct bl *) b)->addr)
- return(1);
- if (((struct bl *)a)->addr < ((struct bl *) b)->addr)
- return(-1);
- return(0);
-}
-
-/*
- * collapse_blacklist takes blacklist/whitelist entries sorts, removes
- * overlaps and whitelist portions, and returns netblocks to blacklist
- * as lists of nonoverlapping cidr blocks suitable for feeding in
- * printable form to pfctl or spamd.
- */
-struct cidr **
-collapse_blacklist(struct bl *bl, int blc)
-{
- int bs = 0, ws = 0, state=0, cli, i;
- u_int32_t bstart = 0;
- struct cidr **cl;
-
- if (blc == 0)
- return(NULL);
- cl = malloc((blc / 2) * sizeof(struct cidr));
- if (cl == NULL) {
- return (NULL);
- }
- qsort(bl, blc, sizeof(struct bl), cmpbl);
- cli = 0;
- cl[cli] = NULL;
- for (i = 0; i < blc;) {
- int laststate = state;
- u_int32_t addr = bl[i].addr;
-
- do {
- bs += bl[i].b;
- ws += bl[i].w;
- i++;
- } while (bl[i].addr == addr);
- if (state == 1 && bs == 0)
- state = 0;
- else if (state == 0 && bs > 0)
- state = 1;
- if (ws > 0)
- state = 0;
- if (laststate == 0 && state == 1) {
- /* start blacklist */
- bstart = addr;
- }
- if (laststate == 1 && state == 0) {
- /* end blacklist */
- cl[cli++] = range2cidrlist(bstart, addr - 1);
- cl[cli] = NULL;
- }
- laststate = state;
- }
- return (cl);
-}
-
-int
-configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists)
-{
- int lport = IPPORT_RESERVED - 1, s;
- struct sockaddr_in sin;
- FILE* sdc;
-
- s = rresvport(&lport);
- if (s == -1)
- return(-1);
- memset(&sin, 0, sizeof sin);
- sin.sin_len = sizeof(sin);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(dport);
- if (connect(s, (struct sockaddr *)&sin, sizeof sin) == -1)
- return(-1);
- sdc = fdopen(s, "w");
- if (sdc == NULL) {
- close(s);
- return(-1);
- }
- fprintf(sdc, "%s", name);
- do_message(sdc, message);
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
- while (b->addr != 0) {
- fprintf(sdc, ";%s/%u", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- fputc('\n', sdc);
- fclose(sdc);
- close(s);
- return(0);
-}
-
-
-#ifndef IPFW
-int
-configure_pf(struct cidr **blacklists)
-{
- char *argv[9]= {"pfctl", "-q", "-t", "spamd", "-T", "replace",
- "-f" "-", NULL};
- static FILE *pf = NULL;
- int pdes[2];
-
- if (pf == NULL) {
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- dup2(pdes[0], STDIN_FILENO);
- close(pdes[0]);
- }
- execvp(PATH_PFCTL, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[0]);
- pf = fdopen(pdes[1], "w");
- if (pf == NULL) {
- close(pdes[1]);
- return(-1);
- }
- }
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
-
- while (b->addr != 0) {
- fprintf(pf, "%s/%u\n", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- return(0);
-}
-#else
-int
-configure_pf(struct cidr **blacklists)
-{
- static int s = -1;
- ipfw_table_entry ent;
-
- if (s == -1)
- s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- if (s < 0)
- {
- err(1, "IPFW socket unavailable");
- return(-1);
- }
-
- /* flush the table */
- ent.tbl = tabno;
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
- {
- err(1, "IPFW setsockopt(IP_FW_TABLE_FLUSH)");
- return(-1);
- }
-
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
-
- while (b->addr != 0) {
- /* add b to tabno */
- ent.tbl = tabno;
- ent.masklen = b->bits;
- ent.value = 0;
- inet_aton(atop(b->addr), (struct in_addr *)&ent.addr);
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD, &ent, sizeof(ent)) < 0)
- {
- err(1, "IPFW setsockopt(IP_FW_TABLE_ADD)");
- return(-1);
- }
- b++;
- }
- blacklists++;
- }
-
- return(0);
-}
-#endif
-
-int
-getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew)
-{
- char *buf, *method, *file, *message;
- int blc, bls, fd, black = 0;
- struct bl *bl = NULL;
- gzFile gzf;
-
- if (cgetent(&buf, db_array, name) != 0)
- err(1, "Can't find \"%s\" in spamd config", name);
- buf = fix_quoted_colons(buf);
- if (cgetcap(buf, "black", ':') != NULL) {
- /* use new list */
- black = 1;
- blc = blistnew->blc;
- bls = blistnew->bls;
- bl = blistnew->bl;
- } else if (cgetcap(buf, "white", ':') != NULL) {
- /* apply to most recent blacklist */
- black = 0;
- blc = blist->blc;
- bls = blist->bls;
- bl = blist->bl;
- } else
- errx(1, "Must have \"black\" or \"white\" in %s", name);
-
- switch (cgetstr(buf, "msg", &message)) {
- case -1:
- if (black)
- errx(1, "No msg for blacklist \"%s\"", name);
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "method", &method)) {
- case -1:
- method = NULL;
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "file", &file)) {
- case -1:
- errx(1, "No file given for %slist %s",
- black ? "black" : "white", name);
- case -2:
- errx(1, "malloc failed");
- default:
- fd = open_file(method, file);
- if (fd == -1)
- err(1, "Can't open %s by %s method",
- file, method ? method : "file");
- free(method);
- free(file);
- gzf = gzdopen(fd, "r");
- if (gzf == NULL)
- errx(1, "gzdopen");
- }
- bl = add_blacklist(bl, &blc, &bls, gzf, !black);
- gzclose(gzf);
- if (bl == NULL) {
- warn("Could not add %slist %s", black ? "black" : "white",
- name);
- return(0);
- }
- if (black) {
- blistnew->message = message;
- blistnew->name = name;
- blistnew->black = black;
- blistnew->bl = bl;
- blistnew->blc = blc;
- blistnew->bls = bls;
- } else {
- /* whitelist applied to last active blacklist */
- blist->bl = bl;
- blist->blc = blc;
- blist->bls = bls;
- }
- if (debug)
- fprintf(stderr, "%slist %s %d entries\n",
- black ? "black" : "white", name, blc / 2);
- return(black);
-}
-
-int
-main(int argc, char *argv[])
-{
- size_t dbs, dbc, blc, bls, black, white;
- char **db_array, *buf, *name;
- struct blacklist *blists;
- struct servent *ent;
- int i, ch;
-
-#ifndef IPFW
- while ((ch = getopt(argc, argv, "nd")) != -1) {
-#else
- while ((ch = getopt(argc, argv, "ndt:")) != -1) {
-#endif
- switch (ch) {
- case 'n':
- dryrun = 1;
- break;
- case 'd':
- debug = 1;
- break;
-#ifdef IPFW
- case 't':
- tabno = atoi(optarg);
- break;
-#endif
- default:
- break;
- }
- }
-
- if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
- errx(1, "cannot find service \"spamd-cfg\" in /etc/services");
- ent->s_port = ntohs(ent->s_port);
-
- dbs = argc + 2;
- dbc = 0;
- db_array = calloc(dbs, sizeof(char *));
- if (db_array == NULL)
- errx(1, "malloc failed");
-
- db_array[dbc]= PATH_SPAMD_CONF;
- dbc++;
- for (i = 1; i < argc; i++)
- db_array[dbc++] = argv[i];
-
- blists = NULL;
- blc = bls = 0;
- if (cgetent(&buf, db_array, "all") != 0)
- err(1, "Can't find \"all\" in spamd config");
- name = strsep(&buf, ": \t"); /* skip "all" at start */
- blc = 0;
- while ((name = strsep(&buf, ": \t")) != NULL) {
- if (*name) {
- /* extract config in order specified in "all" tag */
- if (blc == bls) {
- struct blacklist *tmp;
-
- bls += 1024;
- tmp = realloc(blists,
- bls * sizeof(struct blacklist));
- if (tmp == NULL)
- errx(1, "malloc failed");
- blists = tmp;
- }
- if (blc == 0)
- black = white = 0;
- else {
- white = blc - 1;
- black = blc;
- }
- memset(&blists[black], 0, sizeof(struct blacklist));
- blc += getlist(db_array, name, &blists[white],
- &blists[black]);
- }
- }
- for (i = 0; i < blc; i++) {
- struct cidr **cidrs, **tmp;
-
- if (blists[i].blc > 0) {
- cidrs = collapse_blacklist(blists[i].bl,
- blists[i].blc);
- if (cidrs == NULL)
- errx(1, "malloc failed");
- if (dryrun)
- continue;
-
- if (configure_spamd(ent->s_port, blists[i].name,
- blists[i].message, cidrs) == -1)
- err(1, "Can't connect to spamd on port %d",
- ent->s_port);
- if (configure_pf(cidrs) == -1)
- err(1, "pfctl failed");
- tmp = cidrs;
- while (*tmp != NULL)
- free(*tmp++);
- free(cidrs);
- free(blists[i].bl);
- }
- }
- return (0);
-}
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.bak /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.bak
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.bak Fri Feb 2 10:40:32 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.bak Thu Jan 1 03:00:00 1970
@@ -1,924 +0,0 @@
-/* $OpenBSD: spamd-setup.c,v 1.21 2005/03/02 16:45:30 dhartmei Exp $ */
-
-/*
- * Copyright (c) 2003 Bob Beck. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <err.h>
-#ifdef __OpenBSD__
-#include <netinet/ip_ipsp.h>
-#endif
-#include <netdb.h>
-#include <zlib.h>
-
-#ifdef IPFW
-#include <net/if.h>
-#include <netinet/ip_fw.h>
-#endif
-
-#define PATH_FTP "/usr/bin/ftp"
-#define PATH_PFCTL "%%LOCAL_PFCTL%%"
-#define PATH_SPAMD_CONF "%%LOCAL_SPAMD_CONF%%"
-#define SPAMD_ARG_MAX 256 /* max # of args to an exec */
-
-struct cidr {
- u_int32_t addr;
- u_int8_t bits;
-};
-
-struct bl {
- u_int32_t addr;
- int8_t b;
- int8_t w;
-};
-
-struct blacklist {
- char *name;
- char *message;
- struct bl *bl;
- size_t blc, bls;
- u_int8_t black;
- int count;
-};
-
-u_int32_t imask(u_int8_t b);
-u_int8_t maxblock(u_int32_t addr, u_int8_t bits);
-u_int8_t maxdiff(u_int32_t a, u_int32_t b);
-struct cidr *range2cidrlist(u_int32_t start, u_int32_t end);
-void cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end);
-char *atop(u_int32_t addr);
-u_int32_t ptoa(char *cp);
-int parse_netblock(char *buf, struct bl *start, struct bl *end,
- int white);
-int open_child(char *file, char **argv);
-int fileget(char *url);
-int open_file(char *method, char *file);
-char *fix_quoted_colons(char *buf);
-void do_message(FILE *sdc, char *msg);
-struct bl *add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf,
- int white);
-int cmpbl(const void *a, const void *b);
-struct cidr **collapse_blacklist(struct bl *bl, int blc);
-int configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists);
-int configure_pf(struct cidr **blacklists);
-int getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew);
-
-int debug;
-int dryrun;
-
-#ifdef IPFW
-int tabno=2;
-#endif
-
-
-u_int32_t
-imask(u_int8_t b)
-{
- u_int32_t j = 0;
- int i;
-
- for (i = 31; i > 31 - b; --i)
- j |= (1 << i);
- return(j);
-}
-
-u_int8_t
-maxblock(u_int32_t addr, u_int8_t bits)
-{
- while (bits > 0) {
- u_int32_t m = imask(bits - 1);
-
- if ((addr & m) != addr)
- return (bits);
- bits--;
- }
- return(bits);
-}
-
-u_int8_t
-maxdiff(u_int32_t a, u_int32_t b)
-{
- u_int8_t bits = 0;
-
- b++;
- while (bits < 32) {
- u_int32_t m = imask(bits);
-
- if ((a & m) != (b & m))
- return (bits);
- bits++;
- }
- return(bits);
-}
-
-struct cidr *
-range2cidrlist(u_int32_t start, u_int32_t end)
-{
- struct cidr *list = NULL;
- size_t cs = 0, cu = 0;
-
- while (end >= start) {
- u_int8_t maxsize = maxblock(start, 32);
- u_int8_t diff = maxdiff(start, end);
-
- maxsize = MAX(maxsize, diff);
- if (cs == cu) {
- struct cidr *tmp;
-
- tmp = realloc(list, (cs + 32) * sizeof(struct cidr));
- if (tmp == NULL)
- errx(1, "malloc failed");
- list = tmp;
- cs += 32;
- }
- list[cu].addr = start;
- list[cu].bits = maxsize;
- cu++;
- list[cu].addr = 0;
- list[cu].bits = 0;
- start = start + (1 << (32 - maxsize));
- }
- return(list);
-}
-
-void
-cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end)
-{
- *start = cidr.addr;
- *end = cidr.addr + (1 << (32 - cidr.bits)) - 1;
-}
-
-char *
-atop(u_int32_t addr)
-{
- struct in_addr in;
-
- memset(&in, 0, sizeof(in));
- in.s_addr = htonl(addr);
- return(inet_ntoa(in));
-}
-
-int
-parse_netblock(char *buf, struct bl *start, struct bl *end, int white)
-{
- char astring[16], astring2[16];
- unsigned maskbits;
-
- /* skip leading spaces */
- while (*buf == ' ')
- buf++;
- /* bail if it's a comment */
- if (*buf == '#')
- return(0);
- /* otherwise, look for a netblock of some sort */
- if (sscanf(buf, "%15[^/]/%u", astring, &maskbits) == 2) {
- /* looks like a cidr */
- struct cidr c;
-
- memset(&c.addr, 0, sizeof(c.addr));
- if (inet_net_pton(AF_INET, astring, &c.addr, sizeof(c.addr))
- == -1)
- return(0);
- c.addr = ntohl(c.addr);
- if (maskbits > 32)
- return(0);
- c.bits = maskbits;
- cidr2range(c, &start->addr, &end->addr);
- end->addr += 1;
- } else if (sscanf(buf, "%15[0123456789.]%*[ -]%15[0123456789.]",
- astring, astring2) == 2) {
- /* looks like start - end */
- memset(&start->addr, 0, sizeof(start->addr));
- memset(&end->addr, 0, sizeof(end->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- if (inet_net_pton(AF_INET, astring2, &end->addr,
- sizeof(end->addr)) == -1)
- return(0);
- end->addr = ntohl(end->addr) + 1;
- if (start > end)
- return(0);
- } else if (sscanf(buf, "%15[0123456789.]", astring) == 1) {
- /* just a single address */
- memset(&start->addr, 0, sizeof(start->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- end->addr = start->addr + 1;
- } else
- return(0);
-
- if (white) {
- start->b = 0;
- start->w = 1;
- end->b = 0;
- end->w = -1;
- } else {
- start->b = 1;
- start->w = 0;
- end->b = -1;
- end->w = 0;
- }
- return(1);
-}
-
-int
-open_child(char *file, char **argv)
-{
- int pdes[2];
-
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[0]);
- if (pdes[1] != STDOUT_FILENO) {
- dup2(pdes[1], STDOUT_FILENO);
- close(pdes[1]);
- }
- execvp(file, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[1]);
- return(pdes[0]);
-}
-
-int
-fileget(char *url)
-{
- char *argv[6];
-
- argv[0] = "ftp";
- argv[1] = "-V";
- argv[2] = "-o";
- argv[3] = "-";
- argv[4] = url;
- argv[5] = NULL;
-
- if (debug)
- fprintf(stderr, "Getting %s\n", url);
-
- return open_child(PATH_FTP, argv);
-}
-
-int
-open_file(char *method, char *file)
-{
- char *url;
-
- if ((method == NULL) || (strcmp(method, "file") == 0))
- return(open(file, O_RDONLY));
- if ((strcmp(method, "http") == 0) ||
- strcmp(method, "ftp") == 0) {
- int i;
-
- asprintf(&url, "%s://%s", method, file);
- if (url == NULL)
- return(-1);
- i = fileget(url);
- free(url);
- return(i);
- } else if (strcmp(method, "exec") == 0) {
- char **ap, **argv;
- int len, i, oerrno;
-
- len = strlen(file);
- argv = malloc(len * sizeof(char *));
- if (argv == NULL)
- errx(1, "malloc failed");
- for (ap = argv; ap < &argv[len - 1] &&
- (*ap = strsep(&file, " \t")) != NULL;) {
- if (**ap != '\0')
- ap++;
- }
- *ap = NULL;
- i = open_child(argv[0], argv);
- oerrno = errno;
- free(argv);
- errno = oerrno;
- return(i);
- }
- errx(1, "Unknown method %s", method);
- return(-1); /* NOTREACHED */
-}
-
-/*
- * fix_quoted_colons walks through a buffer returned by cgetent. We
- * look for quoted strings, to escape colons (:) in quoted strings for
- * getcap by replacing them with \C so cgetstr() deals with it correctly
- * without having to see the \C bletchery in a configuration file that
- * needs to have urls in it. Frees the buffer passed to it, passes back
- * another larger one, with can be used with cgetxxx(), like the original
- * buffer, it must be freed by the caller.
- * This should really be a temporary fix until there is a sanctioned
- * way to make getcap(3) handle quoted strings like this in a nicer
- * way.
- */
-char *
-fix_quoted_colons(char *buf)
-{
- int nbs = 0, i = 0, j = 0, in = 0;
- char *newbuf, last;
-
- nbs = strlen(buf) + 128;
- newbuf = malloc(nbs);
- if (newbuf == NULL)
- return NULL;
- last = '\0';
- for (i = 0; i < strlen(buf); i++) {
- switch (buf[i]) {
- case ':':
- if (in) {
- newbuf[j++] = '\\';
- newbuf[j++] = 'C';
- } else
- newbuf[j++] = buf[i];
- break;
- case '"':
- if (last != '\\')
- in = !in;
- newbuf[j++] = buf[i];
- break;
- default:
- newbuf[j++] = buf[i];
- }
- if (j == nbs) {
- char *tmp;
-
- nbs += 128;
- tmp = realloc(newbuf, nbs);
- if (tmp == NULL)
- errx(1, "malloc failed");
- newbuf = tmp;
- }
- }
- free(buf);
- newbuf[j] = '\0';
- return(newbuf);
-}
-
-void
-do_message(FILE *sdc, char *msg)
-{
- int i, n, bu = 0, bs = 0, len;
- char *buf = NULL, last;
-
- len = strlen(msg);
- if (msg[0] == '"' && msg[len - 1] == '"') {
- /* quoted msg, escape newlines and send it out */
- msg[len - 1] = '\0';
- buf = msg+1;
- bu = len - 2;
- goto sendit;
- } else {
- int fd;
-
- /*
- * message isn't quoted - try to open a local
- * file and read the message from it.
- */
- fd = open(msg, O_RDONLY);
- if (fd == -1)
- err(1, "Can't open message from %s", msg);
- for (;;) {
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192);
- if (tmp == NULL)
- errx(1, "malloc failed");
- bs += 8192;
- buf = tmp;
- }
-
- n = read(fd, buf + bu, bs - bu);
- if (n == 0) {
- goto sendit;
- } else if (n == -1) {
- err(1, "Can't read from %s", msg);
- } else
- bu += n;
- }
- buf[bu]='\0';
- }
- sendit:
- fprintf(sdc, ";\"");
- last = '\0';
- for (i = 0; i < bu; i++) {
- /* handle escaping the things spamd wants */
- switch (buf[i]) {
- case 'n':
- if (last == '\\')
- fprintf(sdc, "\\\\n");
- else
- fputc('n', sdc);
- last = '\0';
- break;
- case '\n':
- fprintf(sdc, "\\n");
- last = '\0';
- break;
- case '"':
- fputc('\\', sdc);
- /* fall through */
- default:
- fputc(buf[i], sdc);
- last = '\0';
- }
- }
- fputc('"', sdc);
- if (bs != 0)
- free(buf);
-}
-
-/* retrieve a list from fd. add to blacklist bl */
-struct bl *
-add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf, int white)
-{
- int i, n, start, bu = 0, bs = 0, serrno = 0;
- char *buf = NULL;
-
- for (;;) {
- /* read in gzf, then parse */
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192 + 1);
- if (tmp == NULL) {
- free(buf);
- buf = NULL;
- bs = 0;
- serrno = errno;
- goto bldone;
- }
- bs += 8192;
- buf = tmp;
- }
-
- n = gzread(gzf, buf + bu, bs - bu);
- if (n == 0)
- goto parse;
- else if (n == -1) {
- serrno = errno;
- goto bldone;
- } else
- bu += n;
- }
- parse:
- start = 0;
- for (i = 0; i <= bu; i++) {
- if (*blc == *bls) {
- struct bl *tmp;
-
- *bls += 1024;
- tmp = realloc(bl, *bls * sizeof(struct bl));
- if (tmp == NULL) {
- *bls -= 1024;
- serrno = errno;
- goto bldone;
- }
- bl = tmp;
- }
- if (i == bu || buf[i] == '\n') {
- buf[i] = '\0';
- if (parse_netblock(buf + start,
- bl + *blc, bl + *blc + 1, white))
- *blc+=2;
- start = i+1;
- }
- }
- if (bu == 0)
- errno = EIO;
- bldone:
- if (buf)
- free(buf);
- if (serrno)
- errno = serrno;
- return (bl);
-}
-
-int
-cmpbl(const void *a, const void *b)
-{
- if (((struct bl *)a)->addr > ((struct bl *) b)->addr)
- return(1);
- if (((struct bl *)a)->addr < ((struct bl *) b)->addr)
- return(-1);
- return(0);
-}
-
-/*
- * collapse_blacklist takes blacklist/whitelist entries sorts, removes
- * overlaps and whitelist portions, and returns netblocks to blacklist
- * as lists of nonoverlapping cidr blocks suitable for feeding in
- * printable form to pfctl or spamd.
- */
-struct cidr **
-collapse_blacklist(struct bl *bl, int blc)
-{
- int bs = 0, ws = 0, state=0, cli, i;
- u_int32_t bstart = 0;
- struct cidr **cl;
-
- if (blc == 0)
- return(NULL);
- cl = malloc((blc / 2) * sizeof(struct cidr));
- if (cl == NULL) {
- return (NULL);
- }
- qsort(bl, blc, sizeof(struct bl), cmpbl);
- cli = 0;
- cl[cli] = NULL;
- for (i = 0; i < blc;) {
- int laststate = state;
- u_int32_t addr = bl[i].addr;
-
- do {
- bs += bl[i].b;
- ws += bl[i].w;
- i++;
- } while (bl[i].addr == addr);
- if (state == 1 && bs == 0)
- state = 0;
- else if (state == 0 && bs > 0)
- state = 1;
- if (ws > 0)
- state = 0;
- if (laststate == 0 && state == 1) {
- /* start blacklist */
- bstart = addr;
- }
- if (laststate == 1 && state == 0) {
- /* end blacklist */
- cl[cli++] = range2cidrlist(bstart, addr - 1);
- cl[cli] = NULL;
- }
- laststate = state;
- }
- return (cl);
-}
-
-int
-configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists)
-{
- int lport = IPPORT_RESERVED - 1, s;
- struct sockaddr_in sin;
- FILE* sdc;
-
- s = rresvport(&lport);
- if (s == -1)
- return(-1);
- memset(&sin, 0, sizeof sin);
- sin.sin_len = sizeof(sin);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(dport);
- if (connect(s, (struct sockaddr *)&sin, sizeof sin) == -1)
- return(-1);
- sdc = fdopen(s, "w");
- if (sdc == NULL) {
- close(s);
- return(-1);
- }
- fprintf(sdc, "%s", name);
- do_message(sdc, message);
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
- while (b->addr != 0) {
- fprintf(sdc, ";%s/%u", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- fputc('\n', sdc);
- fclose(sdc);
- close(s);
- return(0);
-}
-
-
-#ifndef IPFW
-int
-configure_pf(struct cidr **blacklists)
-{
- char *argv[9]= {"pfctl", "-q", "-t", "spamd", "-T", "replace",
- "-f" "-", NULL};
- static FILE *pf = NULL;
- int pdes[2];
-
- if (pf == NULL) {
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- dup2(pdes[0], STDIN_FILENO);
- close(pdes[0]);
- }
- execvp(PATH_PFCTL, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[0]);
- pf = fdopen(pdes[1], "w");
- if (pf == NULL) {
- close(pdes[1]);
- return(-1);
- }
- }
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
-
- while (b->addr != 0) {
- fprintf(pf, "%s/%u\n", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- return(0);
-}
-#else
-int
-configure_pf(struct cidr **blacklists)
-{
- static int s = -1;
- ipfw_table_entry ent;
-
- if (s == -1)
- s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- if (s < 0)
- {
- err(1, "IPFW socket unavailable");
- return(-1);
- }
-
- /* flush the table */
- ent.tbl = tabno;
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
- {
- err(1, "IPFW setsockopt(IP_FW_TABLE_FLUSH)");
- return(-1);
- }
-
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
-
- while (b->addr != 0) {
- /* add b to tabno */
- ent.tbl = tabno;
- ent.masklen = b->bits;
- ent.value = 0;
- inet_aton(atop(b->addr), (struct in_addr *)&ent.addr);
- if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD, &ent, sizeof(ent)) < 0)
- {
- err(1, "IPFW setsockopt(IP_FW_TABLE_ADD)");
- return(-1);
- }
- b++;
- }
- blacklists++;
- }
-
- return(0);
-}
-#endif
-
-int
-getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew)
-{
- char *buf, *method, *file, *message;
- int blc, bls, fd, black = 0;
- struct bl *bl = NULL;
- gzFile gzf;
-
- if (cgetent(&buf, db_array, name) != 0)
- err(1, "Can't find \"%s\" in spamd config", name);
- buf = fix_quoted_colons(buf);
- if (cgetcap(buf, "black", ':') != NULL) {
- /* use new list */
- black = 1;
- blc = blistnew->blc;
- bls = blistnew->bls;
- bl = blistnew->bl;
- } else if (cgetcap(buf, "white", ':') != NULL) {
- /* apply to most recent blacklist */
- black = 0;
- blc = blist->blc;
- bls = blist->bls;
- bl = blist->bl;
- } else
- errx(1, "Must have \"black\" or \"white\" in %s", name);
-
- switch (cgetstr(buf, "msg", &message)) {
- case -1:
- if (black)
- errx(1, "No msg for blacklist \"%s\"", name);
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "method", &method)) {
- case -1:
- method = NULL;
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "file", &file)) {
- case -1:
- errx(1, "No file given for %slist %s",
- black ? "black" : "white", name);
- case -2:
- errx(1, "malloc failed");
- default:
- fd = open_file(method, file);
- if (fd == -1)
- err(1, "Can't open %s by %s method",
- file, method ? method : "file");
- free(method);
- free(file);
- gzf = gzdopen(fd, "r");
- if (gzf == NULL)
- errx(1, "gzdopen");
- }
- bl = add_blacklist(bl, &blc, &bls, gzf, !black);
- gzclose(gzf);
- if (bl == NULL) {
- warn("Could not add %slist %s", black ? "black" : "white",
- name);
- return(0);
- }
- if (black) {
- blistnew->message = message;
- blistnew->name = name;
- blistnew->black = black;
- blistnew->bl = bl;
- blistnew->blc = blc;
- blistnew->bls = bls;
- } else {
- /* whitelist applied to last active blacklist */
- blist->bl = bl;
- blist->blc = blc;
- blist->bls = bls;
- }
- if (debug)
- fprintf(stderr, "%slist %s %d entries\n",
- black ? "black" : "white", name, blc / 2);
- return(black);
-}
-
-int
-main(int argc, char *argv[])
-{
- size_t dbs, dbc, blc, bls, black, white;
- char **db_array, *buf, *name;
- struct blacklist *blists;
- struct servent *ent;
- int i, ch;
-
-#ifndef IPFW
- while ((ch = getopt(argc, argv, "nd")) != -1) {
-#else
- while ((ch = getopt(argc, argv, "ndt:")) != -1) {
-#endif
- switch (ch) {
- case 'n':
- dryrun = 1;
- break;
- case 'd':
- debug = 1;
- break;
-#ifdef IPFW
- case 't':
- tabno = atoi(optarg);
- break;
-#endif
- default:
- break;
- }
- }
-
- if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
- errx(1, "cannot find service \"spamd-cfg\" in /etc/services");
- ent->s_port = ntohs(ent->s_port);
-
- dbs = argc + 2;
- dbc = 0;
- db_array = calloc(dbs, sizeof(char *));
- if (db_array == NULL)
- errx(1, "malloc failed");
-
- db_array[dbc]= PATH_SPAMD_CONF;
- dbc++;
- for (i = 1; i < argc; i++)
- db_array[dbc++] = argv[i];
-
- blists = NULL;
- blc = bls = 0;
- if (cgetent(&buf, db_array, "all") != 0)
- err(1, "Can't find \"all\" in spamd config");
- name = strsep(&buf, ": \t"); /* skip "all" at start */
- blc = 0;
- while ((name = strsep(&buf, ": \t")) != NULL) {
- if (*name) {
- /* extract config in order specified in "all" tag */
- if (blc == bls) {
- struct blacklist *tmp;
-
- bls += 1024;
- tmp = realloc(blists,
- bls * sizeof(struct blacklist));
- if (tmp == NULL)
- errx(1, "malloc failed");
- blists = tmp;
- }
- if (blc == 0)
- black = white = 0;
- else {
- white = blc - 1;
- black = blc;
- }
- memset(&blists[black], 0, sizeof(struct blacklist));
- blc += getlist(db_array, name, &blists[white],
- &blists[black]);
- }
- }
- for (i = 0; i < blc; i++) {
- struct cidr **cidrs, **tmp;
-
- if (blists[i].blc > 0) {
- cidrs = collapse_blacklist(blists[i].bl,
- blists[i].blc);
- if (cidrs == NULL)
- errx(1, "malloc failed");
- if (dryrun)
- continue;
-
- if (configure_spamd(ent->s_port, blists[i].name,
- blists[i].message, cidrs) == -1)
- err(1, "Can't connect to spamd on port %d",
- ent->s_port);
- if (configure_pf(cidrs) == -1)
- err(1, "pfctl failed");
- tmp = cidrs;
- while (*tmp != NULL)
- free(*tmp++);
- free(cidrs);
- free(blists[i].bl);
- }
- }
- return (0);
-}
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.orig /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.orig
--- /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.orig Tue Apr 12 20:18:59 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.c.orig Thu Jan 1 03:00:00 1970
@@ -1,859 +0,0 @@
-/* $OpenBSD: spamd-setup.c,v 1.21 2005/03/02 16:45:30 dhartmei Exp $ */
-
-/*
- * Copyright (c) 2003 Bob Beck. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <err.h>
-#ifdef __OpenBSD__
-#include <netinet/ip_ipsp.h>
-#endif
-#include <netdb.h>
-#include <zlib.h>
-
-#define PATH_FTP "/usr/bin/ftp"
-#define PATH_PFCTL "%%LOCAL_PFCTL%%"
-#define PATH_SPAMD_CONF "%%LOCAL_SPAMD_CONF%%"
-#define SPAMD_ARG_MAX 256 /* max # of args to an exec */
-
-struct cidr {
- u_int32_t addr;
- u_int8_t bits;
-};
-
-struct bl {
- u_int32_t addr;
- int8_t b;
- int8_t w;
-};
-
-struct blacklist {
- char *name;
- char *message;
- struct bl *bl;
- size_t blc, bls;
- u_int8_t black;
- int count;
-};
-
-u_int32_t imask(u_int8_t b);
-u_int8_t maxblock(u_int32_t addr, u_int8_t bits);
-u_int8_t maxdiff(u_int32_t a, u_int32_t b);
-struct cidr *range2cidrlist(u_int32_t start, u_int32_t end);
-void cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end);
-char *atop(u_int32_t addr);
-u_int32_t ptoa(char *cp);
-int parse_netblock(char *buf, struct bl *start, struct bl *end,
- int white);
-int open_child(char *file, char **argv);
-int fileget(char *url);
-int open_file(char *method, char *file);
-char *fix_quoted_colons(char *buf);
-void do_message(FILE *sdc, char *msg);
-struct bl *add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf,
- int white);
-int cmpbl(const void *a, const void *b);
-struct cidr **collapse_blacklist(struct bl *bl, int blc);
-int configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists);
-int configure_pf(struct cidr **blacklists);
-int getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew);
-
-int debug;
-int dryrun;
-
-u_int32_t
-imask(u_int8_t b)
-{
- u_int32_t j = 0;
- int i;
-
- for (i = 31; i > 31 - b; --i)
- j |= (1 << i);
- return(j);
-}
-
-u_int8_t
-maxblock(u_int32_t addr, u_int8_t bits)
-{
- while (bits > 0) {
- u_int32_t m = imask(bits - 1);
-
- if ((addr & m) != addr)
- return (bits);
- bits--;
- }
- return(bits);
-}
-
-u_int8_t
-maxdiff(u_int32_t a, u_int32_t b)
-{
- u_int8_t bits = 0;
-
- b++;
- while (bits < 32) {
- u_int32_t m = imask(bits);
-
- if ((a & m) != (b & m))
- return (bits);
- bits++;
- }
- return(bits);
-}
-
-struct cidr *
-range2cidrlist(u_int32_t start, u_int32_t end)
-{
- struct cidr *list = NULL;
- size_t cs = 0, cu = 0;
-
- while (end >= start) {
- u_int8_t maxsize = maxblock(start, 32);
- u_int8_t diff = maxdiff(start, end);
-
- maxsize = MAX(maxsize, diff);
- if (cs == cu) {
- struct cidr *tmp;
-
- tmp = realloc(list, (cs + 32) * sizeof(struct cidr));
- if (tmp == NULL)
- errx(1, "malloc failed");
- list = tmp;
- cs += 32;
- }
- list[cu].addr = start;
- list[cu].bits = maxsize;
- cu++;
- list[cu].addr = 0;
- list[cu].bits = 0;
- start = start + (1 << (32 - maxsize));
- }
- return(list);
-}
-
-void
-cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end)
-{
- *start = cidr.addr;
- *end = cidr.addr + (1 << (32 - cidr.bits)) - 1;
-}
-
-char *
-atop(u_int32_t addr)
-{
- struct in_addr in;
-
- memset(&in, 0, sizeof(in));
- in.s_addr = htonl(addr);
- return(inet_ntoa(in));
-}
-
-int
-parse_netblock(char *buf, struct bl *start, struct bl *end, int white)
-{
- char astring[16], astring2[16];
- unsigned maskbits;
-
- /* skip leading spaces */
- while (*buf == ' ')
- buf++;
- /* bail if it's a comment */
- if (*buf == '#')
- return(0);
- /* otherwise, look for a netblock of some sort */
- if (sscanf(buf, "%15[^/]/%u", astring, &maskbits) == 2) {
- /* looks like a cidr */
- struct cidr c;
-
- memset(&c.addr, 0, sizeof(c.addr));
- if (inet_net_pton(AF_INET, astring, &c.addr, sizeof(c.addr))
- == -1)
- return(0);
- c.addr = ntohl(c.addr);
- if (maskbits > 32)
- return(0);
- c.bits = maskbits;
- cidr2range(c, &start->addr, &end->addr);
- end->addr += 1;
- } else if (sscanf(buf, "%15[0123456789.]%*[ -]%15[0123456789.]",
- astring, astring2) == 2) {
- /* looks like start - end */
- memset(&start->addr, 0, sizeof(start->addr));
- memset(&end->addr, 0, sizeof(end->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- if (inet_net_pton(AF_INET, astring2, &end->addr,
- sizeof(end->addr)) == -1)
- return(0);
- end->addr = ntohl(end->addr) + 1;
- if (start > end)
- return(0);
- } else if (sscanf(buf, "%15[0123456789.]", astring) == 1) {
- /* just a single address */
- memset(&start->addr, 0, sizeof(start->addr));
- if (inet_net_pton(AF_INET, astring, &start->addr,
- sizeof(start->addr)) == -1)
- return(0);
- start->addr = ntohl(start->addr);
- end->addr = start->addr + 1;
- } else
- return(0);
-
- if (white) {
- start->b = 0;
- start->w = 1;
- end->b = 0;
- end->w = -1;
- } else {
- start->b = 1;
- start->w = 0;
- end->b = -1;
- end->w = 0;
- }
- return(1);
-}
-
-int
-open_child(char *file, char **argv)
-{
- int pdes[2];
-
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[0]);
- if (pdes[1] != STDOUT_FILENO) {
- dup2(pdes[1], STDOUT_FILENO);
- close(pdes[1]);
- }
- execvp(file, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[1]);
- return(pdes[0]);
-}
-
-int
-fileget(char *url)
-{
- char *argv[6];
-
- argv[0] = "ftp";
- argv[1] = "-V";
- argv[2] = "-o";
- argv[3] = "-";
- argv[4] = url;
- argv[5] = NULL;
-
- if (debug)
- fprintf(stderr, "Getting %s\n", url);
-
- return open_child(PATH_FTP, argv);
-}
-
-int
-open_file(char *method, char *file)
-{
- char *url;
-
- if ((method == NULL) || (strcmp(method, "file") == 0))
- return(open(file, O_RDONLY));
- if ((strcmp(method, "http") == 0) ||
- strcmp(method, "ftp") == 0) {
- int i;
-
- asprintf(&url, "%s://%s", method, file);
- if (url == NULL)
- return(-1);
- i = fileget(url);
- free(url);
- return(i);
- } else if (strcmp(method, "exec") == 0) {
- char **ap, **argv;
- int len, i, oerrno;
-
- len = strlen(file);
- argv = malloc(len * sizeof(char *));
- if (argv == NULL)
- errx(1, "malloc failed");
- for (ap = argv; ap < &argv[len - 1] &&
- (*ap = strsep(&file, " \t")) != NULL;) {
- if (**ap != '\0')
- ap++;
- }
- *ap = NULL;
- i = open_child(argv[0], argv);
- oerrno = errno;
- free(argv);
- errno = oerrno;
- return(i);
- }
- errx(1, "Unknown method %s", method);
- return(-1); /* NOTREACHED */
-}
-
-/*
- * fix_quoted_colons walks through a buffer returned by cgetent. We
- * look for quoted strings, to escape colons (:) in quoted strings for
- * getcap by replacing them with \C so cgetstr() deals with it correctly
- * without having to see the \C bletchery in a configuration file that
- * needs to have urls in it. Frees the buffer passed to it, passes back
- * another larger one, with can be used with cgetxxx(), like the original
- * buffer, it must be freed by the caller.
- * This should really be a temporary fix until there is a sanctioned
- * way to make getcap(3) handle quoted strings like this in a nicer
- * way.
- */
-char *
-fix_quoted_colons(char *buf)
-{
- int nbs = 0, i = 0, j = 0, in = 0;
- char *newbuf, last;
-
- nbs = strlen(buf) + 128;
- newbuf = malloc(nbs);
- if (newbuf == NULL)
- return NULL;
- last = '\0';
- for (i = 0; i < strlen(buf); i++) {
- switch (buf[i]) {
- case ':':
- if (in) {
- newbuf[j++] = '\\';
- newbuf[j++] = 'C';
- } else
- newbuf[j++] = buf[i];
- break;
- case '"':
- if (last != '\\')
- in = !in;
- newbuf[j++] = buf[i];
- break;
- default:
- newbuf[j++] = buf[i];
- }
- if (j == nbs) {
- char *tmp;
-
- nbs += 128;
- tmp = realloc(newbuf, nbs);
- if (tmp == NULL)
- errx(1, "malloc failed");
- newbuf = tmp;
- }
- }
- free(buf);
- newbuf[j] = '\0';
- return(newbuf);
-}
-
-void
-do_message(FILE *sdc, char *msg)
-{
- int i, n, bu = 0, bs = 0, len;
- char *buf = NULL, last;
-
- len = strlen(msg);
- if (msg[0] == '"' && msg[len - 1] == '"') {
- /* quoted msg, escape newlines and send it out */
- msg[len - 1] = '\0';
- buf = msg+1;
- bu = len - 2;
- goto sendit;
- } else {
- int fd;
-
- /*
- * message isn't quoted - try to open a local
- * file and read the message from it.
- */
- fd = open(msg, O_RDONLY);
- if (fd == -1)
- err(1, "Can't open message from %s", msg);
- for (;;) {
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192);
- if (tmp == NULL)
- errx(1, "malloc failed");
- bs += 8192;
- buf = tmp;
- }
-
- n = read(fd, buf + bu, bs - bu);
- if (n == 0) {
- goto sendit;
- } else if (n == -1) {
- err(1, "Can't read from %s", msg);
- } else
- bu += n;
- }
- buf[bu]='\0';
- }
- sendit:
- fprintf(sdc, ";\"");
- last = '\0';
- for (i = 0; i < bu; i++) {
- /* handle escaping the things spamd wants */
- switch (buf[i]) {
- case 'n':
- if (last == '\\')
- fprintf(sdc, "\\\\n");
- else
- fputc('n', sdc);
- last = '\0';
- break;
- case '\n':
- fprintf(sdc, "\\n");
- last = '\0';
- break;
- case '"':
- fputc('\\', sdc);
- /* fall through */
- default:
- fputc(buf[i], sdc);
- last = '\0';
- }
- }
- fputc('"', sdc);
- if (bs != 0)
- free(buf);
-}
-
-/* retrieve a list from fd. add to blacklist bl */
-struct bl *
-add_blacklist(struct bl *bl, int *blc, int *bls, gzFile gzf, int white)
-{
- int i, n, start, bu = 0, bs = 0, serrno = 0;
- char *buf = NULL;
-
- for (;;) {
- /* read in gzf, then parse */
- if (bu == bs) {
- char *tmp;
-
- tmp = realloc(buf, bs + 8192 + 1);
- if (tmp == NULL) {
- free(buf);
- buf = NULL;
- bs = 0;
- serrno = errno;
- goto bldone;
- }
- bs += 8192;
- buf = tmp;
- }
-
- n = gzread(gzf, buf + bu, bs - bu);
- if (n == 0)
- goto parse;
- else if (n == -1) {
- serrno = errno;
- goto bldone;
- } else
- bu += n;
- }
- parse:
- start = 0;
- for (i = 0; i <= bu; i++) {
- if (*blc == *bls) {
- struct bl *tmp;
-
- *bls += 1024;
- tmp = realloc(bl, *bls * sizeof(struct bl));
- if (tmp == NULL) {
- *bls -= 1024;
- serrno = errno;
- goto bldone;
- }
- bl = tmp;
- }
- if (i == bu || buf[i] == '\n') {
- buf[i] = '\0';
- if (parse_netblock(buf + start,
- bl + *blc, bl + *blc + 1, white))
- *blc+=2;
- start = i+1;
- }
- }
- if (bu == 0)
- errno = EIO;
- bldone:
- if (buf)
- free(buf);
- if (serrno)
- errno = serrno;
- return (bl);
-}
-
-int
-cmpbl(const void *a, const void *b)
-{
- if (((struct bl *)a)->addr > ((struct bl *) b)->addr)
- return(1);
- if (((struct bl *)a)->addr < ((struct bl *) b)->addr)
- return(-1);
- return(0);
-}
-
-/*
- * collapse_blacklist takes blacklist/whitelist entries sorts, removes
- * overlaps and whitelist portions, and returns netblocks to blacklist
- * as lists of nonoverlapping cidr blocks suitable for feeding in
- * printable form to pfctl or spamd.
- */
-struct cidr **
-collapse_blacklist(struct bl *bl, int blc)
-{
- int bs = 0, ws = 0, state=0, cli, i;
- u_int32_t bstart = 0;
- struct cidr **cl;
-
- if (blc == 0)
- return(NULL);
- cl = malloc((blc / 2) * sizeof(struct cidr));
- if (cl == NULL) {
- return (NULL);
- }
- qsort(bl, blc, sizeof(struct bl), cmpbl);
- cli = 0;
- cl[cli] = NULL;
- for (i = 0; i < blc;) {
- int laststate = state;
- u_int32_t addr = bl[i].addr;
-
- do {
- bs += bl[i].b;
- ws += bl[i].w;
- i++;
- } while (bl[i].addr == addr);
- if (state == 1 && bs == 0)
- state = 0;
- else if (state == 0 && bs > 0)
- state = 1;
- if (ws > 0)
- state = 0;
- if (laststate == 0 && state == 1) {
- /* start blacklist */
- bstart = addr;
- }
- if (laststate == 1 && state == 0) {
- /* end blacklist */
- cl[cli++] = range2cidrlist(bstart, addr - 1);
- cl[cli] = NULL;
- }
- laststate = state;
- }
- return (cl);
-}
-
-int
-configure_spamd(u_short dport, char *name, char *message,
- struct cidr **blacklists)
-{
- int lport = IPPORT_RESERVED - 1, s;
- struct sockaddr_in sin;
- FILE* sdc;
-
- s = rresvport(&lport);
- if (s == -1)
- return(-1);
- memset(&sin, 0, sizeof sin);
- sin.sin_len = sizeof(sin);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(dport);
- if (connect(s, (struct sockaddr *)&sin, sizeof sin) == -1)
- return(-1);
- sdc = fdopen(s, "w");
- if (sdc == NULL) {
- close(s);
- return(-1);
- }
- fprintf(sdc, "%s", name);
- do_message(sdc, message);
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
- while (b->addr != 0) {
- fprintf(sdc, ";%s/%u", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- fputc('\n', sdc);
- fclose(sdc);
- close(s);
- return(0);
-}
-
-
-int
-configure_pf(struct cidr **blacklists)
-{
- char *argv[9]= {"pfctl", "-q", "-t", "spamd", "-T", "replace",
- "-f" "-", NULL};
- static FILE *pf = NULL;
- int pdes[2];
-
- if (pf == NULL) {
- if (pipe(pdes) != 0)
- return(-1);
- switch (fork()) {
- case -1:
- close(pdes[0]);
- close(pdes[1]);
- return(-1);
- case 0:
- /* child */
- close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- dup2(pdes[0], STDIN_FILENO);
- close(pdes[0]);
- }
- execvp(PATH_PFCTL, argv);
- _exit(1);
- }
-
- /* parent */
- close(pdes[0]);
- pf = fdopen(pdes[1], "w");
- if (pf == NULL) {
- close(pdes[1]);
- return(-1);
- }
- }
- while (*blacklists != NULL) {
- struct cidr *b = *blacklists;
-
- while (b->addr != 0) {
- fprintf(pf, "%s/%u\n", atop(b->addr), (b->bits));
- b++;
- }
- blacklists++;
- }
- return(0);
-}
-
-int
-getlist(char ** db_array, char *name, struct blacklist *blist,
- struct blacklist *blistnew)
-{
- char *buf, *method, *file, *message;
- int blc, bls, fd, black = 0;
- struct bl *bl = NULL;
- gzFile gzf;
-
- if (cgetent(&buf, db_array, name) != 0)
- err(1, "Can't find \"%s\" in spamd config", name);
- buf = fix_quoted_colons(buf);
- if (cgetcap(buf, "black", ':') != NULL) {
- /* use new list */
- black = 1;
- blc = blistnew->blc;
- bls = blistnew->bls;
- bl = blistnew->bl;
- } else if (cgetcap(buf, "white", ':') != NULL) {
- /* apply to most recent blacklist */
- black = 0;
- blc = blist->blc;
- bls = blist->bls;
- bl = blist->bl;
- } else
- errx(1, "Must have \"black\" or \"white\" in %s", name);
-
- switch (cgetstr(buf, "msg", &message)) {
- case -1:
- if (black)
- errx(1, "No msg for blacklist \"%s\"", name);
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "method", &method)) {
- case -1:
- method = NULL;
- break;
- case -2:
- errx(1, "malloc failed");
- }
-
- switch (cgetstr(buf, "file", &file)) {
- case -1:
- errx(1, "No file given for %slist %s",
- black ? "black" : "white", name);
- case -2:
- errx(1, "malloc failed");
- default:
- fd = open_file(method, file);
- if (fd == -1)
- err(1, "Can't open %s by %s method",
- file, method ? method : "file");
- free(method);
- free(file);
- gzf = gzdopen(fd, "r");
- if (gzf == NULL)
- errx(1, "gzdopen");
- }
- bl = add_blacklist(bl, &blc, &bls, gzf, !black);
- gzclose(gzf);
- if (bl == NULL) {
- warn("Could not add %slist %s", black ? "black" : "white",
- name);
- return(0);
- }
- if (black) {
- blistnew->message = message;
- blistnew->name = name;
- blistnew->black = black;
- blistnew->bl = bl;
- blistnew->blc = blc;
- blistnew->bls = bls;
- } else {
- /* whitelist applied to last active blacklist */
- blist->bl = bl;
- blist->blc = blc;
- blist->bls = bls;
- }
- if (debug)
- fprintf(stderr, "%slist %s %d entries\n",
- black ? "black" : "white", name, blc / 2);
- return(black);
-}
-
-int
-main(int argc, char *argv[])
-{
- size_t dbs, dbc, blc, bls, black, white;
- char **db_array, *buf, *name;
- struct blacklist *blists;
- struct servent *ent;
- int i, ch;
-
- while ((ch = getopt(argc, argv, "nd")) != -1) {
- switch (ch) {
- case 'n':
- dryrun = 1;
- break;
- case 'd':
- debug = 1;
- break;
- default:
- break;
- }
- }
-
- if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
- errx(1, "cannot find service \"spamd-cfg\" in /etc/services");
- ent->s_port = ntohs(ent->s_port);
-
- dbs = argc + 2;
- dbc = 0;
- db_array = calloc(dbs, sizeof(char *));
- if (db_array == NULL)
- errx(1, "malloc failed");
-
- db_array[dbc]= PATH_SPAMD_CONF;
- dbc++;
- for (i = 1; i < argc; i++)
- db_array[dbc++] = argv[i];
-
- blists = NULL;
- blc = bls = 0;
- if (cgetent(&buf, db_array, "all") != 0)
- err(1, "Can't find \"all\" in spamd config");
- name = strsep(&buf, ": \t"); /* skip "all" at start */
- blc = 0;
- while ((name = strsep(&buf, ": \t")) != NULL) {
- if (*name) {
- /* extract config in order specified in "all" tag */
- if (blc == bls) {
- struct blacklist *tmp;
-
- bls += 1024;
- tmp = realloc(blists,
- bls * sizeof(struct blacklist));
- if (tmp == NULL)
- errx(1, "malloc failed");
- blists = tmp;
- }
- if (blc == 0)
- black = white = 0;
- else {
- white = blc - 1;
- black = blc;
- }
- memset(&blists[black], 0, sizeof(struct blacklist));
- blc += getlist(db_array, name, &blists[white],
- &blists[black]);
- }
- }
- for (i = 0; i < blc; i++) {
- struct cidr **cidrs, **tmp;
-
- if (blists[i].blc > 0) {
- cidrs = collapse_blacklist(blists[i].bl,
- blists[i].blc);
- if (cidrs == NULL)
- errx(1, "malloc failed");
- if (dryrun)
- continue;
-
- if (configure_spamd(ent->s_port, blists[i].name,
- blists[i].message, cidrs) == -1)
- err(1, "Can't connect to spamd on port %d",
- ent->s_port);
- if (configure_pf(cidrs) == -1)
- err(1, "pfctl failed");
- tmp = cidrs;
- while (*tmp != NULL)
- free(*tmp++);
- free(cidrs);
- free(blists[i].bl);
- }
- }
- return (0);
-}
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamd-setup/spamd-setup.o and /usr/home/samm/spamd/work/spamd_3.7/spamd-setup/spamd-setup.o differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamdb/Makefile /usr/home/samm/spamd/work/spamd_3.7/spamdb/Makefile
--- /usr/ports/mail/spamd/work/spamd_3.7/spamdb/Makefile Sun Oct 3 16:09:15 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamdb/Makefile Thu Jan 1 03:00:00 1970
@@ -1,9 +0,0 @@
-# $OpenBSD: Makefile,v 1.2 2004/02/27 19:41:39 david Exp $
-
-PROG= spamdb
-SRCS= spamdb.c
-MAN= spamdb.8
-
-CFLAGS+= -Wall -Wstrict-prototypes -ansi -I${.CURDIR}/../spamd
-
-.include <bsd.prog.mk>
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb and /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.8 /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.8
--- /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.8 Tue Apr 12 20:19:22 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.8 Thu Jan 1 03:00:00 1970
@@ -1,132 +0,0 @@
-.\" $OpenBSD: spamdb.8,v 1.6 2005/03/12 23:31:04 jmc Exp $
-.\"
-.\" Copyright (c) 2004 Bob Beck. All rights reserved.
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd February 16, 2004
-.Dt SPAMDB 8
-.Os
-.Sh NAME
-.Nm spamdb
-.Nd spamd database tool
-.Sh SYNOPSIS
-.Nm spamdb
-.Op Fl Tt
-.Op Fl a Ar key
-.Op Fl d Ar key
-.Sh DESCRIPTION
-.Nm
-manipulates the spamd database in
-.Pa /var/db/spamd
-used for
-.Xr spamd 8
-greylisting.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl a Ar key
-Add or update an entry for "key".
-Updates time last seen to now.
-.It Fl d Ar key
-Delete an entry for "key".
-.It Fl T
-Add or delete the key as a SPAMTRAP entry.
-.It Fl t
-Add or delete the key as a TRAPPED entry.
-.El
-.Ss DATABASE OUTPUT FORMAT
-If invoked without any arguments,
-.Nm
-lists the contents of the database in a text format.
-For SPAMTRAP entries the format is:
-.Pp
-.Dl type|mailaddress
-.Pp
-where
-.Em type
-will be SPAMTRAP and
-.Em mailaddress
-will be the email address for which any connections received by
-.Xr spamd 8
-will be blacklisted if mail is sent to this address.
-For TRAPPED entries the format is:
-.Pp
-.Dl type|ip|expire
-.Pp
-where
-.Em type
-will be TRAPPED,
-.Em ip
-will be the IP address blacklisted due to hitting a spamtrap, and
-.Em expire
-will be when the IP is due to be removed from the blacklist.
-For GREY or WHITE entries, the format is:
-.Pp
-.Dl type|source ip|from|to|first|pass|expire|block|pass
-.Pp
-The fields are as follows:
-.Pp
-.Bl -tag -width "source ip" -offset indent -compact
-.It type
-.Em WHITE
-if whitelisted or
-.Em GREY
-if greylisted
-.It source ip
-IP address the connection originated from
-.It from
-envelope-from address for
-.Em GREY
-(empty for
-.Em WHITE
-entries)
-.It to
-envelope-to address for
-.Em GREY
-(empty for
-.Em WHITE
-entries)
-.It first
-time the entry was first seen
-.It pass
-time the entry passed from being
-.Em GREY
-to being
-.Em WHITE
-.It expire
-time the entry will expire and be removed from the database
-.It block
-number of times a corresponding connection received a temporary
-failure from
-.Xr spamd 8
-.It pass
-number of times a corresponding connection has been seen to pass
-to the real MTA by
-.Xr spamlogd 8
-.El
-.Pp
-Note that times are in seconds since the Epoch, in the manner returned by
-.Xr time 3 .
-.Sh FILES
-/var/db/spamd
-.Sh SEE ALSO
-.Xr spamd.conf 5 ,
-.Xr spamd 8 ,
-.Xr spamd-setup 8
-.Sh HISTORY
-The
-.Nm
-command
-appeared in
-.Ox 3.5 .
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.8.gz and /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.8.gz differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.c /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.c Tue Apr 12 20:20:44 2005
+++ /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.c Thu Jan 1 03:00:00 1970
@@ -1,304 +0,0 @@
-/* $OpenBSD: spamdb.c,v 1.14 2005/03/11 23:45:45 beck Exp $ */
-
-/*
- * Copyright (c) 2004 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <db.h>
-#include <err.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include "grey.h"
-
-/* things we may add/delete from the db */
-#define WHITE 0
-#define TRAPHIT 1
-#define SPAMTRAP 2
-
-int
-dbupdate(char *dbname, char *ip, int add, int type)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- struct gdata gd;
- time_t now;
- int r;
- struct addrinfo hints, *res;
-
- now = time(NULL);
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL)
- err(1, "cannot open %s for writing", dbname);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
- if (type == TRAPHIT || type == WHITE) {
- if (getaddrinfo(ip, NULL, &hints, &res) != 0) {
- warnx("invalid ip address %s", ip);
- goto bad;
- }
- freeaddrinfo(res);
- }
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(ip);
- dbk.data = ip;
- memset(&dbd, 0, sizeof(dbd));
- if (!add) {
- /* remove entry */
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1) {
- warn("db->get failed");
- goto bad;
- }
- if (r) {
- warnx("no entry for %s", ip);
- goto bad;
- } else if (db->del(db, &dbk, 0)) {
- warn("db->del failed");
- goto bad;
- }
- } else {
- /* add or update entry */
- r = db->get(db, &dbk, &dbd, 0);
- if (r == -1) {
- warn("db->get failed");
- goto bad;
- }
- if (r) {
- int i;
-
- /* new entry */
- memset(&gd, 0, sizeof(gd));
- gd.first = now;
- gd.bcount = 1;
- switch (type) {
- case WHITE:
- gd.pass = now;
- gd.expire = now + WHITEEXP;
- break;
- case TRAPHIT:
- gd.expire = now + TRAPEXP;
- gd.pcount = -1;
- break;
- case SPAMTRAP:
- gd.expire = 0;
- gd.pcount = -2;
- /* ensure address is lower case*/
- for (i = 0; ip[i] != '\0'; i++)
- if (isupper(ip[i]))
- ip[i] = tolower(ip[i]);
- break;
- default:
- errx(-1, "unknown type %d", type);
- }
- 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);
- if (r) {
- warn("db->put failed");
- goto bad;
- }
- } 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.pcount++;
- switch (type) {
- case WHITE:
- gd.pass = now;
- gd.expire = now + WHITEEXP;
- break;
- case TRAPHIT:
- gd.expire = now + TRAPEXP;
- gd.pcount = -1;
- break;
- case SPAMTRAP:
- gd.expire = 0; /* XXX */
- gd.pcount = -2;
- break;
- default:
- errx(-1, "unknown type %d", type);
- }
-
- 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);
- if (r) {
- warn("db->put failed");
- goto bad;
- }
- }
- }
- db->close(db);
- db = NULL;
- return (0);
- bad:
- db->close(db);
- db = NULL;
- return (1);
-}
-
-int
-dblist(char *dbname)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- struct gdata gd;
- int r;
-
- /* walk db, list in text format */
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDONLY, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL)
- err(1, "cannot open %s for reading", dbname);
- memset(&dbk, 0, sizeof(dbk));
- memset(&dbd, 0, sizeof(dbd));
- for (r = db->seq(db, &dbk, &dbd, R_FIRST); !r;
- r = db->seq(db, &dbk, &dbd, R_NEXT)) {
- char *a, *cp;
-
- if ((dbk.size < 1) || dbd.size != sizeof(struct gdata)) {
- db->close(db);
- errx(1, "bogus size db entry - bad db file?");
- }
- memcpy(&gd, dbd.data, sizeof(gd));
- a = malloc(dbk.size + 1);
- if (a == NULL)
- err(1, "malloc");
- memcpy(a, dbk.data, dbk.size);
- a[dbk.size]='\0';
- cp = strchr(a, '\n');
- if (cp == NULL) {
- /* this is a non-greylist entry */
- switch (gd.pcount) {
- case -1: /* spamtrap hit, with expiry time */
- printf("TRAPPED|%s|%d\n", a, gd.expire);
- break;
- case -2: /* spamtrap address */
- printf("SPAMTRAP|%s\n", a);
- break;
- default: /* whitelist */
- printf("WHITE|%s|||%d|%d|%d|%d|%d\n", a,
- gd.first, gd.pass, gd.expire, gd.bcount,
- gd.pcount);
- break;
- }
- } else {
- char *from, *to;
-
- /* greylist entry */
- *cp = '\0';
- from = cp + 1;
- to = strchr(from, '\n');
- if (to == NULL) {
- warnx("No from part in grey key %s", a);
- free(a);
- goto bad;
- }
- *to = '\0';
- to++;
- printf("GREY|%s|%s|%s|%d|%d|%d|%d|%d\n",
- a, from, to, gd.first, gd.pass, gd.expire,
- gd.bcount, gd.pcount);
- }
- free(a);
- }
- db->close(db);
- db = NULL;
- return (0);
- bad:
- db->close(db);
- db = NULL;
- errx(1, "incorrect db format entry");
- /* NOTREACHED */
- return (1);
-}
-
-extern char *__progname;
-
-static int
-usage(void)
-{
- fprintf(stderr, "usage: %s [-Tt] [-a key] [-d key]\n", __progname);
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, action = 0, type = WHITE;
- char *ip = NULL;
-
- while ((ch = getopt(argc, argv, "a:d:tT")) != -1) {
- switch (ch) {
- case 'a':
- action = 1;
- ip = optarg;
- break;
- case 'd':
- action = 2;
- ip = optarg;
- break;
- case 't':
- type = TRAPHIT;
- break;
- case 'T':
- type = SPAMTRAP;
- break;
- default:
- usage();
- break;
- }
- }
-
- switch (action) {
- case 0:
- return dblist(PATH_SPAMD_DB);
- case 1:
- return dbupdate(PATH_SPAMD_DB, ip, 1, type);
- case 2:
- return dbupdate(PATH_SPAMD_DB, ip, 0, type);
- default:
- errx(-1, "bad action");
- }
- /* NOT REACHED */
- return (0);
-}
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamdb/spamdb.o and /usr/home/samm/spamd/work/spamd_3.7/spamdb/spamdb.o differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/Makefile /usr/home/samm/spamd/work/spamd_3.7/spamlogd/Makefile
--- /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/Makefile Fri Feb 2 10:53:08 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamlogd/Makefile Thu Jan 1 03:00:00 1970
@@ -1,9 +0,0 @@
-# $OpenBSD: Makefile,v 1.2 2004/02/27 19:41:39 david Exp $
-
-PROG= spamlogd
-SRCS= spamlogd.c
-MAN= spamlogd.8
-
-CFLAGS+= -g -Wall -Wstrict-prototypes -ansi -I${.CURDIR}/../spamd
-
-.include <bsd.prog.mk>
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd and /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.8 /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.8
--- /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.8 Sun Oct 3 16:10:56 2004
+++ /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.8 Thu Jan 1 03:00:00 1970
@@ -1,114 +0,0 @@
-.\" $OpenBSD: spamlogd.8,v 1.4 2004/07/14 21:38:09 jmc Exp $
-.\"
-.\" Copyright (c) 2004 Bob Beck. All rights reserved.
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd February 16, 2004
-.Dt SPAMLOGD 8
-.Os
-.Sh NAME
-.Nm spamlogd
-.Nd spamd whitelist updating daemon
-.Sh SYNOPSIS
-.Nm spamlogd
-.Op Fl I
-.Op Fl i Ar interface
-.Sh DESCRIPTION
-.Nm
-manipulates the
-.Xr spamd 8
-database in
-.Pa /var/db/spamd
-used for
-.Xr spamd 8
-greylisting.
-.Nm
-updates the
-.Pa /var/db/spamd
-whitelist entries whenever a connection
-to port 25 is logged to the
-.Xr pflog 4
-interface.
-The source addresses of inbound connections are whitelisted
-when seen by
-.Nm
-to ensure that their entries in
-.Pa /var/db/spamd
-do not expire if the connecting host continues to send legitimate mail.
-The destination addresses of outbound connections are whitelisted
-when seen by
-.Nm
-so that replies to outbound mail may be received without initial
-greylisting delays
-(see
-.Sx GREYLISTING
-in
-.Xr spamd 8 ) .
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl I
-Specify that
-.Nm
-is only to whitelist inbound SMTP connections.
-By default
-.Nm
-will whitelist the source of inbound SMTP connections, and the
-target of outbound SMTP connections.
-.It Fl i Ar interface
-Specify a network interface on which packets must arrive.
-The default is to watch for connections logged from any interfaces.
-.El
-.Pp
-It is important to be sure to log any connections to and from your real
-MTA in order for
-.Nm
-to update the whitelist entries.
-An example
-.Xr pf.conf 5
-configuration for logging such connections is as follows:
-.Bd -literal -offset indent
-EXT_IF = "fxp0"
-MAILHOSTS = "{129.128.11.10, 129.128.11.43}"
-pass in log on $EXT_IF inet proto tcp to $MAILHOSTS \e
- port smtp keep state
-pass out log on $EXT_IF inet proto tcp from $MAILHOSTS \e
- to any port smtp keep state
-.Ed
-.Pp
-.Nm
-sends log messages to
-.Xr syslogd 8
-using facility
-.Em daemon .
-.Nm
-will log each connection it sees at level
-.Dv LOG_DEBUG .
-.Sh FILES
-/var/db/spamd
-.Sh SEE ALSO
-.Xr syslog 3 ,
-.Xr pflog 4 ,
-.Xr spamd.conf 5 ,
-.Xr pflogd 8 ,
-.Xr spamd 8 ,
-.Xr spamd-setup 8 ,
-.Xr spamdb 8 ,
-.Xr syslogd 8 ,
-.Xr tcpdump 8
-.Sh HISTORY
-The
-.Nm
-command first appeared in
-.Ox 3.5 .
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.8.gz and /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.8.gz differ
diff -ruN --exclude=CVS /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.c /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.c
--- /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.c Fri Feb 2 10:58:10 2007
+++ /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.c Thu Jan 1 03:00:00 1970
@@ -1,272 +0,0 @@
-/* $OpenBSD: spamlogd.c,v 1.11 2004/09/18 07:33:03 beck Exp $ */
-
-/*
- * Copyright (c) 2004 Bob Beck. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* watch pf log for mail connections, update whitelist entries. */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <db.h>
-#include <err.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "grey.h"
-#define PATH_TCPDUMP "/usr/sbin/tcpdump"
-
-#ifdef __OpenBSD__
-struct syslog_data sdata = SYSLOG_DATA_INIT;
-#else
-#define syslog_r(l, s, args...) syslog(l,args)
-#define openlog_r(i, l, f, s) openlog(i, l, f)
-int sdata = 0; /* dummy */
-#endif
-int inbound; /* do we only whitelist inbound smtp? */
-
-extern char *__progname;
-
-int
-dbupdate(char *dbname, char *ip)
-{
- BTREEINFO btreeinfo;
- DBT dbk, dbd;
- DB *db;
- struct gdata gd;
- time_t now;
- int r;
- struct in_addr ia;
-
- now = time(NULL);
- memset(&btreeinfo, 0, sizeof(btreeinfo));
- db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
- if (db == NULL)
- return(-1);
- if (inet_pton(AF_INET, ip, &ia) != 1) {
- syslog_r(LOG_NOTICE, &sdata, "invalid ip address %s", ip);
- goto bad;
- }
- memset(&dbk, 0, sizeof(dbk));
- dbk.size = strlen(ip);
- dbk.data = ip;
- memset(&dbd, 0, sizeof(dbd));
- /* add or update whitelist 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.bcount = 1;
- gd.pass = now;
- gd.expire = now + WHITEEXP;
- 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);
- if (r) {
- syslog_r(LOG_NOTICE, &sdata, "db->put failed (%m)");
- goto bad;
- }
- } 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.pcount++;
- gd.expire = now + WHITEEXP;
- 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);
- if (r) {
- syslog_r(LOG_NOTICE, &sdata, "db->put failed (%m)");
- goto bad;
- }
- }
- db->close(db);
- db = NULL;
- return (0);
- bad:
- db->close(db);
- db = NULL;
- return (-1);
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s [-I] [-i interface]\n", __progname);
- exit(1);
-}
-
-char *targv[19] = {
- "tcpdump", "-l", "-n", "-e", "-i", "pflog0", "-q",
- "-t", "port", "25", "and", "action", "pass",
- "and", "tcp[13]&0x12=0x2",
- NULL, NULL, NULL, NULL
-};
-
-int
-main(int argc, char **argv)
-{
- int ch, p[2];
- char *buf, *lbuf;
- size_t len;
- FILE *f;
-
-
- while ((ch = getopt(argc, argv, "i:I")) != -1) {
- switch (ch) {
- case 'i':
- if (targv[17]) /* may only set once */
- usage();
- targv[15] = "and";
- targv[16] = "on";
- targv[17] = optarg;
- break;
- case 'I':
- inbound = 1;
- break;
- default:
- usage();
- break;
- }
- }
-int ii;
-for(ii=0;ii<=17;ii++)
-{
- fprintf(stderr,"test:%d:%s\n",ii,targv[ii]);
-}
-
-/* if (daemon(1, 1) == -1)
- err(1, "daemon"); */
- if (pipe(p) == -1)
- err(1, "pipe");
- switch (fork()) {
- case -1:
- err(1, "fork");
- case 0:
- /* child */
- close(p[0]);
- close(STDERR_FILENO);
- if (dup2(p[1], STDOUT_FILENO) == -1) {
- warn("dup2");
- _exit(1);
- }
- close(p[1]);
- execvp(PATH_TCPDUMP, targv);
- warn("exec of %s failed", PATH_TCPDUMP);
- _exit(1);
- }
- fprintf(stderr,"test2\n");
- /* parent */
- close(p[1]);
- f = fdopen(p[0], "r");
- if (f == NULL)
- err(1, "fdopen");
- tzset();
- fprintf(stderr,"test3\n");
- openlog_r("spamlogd", LOG_PID | LOG_NDELAY, LOG_DAEMON, &sdata);
- fprintf(stderr,"test4\n");
- lbuf = NULL;
- while ((buf = fgetln(f, &len))) {
- char *cp = NULL;
- char *buf2;
-
- if ((buf2 = malloc(len + 1)) == NULL) {
- syslog_r(LOG_ERR, &sdata, "malloc failed");
- fprintf(stderr,"test5.1\n");
- exit(1);
- }
- fprintf(stderr,"test5\n");
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- else {
- if ((lbuf = (char *)malloc(len + 1)) == NULL) {
- syslog_r(LOG_ERR, &sdata, "malloc failed");
- exit(1);
- }
- memcpy(lbuf, buf, len);
- lbuf[len] = '\0';
- buf = lbuf;
- }
- if (strstr(buf, "pass out") != NULL) {
- /*
- * this is outbound traffic - we whitelist
- * the destination address, because we assume
- * that a reply may come to this outgoing mail
- * we are sending.
- */
- if (!inbound && (cp = (strchr(buf, '>'))) != NULL) {
- if (sscanf(cp, "> %s", buf2) == 1) {
- cp = strrchr(buf2, '.');
- if (cp != NULL) {
- *cp = '\0';
- cp = buf2;
- syslog_r(LOG_DEBUG, &sdata,
- "outbound %s\n", cp);
- }
- } else
- cp = NULL;
- }
-
- } else {
- /*
- * this is inbound traffic - we whitelist
- * the source address, because this is
- * traffic presumably to our real MTA
- */
- if ((cp = (strchr(buf, '>'))) != NULL) {
- while (*cp != '.' && cp >= buf) {
- *cp = '\0';
- cp--;
- }
- *cp ='\0';
- while (*cp != ' ' && cp >= buf)
- cp--;
- cp++;
- syslog_r(LOG_DEBUG, &sdata,
- "inbound %s\n", cp);
- }
- }
- if (cp != NULL)
- dbupdate(PATH_SPAMD_DB, cp);
-
- free(lbuf);
- lbuf = NULL;
- free(buf2);
- }
- exit(0);
-}
Binary files /usr/ports/mail/spamd/work/spamd_3.7/spamlogd/spamlogd.o and /usr/home/samm/spamd/work/spamd_3.7/spamlogd/spamlogd.o differ
--- spamd-4.1.1.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list