This patchfile is a collection of qmail patches collected on the net. Created: 2005-08-04 If you have question or comments feel free to email me: qmail@lordy.de Here is an overview of the collection in no particular order: Name: qmail-spp (0.40) URL: http://qmail-spp.sf.net Description: Provides a plug-in interface for qmail-smtpd Name: smtpd-auth (0.4.3) URL: http://www.fehcom.de/qmail/smtpauth.html Description: Adds SMTP authentication to qmail-smtpd (for roaming/dial-up users) Name: outgoingip URL: http://www.qmail.org/outgoingip.patch Description: Allows to set the IP address used by qmail-remote to send out email Name: qmailqueue URL: http://www.qmail.org/qmailqueue-patch Description: Pipe incoming email through a custom program before injecting it into qmail-queue (e.g. qmail-scanner) Name: local 0.0.0.0 URL: http://www.suspectclass.com/~sgifford/qmail/qmail-0.0.0.0.patch Description: qmail recognises 0.0.0.0 as local address Name: hold remote URL: http://www.leverton.org/qmail-hold-1.03.pat.gz Description: Allows to temporarily hold all local and/or remote deliveries Name: big dns URL: http://www.ckdhr.com/ckd/qmail-103.patch Description: Fixes problems with handling big dns answers Name: local bug URL: http://www.ornl.gov/lists/mailing-lists/qmail/2000/10/msg00696.html Description: A small 'just-in-case' patch to qmail-local Name: sendmail flagf URL: http://david.acz.org/software/sendmail-flagf.patch Description: Adds the -f parameter to qmail's sendmail binary Name: glibc errno URL: http://djbware.csi.hu/patches/qmail-1.03.errno.patch Description: Fix compilation problems with glibc 2.3.1+ Name: netscape progress URL: http://qmail.mirrors.space.net/netscape-progress.patch Description: Small patch to qmail-pop3d to make sure progress bar works correctly Name: preline epipe URL: http://www.fefe.de/qmail/qmail-1.03-preline.diff Description: Lets the preline program ignore SIGPIPE if necessary Name: pop3d capa URL: http://tomclegg.net/qmail/#qmail-capa Description: Adds the 'CAPA' command to qmail-pop3d Name: more ipme URL: http://www.suspectclass.com/~sgifford/qmail/qmail-1.03-moreipme.patch Description: Recognise multiple IP address as local Name: rfc2821 extension URL: http://qmail.mirrors.space.net/accept-5xx.patch Description: Increases RFC2821 compliance by correctly handling initial 5xx responses diff -Nur qmail-1.03.orig/FILES.auth qmail-1.03/FILES.auth --- qmail-1.03.orig/FILES.auth 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/FILES.auth 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,17 @@ +The qmail-smtpd Auth patch modifies the following QMAIL 1.03 files: + += TARGETS += Makefile += qmail-smtpd.c += qmail-smtpd.8 + +Added files: + +& base64.c +& base64.h + +Informational files: + +% install_auth.sh (Installation shell script) +% README.auth +% README.auth.old (old description of SMTP Auth) diff -Nur qmail-1.03.orig/Makefile qmail-1.03/Makefile --- qmail-1.03.orig/Makefile 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/Makefile 2005-08-04 00:18:42.000000000 +0200 @@ -23,8 +23,8 @@ auto-ccld.sh: \ conf-cc conf-ld warn-auto.sh ( cat warn-auto.sh; \ - echo CC=\'`head -1 conf-cc`\'; \ - echo LD=\'`head -1 conf-ld`\' \ + echo CC=\'`head -n 1 conf-cc`\'; \ + echo LD=\'`head -n 1 conf-ld`\' \ ) > auto-ccld.sh auto-gid: \ @@ -72,7 +72,7 @@ auto_break.c: \ auto-str conf-break ./auto-str auto_break \ - "`head -1 conf-break`" > auto_break.c + "`head -n 1 conf-break`" > auto_break.c auto_break.o: \ compile auto_break.c @@ -80,7 +80,7 @@ auto_patrn.c: \ auto-int8 conf-patrn - ./auto-int8 auto_patrn `head -1 conf-patrn` > auto_patrn.c + ./auto-int8 auto_patrn `head -n 1 conf-patrn` > auto_patrn.c auto_patrn.o: \ compile auto_patrn.c @@ -88,7 +88,7 @@ auto_qmail.c: \ auto-str conf-qmail - ./auto-str auto_qmail `head -1 conf-qmail` > auto_qmail.c + ./auto-str auto_qmail `head -n 1 conf-qmail` > auto_qmail.c auto_qmail.o: \ compile auto_qmail.c @@ -96,7 +96,7 @@ auto_spawn.c: \ auto-int conf-spawn - ./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c + ./auto-int auto_spawn `head -n 1 conf-spawn` > auto_spawn.c auto_spawn.o: \ compile auto_spawn.c @@ -104,7 +104,7 @@ auto_split.c: \ auto-int conf-split - ./auto-int auto_split `head -1 conf-split` > auto_split.c + ./auto-int auto_split `head -n 1 conf-split` > auto_split.c auto_split.o: \ compile auto_split.c @@ -112,16 +112,16 @@ auto_uids.c: \ auto-uid auto-gid conf-users conf-groups - ( ./auto-uid auto_uida `head -1 conf-users` \ - &&./auto-uid auto_uidd `head -2 conf-users | tail -1` \ - &&./auto-uid auto_uidl `head -3 conf-users | tail -1` \ - &&./auto-uid auto_uido `head -4 conf-users | tail -1` \ - &&./auto-uid auto_uidp `head -5 conf-users | tail -1` \ - &&./auto-uid auto_uidq `head -6 conf-users | tail -1` \ - &&./auto-uid auto_uidr `head -7 conf-users | tail -1` \ - &&./auto-uid auto_uids `head -8 conf-users | tail -1` \ - &&./auto-gid auto_gidq `head -1 conf-groups` \ - &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \ + ( ./auto-uid auto_uida `head -n 1 conf-users` \ + &&./auto-uid auto_uidd `head -n 2 conf-users | tail -n 1` \ + &&./auto-uid auto_uidl `head -n 3 conf-users | tail -n 1` \ + &&./auto-uid auto_uido `head -n 4 conf-users | tail -n 1` \ + &&./auto-uid auto_uidp `head -n 5 conf-users | tail -n 1` \ + &&./auto-uid auto_uidq `head -n 6 conf-users | tail -n 1` \ + &&./auto-uid auto_uidr `head -n 7 conf-users | tail -n 1` \ + &&./auto-uid auto_uids `head -n 8 conf-users | tail -n 1` \ + &&./auto-gid auto_gidq `head -n 1 conf-groups` \ + &&./auto-gid auto_gidn `head -n 2 conf-groups | tail -n 1` \ ) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c auto_uids.o: \ @@ -130,51 +130,55 @@ auto_usera.c: \ auto-str conf-users - ./auto-str auto_usera `head -1 conf-users` > auto_usera.c + ./auto-str auto_usera `head -n 1 conf-users` > auto_usera.c auto_usera.o: \ compile auto_usera.c ./compile auto_usera.c +base64.o: \ +compile base64.c base64.h stralloc.h substdio.h str.h + ./compile base64.c + binm1: \ binm1.sh conf-qmail cat binm1.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm1 chmod 755 binm1 binm1+df: \ binm1+df.sh conf-qmail cat binm1+df.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm1+df chmod 755 binm1+df binm2: \ binm2.sh conf-qmail cat binm2.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm2 chmod 755 binm2 binm2+df: \ binm2+df.sh conf-qmail cat binm2+df.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm2+df chmod 755 binm2+df binm3: \ binm3.sh conf-qmail cat binm3.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm3 chmod 755 binm3 binm3+df: \ binm3+df.sh conf-qmail cat binm3+df.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > binm3+df chmod 755 binm3+df @@ -337,18 +341,18 @@ config: \ warn-auto.sh config.sh conf-qmail conf-break conf-split cat warn-auto.sh config.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > config chmod 755 config config-fast: \ warn-auto.sh config-fast.sh conf-qmail conf-break conf-split cat warn-auto.sh config-fast.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > config-fast chmod 755 config-fast @@ -368,9 +372,9 @@ datemail: \ warn-auto.sh datemail.sh conf-qmail conf-break conf-split cat warn-auto.sh datemail.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > datemail chmod 755 datemail @@ -478,17 +482,17 @@ dot-qmail.5: \ dot-qmail.9 conf-break conf-spawn cat dot-qmail.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > dot-qmail.5 elq: \ warn-auto.sh elq.sh conf-qmail conf-break conf-split cat warn-auto.sh elq.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > elq chmod 755 elq @@ -708,14 +712,14 @@ home: \ home.sh conf-qmail cat home.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > home chmod 755 home home+df: \ home+df.sh conf-qmail cat home+df.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > home+df chmod 755 home+df @@ -787,9 +791,9 @@ ./compile ipme.c ipmeprint: \ -load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \ +load ipmeprint.o ipme.o ip.o ipalloc.o open.a getln.a stralloc.a alloc.a substdio.a \ error.a str.a fs.a socket.lib - ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \ + ./load ipmeprint ipme.o ip.o ipalloc.o open.a getln.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a `cat socket.lib` ipmeprint.o: \ @@ -893,9 +897,9 @@ mailsubj: \ warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split cat warn-auto.sh mailsubj.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > mailsubj chmod 755 mailsubj @@ -995,9 +999,9 @@ pinq: \ warn-auto.sh pinq.sh conf-qmail conf-break conf-split cat warn-auto.sh pinq.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > pinq chmod 755 pinq @@ -1035,14 +1039,14 @@ proc: \ proc.sh conf-qmail cat proc.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > proc chmod 755 proc proc+df: \ proc+df.sh conf-qmail cat proc+df.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ > proc+df chmod 755 proc+df @@ -1053,9 +1057,9 @@ qail: \ warn-auto.sh qail.sh conf-qmail conf-break conf-split cat warn-auto.sh qail.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > qail chmod 755 qail @@ -1102,9 +1106,9 @@ qmail-control.5: \ qmail-control.9 conf-break conf-spawn cat qmail-control.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-control.5 qmail-getpw: \ @@ -1120,9 +1124,9 @@ qmail-getpw.8: \ qmail-getpw.9 conf-break conf-spawn cat qmail-getpw.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-getpw.8 qmail-getpw.o: \ @@ -1165,9 +1169,9 @@ qmail-limits.7: \ qmail-limits.9 conf-break conf-spawn cat qmail-limits.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-limits.7 qmail-local: \ @@ -1230,9 +1234,9 @@ qmail-newmrh.8: \ qmail-newmrh.9 conf-break conf-spawn cat qmail-newmrh.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-newmrh.8 qmail-newmrh.o: \ @@ -1255,9 +1259,9 @@ qmail-newu.8: \ qmail-newu.9 conf-break conf-spawn cat qmail-newu.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-newu.8 qmail-newu.o: \ @@ -1319,9 +1323,9 @@ qmail-pw2u.8: \ qmail-pw2u.9 conf-break conf-spawn cat qmail-pw2u.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-pw2u.8 qmail-pw2u.o: \ @@ -1408,9 +1412,9 @@ qmail-qstat: \ warn-auto.sh qmail-qstat.sh conf-qmail conf-break conf-split cat warn-auto.sh qmail-qstat.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > qmail-qstat chmod 755 qmail-qstat @@ -1483,12 +1487,12 @@ trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \ datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \ lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ -auto_split.o +auto_split.o env.a ./load qmail-send qsutil.o control.o constmap.o newfield.o \ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \ - substdio.a error.a str.a fs.a auto_qmail.o auto_split.o + substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a qmail-send.0: \ qmail-send.8 @@ -1497,9 +1501,9 @@ qmail-send.8: \ qmail-send.9 conf-break conf-spawn cat qmail-send.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-send.8 qmail-send.o: \ @@ -1531,18 +1535,23 @@ auto_split.h ./compile qmail-showctl.c +qmail-spp.o: \ +compile qmail-spp.c readwrite.h stralloc.h substdio.h control.h str.h \ +byte.h env.h exit.h wait.h fork.h fd.h fmt.h getln.h + ./compile qmail-spp.c + 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 \ -fs.a auto_qmail.o socket.lib +fs.a auto_qmail.o base64.o qmail-spp.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 \ - alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ - socket.lib` + datetime.a getln.a open.a sig.a case.a qmail-spp.o env.a stralloc.a \ + alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o \ + `cat socket.lib` qmail-smtpd.0: \ qmail-smtpd.8 @@ -1551,9 +1560,9 @@ qmail-smtpd.o: \ 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 \ +error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.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 +exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h ./compile qmail-smtpd.c qmail-start: \ @@ -1567,9 +1576,9 @@ qmail-start.8: \ qmail-start.9 conf-break conf-spawn cat qmail-start.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-start.8 qmail-start.o: \ @@ -1609,9 +1618,9 @@ qmail-upq: \ warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split cat warn-auto.sh qmail-upq.sh \ - | sed s}QMAIL}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPLIT}"`head -1 conf-split`"}g \ + | sed s}QMAIL}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPLIT}"`head -n 1 conf-split`"}g \ > qmail-upq chmod 755 qmail-upq @@ -1622,9 +1631,9 @@ qmail-users.5: \ qmail-users.9 conf-break conf-spawn cat qmail-users.9 \ - | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ - | sed s}BREAK}"`head -1 conf-break`"}g \ - | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \ + | sed s}BREAK}"`head -n 1 conf-break`"}g \ + | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \ > qmail-users.5 qmail.0: \ diff -Nur qmail-1.03.orig/README.auth qmail-1.03/README.auth --- qmail-1.03.orig/README.auth 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/README.auth 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,58 @@ +README qmail-smtpd SMTP Authentication +====================================== + + +History: +-------- + +This patch is based on Krzysztof Dabrowski's qmail-smtpd-auth-0.31 patch +which itself uses "Mrs. Brisby's" initial code. +Version 0.41 of this patch fixes the "CAPS-LOCK" typo announcing +'CRAM_MD5' instead of 'CRAM-MD5' (german keyboard) - tx to Mike Garrison. +Version 0.42 fixes the '421 unable to read controls (#4.3.0)' problem +(can't read control/morercpthosts.cdb) because FD 3 was already closed - tx Richard Lyons. +Version 0.43 fixes the ba64decode() failure in case CRAM_MD5 is not enabled - tx Vladimir Zidar. + + +Scope: +------ + +This patch supports partly RFC 2554 "SMTP Service Extension for Authentication". +For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html. + + +Installation: +------------- + +* Untar the source in the qmail-1.03 home direcotry. +* Run ./install_auth. +* Modify the compile time option "#define CRAM_MD5" to your needs. +* Re-make qmail. + + +Setup: +------ + +In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module' +PAM to be called by qmail-smtpd; typically + + /var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1 + +Since qmail-smtpd does not run as root, checkpassword has to be made sticky. +There is no need to include additionally the hostname in the call. +In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information. + + +Changes wrt. Krysztof Dabrowski's patch: +---------------------------------------- + +* Avoid the 'hostname' in the call of the PAM. +* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5. +* Doesn't close FD 2; thus not inhibiting logging to STDERR. +* Fixed bugs in base64.c. +* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'. + + +Erwin Hoffmann - Cologne 2004-04-03 (www.fehcom.de) + + diff -Nur qmail-1.03.orig/TARGETS qmail-1.03/TARGETS --- qmail-1.03.orig/TARGETS 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/TARGETS 2005-08-04 00:18:10.000000000 +0200 @@ -10,6 +10,7 @@ qmail.o quote.o now.o +base64.o gfrom.o myctime.o slurpclose.o diff -Nur qmail-1.03.orig/base64.c qmail-1.03/base64.c --- qmail-1.03.orig/base64.c 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/base64.c 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,122 @@ +#include "base64.h" +#include "stralloc.h" +#include "substdio.h" +#include "str.h" + +static char *b64alpha = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#define B64PAD '=' + +/* returns 0 ok, 1 illegal, -1 problem */ + +int b64decode(in,l,out) +const unsigned char *in; +int l; +stralloc *out; /* not null terminated */ +{ + int p = 0; + int n; + unsigned int x; + int i, j; + char *s; + unsigned char b[3]; + + if (l == 0) + { + if (!stralloc_copys(out,"")) return -1; + return 0; + } + + while(in[l-1] == B64PAD) { + p ++; + l--; + } + + n = (l + p) / 4; + out->len = (n * 3) - p; + if (!stralloc_ready(out,out->len)) return -1; + s = out->s; + + for(i = 0; i < n - 1 ; i++) { + x = 0; + for(j = 0; j < 4; j++) { + if(in[j] >= 'A' && in[j] <= 'Z') + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); + else if(in[j] >= 'a' && in[j] <= 'z') + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); + else if(in[j] >= '0' && in[j] <= '9') + x = (x << 6) + (unsigned int)(in[j] - '0' + 52); + else if(in[j] == '+') + x = (x << 6) + 62; + else if(in[j] == '/') + x = (x << 6) + 63; + else if(in[j] == '=') + x = (x << 6); + } + + s[2] = (unsigned char)(x & 255); x >>= 8; + s[1] = (unsigned char)(x & 255); x >>= 8; + s[0] = (unsigned char)(x & 255); x >>= 8; + s += 3; in += 4; + } + + x = 0; + for(j = 0; j < 4; j++) { + if(in[j] >= 'A' && in[j] <= 'Z') + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); + else if(in[j] >= 'a' && in[j] <= 'z') + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); + else if(in[j] >= '0' && in[j] <= '9') + x = (x << 6) + (unsigned int)(in[j] - '0' + 52); + else if(in[j] == '+') + x = (x << 6) + 62; + else if(in[j] == '/') + x = (x << 6) + 63; + else if(in[j] == '=') + x = (x << 6); + } + + b[2] = (unsigned char)(x & 255); x >>= 8; + b[1] = (unsigned char)(x & 255); x >>= 8; + b[0] = (unsigned char)(x & 255); x >>= 8; + + for(i = 0; i < 3 - p; i++) + s[i] = b[i]; + + return 0; +} + +int b64encode(in,out) +stralloc *in; +stralloc *out; /* not null terminated */ +{ + unsigned char a, b, c; + int i; + char *s; + + if (in->len == 0) + { + if (!stralloc_copys(out,"")) return -1; + return 0; + } + + if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1; + s = out->s; + + for (i = 0;i < in->len;i += 3) { + a = in->s[i]; + b = i + 1 < in->len ? in->s[i + 1] : 0; + c = i + 2 < in->len ? in->s[i + 2] : 0; + + *s++ = b64alpha[a >> 2]; + *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)]; + + if (i + 1 >= in->len) *s++ = B64PAD; + else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)]; + + if (i + 2 >= in->len) *s++ = B64PAD; + else *s++ = b64alpha[c & 63]; + } + out->len = s - out->s; + return 0; +} diff -Nur qmail-1.03.orig/base64.h qmail-1.03/base64.h --- qmail-1.03.orig/base64.h 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/base64.h 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,7 @@ +#ifndef BASE64_H +#define BASE64_H + +extern int b64decode(); +extern int b64encode(); + +#endif diff -Nur qmail-1.03.orig/cdb_seek.c qmail-1.03/cdb_seek.c --- qmail-1.03.orig/cdb_seek.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/cdb_seek.c 2005-08-04 00:18:10.000000000 +0200 @@ -1,6 +1,5 @@ #include #include -extern int errno; #include "cdb.h" #ifndef SEEK_SET diff -Nur qmail-1.03.orig/dns.c qmail-1.03/dns.c --- qmail-1.03.orig/dns.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/dns.c 2005-08-04 00:18:10.000000000 +0200 @@ -7,8 +7,6 @@ #include extern int res_query(); extern int res_search(); -extern int errno; -extern int h_errno; #include "ip.h" #include "ipalloc.h" #include "fmt.h" @@ -21,10 +19,12 @@ static unsigned short getshort(c) unsigned char *c; { unsigned short u; u = c[0]; return (u << 8) + c[1]; } -static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response; +static struct { unsigned char *buf; } response; +static int responsebuflen = 0; static int responselen; static unsigned char *responseend; static unsigned char *responsepos; +static unsigned long saveresoptions; static int numanswers; static char name[MAXDNAME]; @@ -45,18 +45,33 @@ errno = 0; if (!stralloc_copy(&glue,domain)) return DNS_MEM; if (!stralloc_0(&glue)) return DNS_MEM; - responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response)); + if (!responsebuflen) + if (response.buf = (unsigned char *)alloc(PACKETSZ+1)) + responsebuflen = PACKETSZ+1; + else return DNS_MEM; + + responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen); + if ((responselen >= responsebuflen) || + (responselen > 0 && (((HEADER *)response.buf)->tc))) + { + if (responsebuflen < 65536) + if (alloc_re(&response.buf, responsebuflen, 65536)) + responsebuflen = 65536; + else return DNS_MEM; + saveresoptions = _res.options; + _res.options |= RES_USEVC; + responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen); + _res.options = saveresoptions; + } if (responselen <= 0) { if (errno == ECONNREFUSED) return DNS_SOFT; if (h_errno == TRY_AGAIN) return DNS_SOFT; return DNS_HARD; } - if (responselen >= sizeof(response)) - responselen = sizeof(response); responseend = response.buf + responselen; responsepos = response.buf + sizeof(HEADER); - n = ntohs(response.hdr.qdcount); + n = ntohs(((HEADER *)response.buf)->qdcount); while (n-- > 0) { i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); @@ -66,7 +81,7 @@ if (i < QFIXEDSZ) return DNS_SOFT; responsepos += QFIXEDSZ; } - numanswers = ntohs(response.hdr.ancount); + numanswers = ntohs(((HEADER *)response.buf)->ancount); return 0; } diff -Nur qmail-1.03.orig/error.3 qmail-1.03/error.3 --- qmail-1.03.orig/error.3 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/error.3 2005-08-04 00:18:10.000000000 +0200 @@ -3,8 +3,7 @@ error \- syscall error codes .SH SYNTAX .B #include - -extern int \fBerrno\fP; +.B #include extern int \fBerror_intr\fP; .br diff -Nur qmail-1.03.orig/error.h qmail-1.03/error.h --- qmail-1.03.orig/error.h 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/error.h 2005-08-04 00:18:10.000000000 +0200 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; diff -Nur qmail-1.03.orig/ipme.c qmail-1.03/ipme.c --- qmail-1.03.orig/ipme.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/ipme.c 2005-08-04 00:18:42.000000000 +0200 @@ -5,6 +5,7 @@ #include #include #include +#include #ifndef SIOCGIFCONF /* whatever works */ #include #endif @@ -14,6 +15,7 @@ #include "ipalloc.h" #include "stralloc.h" #include "ipme.h" +#include "substdio.h" static int ipmeok = 0; ipalloc ipme = {0}; @@ -40,12 +42,24 @@ int len; int s; struct ip_mx ix; + int moreipme_fd; if (ipmeok) return 1; if (!ipalloc_readyplus(&ipme,0)) return 0; ipme.len = 0; ix.pref = 0; + /* 0.0.0.0 is a special address which always refers to + * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a. + */ + byte_copy(&ix.ip,4,"\0\0\0\0"); + if (!ipalloc_append(&ipme,&ix)) { return 0; } + + /* 0.0.0.0 is a special address which always refers to + * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a. + */ + byte_copy(&ix.ip,4,"\0\0\0\0"); + if (!ipalloc_append(&ipme,&ix)) { return 0; } if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; len = 256; @@ -90,6 +104,34 @@ x += len; } close(s); + + /* Now see if there are any supplemental IPs */ + if ( (moreipme_fd = open_read("control/moreipme")) != -1) + { + char inbuf[1024]; + substdio ss; + stralloc l = {0}; + int match; + + substdio_fdbuf(&ss, read, moreipme_fd, inbuf, sizeof(inbuf)); + while (1) + { + if (getln(&ss, &l, &match, '\n') == -1) + { + break; + } + if (!match && !l.len) + { + break; + } + l.len--; + if (!stralloc_0(&l)) { close(moreipme_fd); return 0; } + if (!ip_scan(l.s, &ix.ip)) { continue; } + if (!ipalloc_append(&ipme,&ix)) { close(moreipme_fd); return 0; } + } + } + close(moreipme_fd); + ipmeok = 1; return 1; } diff -Nur qmail-1.03.orig/preline.c qmail-1.03/preline.c --- qmail-1.03.orig/preline.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/preline.c 2005-08-04 00:18:10.000000000 +0200 @@ -20,6 +20,7 @@ int flagufline = 1; char *ufline; int flagrpline = 1; char *rpline; int flagdtline = 1; char *dtline; +int flagpipe = 0; char outbuf[SUBSTDIO_OUTSIZE]; char inbuf[SUBSTDIO_INSIZE]; @@ -41,7 +42,7 @@ if (!(rpline = env_get("RPLINE"))) die_usage(); if (!(dtline = env_get("DTLINE"))) die_usage(); - while ((opt = getopt(argc,argv,"frdFRD")) != opteof) + while ((opt = getopt(argc,argv,"frdFRDp")) != opteof) switch(opt) { case 'f': flagufline = 0; break; case 'r': flagrpline = 0; break; @@ -49,6 +50,7 @@ case 'F': flagufline = 1; break; case 'R': flagrpline = 1; break; case 'D': flagdtline = 1; break; + case 'p': flagpipe = 1; break; default: die_usage(); } argc -= optind; @@ -77,8 +79,10 @@ if (flagufline) substdio_bputs(&ssout,ufline); if (flagrpline) substdio_bputs(&ssout,rpline); if (flagdtline) substdio_bputs(&ssout,dtline); - if (substdio_copy(&ssout,&ssin) != 0) - strerr_die2sys(111,FATAL,"unable to copy input: "); + if (substdio_copy(&ssout,&ssin) != 0) { + if (errno!=error_pipe || !flagpipe) + strerr_die2sys(111,FATAL,"unable to copy input: "); + } substdio_flush(&ssout); close(1); diff -Nur qmail-1.03.orig/qmail-control.9 qmail-1.03/qmail-control.9 --- qmail-1.03.orig/qmail-control.9 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-control.9 2005-08-04 00:18:10.000000000 +0200 @@ -56,6 +56,7 @@ .I localiphost \fIme \fRqmail-smtpd .I locals \fIme \fRqmail-send .I morercpthosts \fR(none) \fRqmail-smtpd +.I outgoingip \fR0.0.0.0 \fRqmail-remote .I percenthack \fR(none) \fRqmail-send .I plusdomain \fIme \fRqmail-inject .I qmqpservers \fR(none) \fRqmail-qmqpc diff -Nur qmail-1.03.orig/qmail-pop3d.c qmail-1.03/qmail-pop3d.c --- qmail-1.03.orig/qmail-pop3d.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-pop3d.c 2005-08-04 00:18:10.000000000 +0200 @@ -267,14 +267,31 @@ fd = open_read(m[i].fn); if (fd == -1) { err_nosuch(); return; } - okay(); + /* okay(); */ + puts("+OK "); + put(strnum,fmt_ulong(strnum,m[i].size)); + puts(" octets\r\n"); + flush(); substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); blast(&ssmsg,limit); close(fd); } +void pop3_capa(arg) char *arg; +{ + puts("+OK Capability list follows\r\n" + "TOP\r\n" + "UIDL\r\n" + "LAST\r\n" + "USER\r\n" + "APOP\r\n" + ".\r\n"); + flush(); +} + struct commands pop3commands[] = { { "quit", pop3_quit, 0 } +, { "capa", pop3_capa, 0 } , { "stat", pop3_stat, 0 } , { "list", pop3_list, 0 } , { "uidl", pop3_uidl, 0 } diff -Nur qmail-1.03.orig/qmail-popup.c qmail-1.03/qmail-popup.c --- qmail-1.03.orig/qmail-popup.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-popup.c 2005-08-04 00:18:10.000000000 +0200 @@ -155,11 +155,23 @@ *space++ = 0; doanddie(arg,space - arg,space); } +void pop3_capa(arg) char *arg; +{ + puts("+OK Capability list follows\r\n" + "TOP\r\n" + "UIDL\r\n" + "LAST\r\n" + "USER\r\n" + "APOP\r\n" + ".\r\n"); + flush(); +} struct commands pop3commands[] = { { "user", pop3_user, 0 } , { "pass", pop3_pass, 0 } , { "apop", pop3_apop, 0 } +, { "capa", pop3_capa, 0 } , { "quit", pop3_quit, 0 } , { "noop", okay, 0 } , { 0, err_authoriz, 0 } diff -Nur qmail-1.03.orig/qmail-remote.8 qmail-1.03/qmail-remote.8 --- qmail-1.03.orig/qmail-remote.8 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-remote.8 2005-08-04 00:18:10.000000000 +0200 @@ -124,6 +124,13 @@ .B qmail-remote refuses to run. .TP 5 +.I outgoingip +IP address to be used on outgoing connections. +Default: system-defined. +The value +.IR 0.0.0.0 +is equivalent to the system default. +.TP 5 .I smtproutes Artificial SMTP routes. Each route has the form diff -Nur qmail-1.03.orig/qmail-remote.c qmail-1.03/qmail-remote.c --- qmail-1.03.orig/qmail-remote.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-remote.c 2005-08-04 00:19:01.000000000 +0200 @@ -39,6 +39,7 @@ static stralloc sauninit = {0}; stralloc helohost = {0}; +stralloc outgoingip = {0}; stralloc routes = {0}; struct constmap maproutes; stralloc host = {0}; @@ -47,6 +48,7 @@ saa reciplist = {0}; struct ip_address partner; +struct ip_address outip; void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } @@ -56,6 +58,7 @@ ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } +void temp_noip() { out("Zinvalid ipaddr in control/outgoingip (#4.3.0)\n"); zerodie(); } void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } void temp_oserr() { out("Z\ System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); } @@ -222,13 +225,17 @@ int flagbother; int i; - if (smtpcode() != 220) quit("ZConnected to "," but greeting failed"); + code = smtpcode(); + if (code >= 500) quit("DConnected to "," but greeting failed"); + if (code != 220) quit("ZConnected to "," but greeting failed"); substdio_puts(&smtpto,"HELO "); substdio_put(&smtpto,helohost.s,helohost.len); substdio_puts(&smtpto,"\r\n"); substdio_flush(&smtpto); - if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); + code = smtpcode(); + if (code >= 500) quit("DConnected to "," but my name was rejected"); + if (code != 250) quit("ZConnected to "," but my name was rejected"); substdio_puts(&smtpto,"MAIL FROM:<"); substdio_put(&smtpto,sender.s,sender.len); @@ -310,6 +317,7 @@ void getcontrols() { + int r; if (control_init() == -1) temp_control(); if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control(); if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) @@ -324,6 +332,12 @@ case 1: if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; } + r = control_readline(&outgoingip,"control/outgoingip"); + if (-1 == r) { if (errno == error_nomem) temp_nomem(); temp_control(); } + if (0 == r && !stralloc_copys(&outgoingip, "0.0.0.0")) temp_nomem(); + if (str_equal(outgoingip.s, "0.0.0.0")) + { outip.d[0]=outip.d[1]=outip.d[2]=outip.d[3]=(unsigned long) 0; } + else if (!ip_scan(outgoingip.s, &outip)) temp_noip(); } void main(argc,argv) @@ -414,7 +428,7 @@ smtpfd = socket(AF_INET,SOCK_STREAM,0); if (smtpfd == -1) temp_oserr(); - if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { + if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) port,timeoutconnect) == 0) { tcpto_err(&ip.ix[i].ip,0); partner = ip.ix[i].ip; smtp(); /* does not return */ diff -Nur qmail-1.03.orig/qmail-send.c qmail-1.03/qmail-send.c --- qmail-1.03.orig/qmail-send.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-send.c 2005-08-04 00:18:10.000000000 +0200 @@ -1,3 +1,11 @@ +/* + * qmail-send.c v1.03 1998/06/15 + * + * Amended Nick Leverton 1998/05/03 to + * provide dynamic hold/release for local and remote message queues + * (revision mark "NJL") + */ + #include #include #include "readwrite.h" @@ -62,6 +70,14 @@ #define CHANNELS 2 char *chanaddr[CHANNELS] = { "local/", "remote/" }; char *chanstatusmsg[CHANNELS] = { " local ", " remote " }; +char *chanjobsheldmsg[CHANNELS] = { /* NJL 1998/05/03 */ + "local deliveries temporarily held\n" +, "remote deliveries temporarily held\n" +}; +char *chanjobsunheldmsg[CHANNELS] = { /* NJL 1998/05/03 */ + "local deliveries resumed\n" +, "remote deliveries resumed\n" +}; char *tochan[CHANNELS] = { " to local ", " to remote " }; int chanfdout[CHANNELS] = { 1, 3 }; int chanfdin[CHANNELS] = { 2, 4 }; @@ -782,6 +798,7 @@ unsigned long masterdelid = 1; unsigned int concurrency[CHANNELS] = { 10, 20 }; unsigned int concurrencyused[CHANNELS] = { 0, 0 }; +unsigned int holdjobs[CHANNELS] = { 0, 0 }; /* Booleans: hold deliveries NJL 1998/05/03 */ struct del *d[CHANNELS]; stralloc dline[CHANNELS]; char delbuf[2048]; @@ -796,6 +813,8 @@ strnum3[fmt_ulong(strnum3,(unsigned long) concurrency[c])] = 0; log2(chanstatusmsg[c],strnum2); log2("/",strnum3); + if (holdjobs[c]) /*NJL*/ + log1(" (held)"); /*NJL*/ } if (flagexitasap) log1(" exitasap"); log1("\n"); @@ -822,7 +841,7 @@ { int c; for (c = 0;c < CHANNELS;++c) - if (flagspawnalive[c]) /* if dead, nothing we can do about its jobs */ + if (flagspawnalive[c] && !holdjobs[c]) /* if dead or held /NJL/, nothing we can do about its jobs */ if (concurrencyused[c]) return 0; return 1; } @@ -830,7 +849,7 @@ int del_avail(c) int c; { - return flagspawnalive[c] && comm_canwrite(c) && (concurrencyused[c] < concurrency[c]); + return flagspawnalive[c] && comm_canwrite(c) && !holdjobs[c] && (concurrencyused[c] < concurrency[c]); /* NJL 1998/07/24 */ } void del_start(j,mpos,recip) @@ -843,6 +862,7 @@ c = jo[j].channel; if (!flagspawnalive[c]) return; + if (holdjobs[c]) return; /* NJL 1998/05/03 */ if (!comm_canwrite(c)) return; for (i = 0;i < concurrency[c];++i) if (!d[c][i].used) break; @@ -1445,6 +1465,8 @@ if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0; if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0; if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0; + if (control_readint(&holdjobs[0],"control/holdlocal") == -1) return 0; /*NJL*/ + if (control_readint(&holdjobs[1],"control/holdremote") == -1) return 0;/*NJL*/ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0; if (control_rldef(&bouncefrom,"control/bouncefrom",0,"MAILER-DAEMON") != 1) return 0; if (control_rldef(&bouncehost,"control/bouncehost",1,"bouncehost") != 1) return 0; @@ -1475,6 +1497,9 @@ void regetcontrols() { int r; + int c; /*NJL*/ + int newholdjobs[CHANNELS] = { 0, 0 }; /*NJL*/ + int runasap = 0; /*Flag: do a mail kick - NJL 1998-05-05 */ if (control_readfile(&newlocals,"control/locals",1) != 1) { log1("alert: unable to reread control/locals\n"); return; } @@ -1482,6 +1507,30 @@ if (r == -1) { log1("alert: unable to reread control/virtualdomains\n"); return; } +/* Add "holdlocal/holdremote" flags - NJL 1998/05/03 */ + if (control_readint(&newholdjobs[0],"control/holdlocal") == -1) + { log1("alert: unable to reread control/holdlocal\n"); return; } + if (control_readint(&newholdjobs[1],"control/holdremote") == -1) + { log1("alert: unable to reread control/holdremote\n"); return; } + + for (c=0; c= MAXHOPS); if (hops) qmail_fail(&qqt); @@ -394,10 +432,237 @@ out("\r\n"); } +/* this file is too long ----------------------------------------- SMTP AUTH */ + +char unique[FMT_ULONG + FMT_ULONG + 3]; +static stralloc authin = {0}; /* input from SMTP client */ +static stralloc user = {0}; /* plain userid */ +static stralloc pass = {0}; /* plain passwd or digest */ +static stralloc resp = {0}; /* b64 response */ +#ifdef CRAM_MD5 +static stralloc chal = {0}; /* plain challenge */ +static stralloc slop = {0}; /* b64 challenge */ +#endif + +int flagauth; + +char **childargs; +char ssauthbuf[512]; +substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf)); + +int authgetl(void) { + int i; + + if (!stralloc_copys(&authin,"")) die_nomem(); + for (;;) { + if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */ + i = substdio_get(&ssin,authin.s + authin.len,1); + if (i != 1) die_read(); + if (authin.s[authin.len] == '\n') break; + ++authin.len; + } + + if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len; + authin.s[authin.len] = 0; + if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); } + if (authin.len == 0) { return err_input(); } + return authin.len; +} + +int authenticate(void) +{ + int child; + int wstat; + int pi[2]; + + if (!stralloc_0(&user)) die_nomem(); + if (!stralloc_0(&pass)) die_nomem(); +#ifdef CRAM_MD5 + if (!stralloc_0(&chal)) die_nomem(); +#endif + + if (pipe(pi) == -1) return err_pipe(); + switch(child = fork()) { + case -1: + return err_fork(); + case 0: + close(pi[1]); + dup2(pi[0],3); + sig_pipedefault(); + execvp(*childargs, childargs); + _exit(1); + } + close(pi[0]); + + substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf); + if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write(); + if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write(); +#ifdef CRAM_MD5 + if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write(); +#endif + if (substdio_flush(&ssauth) == -1) return err_write(); + + close(pi[1]); +#ifdef CRAM_MD5 + byte_zero(chal.s,chal.len); + byte_zero(slop.s,slop.len); +#endif + byte_zero(ssauthbuf,sizeof ssauthbuf); + if (wait_pid(&wstat,child) == -1) return err_child(); + if (wait_crashed(wstat)) return err_child(); + if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */ + return 0; /* yes */ +} + +int auth_login(arg) char *arg; +{ + int r; + + if (*arg) { + if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input(); + } + else { + out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */ + if (authgetl() < 0) return -1; + if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input(); + } + if (r == -1) die_nomem(); + + out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */ + + if (authgetl() < 0) return -1; + if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input(); + if (r == -1) die_nomem(); + + if (!user.len || !pass.len) return err_input(); + return authenticate(); +} + +int auth_plain(arg) char *arg; +{ + int r, id = 0; + + if (*arg) { + if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input(); + } + else { + out("334 \r\n"); flush(); + if (authgetl() < 0) return -1; + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input(); + } + if (r == -1 || !stralloc_0(&resp)) die_nomem(); + while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */ + + if (resp.len > id + 1) + if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem(); + if (resp.len > id + user.len + 2) + if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem(); + + if (!user.len || !pass.len) return err_input(); + return authenticate(); +} + +#ifdef CRAM_MD5 +int auth_cram() +{ + int i, r; + char *s; + + s = unique; + s += fmt_uint(s,getpid()); + *s++ = '.'; + s += fmt_ulong(s,(unsigned long) now()); + *s++ = '@'; + *s++ = 0; + + if (!stralloc_copys(&chal,"<")) die_nomem(); /* generate challenge */ + if (!stralloc_cats(&chal,unique)) die_nomem(); + if (!stralloc_cats(&chal,local)) die_nomem(); + if (!stralloc_cats(&chal,">")) die_nomem(); + if (b64encode(&chal,&slop) < 0) die_nomem(); + if (!stralloc_0(&slop)) die_nomem(); + + out("334 "); /* "334 mychallenge \r\n" */ + out(slop.s); + out("\r\n"); + flush(); + + if (authgetl() < 0) return -1; /* got response */ + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input(); + if (r == -1 || !stralloc_0(&resp)) die_nomem(); + + i = str_chr(resp.s,' '); + s = resp.s + i; + while (*s == ' ') ++s; + resp.s[i] = 0; + if (!stralloc_copys(&user,resp.s)) die_nomem(); /* userid */ + if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */ + + if (!user.len || !pass.len) return err_input(); + return authenticate(); +} +#endif + +struct authcmd { + char *text; + int (*fun)(); +} authcmds[] = { + { "login",auth_login } +, { "plain",auth_plain } +#ifdef CRAM_MD5 +, { "cram-md5",auth_cram } +#endif +, { 0,err_noauth } +}; + +void smtp_auth(arg) +char *arg; +{ + int i; + char *cmd = arg; + + if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; } + if (flagauth) { err_authd(); return; } + if (seenmail) { err_authmail(); return; } + + if (!stralloc_copys(&user,"")) die_nomem(); + if (!stralloc_copys(&pass,"")) die_nomem(); + if (!stralloc_copys(&resp,"")) die_nomem(); +#ifdef CRAM_MD5 + if (!stralloc_copys(&chal,"")) die_nomem(); +#endif + + i = str_chr(cmd,' '); + arg = cmd + i; + while (*arg == ' ') ++arg; + cmd[i] = 0; + + for (i = 0;authcmds[i].text;++i) + if (case_equals(authcmds[i].text,cmd)) break; + + switch (authcmds[i].fun(arg)) { + case 0: + if (!spp_auth(authcmds[i].text, user.s)) return; + flagauth = 1; + relayclient = ""; + remoteinfo = user.s; + if (!env_unset("TCPREMOTEINFO")) die_read(); + if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem(); + if (!env_put2("RELAYCLIENT",relayclient)) die_nomem(); + out("235 ok, go ahead (#2.0.0)\r\n"); + break; + case 1: + err_authfail(user.s,authcmds[i].text); + } +} + +/* this file is too long --------------------------------------------- GO ON */ + struct commands smtpcommands[] = { { "rcpt", smtp_rcpt, 0 } , { "mail", smtp_mail, 0 } , { "data", smtp_data, flush } +, { "auth", smtp_auth, flush } , { "quit", smtp_quit, flush } , { "helo", smtp_helo, flush } , { "ehlo", smtp_ehlo, flush } @@ -408,14 +673,19 @@ , { 0, err_unimpl, flush } } ; -void main() +void main(argc,argv) +int argc; +char **argv; { + childargs = argv + 1; sig_pipeignore(); if (chdir(auto_qmail) == -1) die_control(); setup(); if (ipme_init() != 1) die_ipme(); + if (spp_connect()) { smtp_greet("220 "); out(" ESMTP\r\n"); + } if (commands(&ssin,&smtpcommands) == 0) die_read(); die_nomem(); } diff -Nur qmail-1.03.orig/qmail-spp.c qmail-1.03/qmail-spp.c --- qmail-1.03.orig/qmail-spp.c 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/qmail-spp.c 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2004-2005 Pawel Foremski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + *** Note + * + * This is the core of qmail-spp patch for qmail + * + * Why I made it a separate file? Because I wanted qmail-spp to apply more + * cleanly on heavily patched qmail sources and to make it bit simpler to + * maintain, so don't treat it as a library. + * + * "..." comments marks places where code for other SMTP commands should be + * added, if needed. + * + */ + +#include "readwrite.h" +#include "stralloc.h" +#include "substdio.h" +#include "control.h" +#include "str.h" +#include "byte.h" +#include "env.h" +#include "exit.h" +#include "wait.h" +#include "fork.h" +#include "fd.h" +#include "fmt.h" +#include "getln.h" + +/* stuff needed from qmail-smtpd */ +extern void flush(); +extern void out(); +extern void die_nomem(); +extern stralloc addr; +/* *** */ + +stralloc sppheaders = {0}; +static int spprun = 0; +static int sppfok = 0; +static int sppret; +static stralloc sppf = {0}; +static stralloc plugins_dummy = {0}, plugins_connect = {0}, plugins_helo = {0}, plugins_mail = {0}, + plugins_rcpt = {0}, plugins_data = {0}, plugins_auth = {0}; /* ... */ +static stralloc error_mail = {0}, error_rcpt = {0}, error_data = {0}; /* ... */ +static stralloc sppmsg = {0}; +static char rcptcountstr[FMT_ULONG]; +static unsigned long rcptcount; +static substdio ssdown; +static char downbuf[128]; + +static void err_spp(s1, s2) char *s1, *s2; { out("451 qmail-spp failure: "); out(s1); out(": "); out(s2); out(" (#4.3.0)\r\n"); } + +int spp_init() +{ + int i, len = 0; + stralloc *plugins_to; + char *x, *conffile = "control/smtpplugins"; + + if (!env_get("NOSPP")) { + spprun = 1; + plugins_to = &plugins_dummy; + x = env_get("SPPCONFFILE"); + if (x && *x) conffile = x; + sppfok = control_readfile(&sppf, conffile, 0); + if (sppfok != 1) return -1; + for (i = 0; i < sppf.len; i += len) { + len = str_len(sppf.s + i) + 1; + if (sppf.s[i] == '[') + switch (sppf.s[i + 1]) { + case 'c': plugins_to = &plugins_connect; break; + case 'h': plugins_to = &plugins_helo; break; + case 'm': plugins_to = &plugins_mail; break; + case 'r': plugins_to = &plugins_rcpt; break; + case 'd': plugins_to = &plugins_data; break; + case 'a': plugins_to = &plugins_auth; break; + /* ... */ + default: plugins_to = &plugins_dummy; + } + else + if (!stralloc_catb(plugins_to, sppf.s + i, len)) die_nomem(); + } + } + + return 0; +} + +void sppout() { if (sppmsg.len) out(sppmsg.s); out("\r\n"); } + +int spp(plugins, addrenv) stralloc *plugins; char *addrenv; +{ + static int pipes[2]; + static int i, pid, wstat, match, last; + static stralloc data = {0}; + static char *(args[4]); + static stralloc *errors_to; + + if (!spprun) return 1; + if (addrenv) if (!env_put2(addrenv, addr.s)) die_nomem(); + last = 0; + + for (i = 0; i < plugins->len; i += str_len(plugins->s + i) + 1) { + if (plugins->s[i] == ':') + { args[0] = "/bin/sh"; args[1] = "-c"; args[2] = plugins->s + i + 1; args[3] = 0; } + else + { args[0] = plugins->s + i; args[1] = 0; } + + if (pipe(pipes) == -1) + { err_spp(plugins->s + i, "can't pipe()"); return 0; } + + switch (pid = vfork()) { + case -1: + err_spp(plugins->s + i, "vfork() failed"); + return 0; + case 0: + close(0); close(pipes[0]); fd_move(1, pipes[1]); + execv(*args, args); + _exit(120); + } + + close(pipes[1]); + substdio_fdbuf(&ssdown, read, pipes[0], downbuf, sizeof(downbuf)); + do { + if (getln(&ssdown, &data, &match, '\n') == -1) die_nomem(); + if (data.len > 1) { + data.s[data.len - 1] = 0; + switch (data.s[0]) { + case 'H': + if (!stralloc_catb(&sppheaders, data.s + 1, data.len - 2)) die_nomem(); + if (!stralloc_append(&sppheaders, "\n")) die_nomem(); + break; + case 'C': + if (addrenv) { + if (!stralloc_copyb(&addr, data.s + 1, data.len - 1)) die_nomem(); + if (!env_put2(addrenv, addr.s)) die_nomem(); + } + break; + case 'S': if (!env_put(data.s + 1)) die_nomem(); break; + case 'U': if (!env_unset(data.s + 1)) die_nomem(); break; + case 'A': spprun = 0; + case 'O': + case 'N': + case 'D': last = 1; match = 0; break; + case 'E': + case 'R': last = 1; match = 0; + case 'P': out(data.s + 1); out("\r\n"); break; + case 'L': + switch (data.s[1]) { + case 'M': errors_to = &error_mail; break; + case 'R': errors_to = &error_rcpt; break; + case 'D': errors_to = &error_data; break; + /* ... */ + default: errors_to = 0; + } + if (errors_to) { + if (!stralloc_catb(errors_to, data.s + 2, data.len - 3)) die_nomem(); + if (!stralloc_catb(errors_to, "\r\n", 2)) die_nomem(); + } + break; + } + } + } while (match); + + close(pipes[0]); + if (wait_pid(&wstat,pid) == -1) { err_spp(plugins->s + i, "wait_pid() failed"); return 0; } + if (wait_crashed(wstat)) { err_spp(plugins->s + i, "child crashed"); return 0; } + if (wait_exitcode(wstat) == 120) { err_spp(plugins->s + i, "can't execute"); return 0; } + + if (last) + switch (*data.s) { + case 'E': return 0; + case 'A': + case 'N': return 1; + case 'O': return 2; + case 'R': + case 'D': flush(); _exit(0); + } + } + + return 1; +} + +int spp_errors(errors) stralloc *errors; +{ + if (!errors->len) return 1; + if (!stralloc_0(errors)) die_nomem(); + out(errors->s); + return 0; +} + +int spp_connect() { return spp(&plugins_connect, 0); } + +int spp_helo(arg) char *arg; +{ + if (!env_put2("SMTPHELOHOST", arg)) die_nomem(); + return spp(&plugins_helo, 0); +} + +void spp_rset() +{ + if (!stralloc_copys(&sppheaders, "")) die_nomem(); + if (!stralloc_copys(&error_mail, "")) die_nomem(); + if (!stralloc_copys(&error_rcpt, "")) die_nomem(); + if (!stralloc_copys(&error_data, "")) die_nomem(); + /* ... */ + rcptcount = 0; +} + +int spp_mail() +{ + if (!spp_errors(&error_mail)) return 0; + rcptcount = 0; + return spp(&plugins_mail, "SMTPMAILFROM"); +} + +int spp_rcpt(allowed) int allowed; +{ + if (!spp_errors(&error_rcpt)) return 0; + rcptcountstr[fmt_ulong(rcptcountstr, rcptcount)] = 0; + if (!env_put2("SMTPRCPTCOUNT", rcptcountstr)) die_nomem(); + if (!env_put2("SMTPRCPTHOSTSOK", allowed ? "1" : "0")) die_nomem(); + sppret = spp(&plugins_rcpt, "SMTPRCPTTO"); + return sppret; +} + +void spp_rcpt_accepted() { rcptcount++; } + +int spp_data() +{ + if (!spp_errors(&error_data)) return 0; + return spp(&plugins_data, 0); +} + +int spp_auth(method, user) char *method, *user; +{ + if (!env_put2("SMTPAUTHMETHOD", method)) die_nomem(); + if (!env_put2("SMTPAUTHUSER", user)) die_nomem(); + return spp(&plugins_auth, 0); +} + +/* ... */ diff -Nur qmail-1.03.orig/qmail-spp.h qmail-1.03/qmail-spp.h --- qmail-1.03.orig/qmail-spp.h 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03/qmail-spp.h 2005-08-04 00:18:10.000000000 +0200 @@ -0,0 +1,14 @@ +#ifndef QMAIL_SPP_H +#define QMAIL_SPP_H + +extern stralloc sppheaders; +extern int spp_init(); +extern int spp_connect(); +extern int spp_helo(); +extern void spp_rset(); +extern int spp_mail(); +extern int spp_rcpt(); +extern int spp_data(); +extern int spp_auth(); + +#endif diff -Nur qmail-1.03.orig/qmail.c qmail-1.03/qmail.c --- qmail-1.03.orig/qmail.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail.c 2005-08-04 00:18:10.000000000 +0200 @@ -6,8 +6,17 @@ #include "fd.h" #include "qmail.h" #include "auto_qmail.h" +#include "env.h" -static char *binqqargs[2] = { "bin/qmail-queue", 0 } ; +static char *binqqargs[2] = { 0, 0 } ; + +static void setup_qqargs() +{ + if(!binqqargs[0]) + binqqargs[0] = env_get("QMAILQUEUE"); + if(!binqqargs[0]) + binqqargs[0] = "bin/qmail-queue"; +} int qmail_open(qq) struct qmail *qq; @@ -15,6 +24,8 @@ int pim[2]; int pie[2]; + setup_qqargs(); + if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } diff -Nur qmail-1.03.orig/remoteinfo.c qmail-1.03/remoteinfo.c --- qmail-1.03.orig/remoteinfo.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/remoteinfo.c 2005-08-04 00:18:10.000000000 +0200 @@ -44,12 +44,12 @@ s = socket(AF_INET,SOCK_STREAM,0); if (s == -1) return 0; - byte_zero(&sin,sizeof(sin)); +/* byte_zero(&sin,sizeof(sin)); sin.sin_family = AF_INET; byte_copy(&sin.sin_addr,4,ipl); sin.sin_port = 0; - if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } - if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; } + if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } */ + if (timeoutconn(s,ipr,ipl,113,timeout) == -1) { close(s); return 0; } fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY); len = 0; diff -Nur qmail-1.03.orig/sendmail.c qmail-1.03/sendmail.c --- qmail-1.03.orig/sendmail.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/sendmail.c 2005-08-04 00:18:10.000000000 +0200 @@ -45,6 +45,38 @@ _exit(111); } +void do_sender(s) +const char *s; +{ + char *x; + int n; + int a; + int i; + + env_unset("QMAILNAME"); + env_unset("MAILNAME"); + env_unset("NAME"); + env_unset("QMAILHOST"); + env_unset("MAILHOST"); + + n = str_len(s); + a = str_rchr(s, '@'); + if (a == n) + { + env_put2("QMAILUSER", s); + return; + } + env_put2("QMAILHOST", s + a + 1); + + x = (char *) alloc((a + 1) * sizeof(char)); + if (!x) nomem(); + for (i = 0; i < a; i++) + x[i] = s[i]; + x[i] = 0; + env_put2("QMAILUSER", x); + alloc_free(x); +} + int flagh; char *sender; @@ -118,6 +150,7 @@ if (sender) { *arg++ = "-f"; *arg++ = sender; + do_sender(sender); } *arg++ = "--"; for (i = 0;i < argc;++i) *arg++ = argv[i]; diff -Nur qmail-1.03.orig/timeoutconn.c qmail-1.03/timeoutconn.c --- qmail-1.03.orig/timeoutconn.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/timeoutconn.c 2005-08-04 00:18:10.000000000 +0200 @@ -10,9 +10,10 @@ #include "byte.h" #include "timeoutconn.h" -int timeoutconn(s,ip,port,timeout) +int timeoutconn(s,ip,outip,port,timeout) int s; struct ip_address *ip; +struct ip_address *outip; unsigned int port; int timeout; { @@ -22,6 +23,13 @@ fd_set wfds; struct timeval tv; + /* bind() an outgoing ipaddr */ + byte_zero(&sin,sizeof(sin)); + byte_copy(&sin.sin_addr.s_addr,4,outip); + sin.sin_family = AF_INET; + + if (-1 == bind(s,(struct sockaddr *) &sin,sizeof(sin))) return -1; + byte_zero(&sin,sizeof(sin)); byte_copy(&sin.sin_addr,4,ip); x = (char *) &sin.sin_port;