--- netqmail-1.06.orig/debian/changelog +++ netqmail-1.06/debian/changelog @@ -0,0 +1,273 @@ +netqmail (1.06-5) unstable; urgency=low + + * debian/qmail.postrm: do not forcefully remove files in /etc/qmail/ + (closes: #640593). + * debian/control: Standards-Version: 3.9.3.1. + + -- Gerrit Pape Wed, 11 Apr 2012 23:30:51 +0000 + +netqmail (1.06-4) unstable; urgency=low + + * debian/rules, debian/qmail.postinst, debian/qmail.postrm: don't + include named pipe queue/lock/trigger in the package, but create + in postinst and remove in postrm (policy 10.6). + * debian/control: Standards-Version: 3.8.4.0. + * debian/qmail.postinst: don't restart qmail-send, qmail-verify + services if the update-service program is not available. + + -- Gerrit Pape Thu, 18 Mar 2010 22:38:02 +0000 + +netqmail (1.06-3) unstable; urgency=low + + * debian/diff/0001-Add-realrcptto-functionality-...diff: remove; + obsolete. + * 0001-qmail-errmsg-logging.diff, 0002-qmail-verify.diff; new; add + qmail-verify functionality from Andrew Richards, an update to Paul + Jarc's realrcptto patch. + * debian/rules, debian/sbin: no longer build and install + qmail-smtpd-realrcptto, qmail-qmtpd-realrcptto programs. + * debian/sbin: add qmail-verify. + * debian/diff/0003-qmail-verify-optionally-check-aliases.cdb-...diff: + new: qmail-verify: optionally check aliases.cdb if fastforward is + used. + * debian/qmail.postinst: restart qmail-verify service on upgrade. + * debian/qmail.README.Debian: talk about the qmail-verify and errmsg + patches; typos. + + -- Gerrit Pape Mon, 08 Mar 2010 23:54:13 +0000 + +netqmail (1.06-2) unstable; urgency=low + + * debian/qmail-uids-gids.preinst: don't check and/or create qmail + users and groups in preinst to avoid pre-dependency on adduser. + * debian/qmail-uids-gids.postinst: configure: check and/or create + qmail users and groups. + * debian/rules: place boot/ into /usr/lib/qmail/, link back to + /var/lib/qmail/boot. + * debian/rules, debian/qmail.postinst: install config-fast program + into /usr/lib/qmail/bin/, instead of /var/lib/qmail/bin/. + * debian/control: package qmail: Suggests: fastforward, dot-forward. + * debian/control: Standards-Version: 3.8.0.1. + + -- Gerrit Pape Wed, 27 Aug 2008 20:38:04 +0000 + +netqmail (1.06-1) unstable; urgency=low + + * new upstream version netqmail-1.06. + * debian/control: change Source: to netqmail; no longer Depends: + fastforward, dot-forward; Depends: qmail-uids-gids instead of + Pre-Depends:. + * debian/rules: remove target configure:; use glibc by default instead + of dietlibc; no longer build upstream install, instcheck targets + separately; use proc instead of proc+df as default delivery. + * debian/gcc/, debian/install/: remove; obsolete. + * debian/control: no longer Build-Depends: dietlibc-dev. + * debian/rules: install into /var/lib/qmail/ instead of /var/qmail/; + subdirectory control/ is a symlink to /etc/qmail, and users/ a + symlink to /etc/qmail/users. + * debian/control: add qmail-uids-gids package (previously a separate + unofficial package). + * debian/qmail-uids-gids.README.Debian, qmail-uids-gids.postrm, + debian/qmail-uids-gids.preinst: new; from unofficial package, + slightly adapt; ensure that the proper qmail uids and gids are + installed. + * debian/rules: split install: target into install-arch:, + install-indep:; build qmail-uids-gids package in install-indep:. + * debian/rules: target binary-arch: run dpkg-shlibdeps; target clean: + remove debian/substvars. + * debian/control: Depends: ${shlibs:Depends}; Standards-Version: + 3.7.3.0. + * debian/rules, debian/qmail.postinst, debian/qmail.postinst: the + config-fast program now resides in /var/lib/qmail/bin/ instead of + /etc/qmail/1st-config/. + * debian/rules: target clean: don't ignore error in make clean; drop + /usr/sbin/qmail-rc, drop symlink /etc/qmail/boot -> /var/qmail/boot. + * debian/qmail.conffiles: remove /usr/sbin/qmail-rc (obsolete). + * debian/control: update short and long descriptions; Build-Depends: + qmail-uids-gids (>> 1.06). + * debian/qmail.preinst, debian/qmail-uids-gids.preinst: upgrading qmail + from non-free and unofficial packages is not yet supported. + * debian/implicit: update to revision a09db2e. + * debian/qmail.docs: remove CHANGES, FILES, INSTALL, SYSDEPS, TARGETS, + debian/var-qmail.filelist. + * debian/var-qmail.filelist, debian/mkFilelist: remove; obsolete. + * debian/qmail.postinst: default directory for services in Debian is + /etc/services/; adapt paths; use the update-service program tocheck + whether the qmail-send service is registered. + * debian/qmail.postrm: adapt paths and version check. + * debian/qmail.preinst: remove check for proper qmail uids and gids. + * debian/qmail-uids-gids.preinst: uids and gids are now the same as in + the non-free package, group nofiles is replaced with nogroup; no + longer fixup uids, gids, upgrading is not yet supported. + * debian/rules: target build: set conf-qmail and conf-groups, restore + origs in target clean:. + * debian/control: Recommends: qmail-run (>= 2.0.0), Suggests: + qmail-tools. + * debian/copyright: rewrite copyright. + * debian/qmail-uids-gids.README.Debian, debian/qmail.README.Debian: + redo. + * debian/rules: install cdb.3, error.3, mbox.5 as *.3qmail, *.5qmail + respectively, to avoid conflict with the libcdb-dev, manpages-dev, + mutt packages. + * debian/qmail.preinst, debian/qmail.postrm: no longer divert mutt's + mbox.5 manpage. + * debian/rules: new target patch: apply patches from debian/diff/; + reverse apply in target clean:. + * debian/diff/0001-Add-realrcptto-functionality-...diff: new: Add + realrcptto functionality through qmail-?mtpd-realrcptto. + * debian/rules, debian/sbin: build, install qmail-smtpd-realrcptto, + qmail-qmtpd-realrcptto. + * debian/qmail-uids-gids.postrm, debian/qmail-uids-gids.preinst, + debian/qmail-uids-gids.README.Debian, debian/rules: use nofiles + system group with arbitrary gid. + * debian/control: package qmail-uids-gids: Depends: adduser. + * upload to Debian/main (closes: #457318). + + -- Gerrit Pape Sun, 27 Apr 2008 15:31:23 +0000 + +qmail (1.03-zarge2) sarge; urgency=low + + * build against sarge's dietlibc-dev (0.28-3). + + -- Gerrit Pape Thu, 26 May 2005 18:50:17 +0000 + +qmail (1.03-zarge1) sarge; urgency=low + + * debian/control: Build-Depends: groff-base, instead of groff. + * debian/qmail.postinst, debian/qmail.postrm, debian/qmail.preinst: minor + cleanup. + * debian/rules: minor cleanup. + * debian/implicit: update to revision 1.10. + + -- Gerrit Pape Sun, 15 Aug 2004 16:36:49 +0000 + +qmail (1.03-zarge0.4) sarge; urgency=low + + * debian/control: Pre-Depends: qmail-uids-gids (>> 1.0.0). + * debian/qmail.preinst: run /usr/share/qmail-uids-gids/fixup-nofiles-group. + + -- Gerrit Pape Mon, 26 Apr 2004 17:13:04 +0000 + +qmail (1.03-zarge0.3) sarge; urgency=low + + * debian/control: no longer Build-Depends: dephelper; remove + Standards-Version. + * debian/rules: stop using debhelper, use implicit rules. + * debian/implicit: new; implicit Makefile rules. + * debian/README.Debian: rename to qmail.README.Debian; minor. + * debian/conffiles, debian/docs: rename to debian/qmail.*. + * debian/dirs, debian/links.in, debian/links.sendmail: remove; obsolete. + * debian/copyright: minor. + * debian/preinst, debian/postrm: rename to debian/qmail.*; cleanup. + * debian/postinst: rename to debian/qmail.postinst; cleanup; check for + hostname -f returning a hostname containing a dot (thx benoit delagarde). + + -- Gerrit Pape Mon, 12 Apr 2004 13:43:46 +0000 + +qmail (1.03-zarge0.2) sarge; urgency=low + + * use diet libc. + * debian/rules: new target configure: set up diet program as c compiler + wrapper; conditionally overwrite PATH to have diet program used as c + compiler wrapper; extra build dynamic install and instcheck programs + to perform install and check (supports fakeroot); minor cleanup. + * debian/gcc/gcc*: new; diet program as c compiler wrapper. + * debian/install/Makefile: new; build dynamically linked install and + instcheck programs. + * debian/control: Build-Depends: dietlibc-dev; no longer Depends: + ${shlibs:Depends}. + + -- Gerrit Pape Wed, 12 Nov 2003 12:18:18 +0000 + +qmail (1.03-woody1) woody; urgency=low + + * bump version for release. + + -- Gerrit Pape Tue, 9 Jul 2002 11:05:19 +0200 + +qmail (1.03-woody0.7) woody; urgency=low + + * debian/postrm, debian/preinst: quoting variables. + * debian/preinst: change function declaration syntax (bashism?) to + support more /bin/sh shells, e.g. ash (thx Esben Haabendal Soerensen, + Joost van Baal). + + -- Gerrit Pape Mon, 8 Apr 2002 11:49:41 +0200 + +qmail (1.03-woody0.6) woody; urgency=low + + * woody package; new Standards-Version: 3.5.2. + * provides diversion of mutt's mbox.5.gz to mbox-mutt.5.gz. + * preinst: script cleanup. + * postrm: purge control/* and empty directories on purge. + * pre-depends on qmail-uids-gids. + * supports upgrade from qmail-1.03-20 built by qmail-src (woody); + anyway, it is recommended to purge qmail-1.03-20 first, use: + # dpkg --purge --force-depends qmail + * /var/qmail/rc -> /usr/sbin/qmail-rc marked as conffile. + * doc: improved. + + -- Gerrit Pape Thu, 25 Oct 2001 15:48:40 +0200 + +qmail (1.03-1) stable; urgency=low + + * 1st debian version, no other changes. + + -- Gerrit Pape Thu, 1 Feb 2001 10:01:45 +0100 + +qmail (1.03-0.7) unstable; urgency=low + + * build-depends and depends on qmail-uids-gids. + + -- Gerrit Pape Mon, 18 Dec 2000 15:11:57 +0100 + +qmail (1.03-0.6) unstable; urgency=low + + * removed man-pages also installed in section 9. + + -- Gerrit Pape Fri, 17 Nov 2000 12:10:52 +0100 + +qmail (1.03-0.5) unstable; urgency=low + + * preinst: uids and gid are checked if they exist, if not they are + installed after 5sec timeout. They are also checked against the + uid/gis-Installation of the package qmail-src and may update the + entries interactively. + + -- Gerrit Pape Mon, 29 May 2000 11:21:52 +0200 + +qmail (1.03-0.4) unstable; urgency=low + + * /etc/mailname handling removed. config-fast is called with the output of + hostname -f as argument. + + -- Gerrit Pape Wed, 3 May 2000 12:50:53 +0200 + +qmail (1.03-0.3) unstable; urgency=low + + * Documentation. + * this package does not longer provide/replace mail-transfer-agent, + qmail-run is doing that. + * config-fast is run in postinst, if qmail is unconfigured. + * binaries moved to /usr/{bin,sbin} and linked back to /var/qmail/bin/. + * /var/qmail/{control,boot,users} is accessible through /etc/qmail/. + + -- Gerrit Pape Tue, 2 May 2000 09:29:33 +0200 + +qmail (1.03-0.2) unstable; urgency=low + + * using /etc/mailname for /var/qmail/control/defaulthost. + * prompt for 'mail name' if /etc/mailname does not exist. + * depend on fastforward, using of /etc/aliases is default. + + -- Gerrit Pape Tue, 18 Apr 2000 19:27:22 +0200 + +qmail (1.03-0.1) unstable; urgency=low + + * Initial Release. + + -- Gerrit Pape Thu, 13 Apr 2000 09:41:23 +0200 + +Local variables: +mode: debian-changelog +End: --- netqmail-1.06.orig/debian/qmail-uids-gids.postrm +++ netqmail-1.06/debian/qmail-uids-gids.postrm @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +test "$1" = 'purge' || exit 0 + +cat < +Build-Depends: qmail-uids-gids (>> 1.06), groff-base +Standards-Version: 3.9.3.1 + +Package: qmail +Architecture: any +Depends: ${shlibs:Depends}, qmail-uids-gids (>> 1.06) +Recommends: qmail-run (>= 2.0.0) +Suggests: fastforward, dot-forward, qmail-tools +Description: a secure, reliable, efficient, simple message transfer agent + qmail is meant as a replacement for the entire sendmail-binmail system on + typical Internet-connected UNIX hosts. + . + This package is based on the netqmail distribution of qmail, put + together by a motley krewe of qmail contributors (see the README). + It is derived from Daniel Bernstein's qmail-1.03 plus bug fixes, + a few feature enhancements, and some documentation. + +Package: qmail-uids-gids +Architecture: all +Depends: passwd, adduser +Description: user ids and group ids for qmail + This package is mandatory for building and running the qmail package. --- netqmail-1.06.orig/debian/rules +++ netqmail-1.06/debian/rules @@ -0,0 +1,114 @@ +#!/usr/bin/make -f + +STRIP =strip +ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + STRIP =: nostrip +endif + +DIR=$(shell pwd)/debian/qmail + +patch: deb-checkdir patch-stamp +patch-stamp: + for i in `ls -1 debian/diff/*.diff || :`; do \ + patch -p1 <$$i || exit 1; \ + done + touch patch-stamp + +build: deb-checkdir build-stamp +build-stamp: patch-stamp + test -r conf-qmail'{orig}' || cp conf-qmail conf-qmail'{orig}' + echo /var/lib/qmail >conf-qmail + $(MAKE) it man + touch build-stamp + +clean: deb-checkdir deb-checkuid + $(MAKE) clean + test ! -r conf-qmail'{orig}' || mv -f conf-qmail'{orig}' conf-qmail + test ! -e patch-stamp || \ + for i in `ls -1r debian/diff/*.diff || :`; do patch -p1 -R <$$i; done + rm -f build-stamp patch-stamp + rm -rf '$(DIR)' '$(DIR)'-uids-gids + rm -f debian/files debian/substvars changelog + +install: install-arch install-indep +install-arch: deb-checkdir deb-checkuid build-stamp + rm -rf '$(DIR)' + install -d -m0755 '$(DIR)'/var/lib/qmail + test -r conf-qmail'{orig}' || cp conf-qmail conf-qmail'{orig}' + echo '$(DIR)'/var/lib/qmail >conf-qmail + rm -f auto_qmail.[co] + sleep 1 + $(MAKE) install instcheck + ./install + ./instcheck + for i in bouncesaying condredirect except forward maildir2mbox \ + maildirmake maildirwatch predate preline qbiff qmail-clean \ + qmail-getpw qmail-inject qmail-local qmail-lspawn qmail-newmrh \ + qmail-newu qmail-pop3d qmail-popup qmail-pw2u qmail-qmqpc \ + qmail-qmqpd qmail-qmtpd qmail-qread qmail-queue qmail-remote \ + qmail-rspawn qmail-send qmail-showctl qmail-smtpd qmail-start \ + qmail-tcpok qmail-tcpto qreceipt qsmhook sendmail splogger tcp-env; \ + do $(STRIP) -R .comment -R .note '$(DIR)'/var/lib/qmail/bin/$$i \ + || exit 1; \ + done + install -d -m0755 '$(DIR)'/usr/bin + install -d -m0755 '$(DIR)'/usr/sbin + install -d -m0755 '$(DIR)'/etc/qmail + install -d -m0755 '$(DIR)'/usr/lib/qmail/bin + install -m0755 config-fast '$(DIR)'/usr/lib/qmail/bin/config-fast + # move and link binaries + for i in bin sbin; do \ + for j in `cat debian/$${i}`; do \ + mv -f '$(DIR)'/var/lib/qmail/bin/$${j} '$(DIR)'/usr/$${i}/$${j} && \ + ln -s /usr/$${i}/$${j} '$(DIR)'/var/lib/qmail/bin/$${j} || exit 1; \ + done; \ + done; + mv -f '$(DIR)'/var/lib/qmail/bin/sendmail '$(DIR)'/usr/sbin/qmail-sendmail + ln -s /usr/sbin/qmail-sendmail '$(DIR)'/var/lib/qmail/bin/sendmail + # docs are in /usr/share/doc/qmail (implicit) + rm -rf '$(DIR)'/var/lib/qmail/doc + ln -s /usr/share/doc/qmail '$(DIR)'/var/lib/qmail/doc + # place users/ into /etc/qmail/, link back + mv '$(DIR)'/var/lib/qmail/users '$(DIR)'/etc/qmail/ + ln -s /etc/qmail/users '$(DIR)'/var/lib/qmail/users + # place boot/ into /usr/lib/qmail/, link back + mv '$(DIR)'/var/lib/qmail/boot '$(DIR)'/usr/lib/qmail/ + ln -s /usr/lib/qmail/boot '$(DIR)'/var/lib/qmail/boot + # control/ is /etc/qmail/ + rmdir '$(DIR)'/var/lib/qmail/control + ln -s /etc/qmail '$(DIR)'/var/lib/qmail/control + # policy 10.6, create named pipe in postinst, remove in postrm + rm -f '$(DIR)'/var/lib/qmail/queue/lock/trigger + # man pages system-wide + rm -rf '$(DIR)'/var/lib/qmail/man + for i in 1 3 5 7 8; do \ + install -d -m0755 '$(DIR)'/usr/share/man/man$$i && \ + for j in *.$$i; do \ + install -m0644 $$j '$(DIR)'/usr/share/man/man$$i/ || exit 1; \ + done || exit 1; \ + done + for i in cdb.3 error.3 mbox.5; do \ + mv '$(DIR)'/usr/share/man/man$${i##*.}/$$i \ + '$(DIR)'/usr/share/man/man$${i##*.}/$${i}qmail || exit 1; \ + done + gzip -9 '$(DIR)'/usr/share/man/man?/* + # changelog + rm -f changelog && ln -s CHANGES changelog +install-indep: deb-checkdir deb-checkuid + # qmail-uids-gids + rm -rf '$(DIR)'-uids-gids + install -d -m0755 '$(DIR)'-uids-gids + rm -f changelog && ln -s CHANGES changelog + +binary: binary-indep binary-arch +binary-arch: install-arch qmail.deb + dpkg-shlibdeps '$(DIR)'/usr/bin/* '$(DIR)'/usr/sbin/* + dpkg-gencontrol -isp -pqmail -P'$(DIR)' + dpkg -b '$(DIR)' .. +binary-indep: install-indep qmail-uids-gids.deb + dpkg-gencontrol -isp -pqmail-uids-gids -P'$(DIR)'-uids-gids + dpkg -b '$(DIR)'-uids-gids .. + +.PHONY: patch build clean install binary-indep binary-arch binary + +include debian/implicit --- netqmail-1.06.orig/debian/qmail-uids-gids.README.Debian +++ netqmail-1.06/debian/qmail-uids-gids.README.Debian @@ -0,0 +1,25 @@ +qmail-uids-gids for Debian +-------------------------- + +This package ensures that the following users and groups are installed on +this system: + +/etc/passwd: +alias:x:64010:65534:qmail alias:/var/lib/qmail/alias:/bin/sh +qmaild:x:64011:65534:qmail daemon:/var/lib/qmail:/bin/sh +qmails:x:64012:64010:qmail send:/var/lib/qmail:/bin/sh +qmailr:x:64013:64010:qmail remote:/var/lib/qmail:/bin/sh +qmailq:x:64014:64010:qmail queue:/var/lib/qmail:/bin/sh +qmaill:x:64015:65534:qmail log:/var/lib/qmail:/bin/sh +qmailp:x:64016:65534:qmail pw:/var/lib/qmail:/bin/sh + +/etc/group: +qmail:x:64010: +nofiles:x:65534: + +These uids and gids are mandatory for building and running qmail. Do not +change them while this package is installed. + +Uninstalling this package will not remove these uids and gids. + + -- Gerrit Pape , Mon, 18 Dec 2000 14:32:38 +0100 --- netqmail-1.06.orig/debian/qmail-uids-gids.postinst +++ netqmail-1.06/debian/qmail-uids-gids.postinst @@ -0,0 +1,153 @@ +#!/bin/sh +set -e + +test "$1" = 'configure' || exit 0 + +errcho () { + echo "$*" >&2 +} + +check_uidgid () { + USER=$1 + ID=$2 + GROUP=$3 + GID=$4 + HOM=$5 + + # check for user + ID_=`id -u ${USER} 2>/dev/null` || return 1 + if test "$ID_" -ne "$ID"; then + errcho "$USER: uid must be \"$ID\", not \"$ID_\"." + return 2 + fi + # check group + GROUP_=`id -gn ${USER} 2>/dev/null` || return 100 + if test "$GROUP_" != "$GROUP"; then + errcho "$USER: must be group \"$GROUP\", not \"$GROUP_\"." + return 3 + fi + GID_=`id -g ${USER} 2>/dev/null` || return 100 + if test "$GID" -ne 0 && test "$GID_" -ne "$GID"; then + errcho "$GROUP: gid must be \"$GID\", not \"$GID_\"." + return 4 + fi + # check home + HOM_=`grep -E "^$USER:*" /etc/passwd | cut -d : -f 6` || return 100 + if test "$HOM_" != "$HOM"; then + errcho "$USER: home must be \"$HOM\", not \"$HOM_\"." + return 5 + fi + # ok + return 0 +} +add_usersgroups () { + DEBUG=$* + + $DEBUG groupadd -g 64010 qmail || return 1 + $DEBUG addgroup --system nofiles || return 1 + $DEBUG useradd -u 64010 -g nofiles -d /var/lib/qmail/alias alias || return 1 + $DEBUG useradd -u 64011 -g nofiles -d /var/lib/qmail qmaild || return 1 + $DEBUG useradd -u 64015 -g nofiles -d /var/lib/qmail qmaill || return 1 + $DEBUG useradd -u 64016 -g nofiles -d /var/lib/qmail qmailp || return 1 + $DEBUG useradd -u 64014 -g qmail -d /var/lib/qmail qmailq || return 1 + $DEBUG useradd -u 64013 -g qmail -d /var/lib/qmail qmailr || return 1 + $DEBUG useradd -u 64012 -g qmail -d /var/lib/qmail qmails || return 1 + # done + return 0 +} +check_user () { + getent passwd "$1" >/dev/null || return 0 + errcho "user \"$1\" found in the passwd database." + return 1 +} +check_uid () { + getent passwd "$1" >/dev/null || return 0 + errcho "uid \"$1\" found in the passwd database." + return 1 +} +check_gid () { + getent group "$1" >/dev/null || return 0 + errcho "gid \"$1\" found in the group database." + return 1 +} +check_group () { + getent group "$1" >/dev/null || return 0 + errcho "group \"$1\" found in the group database." + return 1 +} +stopinst () { + cat <&2 + +You must have the following entries in /etc/passwd and /etc/group to install +the Debian qmail packages on this system; if none of these users and groups +exist yet, this package will add them automatically. + +/etc/passwd: +alias:x:64010:XXXXX:qmail alias:/var/lib/qmail/alias:/bin/sh +qmaild:x:64011:XXXXX:qmail daemon:/var/lib/qmail:/bin/sh +qmails:x:64012:64010:qmail send:/var/lib/qmail:/bin/sh +qmailr:x:64013:64010:qmail remote:/var/lib/qmail:/bin/sh +qmailq:x:64014:64010:qmail queue:/var/lib/qmail:/bin/sh +qmaill:x:64015:XXXXX:qmail log:/var/lib/qmail:/bin/sh +qmailp:x:64016:XXXXX:qmail pw:/var/lib/qmail:/bin/sh +/etc/group: +qmail:x:64010: +nofiles:x:XXXXX: + +Where XXXXX is an abritary system group id for the 'nofiles' group. + +Installation aborted. + +EOT + exit 1 +} + +# check uids and gids +ALIAS="alias 64010 nofiles 0 /var/lib/qmail/alias" +QMAILD="qmaild 64011 nofiles 0 /var/lib/qmail" +QMAILL="qmaill 64015 nofiles 0 /var/lib/qmail" +QMAILP="qmailp 64016 nofiles 0 /var/lib/qmail" +QMAILQ="qmailq 64014 qmail 64010 /var/lib/qmail" +QMAILR="qmailr 64013 qmail 64010 /var/lib/qmail" +QMAILS="qmails 64012 qmail 64010 /var/lib/qmail" + +RC=0 +check_uidgid $ALIAS || RC=$? +if test "$RC" -eq 1; then + # check for any existing qmail-groups + for i in alias qmaild qmaill qmailp qmailq qmailr qmails; do + check_user $i || stopinst + done + check_group qmail || stopinst + for i in 64010 64011 64012 64013 64014 64015 64016; do + check_uid $i || stopinst + done + check_gid 64010 || stopinst + cat < /var/lib/qmail after installing this package, do + + # ln -s /var/lib/qmail /var/qmail + +daemontools' (and runit's) directory for supervised services on Debian is +/etc/service/, not /service/. To be consistent with existing programs and +documentation, it is recommended to create a compatibility symlink +/service -> /etc/service. If not yet done, do + + # ln -s /etc/service /service + + +[0] http://lifewithqmail.org/lwq.html +[1] http://free.acrconsulting.co.uk/email/qmail-verify.html +[2] http://free.acrconsulting.co.uk/email/qmail-errmsg.html + + -- Gerrit Pape , Wed, 23 Apr 2008 01:47:25 +0000 --- netqmail-1.06.orig/debian/qmail.docs +++ netqmail-1.06/debian/qmail.docs @@ -0,0 +1,33 @@ +BLURB +BLURB2 +BLURB3 +BLURB4 +FAQ +INSTALL.alias +INSTALL.ctl +INSTALL.ids +INSTALL.maildir +INSTALL.mbox +INSTALL.vsm +INTERNALS +PIC.local2alias +PIC.local2ext +PIC.local2local +PIC.local2rem +PIC.local2virt +PIC.nullclient +PIC.relaybad +PIC.relaygood +PIC.rem2local +README +REMOVE.binmail +REMOVE.sendmail +SECURITY +SENDMAIL +TEST.deliver +TEST.receive +THANKS +THOUGHTS +TODO +UPGRADE +VERSION --- netqmail-1.06.orig/debian/qmail-uids-gids.preinst +++ netqmail-1.06/debian/qmail-uids-gids.preinst @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +test "$1" = 'upgrade' || exit 0 +dpkg --compare-versions "$2" lt 1.06 || exit 0 + +cat >&2 <<-EOT + Upgrading qmail-uids-gids from version $2 is not yet supported. + + EOT +exit 1 --- netqmail-1.06.orig/debian/bin +++ netqmail-1.06/debian/bin @@ -0,0 +1,23 @@ +datemail +elq +maildir2mbox +maildirmake +maildirwatch +mailsubj +pinq +qail +qmail-inject +qmail-showctl +qmail-tcpto + +splogger +predate +tcp-env +qreceipt +qsmhook +qbiff +forward +preline +condredirect +bouncesaying +except --- netqmail-1.06.orig/debian/sbin +++ netqmail-1.06/debian/sbin @@ -0,0 +1,23 @@ +qmail-newmrh +qmail-newu +qmail-pw2u +qmail-qread +qmail-qstat +qmail-tcpok + +qmail-queue +qmail-lspawn +qmail-start +qmail-getpw +qmail-local +qmail-remote +qmail-rspawn +qmail-clean +qmail-send +qmail-pop3d +qmail-popup +qmail-qmqpc +qmail-qmqpd +qmail-qmtpd +qmail-smtpd +qmail-verify --- netqmail-1.06.orig/debian/qmail.preinst +++ netqmail-1.06/debian/qmail.preinst @@ -0,0 +1,27 @@ +#!/bin/sh +set -e + +errcho() { + echo "$*" >&2 +} + +if test "$1" = upgrade && dpkg --compare-versions "$2" lt 1.06; then + case "$2" in + *zarge*) + if test -x /usr/lib/qmail/prepare-upgrade-from-unofficial; then + /usr/lib/qmail/prepare-upgrade-from-unofficial + else + errcho "Upgrading from qmail version $2 is not yet supported." + exit 1 + fi + ;; + *) + if test -x /usr/lib/qmail/prepare-upgrade-from-nonfree; then + /var/usr/qmail/prepare-upgrade-from-nonfree + else + errcho "Upgrading from qmail version $2 is not yet supported." + exit 1 + fi + ;; + esac +fi --- netqmail-1.06.orig/debian/implicit +++ netqmail-1.06/debian/implicit @@ -0,0 +1,93 @@ +# $Id: a09db2e42c8b6a2d820754d741558e5894944746 $ + +.PHONY: deb-checkdir deb-checkuid + +deb-checkdir: + @test -e debian/control || sh -cx '! : wrong directory' +deb-checkuid: + @test "`id -u`" -eq 0 || sh -cx '! : need root privileges' + +%.deb: %.deb-docs %.deb-DEBIAN + @rm -f $*.deb $*.deb-checkdir $*.deb-docs $*.deb-docs-base \ + $*.deb-docs-docs $*.deb-docs-examples $*.deb-DEBIAN \ + $*.deb-DEBIAN-dir $*.deb-DEBIAN-scripts $*.deb-DEBIAN-md5sums + +%.udeb: %.deb-DEBIAN + @rm -f $*.deb $*.deb-checkdir $*.deb-DEBIAN $*.deb-DEBIAN-dir \ + $*.deb-DEBIAN-scripts $*.deb-DEBIAN-md5sums + +%.deb-checkdir: install + @test -d debian/$* || sh -cx '! : directory debian/$* missing' + @test "`id -u`" -eq 0 || sh -cx '! : need root privileges' + +%.deb-docs-base: install + : implicit + @rm -f debian/$*/usr/share/doc/$*/* || : + @install -d -m0755 debian/$*/usr/share/doc/$* + : debian/$*/usr/share/doc/$*/ + @sh -cx 'install -m0644 debian/copyright debian/$*/usr/share/doc/$*/' + @sh -cx 'install -m0644 debian/changelog \ + debian/$*/usr/share/doc/$*/changelog.Debian' + @test ! -r changelog || \ + sh -cx 'install -m0644 changelog debian/$*/usr/share/doc/$*/' + @test -r debian/$*/usr/share/doc/$*/changelog || \ + sh -cx 'mv debian/$*/usr/share/doc/$*/changelog.Debian \ + debian/$*/usr/share/doc/$*/changelog' + @test -s debian/$*/usr/share/doc/$*/changelog || \ + sh -cx 'rm -f debian/$*/usr/share/doc/$*/changelog' + @gzip -9 debian/$*/usr/share/doc/$*/changelog* +%.deb-docs-docs: %.deb-docs-base + @for i in `cat debian/$*.docs 2>/dev/null || :`; do \ + if test -d $$i; then \ + sh -cx "install -d -m0755 debian/$*/usr/share/doc/$*/$${i##*/}" && \ + for j in $$i/*; do \ + sh -cx "install -m0644 $$j \ + debian/$*/usr/share/doc/$*/$${i##*/}/" || exit 1; \ + done || exit 1; \ + continue; \ + fi; \ + sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/" || exit 1; \ + done + @test ! -r debian/$*.README.Debian || \ + sh -cx 'install -m0644 debian/$*.README.Debian \ + debian/$*/usr/share/doc/$*/README.Debian' + @if test -r debian/$*.NEWS.Debian; then \ + sh -cx 'install -m0644 debian/$*.NEWS.Debian \ + debian/$*/usr/share/doc/$*/NEWS.Debian && \ + gzip -9 debian/$*/usr/share/doc/$*/NEWS.Debian'; \ + fi +%.deb-docs-examples: %.deb-docs-docs + @rm -rf debian/$*/usr/share/doc/$*/examples + : debian/$*/usr/share/doc/$*/examples/ + @test ! -r debian/$*.examples || \ + install -d -m0755 debian/$*/usr/share/doc/$*/examples + @for i in `cat debian/$*.examples 2>/dev/null || :`; do \ + sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/examples/" \ + || exit 1; \ + done +%.deb-docs: %.deb-checkdir %.deb-docs-base %.deb-docs-docs %.deb-docs-examples + : debian/$*/usr/share/doc/$*/ ok + +%.deb-DEBIAN-base: install + @rm -rf debian/$*/DEBIAN + : debian/$*/DEBIAN/ + @install -d -m0755 debian/$*/DEBIAN + @for i in conffiles shlibs templates; do \ + test ! -r debian/$*.$$i || \ + sh -cx "install -m0644 debian/$*.$$i debian/$*/DEBIAN/$$i" \ + || exit 1; \ + done +%.deb-DEBIAN-scripts: %.deb-DEBIAN-base + @for i in preinst prerm postinst postrm config; do \ + test ! -r debian/$*.$$i || \ + sh -cx "install -m0755 debian/$*.$$i debian/$*/DEBIAN/$$i" \ + || exit 1; \ + done +%.deb-DEBIAN-md5sums: %.deb-DEBIAN-base %.deb-docs + : debian/$*/DEBIAN/md5sums + @rm -f debian/$*/DEBIAN/md5sums + @cd debian/$* && find * -path 'DEBIAN' -prune -o \ + -type f -exec md5sum {} >>DEBIAN/md5sums \; +%.deb-DEBIAN: %.deb-checkdir %.deb-DEBIAN-base %.deb-DEBIAN-scripts \ + %.deb-DEBIAN-md5sums + : debian/$*/DEBIAN/ ok --- netqmail-1.06.orig/debian/copyright +++ netqmail-1.06/debian/copyright @@ -0,0 +1,55 @@ +This package was debianized by Gerrit Pape on +Thu, 13 Apr 2000 09:41:23 +0200. + +It was downloaded from http://qmail.org/netqmail-1.06.tar.gz + +Upstream Authors: D. J. Bernstein + Russ Nelson + Charles Cazabon + Dave Sill + Peter Samuel + Henning Brauer + Andrew Richards + Richard Lyons + John Levine + Scott Gifford + Kyle Wheeler + Wayne Marshall + +Copyright: + +D. J. Bernstein placed the qmail-1.03 package into the public domain. +From http://cr.yp.to/qmail/dist.html + I hereby place the qmail package (in particular, qmail-1.03.tar.gz, + with MD5 checksum 622f65f982e380dbe86e6574f3abcb7c) into the public + domain. You are free to modify the package, distribute modified + versions, etc. + +James Craig Burley claims copyright on the qmail-isoc patch. + +Apart from James' copyrights, no other copyright is claimed by the +distributors of netqmail for changes from qmail 1.03 to netqmail 1.06. + +The qmail-isoc patch is Copyright (C) 2004 by James Craig Burley; +license: +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +The rest of the package is in the public domain. --- netqmail-1.06.orig/debian/qmail.postrm +++ netqmail-1.06/debian/qmail.postrm @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +rm -f /var/lib/qmail/queue/lock/trigger +test ! -d /var/lib/qmail/queue/lock || rmdir /var/lib/qmail/queue/lock || : +test ! -d /var/lib/qmail/queue || rmdir /var/lib/qmail/queue || : +test ! -d /var/lib/qmail || rmdir /var/lib/qmail || : + +test "$1" = 'purge' || exit 0 +rm -f /etc/qmail/users/* +test ! -d /etc/qmail/users || rmdir /etc/qmail/users || : +test ! -d /etc/qmail || rmdir /etc/qmail || : --- netqmail-1.06.orig/debian/qmail.postinst +++ netqmail-1.06/debian/qmail.postinst @@ -0,0 +1,58 @@ +#!/bin/sh +set -e + +stopinst() { + cat <<-\EOT >&2 + + The hostname -f command returned: $1 + + Your system needs to have a fully qualified domain name (fqdn) in + order to install the var-qmail packages. + + Installation aborted. + + EOT + exit 1 +} +config() { + HN="`hostname -f 2>&1`" || stopinst "$HN" + echo "$HN" |grep -F . >/dev/null || stopinst "$HN" + /usr/lib/qmail/bin/config-fast "$HN" +} + +test "$1" = 'configure' || exit 0 + +# policy 10.6: create named pipe not included in the package +if test ! -p /var/lib/qmail/queue/lock/trigger; then + rm -f /var/lib/qmail/queue/lock/trigger + mkfifo -m0622 /var/lib/qmail/queue/lock/trigger + chown qmails:qmail /var/lib/qmail/queue/lock/trigger +fi + +if test -f /var/lib/qmail/control/me; then + cat <<-\EOT + You already have a '/var/lib/qmail/control/me', assuming that + qmail on your system is already configured. + EOT +else + config +fi + +test -n "$2" || exit 0 + +# upgrading +if test ! -x /usr/sbin/update-service; then + cat <<-\EOT + The update-service program is not available, assuming no qmail + services need to be restarted. + EOT + exit 0 +fi +if update-service --check qmail-send; then + echo 'Restarting qmail-send...' + svc -t /etc/service/qmail-send +fi +if update-service --check qmail-verify; then + echo 'Restarting qmail-verify...' + svc -t /etc/service/qmail-verify +fi --- netqmail-1.06.orig/debian/diff/0002-qmail-verify.diff +++ netqmail-1.06/debian/diff/0002-qmail-verify.diff @@ -0,0 +1,1273 @@ +From f035d0b17145b78ae5490eb3d95ac72de188ae65 Mon Sep 17 00:00:00 2001 +From: Gerrit Pape +Date: Thu, 4 Mar 2010 22:33:00 +0000 +Subject: [PATCH 2/3] qmail-verify + +This patchset adds a feature to qmail-smtpd's behaviour, enabled by an +environment variable: Each recipient specified in the SMTP session (RCPT +command) may be verified to see if it is a valid address on the system. A +new daemon, qmail-verify is used by qmail-smtpd to determine if addresses +are valid; qmail-smtpd communicates with qmail-verify using UDP. + +Patch is from Andrew Richards +http://free.acrconsulting.co.uk/sw/qv/qmail-verify_v1.32.patch +http://free.acrconsulting.co.uk/email/qmail-verify.html + + " +Security + +Here are some notes relating to security with this patchset, these notes +are unlikely to be exhaustive: + +It is conceivable that an attacker or spammer could abuse a system patched +using this patchset to mount dictionary attacks. To vary how a +qmail-verify patched system responds, you should make sure you understand +the difference between immediate and DEFERred recipient verification and +set your system appropriately. Immediate verification is likely to be more +attractive to an attacker/spammer. + +On the other hand, with this patchset you have a greater degree of +certainty that messages in the queue for local users are destined for real +mailboxes. + +This patchset deliberately splits the functionality of the original +realrcptto patch such that the address verification part runs as a +separate daemon, qmail-verify (running as root), with qmail-smtpd still +able to run as user qmaild. This also means that the changes to +qmail-smtpd are minimal. + +There is no attempt made to check that the replies to the queries to +qmail-verify are genuine: It is conceivable that an attacker might wish to +generate spoof UDP replies to tell qmail-smtpd that an address is valid. +For this to occur, the attacker would either need to be a 'local' user to +generate such 'replies' on the loopback interface (default configuration), +or qmail-verify would need to be running on an external interface. In the +latter case it should be possible to block the qmail-verify port at a +firewall. + +All that said however, such an attack is of limited use, since qmail will +still bounce the message at delivery time for an invalid recipient. + " +--- + Makefile | 59 +++++++- + TARGETS | 7 + + hier.c | 3 + + qmail-smtpd.8 | 63 ++++++++- + qmail-smtpd.c | 49 +++++++ + qmail-verify.8 | 136 +++++++++++++++++ + qmail-verify.c | 438 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + qmail-verify.h | 34 +++++ + scan.h | 3 + + scan_misc.c | 39 +++++ + sockbits.c | 31 ++++ + sockbits.h | 1 + + udpbits.c | 24 +++ + udpbits.h | 1 + + verifyrcpt.c | 45 ++++++ + verifyrcpt.h | 3 + + 16 files changed, 932 insertions(+), 4 deletions(-) + create mode 100644 qmail-verify.8 + create mode 100644 qmail-verify.c + create mode 100644 qmail-verify.h + create mode 100644 scan_misc.c + create mode 100644 sockbits.c + create mode 100644 sockbits.h + create mode 100644 udpbits.c + create mode 100644 udpbits.h + create mode 100644 verifyrcpt.c + create mode 100644 verifyrcpt.h + +diff --git a/Makefile b/Makefile +index a27a809..69d401d 100644 +--- a/Makefile ++++ b/Makefile +@@ -812,7 +812,7 @@ dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ + forward preline condredirect bouncesaying except maildirmake \ + maildir2mbox maildirwatch qail elq pinq idedit install-big install \ + instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \ +-binm3 binm3+df ++binm3 binm3+df qmail-verify + + load: \ + make-load warn-auto.sh systype +@@ -939,7 +939,7 @@ preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \ + maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \ + qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \ + qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \ +-envelopes.0 forgeries.0 ++envelopes.0 forgeries.0 qmail-verify.0 + + mbox.0: \ + mbox.5 +@@ -1537,14 +1537,19 @@ auto_split.h + + qmail-smtpd: \ + load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ ++sockbits.o udpbits.o verifyrcpt.o \ + timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ +-date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ ++date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ ++scan_misc.o \ ++datetime.a getln.a \ + open.a sig.a case.a env.a stralloc.a errbits.o \ + alloc.a substdio.a error.a str.a \ + fs.a auto_qmail.o socket.lib + ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ ++ sockbits.o udpbits.o verifyrcpt.o \ + timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ + received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ ++ scan_misc.o \ + datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ + errbits.o \ + alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ +@@ -1559,6 +1564,7 @@ compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \ + substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ + error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ + substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ ++sockbits.h udpbits.h qmail-verify.h \ + exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h + ./compile qmail-smtpd.c + +@@ -1633,6 +1639,31 @@ qmail-users.9 conf-break conf-spawn + | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + > qmail-users.5 + ++qmail-verify.o: \ ++qmail-verify.h compile qmail-verify.c auto_break.h auto_usera.h auto_qmail.h byte.h case.h cdb.h \ ++constmap.h error.h fmt.h ip.h open.h str.h stralloc.h uint32.h errbits.h ++ ./compile qmail-verify.c ++ ++qmail-verify: \ ++load qmail-verify.o timeoutread.o \ ++timeoutwrite.o control.o ip.o constmap.o \ ++cdb.a fd.a wait.a getln.a \ ++open.a sig.a case.a env.a stralloc.a \ ++auto_usera.o auto_break.o auto_qmail.o errbits.o \ ++alloc.a substdio.a error.a str.a fs.a \ ++socket.lib ++ ./load qmail-verify timeoutread.o \ ++ timeoutwrite.o control.o ip.o constmap.o \ ++ cdb.a fd.a wait.a \ ++ getln.a open.a sig.a case.a env.a stralloc.a \ ++ auto_usera.o auto_break.o auto_qmail.o errbits.o \ ++ alloc.a substdio.a error.a str.a fs.a `cat \ ++ socket.lib` ++ ++qmail-verify.0: \ ++qmail-verify.8 ++ nroff -man qmail-verify.8 > qmail-verify.0 ++ + qmail.0: \ + qmail.7 + nroff -man qmail.7 > qmail.0 +@@ -1706,6 +1737,10 @@ scan_8long.o: \ + compile scan_8long.c scan.h + ./compile scan_8long.c + ++scan_misc.o: \ ++compile scan_misc.c scan.h ++ ./compile scan_misc.c ++ + scan_ulong.o: \ + compile scan_ulong.c scan.h + ./compile scan_ulong.c +@@ -1777,6 +1812,7 @@ qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \ + qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \ + qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \ + qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \ ++qmail-verify.8 \ + qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \ + qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \ + qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \ +@@ -1889,6 +1925,10 @@ compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \ + error.h + ./compile slurpclose.c + ++sockbits.o: \ ++compile sockbits.c sockbits.h stralloc.h gen_alloc.h ++ ./compile sockbits.c ++ + socket.lib: \ + trylsock.c compile load + ( ( ./compile trylsock.c && \ +@@ -2127,6 +2167,10 @@ triggerpull.o: \ + compile triggerpull.c ndelay.h open.h triggerpull.h + ./compile triggerpull.c + ++udpbits.o: \ ++compile udpbits.c udpbits.h ip.h ++ ./compile udpbits.c ++ + uint32.h: \ + tryulong32.c compile load uint32.h1 uint32.h2 + ( ( ./compile tryulong32.c && ./load tryulong32 && \ +@@ -2134,6 +2178,15 @@ tryulong32.c compile load uint32.h1 uint32.h2 + && cat uint32.h2 || cat uint32.h1 ) > uint32.h + rm -f tryulong32.o tryulong32 + ++verifyrcpt.o: \ ++compile verifyrcpt.c verifyrcpt.h sig.h readwrite.h stralloc.h gen_alloc.h \ ++substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ ++error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ ++substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ ++exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h \ ++sockbits.h udpbits.h qmail-verify.h ++ ./compile verifyrcpt.c ++ + wait.a: \ + makelib wait_pid.o wait_nohang.o + ./makelib wait.a wait_pid.o wait_nohang.o +diff --git a/TARGETS b/TARGETS +index 0dbad3e..1117464 100644 +--- a/TARGETS ++++ b/TARGETS +@@ -251,8 +251,14 @@ qmail-qmqpd + qmail-qmtpd.o + rcpthosts.o + qmail-qmtpd ++verifyrcpt.o ++sockbits.o ++udpbits.o ++scan_misc.o + qmail-smtpd.o + qmail-smtpd ++qmail-verify.o ++qmail-verify + sendmail.o + sendmail + tcp-env.o +@@ -352,6 +358,7 @@ qmail-qmqpc.0 + qmail-qmqpd.0 + qmail-qmtpd.0 + qmail-smtpd.0 ++qmail-verify.0 + tcp-env.0 + qmail-newmrh.8 + qmail-newmrh.0 +diff --git a/hier.c b/hier.c +index 28e568d..6c6e929 100644 +--- a/hier.c ++++ b/hier.c +@@ -127,6 +127,7 @@ void hier() + c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-verify",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755); +@@ -249,4 +250,6 @@ void hier() + c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"man/man8","qmail-verify.8",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"man/cat8","qmail-verify.0",auto_uido,auto_gidq,0644); + } +diff --git a/qmail-smtpd.8 b/qmail-smtpd.8 +index c4640b8..77f24e4 100644 +--- a/qmail-smtpd.8 ++++ b/qmail-smtpd.8 +@@ -169,6 +169,66 @@ Number of seconds + .B qmail-smtpd + will wait for each new buffer of data from the remote SMTP client. + Default: 1200. ++.SH "RECIPIENT VERIFICATION" ++Recipient verification is enabled with the ++.B VERIFY ++environment variable. This can be used to specify per-recipient ++rejection of invalid recipient addresses (immediate verification ++causing a permanent 550 error response to the RCPT command), ++or deferred rejection at DATA time (554 response) of the whole ++session if any recipient addresses don't exist. ++ ++To verify an address, ++.B qmail-smtpd ++uses a separate ++.B qmail-verify ++UDP server. By default this will be on the loopback address 127.0.0.1, ++port 11113. Enable verification like this, ++ ++.EX ++ VERIFY=":" ++ ++ VERIFY="DEFER" ++.EE ++ ++(for immediate, deferred verification respectively). A different IP ++address and/or port can be specified for ++.B qmail-verify ++as in these examples, ++ ++.EX ++ VERIFY="192.168.1.1" ++ VERIFY=":10101" ++ VERIFY="DEFER,:10101" ++ VERIFY="DEFER,192.168.1.1:10101" ++.EE ++ ++Recipient verification may be explicitly disabled by setting ++.B VERIFY ++to an empty string, ++ ++.EX ++ VERIFY="" ++.EE ++ ++Addresses with domains appearing in ++.B control/rcpthosts ++but not in ++.B control/locals ++or ++.B control/virtualdomains ++will be considered valid, reflecting qmail's standard behaviour. ++.P ++Note that if the environment variable ++.B RELAYCLIENT ++is set, no checking is carried out. ++.P ++.B qmail-verify ++needs to be running to respond to recipient ++verification queries. If no ++.B qmail-verify ++response is received a temporary 451 error response is ++given to the remote system and the session terminated. + .SH "SEE ALSO" + tcp-env(1), + tcp-environ(5), +@@ -176,4 +236,5 @@ qmail-control(5), + qmail-inject(8), + qmail-newmrh(8), + qmail-queue(8), +-qmail-remote(8) ++qmail-remote(8), ++qmail-verify(8) +diff --git a/qmail-smtpd.c b/qmail-smtpd.c +index 89ad712..001cedd 100644 +--- a/qmail-smtpd.c ++++ b/qmail-smtpd.c +@@ -24,6 +24,7 @@ + #include "timeoutwrite.h" + #include "commands.h" + #include "errbits.h" ++#include "verifyrcpt.h" + + #define enew() { eout("qmail-smtpd: pid "); epid(); eout3(" from ",remoteip,": "); } + /* Or if you prefer shorter log messages (deduce IP from tcpserver PID entry), */ +@@ -37,6 +38,8 @@ char *remotehost; + char *remoteinfo; + char *local; + char *relayclient; ++char *verify; ++int verifydefer=0; + + stralloc mailfrom = {0}; + stralloc rcptto = {0}; +@@ -148,6 +151,31 @@ void err_databytes() + enew(); eout("Exceeded DATABYTES limit\n"); eflush(); + out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); + } ++void die_qvsetup() ++{ ++ enew(); eout3("setup failure (",error_str(errno),")\n"); eflush(); ++ out("451 qv setup failure (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void die_qvtimeout() ++{ ++ enew(); eout("Timeout (no response from verification server)\n"); eflush(); ++ out("451 qv temporary failure (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void die_qvmiscfail() ++{ ++ enew(); eout3("temporary failure (",error_str(errno),")\n"); eflush(); ++ out("451 qv temporary failure (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void err_nosuchuser550() ++{ ++ enew(); eout("Unverified mailbox at RCPT time\n"); eflush(); ++ out("550 sorry, no mailbox here by that name. (#5.1.1)\r\n"); ++} ++void err_nosuchuser554() ++{ ++ enew(); eout("Unverified mailbox(es) at DATA time\n"); eflush(); ++ out("554 sorry, invalid mailbox name(s). (#5.1.1)\r\n"); ++} + + + stralloc greeting = {0}; +@@ -216,6 +244,18 @@ void setup() + if (!remotehost) remotehost = "unknown"; + remoteinfo = env_get("TCPREMOTEINFO"); + relayclient = env_get("RELAYCLIENT"); ++ verify = env_get("VERIFY"); ++ if (verify) ++ { ++ if (*verify == '\0') /* Disable verification if VERIFY="" */ ++ { ++ verify = 0; ++ /* Warning message since previous version of qmail-verify used VERIFY="" to enable verification */ ++ enew(); eout("Note recipient verification explicitly disabled.\n"); eflush(); ++ } ++ else ++ if ((*verify == 'D') || (*verify == 'd')) verifydefer=1; ++ } + dohelo(remotehost); + enew(); eout("New session\n"); eflush(); + } +@@ -318,6 +358,7 @@ void smtp_ehlo(arg) char *arg; + } + void smtp_rset(arg) char *arg; + { ++ flagdenyany = 0; + seenmail = 0; + enew(); eout("Session RSET\n"); eflush(); + out("250 flushed\r\n"); +@@ -344,7 +385,14 @@ void smtp_rcpt(arg) char *arg; { + if (!stralloc_0(&addr)) die_nomem(); + } + else ++ { + if (!addrallowed()) { err_nogateway(); return; } ++ if (verify && verifyrcpt(find_digit_colon_eos(verify),&addr,verifydefer,die_qvtimeout,die_qvmiscfail)) ++ { ++ err_nosuchuser550(); ++ return; ++ } ++ } + if (!stralloc_cats(&rcptto,"T")) die_nomem(); + if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_0(&rcptto)) die_nomem(); +@@ -468,6 +516,7 @@ void smtp_data(arg) char *arg; { + + if (!seenmail) { err_wantmail(); return; } + if (!rcptto.len) { err_wantrcpt(); return; } ++ if (verifydefer && flagdenyany) { err_nosuchuser554(); return; } + seenmail = 0; + if (databytes) bytestooverflow = databytes + 1; + messagebytes = 0; +diff --git a/qmail-verify.8 b/qmail-verify.8 +new file mode 100644 +index 0000000..9646d5b +--- /dev/null ++++ b/qmail-verify.8 +@@ -0,0 +1,136 @@ ++.TH qmail-verify 8 "Andrew Richards" "28th August 2009" "v1.32" ++.SH NAME ++qmail-verify \- Address verification daemon ++.SH SYNOPSIS ++.B qmail-verify ++.SH DESCRIPTION ++.B qmail-verify ++receives UDP packets containing local email addresses and returns a ++single byte to indicate if the address is valid or invalid to the ++sender of the UDP packet. ++.B qmail-smtpd ++or ++.B qmail-qmtpd ++are typical clients using the ++.B qmail-verify ++service, although at present only ++.B qmail-smtpd ++has had this functionality added. ++.B qmail-verify ++is based on Paul Jarc's ++.B realrcptto ++patch for qmail ++.I (http://code.dogmap.org/qmail/). ++ ++.B qmail-verify ++uses the files ++.I control/locals, control/virtualdomains, users/cdb, ++the system password file entries (typically in ++.B /etc/passwd ++) as well as the existence or not of users' home directories and ++.B .qmail[-xxx] ++files to determine if a given address is valid. ++ ++Where a qmail system uses ++.B .qmail-default ++files on a per-domain basis in a virtual domains setup, this is ++likely to result in all addresses being considered 'valid'. This ++may not in fact be the case in certain situations, such as with ++extensions/adaptations to qmail like vpopmail which use ++.B .qmail-default ++files throughout (delivery in this case is subsequently handled ++by a vpopmail component). In these cases a replacement for ++.B qmail-verify ++will be required that can determine address validity. ++ ++Other customised qmail installations that use different methods ++to locate users' mailboxes are likely to need alternatives to ++.B qmail-verify ++or a modified version of it for address verification. ++ ++.SH INVOCATION ++.B qmail-verify ++should be invoked as user ++.I root ++to have sufficient privileges to ++determine the validity of a given address. In certain single-UID ++virtual domains setups, it may be sufficient to run ++.B qmail-verify ++as the single-UID. ++ ++By default, ++.B qmail-verify ++listens on localhost (127.0.0.1) on port 11113. This behaviour ++can be changed by setting the environment variable ++.B LISTEN ++to specify the IP address and/or port: Set this to the desired ++IP address, optionally followed by a colon and port, thus for ++example LISTEN="192.168.1.1:10101". ++ ++.SH ADDRESS VERIFICATION DETAILS ++.B qmail-verify ++is implemented by taking the various pieces of qmail that parse an ++address and combining them in the same executable, ++.B qmail-verify. ++Thus logic is taken from ++.B qmail-send, qmail-lspawn, qmail-getpw ++and ++.B qmail-local. ++ ++.SH "UDP PACKET DETAILS" ++The incoming packet contains just the email address to be checked ++as a string. The string is optionally terminated with a 0 byte. ++ ++The response packet contains a single byte to indicate whether the ++address is valid. The lowest-order bit of this byte indicates the ++result: ++.B 0 ++for 'valid', ++.B 1 ++for 'invalid'. Other bits of this response byte are set by ++.B qmail-verify ++to give further debugging information; these other bits should ++generally be disregarded. ++ ++Although not especially designed as a new protocol, extensions to ++.B qmail-verify ++could require the query string to be 0 terminated ++to separate it from other data to follow. Currently the response packet ++contains the response byte and the 'Controlling user'; more ++information could potentially be returned if required. ++ ++.SH CONTROL FILES ++At startup ++.B qmail-verify ++reads the following qmail control files: ++.I control/envnoathost, control/locals, control/percenthack, control/virtualdomains. ++If changes are made to any of these files, ++.B qmail-verify ++should be restarted for the changes to take effect in ++.B qmail-verify. ++ ++If you are using different machines for ++.B qmail-verify ++and ++.B qmail-smtpd ++you should ensure that the machine providing the ++.B qmail-verify ++service has a full set of control files as well as the mailboxes; the machine ++running ++.B qmail-smtpd ++still needs ++.I control/rcpthosts ++to be setup. ++ ++.SH LOGGING ++.B qmail-verify ++logs each decision it makes to stderr: The address followed by whether ++it's valid or not. ++ ++.SH AUTHOR ++Andrew Richards, building on the work of Paul Jarc and Dan Bernstein, and with ++plenty of help along the way from Russell Nelson, John Levine and Charles Cazabon ++amongst others. ++ ++.SH "SEE ALSO" ++qmail-smtpd(8). +diff --git a/qmail-verify.c b/qmail-verify.c +new file mode 100644 +index 0000000..641f920 +--- /dev/null ++++ b/qmail-verify.c +@@ -0,0 +1,438 @@ ++/* qmail-verify: Based on Paul Jarc's realrcptto-2006.12.10 patch ++ * this separates its functionality into a separate ++ * program that can be invoked by an appropriately ++ * modified qmail-smtpd. The assumption is that ++ * qmail-verify will run as root or the UID that ++ * owns mailboxes in a SingleUID setup, whilst ++ * qmail-smtpd can continue to run as user qmaild. ++ * ++ * Comments have been added to show which parts of ++ * qmail-1.03 various sections of code relate to. ++ * ++ * *This program is written to be used by ++ * qmail-smtpd communicating with it using UDP. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "auto_break.h" ++#include "auto_usera.h" ++#include "auto_qmail.h" ++#include "byte.h" ++#include "case.h" ++#include "cdb.h" ++#include "constmap.h" ++#include "error.h" ++#include "fmt.h" ++#include "open.h" ++#include "str.h" ++#include "stralloc.h" ++#include "uint32.h" ++#include "substdio.h" ++#include "getln.h" ++#include "env.h" ++#include "ip.h" ++#include "qmail-verify.h" ++#include "errbits.h" ++ ++#define enew() { eout("qmail-verify: "); } ++#define GETPW_USERLEN 32 ++#define MAXQUERYSIZE 900 ++/* 900 derived as max packet size from logic in addrparse() in qmail-smtpd.c */ ++ ++stralloc envnoathost = {0}; ++stralloc percenthack = {0}; ++stralloc locals = {0}; ++stralloc vdoms = {0}; ++ ++struct constmap mappercenthack; ++struct constmap maplocals; ++struct constmap mapvdoms; ++ ++char *quser; ++ ++stralloc response = {0}; ++ ++char *local, *dash, *extension; ++struct passwd *pw; ++ ++char ppid_s[FMT_ULONG]; ++char *remoteip; ++char inbuf[MAXQUERYSIZE+1]; /* +1 for trailing \0 added after receipt */ ++ ++void die_nomem() { enew(); eout("Out of memory: exiting.\n"); eflush(); _exit(1); } ++void die_control() { enew(); eout("Unable to read controls: exiting.\n"); eflush(); _exit(1); } ++void die_cdb() { enew(); eout("Unable to read cdb user database: exiting.\n"); eflush(); _exit(1); } ++void die_sys() { enew(); eout("Unable to read system user database: exiting.\n"); eflush(); _exit(1); } ++void die_comms() { enew(); eout("Misc. comms problem: exiting.\n"); eflush(); _exit(1); } ++void die_inuse() { enew(); eout("Port already in use: exiting.\n"); eflush(); _exit(1); } ++void die_socket() { enew(); eout("Error setting up socket: exiting.\n"); eflush(); _exit(1); } ++ ++char *posstr(buf,status) ++char *buf; int status; ++{ ++int pos; ++ ++pos = status & QVPOSBITS; ++if (pos==QVPOS1) str_copy(buf,"1"); ++else if (pos==QVPOS2) str_copy(buf,"2"); ++ else if (pos==QVPOS3) str_copy(buf,"3"); ++ else if (pos==QVPOS4) str_copy(buf,"4"); ++ else if (pos==QVPOS5) str_copy(buf,"5"); ++ else if (pos==QVPOS6) str_copy(buf,"6"); ++ else if (pos==QVPOS7) str_copy(buf,"7"); ++ else if (pos==QVPOS8) str_copy(buf,"8"); ++ else if (pos==QVPOS9) str_copy(buf,"9"); ++ else if (pos==QVPOS10) str_copy(buf,"10"); ++ else if (pos==QVPOS11) str_copy(buf,"11"); ++ else if (pos==QVPOS12) str_copy(buf,"12"); ++ else if (pos==QVPOS13) str_copy(buf,"13"); ++ else if (pos==QVPOS14) str_copy(buf,"14"); ++ else if (pos==QVPOS15) str_copy(buf,"15"); ++ else str_copy(buf,"??"); ++return buf; ++} ++ ++char posbuf[10]; /* Large enough for anything posstr() will put in it. */ ++ ++int allowaddr(addr,ret) ++char *addr; ++int ret; ++{ ++/*eout3("[DEBUG] Pos ",posstr(posbuf,ret),", ");*/ ++/*eout3("qmail-verify: ",addr," permitted.\n");*/ ++ enew(); eout4(addr," permitted for ",quser?quser:"UNKNOWN",".\n"); ++ eflush(); ++ return ret; ++} ++ ++int denyaddr(addr,ret) ++char *addr; ++int ret; ++{ ++/*eout3("[DEBUG] Pos ",posstr(posbuf,ret),", ");*/ ++/*eout3("qmail-verify: ",addr," denied.\n");*/ ++ enew(); eout2(addr," denied.\n"); ++ eflush(); ++ return ret; ++} ++ ++int stat_error(path,staterror,ret) ++char* path; ++int staterror,ret; ++{ ++/*eout3("[DEBUG] Pos ",posstr(posbuf,ret),", ");*/ ++/*eout5("qmail-verify: Unable to stat ",path,": ",error_str(staterror),".\n");*/ ++ enew(); eout5("Unable to stat ",path,": ",error_str(staterror),".\n"); ++ eflush(); ++ return ret; ++} ++ ++int userext() /* from qmail-getpw.c */ ++{ ++ char username[GETPW_USERLEN]; ++ struct stat st; ++ ++ extension = local + str_len(local); ++ for (;;) { ++ if (extension - local < sizeof(username)) ++ if (!*extension || (*extension == *auto_break)) { ++ byte_copy(username,extension - local,local); ++ username[extension - local] = 0; ++ case_lowers(username); ++ errno = 0; ++ pw = getpwnam(username); ++ if (errno == error_txtbsy) die_sys(); ++ if (pw) ++ if (pw->pw_uid) ++ if (stat(pw->pw_dir,&st) == 0) { ++ if (st.st_uid == pw->pw_uid) { ++ dash = ""; ++ if (*extension) { ++extension; dash = "-"; } ++ return 1; ++ } ++ } ++ else ++ if (error_temp(errno)) die_sys(); ++ } ++ if (extension == local) return 0; ++ --extension; ++ } ++} ++ ++int verifyaddr(addr) ++char *addr; ++{ ++ char *homedir; ++ /* static since they get re-used on each call to verifyaddr(). Note ++ that they don't need resetting since initial use is always with ++ stralloc_copys() except wildchars (reset with ...len=0 below). */ ++ static stralloc localpart = {0}; ++ static stralloc lower = {0}; ++ static stralloc nughde = {0}; ++ static stralloc wildchars = {0}; ++ static stralloc safeext = {0}; ++ static stralloc qme = {0}; ++ unsigned int i,at; ++ wildchars.len=0; ++ ++ /* qmail-send:rewrite */ ++ if (!stralloc_copys(&localpart,addr)) die_nomem(); ++ i = byte_rchr(localpart.s,localpart.len,'@'); ++ if (i == localpart.len) { ++ if (!stralloc_cats(&localpart,"@")) die_nomem(); ++ if (!stralloc_cat(&localpart,&envnoathost)) die_nomem(); ++ } ++ while (constmap(&mappercenthack,localpart.s + i + 1,localpart.len - i - 1)) { ++ unsigned int j = byte_rchr(localpart.s,i,'%'); ++ if (j == i) break; ++ localpart.len = i; ++ i = j; ++ localpart.s[i] = '@'; ++ } ++ at = byte_rchr(localpart.s,localpart.len,'@'); ++ if (constmap(&maplocals,localpart.s + at + 1,localpart.len - at - 1)) { ++ localpart.len = at; ++ localpart.s[at] = '\0'; ++ } else { ++ unsigned int xlen,newlen; ++ char *x; ++ for (i = 0;;++i) { ++ if (i > localpart.len) return allowaddr(addr,ADDR_OK|QVPOS1); ++ if (!i || (i == at + 1) || (i == localpart.len) || ++ ((i > at) && (localpart.s[i] == '.'))) { ++ x = constmap(&mapvdoms,localpart.s + i,localpart.len - i); ++ if (x) break; ++ } ++ } ++ if (!*x) return allowaddr(addr,ADDR_OK|QVPOS2); ++ xlen = str_len(x) + 1; /* +1 for '-' */ ++ newlen = xlen + at + 1; /* +1 for \0 */ ++ if (xlen < 1 || newlen - 1 < xlen || newlen < 1 || ++ !stralloc_ready(&localpart,newlen)) ++ die_nomem(); ++ localpart.s[newlen - 1] = '\0'; ++ byte_copyr(localpart.s + xlen,at,localpart.s); ++ localpart.s[xlen - 1] = '-'; ++ byte_copy(localpart.s,xlen - 1,x); ++ localpart.len = newlen; ++ } ++ ++ /* qmail-lspawn:nughde_get */ ++ { ++ /* qmail-lspawn lines 83-128 */ ++ int r,fd,flagwild; ++ ++ if (!stralloc_copys(&lower,"!")) die_nomem(); ++ if (!stralloc_cats(&lower,localpart.s)) die_nomem(); ++ if (!stralloc_0(&lower)) die_nomem(); ++ case_lowerb(lower.s,lower.len); ++ ++ if (!stralloc_copys(&nughde,"")) die_nomem(); ++ ++ fd = open_read("users/cdb"); ++ if (fd == -1) { ++ if (errno != error_noent) die_cdb(); ++ } ++ else ++ { /* This section parses users/cdb file */ ++ uint32 dlen; ++ ++ r = cdb_seek(fd,"",0,&dlen); ++ if (r != 1) die_cdb(); ++ if (!stralloc_ready(&wildchars,(unsigned int) dlen)) die_nomem(); ++ wildchars.len = dlen; ++ if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) die_cdb(); ++ ++ i = lower.len; ++ flagwild = 0; ++ ++ do { /* i > 0 */ ++ if (!flagwild || (i == 1) || ++ (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1]) < wildchars.len)) ++ { ++ r = cdb_seek(fd,lower.s,i,&dlen); ++ if (r == -1) die_cdb(); ++ if (r == 1) ++ { ++ char *x; ++ if (!stralloc_ready(&nughde,(unsigned int) dlen)) die_nomem(); ++ nughde.len = dlen; ++ if (cdb_bread(fd,nughde.s,nughde.len) == -1) die_cdb(); ++ if (flagwild) ++ if (!stralloc_cats(&nughde,localpart.s + i - 1)) die_nomem(); ++ if (!stralloc_0(&nughde)) die_nomem(); ++ close(fd); ++ /* maybe based on qmail-lspawn lines 190-214 */ ++ x=nughde.s; ++ quser=nughde.s; ++ /* skip username */ ++ x += byte_chr(x,nughde.s + nughde.len - x,'\0'); ++ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS3); ++ ++x; ++ /* skip uid */ ++ x += byte_chr(x,nughde.s + nughde.len - x,'\0'); ++ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS4); ++ ++x; ++ /* skip gid */ ++ x += byte_chr(x,nughde.s + nughde.len - x,'\0'); ++ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS5); ++ ++x; ++ /* skip homedir */ ++ homedir=x; ++ x += byte_chr(x,nughde.s + nughde.len - x,'\0'); ++ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS6); ++ ++x; ++ /* skip dash */ ++ dash=x; ++ x += byte_chr(x,nughde.s + nughde.len - x,'\0'); ++ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS7); ++ ++x; ++ extension=x; ++ goto got_nughde; ++ } ++ } ++ /* qmail-lspawn lines 132-137 */ ++ --i; ++ flagwild = 1; ++ } while (i); ++ close(fd); ++ } ++ } ++ ++ /* qmail-getpw lines 61-70 */ ++ local = localpart.s; ++ quser = local; ++ if (!userext()) { ++ extension = local; ++ dash = "-"; ++ pw = getpwnam(auto_usera); ++ quser = auto_usera; ++ } ++ if (!pw) return denyaddr(addr,ADDR_NOK|QVPOS8); ++ if (!stralloc_copys(&nughde,pw->pw_dir)) die_nomem(); ++ if (!stralloc_0(&nughde)) die_nomem(); ++ homedir=nughde.s; ++ ++ got_nughde: ++ ++ /* qmail-local:qmesearch, note qmeexists() becomes stralloc_0 + stat() */ ++ if (!*dash) return allowaddr(addr,ADDR_OK|QVPOS9); ++ if (!stralloc_copys(&safeext,extension)) die_nomem(); ++ case_lowerb(safeext.s,safeext.len); ++ for (i = 0;i < safeext.len;++i) ++ if (safeext.s[i] == '.') ++ safeext.s[i] = ':'; ++ { ++ /* qmail-local lines 383-388 */ ++ struct stat st; ++ int i; ++ if (!stralloc_copys(&qme,homedir)) die_nomem(); ++ if (!stralloc_cats(&qme,"/.qmail")) die_nomem(); ++ if (!stralloc_cats(&qme,dash)) die_nomem(); ++ if (!stralloc_cat(&qme,&safeext)) die_nomem(); ++ if (!stralloc_0(&qme)) die_nomem(); ++/* e.g. homedir/.qmail-localpart */ ++ if (stat(qme.s,&st) == 0) return allowaddr(addr,ADDR_OK|QVPOS10); ++ if (errno != error_noent) { ++ return stat_error(qme.s,errno, STATERR|QVPOS11); /* Maybe not running as root so access denied */ ++ } ++ /* qmail-local lines 398-404 */ ++ for (i = safeext.len;i >= 0;--i) ++ if (!i || (safeext.s[i - 1] == '-')) { ++ if (!stralloc_copys(&qme,homedir)) die_nomem(); ++ if (!stralloc_cats(&qme,"/.qmail")) die_nomem(); ++ if (!stralloc_cats(&qme,dash)) die_nomem(); ++ if (!stralloc_catb(&qme,safeext.s,i)) die_nomem(); ++ if (!stralloc_cats(&qme,"default")) die_nomem(); ++ if (!stralloc_0(&qme)) die_nomem(); ++/* e.g. homedir/.qmail-[xxx-]default */ ++ if (stat(qme.s,&st) == 0) return allowaddr(addr,ADDR_OK|QVPOS12); ++ if (errno != error_noent) /* Maybe not running as root so access denied */ ++ return stat_error(qme.s,errno,STATERR|QVPOS13); ++ } ++ return denyaddr(addr,ADDR_NOK|QVPOS14); ++ } ++ return denyaddr(addr,ADDR_NOK|QVPOS15); /* Not sure under what conditions this line triggered, if any */ ++} ++ ++int main() ++{ ++ int n, sock; ++ char result; ++ socklen_t clientaddrlen; ++ struct sockaddr_in sin, clientaddr; ++ unsigned long lport; /* for scan_ulong, scan_uint not in qmail src */ ++ struct ip_address i; ++ char *s; ++ ++ if (chdir(auto_qmail) == -1) die_control(); ++ ++ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) ++ die_control(); ++ ++ if (control_readfile(&locals,"control/locals",1) != 1) die_control(); ++ if (!constmap_init(&maplocals,locals.s,locals.len,0)) die_nomem(); ++ switch(control_readfile(&percenthack,"control/percenthack",0)) { ++ case -1: die_control(); ++ case 0: if (!constmap_init(&mappercenthack,"",0,0)) die_nomem(); ++ case 1: ++ if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) ++ die_nomem(); ++ } ++ switch(control_readfile(&vdoms,"control/virtualdomains",0)) { ++ case -1: die_control(); ++ case 0: if (!constmap_init(&mapvdoms,"",0,1)) die_nomem(); ++ case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) die_nomem(); ++ } ++ if (!(s = env_get("LISTEN"))) s=DEFAULTQVIP; ++ ++ /* Re-read control files above on SIGHUP? */ ++ ++ if (!(n=ip_scan(s,&i))) ip_scan(DEFAULTQVIP,&i); ++ s+=n; if ((*s==':') && scan_ulong(s+1,&lport)) ; else lport=DEFAULTQVPORT; ++ ++ byte_zero(&sin, sizeof(sin)); ++ sin.sin_family = AF_INET; ++ sin.sin_port = htons(lport); ++/*sin.sin_len = sizeof(sin); (optional, not defined on all systems) */ ++ byte_copy(&sin.sin_addr, sizeof(i),&i); ++ ++ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) die_socket(); ++ if (bind(sock, (struct sockaddr *) &sin, sizeof(sin))< 0) die_inuse(); ++ ++ { char tmps1[IPFMT+1], tmps2[FMT_ULONG+1]; ++ tmps1[ip_fmt(tmps1,&i)]=0; ++ tmps2[fmt_ulong(tmps2,ntohs(sin.sin_port))]=0; ++ enew(); eout5("Listening on address: ",tmps1,", port ",tmps2,".\n"); eflush(); ++ } ++ for (;;) ++ { ++ clientaddrlen=sizeof(clientaddr); /* Read & set by recvfrom */ ++ n = recvfrom(sock,inbuf, MAXQUERYSIZE, 0, (struct sockaddr *)&clientaddr, &clientaddrlen); ++ if (n<=0) /* <0 for error, 0 for empty packet. */ ++ { ++ enew(); eout("Error receiving packet.\n"); eflush(); ++ continue; ++ } ++ inbuf[n]='\0'; /* Turn it into a string ('\0' terminated) */ ++ ++ quser = 0; ++ result=(char)verifyaddr(inbuf); ++ ++ /* 'short' response packet - just the status byte - use the line below to replace 'long' version */ ++ /* if (sendto(sock,&result,1,0,(struct sockaddr *)&clientaddr,sizeof(clientaddr)) < 0) die_comms(); */ ++ ++ /* 'long' response packet - status byte + controlling user (quser) */ ++ stralloc_ready(&response, 2); ++ stralloc_copyb(&response, &result, 1); ++ if (quser) stralloc_cats(&response, quser); ++ if (response.len > QVRESPONSELEN) response.len = QVRESPONSELEN; /* Trim oversize response */ ++ if (sendto(sock,response.s,response.len,0,(struct sockaddr *)&clientaddr,sizeof(clientaddr)) < 0) die_comms(); ++ ++ } ++} +diff --git a/qmail-verify.h b/qmail-verify.h +new file mode 100644 +index 0000000..5a1b8d5 +--- /dev/null ++++ b/qmail-verify.h +@@ -0,0 +1,34 @@ ++#define DEFAULTQVPORT 11113 ++#define DEFAULTQVIP "127.0.0.1" ++#define DEFAULTQVTIMEOUT 5 ++ ++#define GETPW_USERLEN 32 ++/* Response length is status byte + username length */ ++#define QVRESPONSELEN (1+GETPW_USERLEN) ++ ++/* ADDR_NOK, ADDR_OK, ADDR_NOK_TEMP get ORed with POSx for possible debugging. */ ++#define ADDR_NOK_TEMP 0x02 ++#define ADDR_NOK 0x01 ++#define ADDR_OK 0x00 ++/* Treat a stat() error as 'valid address'; maybe not running with sufficient rights */ ++#define STATERR ADDR_OK ++/* Which bits show OK / NOK: */ ++#define QVRESULTBITS 0x0f ++ ++#define QVPOS1 0x10 ++#define QVPOS2 0x20 ++#define QVPOS3 0x30 ++#define QVPOS4 0x40 ++#define QVPOS5 0x50 ++#define QVPOS6 0x60 ++#define QVPOS7 0x70 ++#define QVPOS8 0x80 ++#define QVPOS9 0x90 ++#define QVPOS10 0xa0 ++#define QVPOS11 0xb0 ++#define QVPOS12 0xc0 ++#define QVPOS13 0xd0 ++#define QVPOS14 0xe0 ++#define QVPOS15 0xf0 ++/* Which bits show QVPOSx: */ ++#define QVPOSBITS 0xf0 +diff --git a/scan.h b/scan.h +index 53ce703..eddbaa8 100644 +--- a/scan.h ++++ b/scan.h +@@ -24,4 +24,7 @@ extern unsigned int scan_memcmp(); + + extern unsigned int scan_long(); + ++extern char *find_digit_colon_eos(); ++extern int scan_ip_port(); ++ + #endif +diff --git a/scan_misc.c b/scan_misc.c +new file mode 100644 +index 0000000..3e20a75 +--- /dev/null ++++ b/scan_misc.c +@@ -0,0 +1,39 @@ ++#include "stralloc.h" ++#include "ip.h" ++#include "scan.h" ++ ++/* Returns pointer to first digit or ':' in string, or end-of-string ++ * if neither found. Useful prior to scan_ip_port() if any options ++ * may precede the IP / port in the string. */ ++char *find_digit_colon_eos(s) ++char *s; ++{ ++ while (*s != '\0') ++ { ++ if ( *s == ':') return s; ++ if ((*s >= '0') && (*s <= '9')) return s; ++ s++; ++ } ++ return s; /* end of string '\0' */ ++} ++ ++/* Takes a string specifying IP address and port, separated by ':' ++ * If IP address and/or port are missing, supplied defaults are used. ++ * 0, -1 returned on success, failure respectively. */ ++int scan_ip_port(s,defaultip,defaultport,ipp,portp) ++char *s, *defaultip; ++struct ip_address *ipp; ++unsigned int defaultport, *portp; ++{ ++ int n; ++ char *sp; ++ unsigned long port; /* long because of scan_ulong */ ++ ++ if (!s) return -1; /* Can't scan a null string */ ++ sp = s; ++ if (!(n=ip_scan(sp, ipp))) ip_scan(defaultip,ipp); ++ sp += n; /* n is 0 if no IP found */ ++ if (!((*sp==':') && scan_ulong(sp+1,&port))) port=defaultport; ++ *portp = (unsigned int)port; ++ return 0; ++} +diff --git a/sockbits.c b/sockbits.c +new file mode 100644 +index 0000000..05d1953 +--- /dev/null ++++ b/sockbits.c +@@ -0,0 +1,31 @@ ++#include "sockbits.h" ++#include "stralloc.h" ++#include ++#include ++#include "error.h" ++ ++int query_skt(fd,queryp,responsep,maxresponsesize,timeout,timeoutfn,errfn) ++int fd; ++stralloc *queryp; ++char *responsep; ++int maxresponsesize, timeout; ++void (*errfn)(), (*timeoutfn)(); ++{ ++ fd_set rfs; ++ struct timeval tv; ++ int nbytes; ++ int r=0; ++ ++ if (write(fd,queryp->s,queryp->len) < 0) (*errfn)(); ++ tv.tv_sec=timeout; tv.tv_usec=0; ++ FD_ZERO(&rfs); FD_SET(fd,&rfs); ++ if ((r=select(fd+1,&rfs,(fd_set *) 0,(fd_set *) 0,&tv)) <= 0) /* 0 timeout or -1 error */ ++ { ++ if ((r == 0) && (errno == error_timeout)) (*timeoutfn)(); ++ else (*errfn)(); ++ return r; /* if timeoutfn() / errfn() doesn't _exit() */ ++ } ++ nbytes = read(fd,responsep,maxresponsesize); ++ if (nbytes < 0) (*errfn)(); ++ return (nbytes); /* including 0 = no output */ ++} +diff --git a/sockbits.h b/sockbits.h +new file mode 100644 +index 0000000..2a02749 +--- /dev/null ++++ b/sockbits.h +@@ -0,0 +1 @@ ++extern int query_skt(); +diff --git a/udpbits.c b/udpbits.c +new file mode 100644 +index 0000000..3b17f52 +--- /dev/null ++++ b/udpbits.c +@@ -0,0 +1,24 @@ ++#include "udpbits.h" ++#include "ip.h" ++#include "byte.h" ++#include ++#include ++#include ++ ++int connect_udp(ip,port,errfn) ++struct ip_address ip; ++unsigned int port; ++void (*errfn)(); ++{ ++ struct sockaddr_in sout; ++ int fd; ++ ++ byte_zero(&sout,sizeof(sout)); ++ sout.sin_port = htons(port); ++ sout.sin_family=AF_INET; ++ byte_copy(&sout.sin_addr,sizeof(ip),&ip); ++/*sout.sin_len = sizeof(sout); Commented out since optional & sin_len not defined on all OSes */ ++ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) (*errfn)(); ++ if (connect(fd,(struct sockaddr *)&sout,sizeof(sout)) < 0) (*errfn)(); ++ return fd; ++} +diff --git a/udpbits.h b/udpbits.h +new file mode 100644 +index 0000000..d19e12a +--- /dev/null ++++ b/udpbits.h +@@ -0,0 +1 @@ ++extern int connect_udp(); +diff --git a/verifyrcpt.c b/verifyrcpt.c +new file mode 100644 +index 0000000..8f737b1 +--- /dev/null ++++ b/verifyrcpt.c +@@ -0,0 +1,45 @@ ++#include "verifyrcpt.h" ++#include "qmail-verify.h" ++#include "ip.h" ++#include "stralloc.h" ++#include "scan.h" ++#include ++ ++static int verifyrcpt_initialised=0; ++static int sockfd; ++ ++int flagdenyany=0; /* Can be interrogated in qmail-smtpd.c */ ++ ++void verifyrcpt_init(svr,errfn) /* errfn must _exit */ ++char *svr; void (*errfn)(); ++{ ++ struct ip_address ip; ++ unsigned int port; ++ ++ if (scan_ip_port(svr,DEFAULTQVIP,DEFAULTQVPORT,&ip,&port) == -1) (*errfn)(); ++ sockfd = connect_udp(ip,port,errfn); ++ verifyrcpt_initialised=1; ++} ++ ++int verifyrcpt(vip,r,defer,timeoutfn,errfn) ++char *vip; stralloc *r; int defer; void (*timeoutfn)(),(*errfn)(); ++{ ++ char qvresponse[QVRESPONSELEN+1]; /* +1 for '\0' at end */ ++ int result,n; ++ ++ if (!vip) (*errfn)(); /* verifyrcpt should only be called if vip set */ ++ if (!verifyrcpt_initialised) verifyrcpt_init(vip,errfn); ++ ++ if (defer && flagdenyany) return ADDR_OK; /* Optional short circuit; "Controlling user" not discovered; remove this line if it's needed */ ++ n = query_skt(sockfd,r,qvresponse,QVRESPONSELEN,DEFAULTQVTIMEOUT,timeoutfn,errfn); ++ if (n == 0) (*errfn)(); ++ result = qvresponse[0] & QVRESULTBITS; ++ qvresponse[ ( (n > QVRESPONSELEN) ? QVRESPONSELEN : n) ] = '\0'; ++ /* "Controlling user" available in qvresponse+1 for logging etc. */ ++ ++ if (result == ADDR_OK) ++ return ADDR_OK; ++ /* NOK: */ ++ flagdenyany = 1; ++ return defer?ADDR_OK:ADDR_NOK; /* ADDR_OK if we're rejecting later */ ++} +diff --git a/verifyrcpt.h b/verifyrcpt.h +new file mode 100644 +index 0000000..07c48b5 +--- /dev/null ++++ b/verifyrcpt.h +@@ -0,0 +1,3 @@ ++extern int flagdenyany; ++void verifyrcpt_init(); ++int verifyrcpt(); +-- +1.7.0 + --- netqmail-1.06.orig/debian/diff/0001-qmail-errmsg-logging.diff +++ netqmail-1.06/debian/diff/0001-qmail-errmsg-logging.diff @@ -0,0 +1,445 @@ +From 9d9ed9e968be498ff263ebd3137556481c042791 Mon Sep 17 00:00:00 2001 +From: Gerrit Pape +Date: Thu, 4 Mar 2010 22:31:08 +0000 +Subject: [PATCH 1/3] qmail-errmsg logging + +This patch adds extensive logging to qmail-smtpd for netqmail-1.06. +Initial connection through to message acceptance or rejection / +disconnection is logged, with all log entries showing the process id and +remote IP address to enable identification of individual SMTP sessions. +Accepted messages are logged with the number of recipients. + +Patch is from Andrew Richards: +http://free.acrconsulting.co.uk/email/qmail-errmsg.html +http://free.acrconsulting.co.uk/sw/patches/netqmail-1.06.errmsg-v1.2.patch +--- + Makefile | 8 +++- + TARGETS | 1 + + errbits.c | 54 +++++++++++++++++++ + errbits.h | 13 +++++ + qmail-smtpd.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++----------- + 5 files changed, 207 insertions(+), 31 deletions(-) + create mode 100644 errbits.c + create mode 100644 errbits.h + +diff --git a/Makefile b/Makefile +index 0f0e31a..a27a809 100644 +--- a/Makefile ++++ b/Makefile +@@ -508,6 +508,10 @@ envread.o: \ + compile envread.c env.h str.h + ./compile envread.c + ++errbits.o: \ ++compile errbits.c errbits.h stralloc.h gen_alloc.h fmt.h exit.h ++ ./compile errbits.c ++ + error.a: \ + makelib error.o error_str.o error_temp.o + ./makelib error.a error.o error_str.o error_temp.o +@@ -1535,12 +1539,14 @@ qmail-smtpd: \ + load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ + timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ + date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ +-open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \ ++open.a sig.a case.a env.a stralloc.a errbits.o \ ++alloc.a substdio.a error.a str.a \ + fs.a auto_qmail.o socket.lib + ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ + timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ + received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ + datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ ++ errbits.o \ + alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ + socket.lib` + +diff --git a/TARGETS b/TARGETS +index facdad7..0dbad3e 100644 +--- a/TARGETS ++++ b/TARGETS +@@ -96,6 +96,7 @@ error.o + error_str.o + error_temp.o + error.a ++errbits.o + str_len.o + str_diff.o + str_diffn.o +diff --git a/errbits.c b/errbits.c +new file mode 100644 +index 0000000..4867c76 +--- /dev/null ++++ b/errbits.c +@@ -0,0 +1,54 @@ ++#include "stralloc.h" ++#include "readwrite.h" ++#include "errbits.h" ++#include "substdio.h" ++#include "fmt.h" ++#include "exit.h" ++ ++char sserrbuf[512]; ++static substdio sserr = SUBSTDIO_FDBUF(write,2,sserrbuf,sizeof sserrbuf); ++static stralloc foo = {0}; ++ ++static char pid_str[FMT_ULONG]="?PID?"; ++ ++void esetfd(fd) int fd; { sserr.fd=fd; } ++ ++void eout(s1) char *s1; {substdio_puts(&sserr,s1);} ++void eout2(s1,s2) char *s1,*s2; {substdio_puts(&sserr,s1);substdio_puts(&sserr,s2);} ++void eout3(s1,s2,s3) char *s1,*s2,*s3; {substdio_puts(&sserr,s1);substdio_puts(&sserr,s2);substdio_puts(&sserr,s3);} ++ ++void epid() ++{ ++ if (*pid_str == '?') /* not yet set from getpid() */ ++ pid_str[fmt_ulong(pid_str,getpid())] = 0; ++ eout(pid_str); ++} ++void eflush() { substdio_flush(&sserr); } ++ ++/* The functions below here come from qsutil.c with minor changes */ ++void eoutsa(sa) stralloc *sa; { substdio_putflush(&sserr,sa->s,sa->len); } ++ ++void nomem() { substdio_putsflush(&sserr,"Out Of Memory: quitting.\n"); _exit(1); } ++ ++static int issafe(ch) char ch; ++{ /* Differs from qsutil.c version: space and % permitted */ ++ if (ch == ':') return 0; /* Replace since used as delimiter in logs */ ++ if (ch == '<') return 0; /* Replace since used around addresses in logs */ ++ if (ch == '>') return 0; /* Replace since used around addresses in logs */ ++ if (ch < 32) return 0; /* Note that space (32) is permitted */ ++ if (ch > 126) return 0; ++ return 1; ++} ++ ++void eoutclean(s) char *s; ++{ ++ int i; ++ while (!stralloc_copys(&foo,s)) nomem(); ++ for (i = 0;i < foo.len;++i) ++ if (foo.s[i] == '\n') ++ foo.s[i] = '/'; ++ else ++ if (!issafe(foo.s[i])) ++ foo.s[i] = '_'; ++ eoutsa(&foo); ++} +diff --git a/errbits.h b/errbits.h +new file mode 100644 +index 0000000..382f1ba +--- /dev/null ++++ b/errbits.h +@@ -0,0 +1,13 @@ ++extern void esetfd(); /* functions in this module default to FD 2 (stderr) for output, change with esetfd */ ++extern void eout(); ++extern void eout2(); ++extern void eout3(); ++#define eout4(s1,s2,s3,s4) { eout3(s1,s2,s3); eout(s4); } ++#define eout5(s1,s2,s3,s4,s5) { eout3(s1,s2,s3); eout2(s4,s5); } ++#define eout6(s1,s2,s3,s4,s5,s6) { eout3(s1,s2,s3); eout3(s4,s5,s6); } ++#define eout7(s1,s2,s3,s4,s5,s6,s7) { eout3(s1,s2,s3); eout4(s4,s5,s6,s7); } ++#define eout8(s1,s2,s3,s4,s5,s6,s7,s8) { eout3(s1,s2,s3); eout5(s4,s5,s6,s7,s8); } ++#define eout9(s1,s2,s3,s4,s5,s6,s7,s8,s9) { eout3(s1,s2,s3); eout6(s4,s5,s6,s7,s8,s9); } ++extern void eoutsa(); ++extern void epid(); ++extern void eflush(); +diff --git a/qmail-smtpd.c b/qmail-smtpd.c +index 54df00c..89ad712 100644 +--- a/qmail-smtpd.c ++++ b/qmail-smtpd.c +@@ -23,16 +23,35 @@ + #include "timeoutread.h" + #include "timeoutwrite.h" + #include "commands.h" ++#include "errbits.h" + ++#define enew() { eout("qmail-smtpd: pid "); epid(); eout3(" from ",remoteip,": "); } ++/* Or if you prefer shorter log messages (deduce IP from tcpserver PID entry), */ ++/* { eout("qmail-smtpd: pid "); epid(); eout(": "); } */ + #define MAXHOPS 100 + unsigned int databytes = 0; + int timeout = 1200; + ++char *remoteip="(not yet set)"; ++char *remotehost; ++char *remoteinfo; ++char *local; ++char *relayclient; ++ ++stralloc mailfrom = {0}; ++stralloc rcptto = {0}; ++int rcptcount; ++stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ ++ + int safewrite(fd,buf,len) int fd; char *buf; int len; + { + int r; + r = timeoutwrite(timeout,fd,buf,len); +- if (r <= 0) _exit(1); ++ if (r <= 0) ++ { ++ enew(); eout("Write error (disconnect?): quitting\n"); eflush(); ++ _exit(1); ++ } + return r; + } + +@@ -42,22 +61,93 @@ substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); + void flush() { substdio_flush(&ssout); } + void out(s) char *s; { substdio_puts(&ssout,s); } + +-void die_read() { _exit(1); } +-void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } +-void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } +-void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } +-void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } +-void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } ++void die_read() ++{ ++ enew(); eout("Read error (disconnect?): quitting\n"); eflush(); _exit(1); ++} ++void die_alarm() ++{ ++ enew(); eout("Connection timed out: quitting\n"); eflush(); ++ out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); ++} ++void die_nomem() ++{ ++ enew(); eout("Out of memory: quitting\n"); eflush(); ++ out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void die_control() ++{ ++ enew(); eout("Unable to read controls: quitting\n"); eflush(); ++ out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void die_ipme() ++{ ++ enew(); eout("Unable to figure out my IP addresses: quitting\n"); eflush(); ++ out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); ++} ++void straynewline() ++{ ++ enew(); eout("Stray newline: quitting\n"); eflush(); ++ out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); ++} + +-void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } +-void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } +-void err_unimpl(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); } +-void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } +-void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } +-void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } +-void err_noop(arg) char *arg; { out("250 ok\r\n"); } +-void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); } +-void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } ++void err_bmf() ++{ ++ enew(); eout("Sender address in badmailfrom\n"); eflush(); ++ out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); ++} ++void err_nogateway() ++{ ++ enew(); eout("Recipient domain not in rcpthosts <"); eoutclean(addr.s); eout(">\n"); eflush(); ++ out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); ++} ++void err_unimpl(arg) char *arg; ++{ ++ enew(); eout("Unimplemented command\n"); eflush(); ++ out("502 unimplemented (#5.5.1)\r\n"); ++} ++void err_syntax(cmd) char *cmd; ++{ ++ char tmp_buf[FMT_ULONG]; ++ tmp_buf[fmt_ulong(tmp_buf,addr.len)] = 0; ++ enew(); eout4(cmd," with too long address (",tmp_buf," bytes) given\n"); eflush(); ++ out("555 syntax error (#5.5.4)\r\n"); ++} ++void err_wantmail() ++{ ++ enew(); eout("Attempted RCPT or DATA before MAIL\n"); eflush(); ++ out("503 MAIL first (#5.5.1)\r\n"); ++} ++void err_wantrcpt() ++{ ++ enew(); eout("Attempted DATA before RCPT\n"); eflush(); ++ out("503 RCPT first (#5.5.1)\r\n"); ++} ++void err_noop(arg) char *arg; ++{ ++ enew(); eout("NOOP\n"); eflush(); ++ out("250 ok\r\n"); ++} ++void err_vrfy(arg) char *arg; ++{ ++ enew(); eout("VRFY requested\n"); eflush(); ++ out("252 send some mail, i'll try my best\r\n"); ++} ++void err_qqt() ++{ ++ enew(); eout("qqt failure\n"); eflush(); ++ out("451 qqt failure (#4.3.0)\r\n"); ++} ++void err_hops() ++{ ++ enew(); eout("Exceeded hop count\n"); eflush(); ++ out("554 too many hops, this message is looping (#5.4.6)\r\n"); ++} ++void err_databytes() ++{ ++ enew(); eout("Exceeded DATABYTES limit\n"); eflush(); ++ out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); ++} + + + stralloc greeting = {0}; +@@ -73,15 +163,10 @@ void smtp_help(arg) char *arg; + } + void smtp_quit(arg) char *arg; + { ++ enew(); eout("Remote end QUIT: quitting\n"); eflush(); + smtp_greet("221 "); out("\r\n"); flush(); _exit(0); + } + +-char *remoteip; +-char *remotehost; +-char *remoteinfo; +-char *local; +-char *relayclient; +- + stralloc helohost = {0}; + char *fakehelo; /* pointer into helohost, or 0 */ + +@@ -132,11 +217,10 @@ void setup() + remoteinfo = env_get("TCPREMOTEINFO"); + relayclient = env_get("RELAYCLIENT"); + dohelo(remotehost); ++ enew(); eout("New session\n"); eflush(); + } + + +-stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ +- + int addrparse(arg) + char *arg; + { +@@ -219,37 +303,40 @@ int addrallowed() + + int seenmail = 0; + int flagbarf; /* defined if seenmail */ +-stralloc mailfrom = {0}; +-stralloc rcptto = {0}; + + void smtp_helo(arg) char *arg; + { ++ enew(); eout("Received HELO "); eoutclean(arg); eout("\n"); eflush(); + smtp_greet("250 "); out("\r\n"); + seenmail = 0; dohelo(arg); + } + void smtp_ehlo(arg) char *arg; + { ++ enew(); eout("Received EHLO "); eoutclean(arg); eout("\n"); eflush(); + smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); + seenmail = 0; dohelo(arg); + } + void smtp_rset(arg) char *arg; + { + seenmail = 0; ++ enew(); eout("Session RSET\n"); eflush(); + out("250 flushed\r\n"); + } + void smtp_mail(arg) char *arg; + { +- if (!addrparse(arg)) { err_syntax(); return; } ++ if (!addrparse(arg)) { err_syntax("MAIL"); return; } + flagbarf = bmfcheck(); + seenmail = 1; + if (!stralloc_copys(&rcptto,"")) die_nomem(); + if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); + if (!stralloc_0(&mailfrom)) die_nomem(); ++ rcptcount = 0; ++ enew(); eout("Sender <"); eoutclean(mailfrom.s); eout(">\n"); eflush(); + out("250 ok\r\n"); + } + void smtp_rcpt(arg) char *arg; { + if (!seenmail) { err_wantmail(); return; } +- if (!addrparse(arg)) { err_syntax(); return; } ++ if (!addrparse(arg)) { err_syntax("RCPT"); return; } + if (flagbarf) { err_bmf(); return; } + if (relayclient) { + --addr.len; +@@ -261,6 +348,8 @@ void smtp_rcpt(arg) char *arg; { + if (!stralloc_cats(&rcptto,"T")) die_nomem(); + if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_0(&rcptto)) die_nomem(); ++ ++rcptcount; ++ enew(); eout("Recipient <"); eoutclean(addr.s); eout(">\n"); eflush(); + out("250 ok\r\n"); + } + +@@ -280,6 +369,7 @@ substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + + struct qmail qqt; + unsigned int bytestooverflow = 0; ++unsigned int messagebytes = 0; + + void put(ch) + char *ch; +@@ -287,6 +377,7 @@ char *ch; + if (bytestooverflow) + if (!--bytestooverflow) + qmail_fail(&qqt); ++ messagebytes++; + qmail_put(&qqt,ch,1); + } + +@@ -363,6 +454,11 @@ void acceptmessage(qp) unsigned long qp; + accept_buf[fmt_ulong(accept_buf,qp)] = 0; + out(accept_buf); + out("\r\n"); ++ enew(); eout2("Message accepted, qp ",accept_buf); ++ accept_buf[fmt_ulong(accept_buf,rcptcount)] = 0; ++ eout3(" (",accept_buf," recipients, "); ++ accept_buf[fmt_ulong(accept_buf,messagebytes)] = 0; ++ eout2(accept_buf," bytes)\n"); eflush(); + } + + void smtp_data(arg) char *arg; { +@@ -374,6 +470,7 @@ void smtp_data(arg) char *arg; { + if (!rcptto.len) { err_wantrcpt(); return; } + seenmail = 0; + if (databytes) bytestooverflow = databytes + 1; ++ messagebytes = 0; + if (qmail_open(&qqt) == -1) { err_qqt(); return; } + qp = qmail_qp(&qqt); + out("354 go ahead\r\n"); +@@ -387,11 +484,15 @@ void smtp_data(arg) char *arg; { + + qqx = qmail_close(&qqt); + if (!*qqx) { acceptmessage(qp); return; } +- if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; } +- if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; } ++ if (hops) { err_hops(); return; } ++ if (databytes) if (!bytestooverflow) { err_databytes(); return; } + if (*qqx == 'D') out("554 "); else out("451 "); + out(qqx + 1); + out("\r\n"); ++ enew(); eout("Message rejected ("); ++ if (*qqx == 'D') eout("554 "); else eout("451 "); ++ eoutclean(qqx + 1); eout(")\n"); ++ eflush(); + } + + struct commands smtpcommands[] = { +@@ -411,6 +512,7 @@ struct commands smtpcommands[] = { + void main() + { + sig_pipeignore(); ++ /* esetfd(2); Errors default to FD2 (stderr), change here if needed */ + if (chdir(auto_qmail) == -1) die_control(); + setup(); + if (ipme_init() != 1) die_ipme(); +-- +1.7.0 + --- netqmail-1.06.orig/debian/diff/0003-qmail-verify-optionally-check-aliases.cdb-if-fastforw.diff +++ netqmail-1.06/debian/diff/0003-qmail-verify-optionally-check-aliases.cdb-if-fastforw.diff @@ -0,0 +1,88 @@ +From e0a12b4e5772df5b656ea4cf7b7e6e2d39b9bc55 Mon Sep 17 00:00:00 2001 +From: Gerrit Pape +Date: Fri, 5 Mar 2010 01:14:31 +0000 +Subject: [PATCH 3/3] qmail-verify: optionally check aliases.cdb if fastforward is used + +If qmail-verify finds ~alias/.qmail-default and the environment variable +VERIFY_FASTFORWARDCDB is set to e.g. /etc/aliases.cdb, instead of allowing +all addresses it will lookup the recipient address in that constant +database, and only allow the address if a matching entry is found. +--- + qmail-verify.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 53 insertions(+), 1 deletions(-) + +diff --git a/qmail-verify.c b/qmail-verify.c +index 641f920..a33c20d 100644 +--- a/qmail-verify.c ++++ b/qmail-verify.c +@@ -164,6 +164,49 @@ int userext() /* from qmail-getpw.c */ + } + } + ++int verify_aliasescdb(addr, fn) ++char *addr; ++char *fn; ++{ ++ int fd; ++ static stralloc key = {}; ++ uint32 dlen; ++ int r; ++ int at; ++ ++ fd = open_read(fn); ++ if (fd == -1) die_cdb(); ++ if (!stralloc_copys(&key,":")) die_nomem(); ++ if (!stralloc_cats(&key,addr)) die_nomem(); ++ case_lowerb(key.s,key.len); ++ ++ r = cdb_seek(fd,key.s,key.len,&dlen); ++ if (r == -1) die_cdb(); ++ if (r) { close(fd); return 1; } ++ ++ at = str_rchr(addr,'@'); ++ if (!addr[at]) { close(fd); return 0; } ++ ++ if (!stralloc_copys(&key,":")) die_nomem(); ++ if (!stralloc_cats(&key,addr + at)) nomem(); ++ case_lowerb(key.s,key.len); ++ ++ r = cdb_seek(fd,key.s,key.len,&dlen); ++ if (r == -1) die_cdb(); ++ if (r) { close(fd); return 1; } ++ ++ if (!stralloc_copys(&key,":")) nomem(); ++ if (!stralloc_catb(&key,addr,at + 1)) nomem(); ++ case_lowerb(key.s,key.len); ++ ++ r = cdb_seek(fd,key.s,key.len,&dlen); ++ if (r == -1) die_cdb(); ++ close(fd); ++ if (r) return 1; ++ ++ return 0; ++} ++ + int verifyaddr(addr) + char *addr; + { +@@ -351,7 +394,16 @@ char *addr; + if (!stralloc_cats(&qme,"default")) die_nomem(); + if (!stralloc_0(&qme)) die_nomem(); + /* e.g. homedir/.qmail-[xxx-]default */ +- if (stat(qme.s,&st) == 0) return allowaddr(addr,ADDR_OK|QVPOS12); ++ if (stat(qme.s,&st) == 0) { ++ /* if it's ~alias/.qmail-default, optionally check aliases.cdb */ ++ if (!i && (quser == auto_usera)) { ++ char *s; ++ if (s = env_get("VERIFY_FASTFORWARDCDB")) ++ if (!verify_aliasescdb(addr, s)) ++ return denyaddr(addr,ADDR_NOK|QVPOS12); ++ } ++ return allowaddr(addr,ADDR_OK|QVPOS12); ++ } + if (errno != error_noent) /* Maybe not running as root so access denied */ + return stat_error(qme.s,errno,STATERR|QVPOS13); + } +-- +1.7.0 +