--- qmail-1.03.orig/contrib/checkpassword-0.81/strerr_die.c +++ qmail-1.03/contrib/checkpassword-0.81/strerr_die.c @@ -0,0 +1,37 @@ +#include "substdio.h" +#include "subfd.h" +#include "exit.h" +#include "strerr.h" + +void strerr_warn(x1,x2,x3,x4,x5,x6,se) +char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; +struct strerr *se; +{ + strerr_sysinit(); + + if (x1) substdio_puts(subfderr,x1); + if (x2) substdio_puts(subfderr,x2); + if (x3) substdio_puts(subfderr,x3); + if (x4) substdio_puts(subfderr,x4); + if (x5) substdio_puts(subfderr,x5); + if (x6) substdio_puts(subfderr,x6); + + while(se) { + if (se->x) substdio_puts(subfderr,se->x); + if (se->y) substdio_puts(subfderr,se->y); + if (se->z) substdio_puts(subfderr,se->z); + se = se->who; + } + + substdio_puts(subfderr,"\n"); + substdio_flush(subfderr); +} + +void strerr_die(e,x1,x2,x3,x4,x5,x6,se) +int e; +char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; +struct strerr *se; +{ + strerr_warn(x1,x2,x3,x4,x5,x6,se); + _exit(e); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/instcheck.c +++ qmail-1.03/contrib/checkpassword-0.81/instcheck.c @@ -0,0 +1,108 @@ +#include +#include +#include "strerr.h" +#include "error.h" +#include "readwrite.h" +#include "exit.h" + +extern void hier(); + +#define FATAL "instcheck: fatal: " +#define WARNING "instcheck: warning: " + +void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode) +char *prefix1; +char *prefix2; +char *prefix3; +char *file; +int type; +int uid; +int gid; +int mode; +{ + struct stat st; + + if (stat(file,&st) == -1) { + if (errno == error_noent) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0); + else + strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys); + return; + } + + if ((uid != -1) && (st.st_uid != uid)) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0); + if ((gid != -1) && (st.st_gid != gid)) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0); + if ((st.st_mode & 07777) != mode) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0); + if ((st.st_mode & S_IFMT) != type) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0); +} + +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + perm("","","",home,S_IFDIR,uid,gid,mode); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",subdir,S_IFDIR,uid,gid,mode); +} + +void p(home,fifo,uid,gid,mode) +char *home; +char *fifo; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",fifo,S_IFIFO,uid,gid,mode); +} + +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode); +} + +void z(home,file,len,uid,gid,mode) +char *home; +char *file; +int len; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",file,S_IFREG,uid,gid,mode); +} + +void main() +{ + hier(); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/auto_home.h +++ qmail-1.03/contrib/checkpassword-0.81/auto_home.h @@ -0,0 +1,6 @@ +#ifndef AUTO_HOME_H +#define AUTO_HOME_H + +extern char auto_home[]; + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/subfderr.c +++ qmail-1.03/contrib/checkpassword-0.81/subfderr.c @@ -0,0 +1,7 @@ +#include "readwrite.h" +#include "substdio.h" +#include "subfd.h" + +char subfd_errbuf[256]; +static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256); +substdio *subfderr = ⁢ --- qmail-1.03.orig/contrib/checkpassword-0.81/warn-auto.sh +++ qmail-1.03/contrib/checkpassword-0.81/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! --- qmail-1.03.orig/contrib/checkpassword-0.81/hier.c +++ qmail-1.03/contrib/checkpassword-0.81/hier.c @@ -0,0 +1,6 @@ +#include "auto_home.h" + +void hier() +{ + c(auto_home,"bin","checkpassword",-1,-1,0700); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/chkshsgr.c +++ qmail-1.03/contrib/checkpassword-0.81/chkshsgr.c @@ -0,0 +1,9 @@ +#include "exit.h" +void main() +{ + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/tryspnam.c +++ qmail-1.03/contrib/checkpassword-0.81/tryspnam.c @@ -0,0 +1,9 @@ +#include + +void main() +{ + struct spwd *spw; + + spw = getspnam(""); + puts(spw->sp_pwdp); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/CHANGES +++ qmail-1.03/contrib/checkpassword-0.81/CHANGES @@ -0,0 +1,12 @@ +19981121 version: checkpassword 0.81, beta. +19981121 portability problem: some Linux systems _simultaneously_ + support shadow passwords and non-shadow passwords. impact: + checkpassword would see only the shadow passwords. fix: in + doit(), use getpwnam() password if getspnam() fails (except + with ETXTBSY). tnx to several people. +19981121 portability problem: AIX needs -ls for getuserpw(). impact: + couldn't compile. fix: check for -ls; also use in hasuserpw.h. +19981121 portability problem: Linux systems with libc5 incorrectly + return EEXIST for mkdir("/",...). impact: couldn't install. + fix: don't bother installing anything except checkpassword. +19981103 version: checkpassword 0.80, beta. --- qmail-1.03.orig/contrib/checkpassword-0.81/tryslib.c +++ qmail-1.03/contrib/checkpassword-0.81/tryslib.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/byte_copy.c +++ qmail-1.03/contrib/checkpassword-0.81/byte_copy.c @@ -0,0 +1,14 @@ +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.81/error.c +++ qmail-1.03/contrib/checkpassword-0.81/error.c @@ -0,0 +1,95 @@ +#include +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/find-systype.sh +++ qmail-1.03/contrib/checkpassword-0.81/find-systype.sh @@ -0,0 +1,144 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" + kern="" + ;; + freebsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + netbsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + $CC -c trycpp.c + $LD -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' --- qmail-1.03.orig/contrib/checkpassword-0.81/strerr_sys.c +++ qmail-1.03/contrib/checkpassword-0.81/strerr_sys.c @@ -0,0 +1,12 @@ +#include "error.h" +#include "strerr.h" + +struct strerr strerr_sys; + +void strerr_sysinit() +{ + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); + strerr_sys.y = ""; + strerr_sys.z = ""; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/FILES +++ qmail-1.03/contrib/checkpassword-0.81/FILES @@ -0,0 +1,57 @@ +BLURB +README +TODO +CHANGES +THANKS +FILES +VERSION +SYSDEPS +TARGETS +Makefile +checkpassword.8 +checkpassword.c +tryshadow.c +trycrypt.c +tryslib.c +tryspnam.c +tryuserpw.c +conf-cc +conf-ld +find-systype.sh +trycpp.c +warn-auto.sh +INSTALL +hier.c +conf-home +auto-str.c +auto_home.h +install.c +instcheck.c +substdio.h +substdio.c +substdi.c +substdo.c +substdio_copy.c +subfd.h +subfderr.c +readwrite.h +exit.h +strerr.h +strerr_sys.c +strerr_die.c +error.h +error.c +error_str.c +open.h +open_read.c +open_trunc.c +byte.h +byte_copy.c +byte_cr.c +str.h +str_len.c +prot.h +prot.c +chkshsgr.c +warn-shsgr +tryshsgr.c --- qmail-1.03.orig/contrib/checkpassword-0.81/trycpp.c +++ qmail-1.03/contrib/checkpassword-0.81/trycpp.c @@ -0,0 +1,7 @@ +void main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/prot.c +++ qmail-1.03/contrib/checkpassword-0.81/prot.c @@ -0,0 +1,21 @@ +#include "hasshsgr.h" +#include "prot.h" + +/* XXX: there are more portability problems here waiting to leap out at me */ + +int prot_gid(gid) int gid; +{ +#ifdef HASSHORTSETGROUPS + short x[2]; + x[0] = gid; x[1] = 73; /* catch errors */ + if (setgroups(1,x) == -1) return -1; +#else + if (setgroups(1,&gid) == -1) return -1; +#endif + return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ +} + +int prot_uid(uid) int uid; +{ + return setuid(uid); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/checkpassword.c +++ qmail-1.03/contrib/checkpassword-0.81/checkpassword.c @@ -0,0 +1,132 @@ +#include +extern int errno; +extern char *crypt(); +extern char *malloc(); +extern char **environ; + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +#include "prot.h" +#include +static struct passwd *pw; +static char *stored; + +#include "hasspnam.h" +#ifdef HASGETSPNAM +#include +static struct spwd *spw; +#endif + +#include "hasuserpw.h" +#ifdef HASUSERPW +#include +static struct userpw *upw; +#endif + +void doit(login) +char *login; +{ + pw = getpwnam(login); + if (pw) + stored = pw->pw_passwd; + else { + if (errno == error_txtbsy) _exit(111); + _exit(1); + } + +#ifdef HASUSERPW + upw = getuserpw(login); + if (upw) + stored = upw->upw_passwd; + else + if (errno == error_txtbsy) _exit(111); +#endif + +#ifdef HASGETSPNAM + spw = getspnam(login); + if (spw) + stored = spw->sp_pwdp; + else + if (errno == error_txtbsy) _exit(111); +#endif +} + +char *str1e2(name,value) char *name; char *value; +{ + char *nv; + nv = malloc(strlen(name) + strlen(value) + 2); + if (!nv) _exit(111); + strcpy(nv,name); + strcat(nv,"="); + strcat(nv,value); + return nv; +} + +char up[513]; +int uplen; + +void main(argc,argv) +int argc; +char **argv; +{ + char *login; + char *password; + char *encrypted; + int r; + int i; + char **newenv; + int numenv; + + if (!argv[1]) _exit(2); + + uplen = 0; + for (;;) { + do + r = read(3,up + uplen,sizeof(up) - uplen); + while ((r == -1) && (errno == EINTR)); + if (r == -1) _exit(111); + if (r == 0) break; + uplen += r; + if (uplen >= sizeof(up)) _exit(1); + } + + close(3); + + i = 0; + login = up + i; + while (up[i++]) if (i == uplen) _exit(2); + password = up + i; + if (i == uplen) _exit(2); + while (up[i++]) if (i == uplen) _exit(2); + + doit(login); + + encrypted = crypt(password,stored); + + for (i = 0;i < sizeof(up);++i) up[i] = 0; + + if (!*stored || strcmp(encrypted,stored)) _exit(1); + + if (prot_gid((int) pw->pw_gid) == -1) _exit(1); + if (prot_uid((int) pw->pw_uid) == -1) _exit(1); + if (chdir(pw->pw_dir) == -1) _exit(111); + + numenv = 0; + while (environ[numenv]) ++numenv; + newenv = (char **) malloc((numenv + 4) * sizeof(char *)); + if (!newenv) _exit(111); + for (i = 0;i < numenv;++i) newenv[i] = environ[i]; + newenv[numenv++] = str1e2("USER",pw->pw_name); + newenv[numenv++] = str1e2("HOME",pw->pw_dir); + newenv[numenv++] = str1e2("SHELL",pw->pw_shell); + newenv[numenv] = 0; + environ = newenv; + + execvp(argv[1],argv + 1); + _exit(111); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/auto_home.c +++ qmail-1.03/contrib/checkpassword-0.81/auto_home.c @@ -0,0 +1,3 @@ +char auto_home[] = "\ +\057\ +"; --- qmail-1.03.orig/contrib/checkpassword-0.81/substdo.c +++ qmail-1.03/contrib/checkpassword-0.81/substdo.c @@ -0,0 +1,108 @@ +#include "substdio.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +static int allwrite(op,fd,buf,len) +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + register int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +int substdio_flush(s) +register substdio *s; +{ + register int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int substdio_bput(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (substdio_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int substdio_put(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int n; + + n = s->n; + if (len > n - s->p) { + if (substdio_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < SUBSTDIO_OUTSIZE) n = SUBSTDIO_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int substdio_putflush(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + if (substdio_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int substdio_bputs(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_bput(s,buf,str_len(buf)); +} + +int substdio_puts(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_put(s,buf,str_len(buf)); +} + +int substdio_putsflush(s,buf) +register substdio *s; +register char *buf; +{ + return substdio_putflush(s,buf,str_len(buf)); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/systype +++ qmail-1.03/contrib/checkpassword-0.81/systype @@ -0,0 +1 @@ +linux-2.2.14-:i386-:-:pentium-:- --- qmail-1.03.orig/contrib/checkpassword-0.81/tryshadow.c +++ qmail-1.03/contrib/checkpassword-0.81/tryshadow.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/conf-ld +++ qmail-1.03/contrib/checkpassword-0.81/conf-ld @@ -0,0 +1,3 @@ +cc -s + +This will be used to link .o files into an executable. --- qmail-1.03.orig/contrib/checkpassword-0.81/prot.h +++ qmail-1.03/contrib/checkpassword-0.81/prot.h @@ -0,0 +1,7 @@ +#ifndef PROT_H +#define PROT_H + +extern int prot_gid(); +extern int prot_uid(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/substdio.c +++ qmail-1.03/contrib/checkpassword-0.81/substdio.c @@ -0,0 +1,15 @@ +#include "substdio.h" + +void substdio_fdbuf(s,op,fd,buf,len) +register substdio *s; +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/README +++ qmail-1.03/contrib/checkpassword-0.81/README @@ -0,0 +1,21 @@ +checkpassword 0.81, beta. +19981121 +D. J. Bernstein, djb@pobox.com +http://pobox.com/~djb/checkpwd.html + +checkpassword provides a simple, uniform password-checking interface +to all root applications. See BLURB for a more detailed advertisement. + +INSTALL says how to set up and test checkpassword. + +The checkpassword code is in the public domain. + +The rest of this file is a list of systypes where various versions of +checkpassword have been reported to work. + +0.80: bsd.os-2.0.1-:i386-:-:pentium-:- +0.80: linux-2.0.35-:i386-:-:i486-:- (tnx PJR) +0.80: linux-2.0.35-:i386-:-:ppro-:- (tnx JRDM) +0.80: linux-2.1.128-:alpha-:-:alpha-:- (tnx PJR) +0.80: netbsd-1.3h-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GCW) +0.80: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m- --- qmail-1.03.orig/contrib/checkpassword-0.81/strerr.h +++ qmail-1.03/contrib/checkpassword-0.81/strerr.h @@ -0,0 +1,80 @@ +#ifndef STRERR_H +#define STRERR_H + +struct strerr + { + struct strerr *who; + char *x; + char *y; + char *z; + } +; + +extern struct strerr strerr_sys; +extern void strerr_sysinit(); + +extern char *strerr(); +extern void strerr_warn(); +extern void strerr_die(); + +#define STRERR(r,se,a) \ +{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } + +#define STRERR_SYS(r,se,a) \ +{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } +#define STRERR_SYS3(r,se,a,b,c) \ +{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } + +#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) +#define strerr_warn5(x1,x2,x3,x4,x5,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) +#define strerr_warn4(x1,x2,x3,x4,se) \ +strerr_warn((x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn3(x1,x2,x3,se) \ +strerr_warn((x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn2(x1,x2,se) \ +strerr_warn((x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_warn1(x1,se) \ +strerr_warn((x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) + +#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) +#define strerr_die5(e,x1,x2,x3,x4,x5,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) +#define strerr_die4(e,x1,x2,x3,x4,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die3(e,x1,x2,x3,se) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die2(e,x1,x2,se) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) +#define strerr_die1(e,x1,se) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) + +#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) +#define strerr_die5sys(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,&strerr_sys) +#define strerr_die4sys(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die3sys(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die2sys(e,x1,x2) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) +#define strerr_die1sys(e,x1) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) + +#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) 0) +#define strerr_die5x(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) 0) +#define strerr_die4x(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die3x(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die2x(e,x1,x2) \ +strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) +#define strerr_die1x(e,x1) \ +strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/str_len.c +++ qmail-1.03/contrib/checkpassword-0.81/str_len.c @@ -0,0 +1,15 @@ +#include "str.h" + +unsigned int str_len(s) +register char *s; +{ + register char *t; + + t = s; + for (;;) { + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.81/substdi.c +++ qmail-1.03/contrib/checkpassword-0.81/substdi.c @@ -0,0 +1,91 @@ +#include "substdio.h" +#include "byte.h" +#include "error.h" + +static int oneread(op,fd,buf,len) +register int (*op)(); +register int fd; +register char *buf; +register int len; +{ + register int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == error_intr) continue; + return r; + } +} + +static int getthis(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + register int q; + + r = s->p; + q = r - len; + if (q > 0) { r = len; s->p = q; } else s->p = 0; + byte_copy(buf,r,s->x + s->n); + s->n += r; + return r; +} + +int substdio_feed(s) +register substdio *s; +{ + register int r; + register int q; + + if (s->p) return s->p; + q = s->n; + r = oneread(s->op,s->fd,s->x,q); + if (r <= 0) return r; + s->p = r; + q -= r; + s->n = q; + if (q > 0) /* damn, gotta shift */ byte_copyr(s->x + q,r,s->x); + return r; +} + +int substdio_bget(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + + if (s->p > 0) return getthis(s,buf,len); + r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r); + r = substdio_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +int substdio_get(s,buf,len) +register substdio *s; +register char *buf; +register int len; +{ + register int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = substdio_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *substdio_peek(s) +register substdio *s; +{ + return s->x + s->n; +} + +void substdio_seek(s,len) +register substdio *s; +register int len; +{ + s->n += len; + s->p -= len; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/substdio_copy.c +++ qmail-1.03/contrib/checkpassword-0.81/substdio_copy.c @@ -0,0 +1,18 @@ +#include "substdio.h" + +int substdio_copy(ssout,ssin) +register substdio *ssout; +register substdio *ssin; +{ + register int n; + register char *x; + + for (;;) { + n = substdio_feed(ssin); + if (n < 0) return -2; + if (!n) return 0; + x = substdio_PEEK(ssin); + if (substdio_put(ssout,x,n) == -1) return -3; + substdio_SEEK(ssin,n); + } +} --- qmail-1.03.orig/contrib/checkpassword-0.81/exit.h +++ qmail-1.03/contrib/checkpassword-0.81/exit.h @@ -0,0 +1,6 @@ +#ifndef EXIT_H +#define EXIT_H + +extern void _exit(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/tryshsgr.c +++ qmail-1.03/contrib/checkpassword-0.81/tryshsgr.c @@ -0,0 +1,14 @@ +void main() +{ + short x[4]; + + x[0] = x[1] = 1; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 1) _exit(1); + x[1] = 2; + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 2) _exit(1); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/Makefile +++ qmail-1.03/contrib/checkpassword-0.81/Makefile @@ -0,0 +1,254 @@ +# Don't edit Makefile! Use conf-* for configuration. + +SHELL=/bin/sh + +default: it + +auto-str: \ +load auto-str.o substdio.a error.a str.a + ./load auto-str substdio.a error.a str.a + +auto-str.o: \ +compile auto-str.c substdio.h readwrite.h exit.h + ./compile auto-str.c + +auto_home.c: \ +auto-str conf-home + ./auto-str auto_home `head -1 conf-home` > auto_home.c + +auto_home.o: \ +compile auto_home.c + ./compile auto_home.c + +byte_copy.o: \ +compile byte_copy.c byte.h + ./compile byte_copy.c + +byte_cr.o: \ +compile byte_cr.c byte.h + ./compile byte_cr.c + +check: \ +it instcheck + ./instcheck + +checkpassword: \ +load checkpassword.o prot.o shadow.lib crypt.lib s.lib + ./load checkpassword prot.o `cat shadow.lib` `cat \ + crypt.lib` `cat s.lib` + +checkpassword.0: \ +checkpassword.8 + nroff -man checkpassword.8 > checkpassword.0 + +checkpassword.o: \ +compile checkpassword.c prot.h hasspnam.h hasuserpw.h + ./compile checkpassword.c + +chkshsgr: \ +load chkshsgr.o + ./load chkshsgr + +chkshsgr.o: \ +compile chkshsgr.c exit.h + ./compile chkshsgr.c + +clean: + rm -rf rm auto-str checkpassword chkshsgr compile install instcheck load makelib *o *a checkpassword.0 + +compile: \ +warn-auto.sh conf-cc + ( cat warn-auto.sh; \ + echo exec "`head -1 conf-cc`" '-c $${1+"$$@"}' \ + ) > compile + chmod 755 compile + +crypt.lib: \ +trycrypt.c compile load + ( ( ./compile trycrypt.c && \ + ./load trycrypt -lcrypt ) >/dev/null 2>&1 \ + && echo -lcrypt || exit 0 ) > crypt.lib + rm -f trycrypt.o trycrypt + +error.a: \ +makelib error.o error_str.o + ./makelib error.a error.o error_str.o + +error.o: \ +compile error.c error.h + ./compile error.c + +error_str.o: \ +compile error_str.c error.h + ./compile error_str.c + +hasshsgr.h: \ +chkshsgr warn-shsgr tryshsgr.c compile load + ./chkshsgr || ( cat warn-shsgr; exit 1 ) + ( ( ./compile tryshsgr.c \ + && ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \ + && echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \ + hasshsgr.h + rm -f tryshsgr.o tryshsgr + +hasspnam.h: \ +tryspnam.c compile load + ( ( ./compile tryspnam.c && ./load tryspnam ) >/dev/null \ + 2>&1 \ + && echo \#define HASGETSPNAM 1 || exit 0 ) > hasspnam.h + rm -f tryspnam.o tryspnam + +hasuserpw.h: \ +tryuserpw.c s.lib compile load + ( ( ./compile tryuserpw.c \ + && ./load tryuserpw `cat s.lib` ) >/dev/null 2>&1 \ + && echo \#define HASGETUSERPW 1 || exit 0 ) > hasuserpw.h + rm -f tryuserpw.o tryuserpw + +hier.o: \ +compile hier.c auto_home.h + ./compile hier.c + +install: \ +load install.o hier.o auto_home.o strerr.a substdio.a open.a error.a \ +str.a + ./load install hier.o auto_home.o strerr.a substdio.a \ + open.a error.a str.a + +install.o: \ +compile install.c substdio.h strerr.h error.h open.h readwrite.h \ +exit.h + ./compile install.c + +instcheck: \ +load instcheck.o hier.o auto_home.o strerr.a substdio.a error.a str.a + ./load instcheck hier.o auto_home.o strerr.a substdio.a \ + error.a str.a + +instcheck.o: \ +compile instcheck.c strerr.h error.h readwrite.h exit.h + ./compile instcheck.c + +it: \ +man prog install instcheck + +load: \ +warn-auto.sh conf-ld + ( cat warn-auto.sh; \ + echo 'main="$$1"; shift'; \ + echo exec "`head -1 conf-ld`" \ + '-o "$$main" "$$main".o $${1+"$$@"}' \ + ) > load + chmod 755 load + +makelib: \ +warn-auto.sh systype + ( cat warn-auto.sh; \ + echo 'main="$$1"; shift'; \ + echo 'rm -f "$$main"'; \ + echo 'ar cr "$$main" $${1+"$$@"}'; \ + case "`cat systype`" in \ + sunos-5.*) ;; \ + unix_sv*) ;; \ + irix64-*) ;; \ + irix-*) ;; \ + dgux-*) ;; \ + hp-ux-*) ;; \ + sco*) ;; \ + *) echo 'ranlib "$$main"' ;; \ + esac \ + ) > makelib + chmod 755 makelib + +man: \ +checkpassword.0 + +open.a: \ +makelib open_read.o open_trunc.o + ./makelib open.a open_read.o open_trunc.o + +open_read.o: \ +compile open_read.c open.h + ./compile open_read.c + +open_trunc.o: \ +compile open_trunc.c open.h + ./compile open_trunc.c + +prog: \ +checkpassword + +prot.o: \ +compile prot.c hasshsgr.h prot.h + ./compile prot.c + +s.lib: \ +tryslib.c compile load + ( ( ./compile tryslib.c && \ + ./load tryslib -ls ) >/dev/null 2>&1 \ + && echo -ls || exit 0 ) > s.lib + rm -f tryslib.o tryslib + +setup: \ +it install + ./install + +shadow.lib: \ +tryshadow.c compile load + ( ( ./compile tryshadow.c && \ + ./load tryshadow -lshadow ) >/dev/null 2>&1 \ + && echo -lshadow || exit 0 ) > shadow.lib + rm -f tryshadow.o tryshadow + +str.a: \ +makelib str_len.o byte_copy.o byte_cr.o + ./makelib str.a str_len.o byte_copy.o byte_cr.o + +str_len.o: \ +compile str_len.c str.h + ./compile str_len.c + +strerr.a: \ +makelib strerr_sys.o strerr_die.o + ./makelib strerr.a strerr_sys.o strerr_die.o + +strerr_die.o: \ +compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h + ./compile strerr_die.c + +strerr_sys.o: \ +compile strerr_sys.c error.h strerr.h + ./compile strerr_sys.c + +subfderr.o: \ +compile subfderr.c readwrite.h substdio.h subfd.h substdio.h + ./compile subfderr.c + +substdi.o: \ +compile substdi.c substdio.h byte.h error.h + ./compile substdi.c + +substdio.a: \ +makelib substdio.o substdi.o substdo.o subfderr.o substdio_copy.o + ./makelib substdio.a substdio.o substdi.o substdo.o \ + subfderr.o substdio_copy.o + +substdio.o: \ +compile substdio.c substdio.h + ./compile substdio.c + +substdio_copy.o: \ +compile substdio_copy.c substdio.h + ./compile substdio_copy.c + +substdo.o: \ +compile substdo.c substdio.h str.h byte.h error.h + ./compile substdo.c + +systype: \ +find-systype.sh conf-cc conf-ld trycpp.c + ( cat warn-auto.sh; \ + echo CC=\'`head -1 conf-cc`\'; \ + echo LD=\'`head -1 conf-ld`\'; \ + cat find-systype.sh; \ + ) | sh > systype --- qmail-1.03.orig/contrib/checkpassword-0.81/VERSION +++ qmail-1.03/contrib/checkpassword-0.81/VERSION @@ -0,0 +1 @@ +checkpassword 0.81 --- qmail-1.03.orig/contrib/checkpassword-0.81/checkpassword.8 +++ qmail-1.03/contrib/checkpassword-0.81/checkpassword.8 @@ -0,0 +1,119 @@ +.TH checkpassword 8 +.SH NAME +checkpassword \- check a password +.SH SYNOPSIS +.B checkpassword +.I subprogram +[ +.I args ... +] +.SH DESCRIPTION +.B checkpassword +reads descriptor 3 through end of file +and then closes descriptor 3. +There must be at most 512 bytes of data before end of file. + +The information supplied on descriptor 3 +is a login name terminated by \e0, +a password terminated by \e0, +a timestamp terminated by \e0, +and possibly more data. +There are no other restrictions on +the form of the login name, password, and timestamp. + +If the password is unacceptable, +.B checkpassword +exits 1. +If +.B checkpassword +is misused, +it may instead exit 2. +If there is a temporary problem checking the password, +.B checkpassword +exits 111. + +If the password is acceptable, +.B checkpassword +uses +.B execvp +to run +.B subprogram +with the given arguments. +.SH "CHECKPASSWORD-COMPATIBLE TOOLS" +There are other tools that offer the same interface as +.BR checkpassword . +Applications that use +.B checkpassword +are encouraged to take the +.B checkpassword +name as an argument, +so that they can be used with different +.BR checkpassword -compatible +tools. + +Note that these tools do not follow the +.B getopt +interface. +Optional features are controlled through +(1) the tool name and +(2) environment variables. +.SH "THE PASSWORD DATABASE" +.B checkpassword +checks the login name and password against +.BR /etc/passwd , +using the operating system's +.B getpwnam +and +.B crypt +functions. +It rejects accounts with empty passwords. +It ignores the timestamp. + +Other +.BR checkpassword -compatible +tools have different interpretations of +login names, passwords, and timestamps. +Both the login name and the password +should be treated as secrets by the application calling +.BR checkpassword ; +the only distinction is for administrative convenience. +The timestamp should include any other information +that the password is based on; +for example, the challenge in a challenge-response system such as APOP. + +.B WARNING: +.B getpwnam +is inherently unreliable. +It fails to distinguish between temporary errors and nonexistent users. +Future versions of +.B getpwnam +should return ETXTBSY to indicate temporary errors +and ESRCH to indicate nonexistent users. +.SH "PROCESS-STATE CHANGES" +Before invoking +.BR subprogram , +.B checkpassword +sets up +.BR $USER , +.BR $HOME , +.BR $SHELL , +its supplementary groups, +its gid, +its uid, +and its working directory. + +Other +.BR checkpassword -compatible +tools may make different changes to the process state. +These effects must be documented; +applications will differ in their requirements. +.SH "VERSION" +This documentation describes +.B checkpassword +version 0.80. +See +.B http://pobox.com/~djb/checkpwd.html +for updates. +.SH "SEE ALSO" +getpwnam(3), +crypt(3) --- qmail-1.03.orig/contrib/checkpassword-0.81/readwrite.h +++ qmail-1.03/contrib/checkpassword-0.81/readwrite.h @@ -0,0 +1,7 @@ +#ifndef READWRITE_H +#define READWRITE_H + +extern int read(); +extern int write(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/auto-str.c +++ qmail-1.03/contrib/checkpassword-0.81/auto-str.c @@ -0,0 +1,44 @@ +#include "substdio.h" +#include "readwrite.h" +#include "exit.h" + +char buf1[256]; +substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); + +void puts(s) +char *s; +{ + if (substdio_puts(&ss1,s) == -1) _exit(111); +} + +void main(argc,argv) +int argc; +char **argv; +{ + char *name; + char *value; + unsigned char ch; + char octal[4]; + + name = argv[1]; + if (!name) _exit(100); + value = argv[2]; + if (!value) _exit(100); + + puts("char "); + puts(name); + puts("[] = \"\\\n"); + + while (ch = *value++) { + puts("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); + puts(octal); + } + + puts("\\\n\";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/substdio.h +++ qmail-1.03/contrib/checkpassword-0.81/substdio.h @@ -0,0 +1,47 @@ +#ifndef SUBSTDIO_H +#define SUBSTDIO_H + +typedef struct substdio { + char *x; + int p; + int n; + int fd; + int (*op)(); +} substdio; + +#define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } + +extern void substdio_fdbuf(); + +extern int substdio_flush(); +extern int substdio_put(); +extern int substdio_bput(); +extern int substdio_putflush(); +extern int substdio_puts(); +extern int substdio_bputs(); +extern int substdio_putsflush(); + +extern int substdio_get(); +extern int substdio_bget(); +extern int substdio_feed(); + +extern char *substdio_peek(); +extern void substdio_seek(); + +#define substdio_fileno(s) ((s)->fd) + +#define SUBSTDIO_INSIZE 8192 +#define SUBSTDIO_OUTSIZE 8192 + +#define substdio_PEEK(s) ( (s)->x + (s)->n ) +#define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) + +#define substdio_BPUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : substdio_bput((s),&(c),1) \ + ) + +extern int substdio_copy(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/conf-cc +++ qmail-1.03/contrib/checkpassword-0.81/conf-cc @@ -0,0 +1,3 @@ +cc -O2 + +This will be used to compile .c files. --- qmail-1.03.orig/contrib/checkpassword-0.81/hasspnam.h +++ qmail-1.03/contrib/checkpassword-0.81/hasspnam.h @@ -0,0 +1 @@ +#define HASGETSPNAM 1 --- qmail-1.03.orig/contrib/checkpassword-0.81/warn-shsgr +++ qmail-1.03/contrib/checkpassword-0.81/warn-shsgr @@ -0,0 +1,3 @@ +Oops. Your getgroups() returned 0, and setgroups() failed; this means +that I can't reliably do my shsgr test. Please either ``make'' as root +or ``make'' while you're in one or more supplementary groups. --- qmail-1.03.orig/contrib/checkpassword-0.81/TARGETS +++ qmail-1.03/contrib/checkpassword-0.81/TARGETS @@ -0,0 +1,49 @@ +checkpassword.0 +man +load +compile +hasspnam.h +s.lib +hasuserpw.h +checkpassword.o +chkshsgr.o +chkshsgr +hasshsgr.h +prot.o +shadow.lib +crypt.lib +checkpassword +prog +install.o +hier.o +auto-str.o +systype +makelib +substdio.o +substdi.o +substdo.o +subfderr.o +substdio_copy.o +substdio.a +error.o +error_str.o +error.a +str_len.o +byte_copy.o +byte_cr.o +str.a +auto-str +auto_home.c +auto_home.o +strerr_sys.o +strerr_die.o +strerr.a +open_read.o +open_trunc.o +open.a +install +instcheck.o +instcheck +it +setup +check --- qmail-1.03.orig/contrib/checkpassword-0.81/byte_cr.c +++ qmail-1.03/contrib/checkpassword-0.81/byte_cr.c @@ -0,0 +1,16 @@ +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.81/open.h +++ qmail-1.03/contrib/checkpassword-0.81/open.h @@ -0,0 +1,10 @@ +#ifndef OPEN_H +#define OPEN_H + +extern int open_read(); +extern int open_excl(); +extern int open_append(); +extern int open_trunc(); +extern int open_write(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/install.c +++ qmail-1.03/contrib/checkpassword-0.81/install.c @@ -0,0 +1,149 @@ +#include "substdio.h" +#include "strerr.h" +#include "error.h" +#include "open.h" +#include "readwrite.h" +#include "exit.h" + +extern void hier(); + +#define FATAL "install: fatal: " + +int fdsourcedir = -1; + +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + if (mkdir(home,0700) == -1) + if (errno != error_exist) + strerr_die4sys(111,FATAL,"unable to mkdir ",home,": "); + if (chown(home,uid,gid) == -1) + strerr_die4sys(111,FATAL,"unable to chown ",home,": "); + if (chmod(home,mode) == -1) + strerr_die4sys(111,FATAL,"unable to chmod ",home,": "); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (mkdir(subdir,0700) == -1) + if (errno != error_exist) + strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": "); + if (chown(subdir,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": "); + if (chmod(subdir,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": "); +} + +char inbuf[SUBSTDIO_INSIZE]; +char outbuf[SUBSTDIO_OUTSIZE]; +substdio ssin; +substdio ssout; + +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; +{ + int fdin; + int fdout; + + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); + + fdin = open_read(file); + if (fdin == -1) + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof inbuf); + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); + + switch(substdio_copy(&ssout,&ssin)) { + case -2: + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + case -3: + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + } + + close(fdin); + if (substdio_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); +} + +void z(home,subdir,file,len,uid,gid,mode) +char *home; +char *subdir; +char *file; +int len; +int uid; +int gid; +int mode; +{ + int fdout; + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); + + while (len-- > 0) + if (substdio_put(&ssout,"",1) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (substdio_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); +} + +void main() +{ + fdsourcedir = open_read("."); + if (fdsourcedir == -1) + strerr_die2sys(111,FATAL,"unable to open current directory: "); + + umask(077); + hier(); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/SYSDEPS +++ qmail-1.03/contrib/checkpassword-0.81/SYSDEPS @@ -0,0 +1,8 @@ +VERSION +systype +crypt.lib +shadow.lib +s.lib +hasspnam.h +hasuserpw.h +hasshsgr.h --- qmail-1.03.orig/contrib/checkpassword-0.81/BLURB +++ qmail-1.03/contrib/checkpassword-0.81/BLURB @@ -0,0 +1,9 @@ +checkpassword provides a simple, uniform password-checking interface +to all root applications. It is suitable for use by applications such as +login, ftpd, and pop3d. + +There are checkpassword-compatible tools that support alternate password +databases, secret login names, long passwords, subaccounts, one-time +passwords, detailed accounting, and many other features. Applications +that use the checkpassword interface will work with all of these tools. +Several tools have been specifically designed to support POP toasters. --- qmail-1.03.orig/contrib/checkpassword-0.81/TODO +++ qmail-1.03/contrib/checkpassword-0.81/TODO @@ -0,0 +1 @@ +check portability --- qmail-1.03.orig/contrib/checkpassword-0.81/THANKS +++ qmail-1.03/contrib/checkpassword-0.81/THANKS @@ -0,0 +1,12 @@ +CJ = Chris Johnson +GCW = Geoff C. Wing +IN = Ivan Nejgebauer +JB = Jos Backus +JRDM = James R. DeMong +MB = Mark Boyns +MS = Mikael Suokas +MW = Mate Wierdl +PJR = Peter J. Rye +RN = Russ Nelson +SS = Simon Shapiro +TN = Thomas Neumann --- qmail-1.03.orig/contrib/checkpassword-0.81/open_read.c +++ qmail-1.03/contrib/checkpassword-0.81/open_read.c @@ -0,0 +1,6 @@ +#include +#include +#include "open.h" + +int open_read(fn) char *fn; +{ return open(fn,O_RDONLY | O_NDELAY); } --- qmail-1.03.orig/contrib/checkpassword-0.81/open_trunc.c +++ qmail-1.03/contrib/checkpassword-0.81/open_trunc.c @@ -0,0 +1,6 @@ +#include +#include +#include "open.h" + +int open_trunc(fn) char *fn; +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } --- qmail-1.03.orig/contrib/checkpassword-0.81/str.h +++ qmail-1.03/contrib/checkpassword-0.81/str.h @@ -0,0 +1,14 @@ +#ifndef STR_H +#define STR_H + +extern unsigned int str_copy(); +extern int str_diff(); +extern int str_diffn(); +extern unsigned int str_len(); +extern unsigned int str_chr(); +extern unsigned int str_rchr(); +extern int str_start(); + +#define str_equal(s,t) (!str_diff((s),(t))) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/byte.h +++ qmail-1.03/contrib/checkpassword-0.81/byte.h @@ -0,0 +1,13 @@ +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/trycrypt.c +++ qmail-1.03/contrib/checkpassword-0.81/trycrypt.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/subfd.h +++ qmail-1.03/contrib/checkpassword-0.81/subfd.h @@ -0,0 +1,15 @@ +#ifndef SUBFD_H +#define SUBFD_H + +#include "substdio.h" + +extern substdio *subfdin; +extern substdio *subfdinsmall; +extern substdio *subfdout; +extern substdio *subfdoutsmall; +extern substdio *subfderr; + +extern int subfd_read(); +extern int subfd_readsmall(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/error_str.c +++ qmail-1.03/contrib/checkpassword-0.81/error_str.c @@ -0,0 +1,276 @@ +#include +#include "error.h" + +#define X(e,s) if (i == e) return s; + +char *error_str(i) +int i; +{ + X(0,"no error") + X(error_intr,"interrupted system call") + X(error_nomem,"out of memory") + X(error_noent,"file does not exist") + X(error_txtbsy,"text busy") + X(error_io,"input/output error") + X(error_exist,"file already exists") + X(error_timeout,"timed out") + X(error_inprogress,"operation in progress") + X(error_again,"temporary failure") + X(error_wouldblock,"input/output would block") + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") +#ifdef ESRCH + X(ESRCH,"no such process") +#endif +#ifdef ENXIO + X(ENXIO,"device not configured") +#endif +#ifdef E2BIG + X(E2BIG,"argument list too long") +#endif +#ifdef ENOEXEC + X(ENOEXEC,"exec format error") +#endif +#ifdef EBADF + X(EBADF,"file descriptor not open") +#endif +#ifdef ECHILD + X(ECHILD,"no child processes") +#endif +#ifdef EDEADLK + X(EDEADLK,"operation would cause deadlock") +#endif +#ifdef EFAULT + X(EFAULT,"bad address") +#endif +#ifdef ENOTBLK + X(ENOTBLK,"not a block device") +#endif +#ifdef EBUSY + X(EBUSY,"device busy") +#endif +#ifdef EXDEV + X(EXDEV,"cross-device link") +#endif +#ifdef ENODEV + X(ENODEV,"device does not support operation") +#endif +#ifdef ENOTDIR + X(ENOTDIR,"not a directory") +#endif +#ifdef EISDIR + X(EISDIR,"is a directory") +#endif +#ifdef EINVAL + X(EINVAL,"invalid argument") +#endif +#ifdef ENFILE + X(ENFILE,"system cannot open more files") +#endif +#ifdef EMFILE + X(EMFILE,"process cannot open more files") +#endif +#ifdef ENOTTY + X(ENOTTY,"not a tty") +#endif +#ifdef EFBIG + X(EFBIG,"file too big") +#endif +#ifdef ENOSPC + X(ENOSPC,"out of disk space") +#endif +#ifdef ESPIPE + X(ESPIPE,"unseekable descriptor") +#endif +#ifdef EROFS + X(EROFS,"read-only file system") +#endif +#ifdef EMLINK + X(EMLINK,"too many links") +#endif +#ifdef EDOM + X(EDOM,"input out of range") +#endif +#ifdef ERANGE + X(ERANGE,"output out of range") +#endif +#ifdef EALREADY + X(EALREADY,"operation already in progress") +#endif +#ifdef ENOTSOCK + X(ENOTSOCK,"not a socket") +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ,"destination address required") +#endif +#ifdef EMSGSIZE + X(EMSGSIZE,"message too long") +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE,"incorrect protocol type") +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT,"protocol not available") +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT,"protocol not supported") +#endif +#ifdef ESOCKTNOSUPPORT + X(ESOCKTNOSUPPORT,"socket type not supported") +#endif +#ifdef EOPNOTSUPP + X(EOPNOTSUPP,"operation not supported") +#endif +#ifdef EPFNOSUPPORT + X(EPFNOSUPPORT,"protocol family not supported") +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT,"address family not supported") +#endif +#ifdef EADDRINUSE + X(EADDRINUSE,"address already used") +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL,"address not available") +#endif +#ifdef ENETDOWN + X(ENETDOWN,"network down") +#endif +#ifdef ENETUNREACH + X(ENETUNREACH,"network unreachable") +#endif +#ifdef ENETRESET + X(ENETRESET,"network reset") +#endif +#ifdef ECONNABORTED + X(ECONNABORTED,"connection aborted") +#endif +#ifdef ECONNRESET + X(ECONNRESET,"connection reset") +#endif +#ifdef ENOBUFS + X(ENOBUFS,"out of buffer space") +#endif +#ifdef EISCONN + X(EISCONN,"already connected") +#endif +#ifdef ENOTCONN + X(ENOTCONN,"not connected") +#endif +#ifdef ESHUTDOWN + X(ESHUTDOWN,"socket shut down") +#endif +#ifdef ETOOMANYREFS + X(ETOOMANYREFS,"too many references") +#endif +#ifdef ECONNREFUSED + X(ECONNREFUSED,"connection refused") +#endif +#ifdef ELOOP + X(ELOOP,"symbolic link loop") +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG,"file name too long") +#endif +#ifdef EHOSTDOWN + X(EHOSTDOWN,"host down") +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH,"host unreachable") +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY,"directory not empty") +#endif +#ifdef EPROCLIM + X(EPROCLIM,"too many processes") +#endif +#ifdef EUSERS + X(EUSERS,"too many users") +#endif +#ifdef EDQUOT + X(EDQUOT,"disk quota exceeded") +#endif +#ifdef ESTALE + X(ESTALE,"stale NFS file handle") +#endif +#ifdef EREMOTE + X(EREMOTE,"too many levels of remote in path") +#endif +#ifdef EBADRPC + X(EBADRPC,"RPC structure is bad") +#endif +#ifdef ERPCMISMATCH + X(ERPCMISMATCH,"RPC version mismatch") +#endif +#ifdef EPROGUNAVAIL + X(EPROGUNAVAIL,"RPC program unavailable") +#endif +#ifdef EPROGMISMATCH + X(EPROGMISMATCH,"program version mismatch") +#endif +#ifdef EPROCUNAVAIL + X(EPROCUNAVAIL,"bad procedure for program") +#endif +#ifdef ENOLCK + X(ENOLCK,"no locks available") +#endif +#ifdef ENOSYS + X(ENOSYS,"system call not available") +#endif +#ifdef EFTYPE + X(EFTYPE,"bad file type") +#endif +#ifdef EAUTH + X(EAUTH,"authentication error") +#endif +#ifdef ENEEDAUTH + X(ENEEDAUTH,"not authenticated") +#endif +#ifdef ENOSTR + X(ENOSTR,"not a stream device") +#endif +#ifdef ETIME + X(ETIME,"timer expired") +#endif +#ifdef ENOSR + X(ENOSR,"out of stream resources") +#endif +#ifdef ENOMSG + X(ENOMSG,"no message of desired type") +#endif +#ifdef EBADMSG + X(EBADMSG,"bad message type") +#endif +#ifdef EIDRM + X(EIDRM,"identifier removed") +#endif +#ifdef ENONET + X(ENONET,"machine not on network") +#endif +#ifdef ERREMOTE + X(ERREMOTE,"object not local") +#endif +#ifdef ENOLINK + X(ENOLINK,"link severed") +#endif +#ifdef EADV + X(EADV,"advertise error") +#endif +#ifdef ESRMNT + X(ESRMNT,"srmount error") +#endif +#ifdef ECOMM + X(ECOMM,"communication error") +#endif +#ifdef EPROTO + X(EPROTO,"protocol error") +#endif +#ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +#endif +#ifdef EREMCHG + X(EREMCHG,"remote address changed") +#endif + return "unknown error"; +} --- qmail-1.03.orig/contrib/checkpassword-0.81/tryuserpw.c +++ qmail-1.03/contrib/checkpassword-0.81/tryuserpw.c @@ -0,0 +1,9 @@ +#include + +void main() +{ + struct userpw *upw; + + upw = getuserpw(""); + puts(upw->upw_passwd); +} --- qmail-1.03.orig/contrib/checkpassword-0.81/INSTALL +++ qmail-1.03/contrib/checkpassword-0.81/INSTALL @@ -0,0 +1,40 @@ +Like any other piece of software (and information generally), +checkpassword comes with NO WARRANTY. + + +Things you have to decide before starting: + +* The checkpassword home directory, normally /. To change this +directory, edit conf-home now. + + +How to install: + + 1. Compile the programs and create the formatted man pages: + % make + + 2. Install the programs and man pages: + # make setup check + + +How to test (if you have qmail installed): + + 3. Simulate a failed POP login: + # /var/qmail/bin/qmail-popup host /bin/checkpassword pwd + +OK <...@host> + user Frodo + +OK + pass Friend + -ERR authorization failed + + 4. Simulate a successful POP login, using a correct account name and + password instead of Frodo and Friend. You should see the account's + home directory. + + 5. Simulate a successful POP login again, with id instead of pwd. You + should see the account's uid and gid. + + +That's it! To report success: + % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to +Replace First M. Last with your name. --- qmail-1.03.orig/contrib/checkpassword-0.81/error.h +++ qmail-1.03/contrib/checkpassword-0.81/error.h @@ -0,0 +1,23 @@ +#ifndef ERROR_H +#define ERROR_H + +extern int errno; + +extern int error_intr; +extern int error_nomem; +extern int error_noent; +extern int error_txtbsy; +extern int error_io; +extern int error_exist; +extern int error_timeout; +extern int error_inprogress; +extern int error_wouldblock; +extern int error_again; +extern int error_pipe; +extern int error_perm; +extern int error_acces; + +extern char *error_str(); +extern int error_temp(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.81/conf-home +++ qmail-1.03/contrib/checkpassword-0.81/conf-home @@ -0,0 +1,4 @@ +/ + +This is the checkpassword home directory. Programs will be installed in +.../bin; man pages will be installed in subdirectories of .../man. --- qmail-1.03.orig/contrib/checkpassword-0.81/crypt.lib +++ qmail-1.03/contrib/checkpassword-0.81/crypt.lib @@ -0,0 +1 @@ +-lcrypt --- qmail-1.03.orig/contrib/mbox2maildir/mbox2maildir +++ qmail-1.03/contrib/mbox2maildir/mbox2maildir @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# +# mbox2maildir: coverts mbox file to maildir directory - the reverse of +# maildir2mbox from the qmail distribution. +# +# Usage: mbox2maildir uses the same environment variables as maildir2mbox: +# MAILDIR is the name of your maildir directory; MAIL is the name of your +# mbox file; MAILTMP is ignored. MAIL is deleted after the conversion. +# +# WARNING: there is no locking; don't run more than one of these! you +# have been warned. +# +# based on convert-and-create by Russell Nelson +# kludged into this by Ivan Kohler 97-sep-17 + +require 'stat.pl'; + +local $SIG{HUP} = 'IGNORE'; +local $SIG{INT} = 'IGNORE'; +local $SIG{QUIT} = 'IGNORE'; +local $SIG{TERM} = 'IGNORE'; +local $SIG{TSTP} = 'IGNORE'; + +($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = + getpwuid($<); + +die "fatal: home dir $dir doesn't exist\n" unless -e $dir; +&Stat($dir); +die "fatal: $name is $uid, but $dir is owned by $st_uid\n" if $uid != $st_uid; + +chdir($dir) or die "fatal: unable to chdir to $dir\n"; +$spoolname = "$ENV{MAILDIR}"; +-d $spoolname or mkdir $spoolname,0700 + or die("fatal: $spoolname doesn't exist and can't be created.\n"); + +chdir($spoolname) or die("fatal: unable to chdir to $spoolname.\n"); +-d "tmp" or mkdir("tmp",0700) or die("fatal: unable to make tmp/ subdir\n"); +-d "new" or mkdir("new",0700) or die("fatal: unable to make new/ subdir\n"); +-d "cur" or mkdir("cur",0700) or die("fatal: unable to make cur/ subdir\n"); + +open(SPOOL, "<$ENV{MAIL}") + or die "Unable to open $ENV{$MAIL}\n"; +$i = time; +while() { + if (/^From /) { + $fn = sprintf("new/%d.$$.mbox", $i); + open(OUT, ">$fn") or die("fatal: unable to create new message"); + $i++; + next; + } + s/^>From /From /; + print OUT or die("fatal: unable to write to new message"); +} +close(SPOOL); +close(OUT); +unlink("$ENV{MAIL}"); --- qmail-1.03.orig/contrib/checkpassword-0.90/strerr_die.c +++ qmail-1.03/contrib/checkpassword-0.90/strerr_die.c @@ -0,0 +1,31 @@ +#include "buffer.h" +#include "exit.h" +#include "strerr.h" + +void strerr_warn(char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se) +{ + strerr_sysinit(); + + if (x1) buffer_puts(buffer_2,x1); + if (x2) buffer_puts(buffer_2,x2); + if (x3) buffer_puts(buffer_2,x3); + if (x4) buffer_puts(buffer_2,x4); + if (x5) buffer_puts(buffer_2,x5); + if (x6) buffer_puts(buffer_2,x6); + + while(se) { + if (se->x) buffer_puts(buffer_2,se->x); + if (se->y) buffer_puts(buffer_2,se->y); + if (se->z) buffer_puts(buffer_2,se->z); + se = se->who; + } + + buffer_puts(buffer_2,"\n"); + buffer_flush(buffer_2); +} + +void strerr_die(int e,char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se) +{ + strerr_warn(x1,x2,x3,x4,x5,x6,se); + _exit(e); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/instcheck.c +++ qmail-1.03/contrib/checkpassword-0.90/instcheck.c @@ -0,0 +1,108 @@ +#include +#include +#include "strerr.h" +#include "error.h" +#include "readwrite.h" +#include "exit.h" + +extern void hier(); + +#define FATAL "instcheck: fatal: " +#define WARNING "instcheck: warning: " + +void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode) +char *prefix1; +char *prefix2; +char *prefix3; +char *file; +int type; +int uid; +int gid; +int mode; +{ + struct stat st; + + if (stat(file,&st) == -1) { + if (errno == error_noent) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0); + else + strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys); + return; + } + + if ((uid != -1) && (st.st_uid != uid)) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0); + if ((gid != -1) && (st.st_gid != gid)) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0); + if ((st.st_mode & 07777) != mode) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0); + if ((st.st_mode & S_IFMT) != type) + strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0); +} + +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + perm("","","",home,S_IFDIR,uid,gid,mode); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",subdir,S_IFDIR,uid,gid,mode); +} + +void p(home,fifo,uid,gid,mode) +char *home; +char *fifo; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",fifo,S_IFIFO,uid,gid,mode); +} + +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode); +} + +void z(home,file,len,uid,gid,mode) +char *home; +char *file; +int len; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + perm("",home,"/",file,S_IFREG,uid,gid,mode); +} + +main() +{ + hier(); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/alloc.c +++ qmail-1.03/contrib/checkpassword-0.90/alloc.c @@ -0,0 +1,32 @@ +#include "alloc.h" +#include "error.h" +extern char *malloc(); +extern void free(); + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 2048 /* must be multiple of ALIGNMENT */ + +typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; +static aligned realspace[SPACE / ALIGNMENT]; +#define space ((char *) realspace) +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +/*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +void alloc_free(x) +char *x; +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/auto_home.h +++ qmail-1.03/contrib/checkpassword-0.90/auto_home.h @@ -0,0 +1,6 @@ +#ifndef AUTO_HOME_H +#define AUTO_HOME_H + +extern const char auto_home[]; + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/warn-auto.sh +++ qmail-1.03/contrib/checkpassword-0.90/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! --- qmail-1.03.orig/contrib/checkpassword-0.90/byte_diff.c +++ qmail-1.03/contrib/checkpassword-0.90/byte_diff.c @@ -0,0 +1,16 @@ +#include "byte.h" + +int byte_diff(s,n,t) +register char *s; +register unsigned int n; +register char *t; +{ + for (;;) { + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + } + return ((int)(unsigned int)(unsigned char) *s) + - ((int)(unsigned int)(unsigned char) *t); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/hier.c +++ qmail-1.03/contrib/checkpassword-0.90/hier.c @@ -0,0 +1,6 @@ +#include "auto_home.h" + +void hier() +{ + c(auto_home,"bin","checkpassword",-1,-1,0700); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/chkshsgr.c +++ qmail-1.03/contrib/checkpassword-0.90/chkshsgr.c @@ -0,0 +1,10 @@ +#include "exit.h" + +main() +{ + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/tryspnam.c +++ qmail-1.03/contrib/checkpassword-0.90/tryspnam.c @@ -0,0 +1,9 @@ +#include + +void main() +{ + struct spwd *spw; + + spw = getspnam(""); + puts(spw->sp_pwdp); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/CHANGES +++ qmail-1.03/contrib/checkpassword-0.90/CHANGES @@ -0,0 +1,25 @@ +19981103 + version: checkpassword 0.80, beta. +19981121 + portability problem: some Linux systems _simultaneously_ support + shadow passwords and non-shadow passwords. impact: + checkpassword would see only the shadow passwords. fix: + in doit(), use getpwnam() password if getspnam() fails + (except with ETXTBSY). tnx to several people. + portability problem: AIX needs -ls for getuserpw(). impact: + couldn't compile. fix: check for -ls; also use in + hasuserpw.h. + portability problem: some systems incorrectly return EISDIR for + mkdir("/",...). impact: couldn't install. fix: don't + bother installing anything except checkpassword. + version: checkpassword 0.81, beta. +20001115 + portability problem: PAM-based systems can put 0 into pw_passwd. + nitwits. impact: checkpassword inspects *0 and crashes. + fix: check for 0 and use "*" instead. tnx Sverre. +20001222 + internal: switched to new install system. + internal: prototypes. + internal: incorporated doit() into main(). + internal: switched to pathexec and friends. + version: checkpassword 0.90, gamma. --- qmail-1.03.orig/contrib/checkpassword-0.90/env.c +++ qmail-1.03/contrib/checkpassword-0.90/env.c @@ -0,0 +1,15 @@ +#include "str.h" +#include "env.h" + +extern /*@null@*/char *env_get(char *s) +{ + int i; + unsigned int len; + + if (!s) return 0; + len = str_len(s); + for (i = 0;environ[i];++i) + if (str_start(environ[i],s) && (environ[i][len] == '=')) + return environ[i] + len + 1; + return 0; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer.c +++ qmail-1.03/contrib/checkpassword-0.90/buffer.c @@ -0,0 +1,10 @@ +#include "buffer.h" + +void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len) +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/tryslib.c +++ qmail-1.03/contrib/checkpassword-0.90/tryslib.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/byte_copy.c +++ qmail-1.03/contrib/checkpassword-0.90/byte_copy.c @@ -0,0 +1,14 @@ +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/error.c +++ qmail-1.03/contrib/checkpassword-0.90/error.c @@ -0,0 +1,123 @@ +#include +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif + +int error_nodevice = +#ifdef ENXIO +ENXIO; +#else +-14; +#endif + +int error_proto = +#ifdef EPROTO +EPROTO; +#else +-15; +#endif + +int error_isdir = +#ifdef EISDIR +EISDIR; +#else +-16; +#endif + +int error_connrefused = +#ifdef ECONNREFUSED +ECONNREFUSED; +#else +-17; +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/find-systype.sh +++ qmail-1.03/contrib/checkpassword-0.90/find-systype.sh @@ -0,0 +1,143 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null + +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os|freebsd|netbsd|openbsd) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + gcc -c trycpp.c + gcc -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +if gcc -c x86cpuid.c +then + if gcc -o x86cpuid x86cpuid.o + then + x86cpuid="`./x86cpuid | tr /: ..`" + case "$x86cpuid" in + ?*) + chip="$x86cpuid" + ;; + esac + fi +fi +rm -f x86cpuid x86cpuid.o + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' --- qmail-1.03.orig/contrib/checkpassword-0.90/strerr_sys.c +++ qmail-1.03/contrib/checkpassword-0.90/strerr_sys.c @@ -0,0 +1,12 @@ +#include "error.h" +#include "strerr.h" + +struct strerr strerr_sys; + +void strerr_sysinit(void) +{ + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); + strerr_sys.y = ""; + strerr_sys.z = ""; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_opys.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_opys.c @@ -0,0 +1,8 @@ +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_copys(stralloc *sa,char *s) +{ + return stralloc_copyb(sa,s,str_len(s)); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/FILES +++ qmail-1.03/contrib/checkpassword-0.90/FILES @@ -0,0 +1,78 @@ +README +TODO +CHANGES +VERSION +FILES +SYSDEPS +TARGETS +Makefile +alloc.c +alloc.h +alloc_re.c +auto-str.c +auto_home.h +buffer.c +buffer.h +buffer_2.c +buffer_copy.c +buffer_get.c +buffer_put.c +byte.h +byte_copy.c +byte_cr.c +byte_diff.c +checkpassword.c +chkshsgr.c +choose.sh +conf-cc +conf-home +conf-ld +env.c +env.h +error.c +error.h +error_str.c +exit.h +find-systype.sh +gen_alloc.h +gen_allocdefs.h +hasshsgr.h1 +hasshsgr.h2 +hier.c +install.c +instcheck.c +open.h +open_read.c +open_trunc.c +pathexec.h +pathexec_env.c +pathexec_run.c +print-cc.sh +prot.c +prot.h +readwrite.h +str.h +str_chr.c +str_len.c +str_start.c +stralloc.h +stralloc_cat.c +stralloc_catb.c +stralloc_cats.c +stralloc_eady.c +stralloc_opyb.c +stralloc_opys.c +stralloc_pend.c +strerr.h +strerr_die.c +strerr_sys.c +trycpp.c +trycrypt.c +tryshadow.c +tryshsgr.c +tryslib.c +tryspnam.c +tryuserpw.c +warn-auto.sh +warn-shsgr +x86cpuid.c --- qmail-1.03.orig/contrib/checkpassword-0.90/trycpp.c +++ qmail-1.03/contrib/checkpassword-0.90/trycpp.c @@ -0,0 +1,7 @@ +main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/prot.c +++ qmail-1.03/contrib/checkpassword-0.90/prot.c @@ -0,0 +1,19 @@ +#include "hasshsgr.h" +#include "prot.h" + +int prot_gid(int gid) +{ +#ifdef HASSHORTSETGROUPS + short x[2]; + x[0] = gid; x[1] = 73; /* catch errors */ + if (setgroups(1,x) == -1) return -1; +#else + if (setgroups(1,&gid) == -1) return -1; +#endif + return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ +} + +int prot_uid(int uid) +{ + return setuid(uid); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/print-cc.sh +++ qmail-1.03/contrib/checkpassword-0.90/print-cc.sh @@ -0,0 +1,5 @@ +cc="`head -1 conf-cc`" +systype="`cat systype`" + +cat warn-auto.sh +echo exec "$cc" '-c ${1+"$@"}' --- qmail-1.03.orig/contrib/checkpassword-0.90/checkpassword.c +++ qmail-1.03/contrib/checkpassword-0.90/checkpassword.c @@ -0,0 +1,92 @@ +#include "error.h" +#include "pathexec.h" +#include "prot.h" + +extern char *crypt(); +#include +static struct passwd *pw; + +#include "hasspnam.h" +#ifdef HASGETSPNAM +#include +static struct spwd *spw; +#endif + +#include "hasuserpw.h" +#ifdef HASUSERPW +#include +static struct userpw *upw; +#endif + +static char up[513]; +static int uplen; + +main(int argc,char **argv) +{ + char *login; + char *password; + char *encrypted; + char *stored; + int r; + int i; + + if (!argv[1]) _exit(2); + + uplen = 0; + for (;;) { + do + r = read(3,up + uplen,sizeof(up) - uplen); + while ((r == -1) && (errno == error_intr)); + if (r == -1) _exit(111); + if (r == 0) break; + uplen += r; + if (uplen >= sizeof(up)) _exit(1); + } + close(3); + + i = 0; + if (i >= uplen) _exit(2); + login = up + i; + while (up[i++]) if (i >= uplen) _exit(2); + password = up + i; + if (i >= uplen) _exit(2); + while (up[i++]) if (i >= uplen) _exit(2); + + pw = getpwnam(login); + if (pw) + stored = pw->pw_passwd; + else { + if (errno == error_txtbsy) _exit(111); + _exit(1); + } +#ifdef HASUSERPW + upw = getuserpw(login); + if (upw) + stored = upw->upw_passwd; + else + if (errno == error_txtbsy) _exit(111); +#endif +#ifdef HASGETSPNAM + spw = getspnam(login); + if (spw) + stored = spw->sp_pwdp; + else + if (errno == error_txtbsy) _exit(111); +#endif + if (!stored) _exit(1); + + encrypted = crypt(password,stored); + for (i = 0;i < sizeof(up);++i) up[i] = 0; + + if (!*stored || strcmp(encrypted,stored)) _exit(1); + + if (prot_gid((int) pw->pw_gid) == -1) _exit(1); + if (prot_uid((int) pw->pw_uid) == -1) _exit(1); + if (chdir(pw->pw_dir) == -1) _exit(111); + + if (!pathexec_env("USER",pw->pw_name)) _exit(111); + if (!pathexec_env("HOME",pw->pw_dir)) _exit(111); + if (!pathexec_env("SHELL",pw->pw_shell)) _exit(111); + pathexec(argv + 1); + _exit(111); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_cat.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_cat.c @@ -0,0 +1,7 @@ +#include "byte.h" +#include "stralloc.h" + +int stralloc_cat(stralloc *sato,stralloc *safrom) +{ + return stralloc_catb(sato,safrom->s,safrom->len); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_opyb.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_opyb.c @@ -0,0 +1,11 @@ +#include "stralloc.h" +#include "byte.h" + +int stralloc_copyb(stralloc *sa,char *s,unsigned int n) +{ + if (!stralloc_ready(sa,n + 1)) return 0; + byte_copy(sa->s,n,s); + sa->len = n; + sa->s[n] = 'Z'; /* ``offensive programming'' */ + return 1; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_catb.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_catb.c @@ -0,0 +1,12 @@ +#include "stralloc.h" +#include "byte.h" + +int stralloc_catb(stralloc *sa,char *s,unsigned int n) +{ + if (!sa->s) return stralloc_copyb(sa,s,n); + if (!stralloc_readyplus(sa,n + 1)) return 0; + byte_copy(sa->s + sa->len,n,s); + sa->len += n; + sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ + return 1; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/pathexec.h +++ qmail-1.03/contrib/checkpassword-0.90/pathexec.h @@ -0,0 +1,8 @@ +#ifndef PATHEXEC_H +#define PATHEXEC_H + +extern void pathexec_run(char *,char **,char **); +extern int pathexec_env(char *,char *); +extern void pathexec(char **); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/tryshadow.c +++ qmail-1.03/contrib/checkpassword-0.90/tryshadow.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_eady.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_eady.c @@ -0,0 +1,6 @@ +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) +GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) --- qmail-1.03.orig/contrib/checkpassword-0.90/conf-ld +++ qmail-1.03/contrib/checkpassword-0.90/conf-ld @@ -0,0 +1,3 @@ +gcc -s + +This will be used to link .o files into an executable. --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc.h +++ qmail-1.03/contrib/checkpassword-0.90/stralloc.h @@ -0,0 +1,29 @@ +#ifndef STRALLOC_H +#define STRALLOC_H + +#include "gen_alloc.h" + +GEN_ALLOC_typedef(stralloc,char,s,len,a) + +extern int stralloc_ready(stralloc *,unsigned int); +extern int stralloc_readyplus(stralloc *,unsigned int); +extern int stralloc_copy(stralloc *,stralloc *); +extern int stralloc_cat(stralloc *,stralloc *); +extern int stralloc_copys(stralloc *,char *); +extern int stralloc_cats(stralloc *,char *); +extern int stralloc_copyb(stralloc *,char *,unsigned int); +extern int stralloc_catb(stralloc *,char *,unsigned int); +extern int stralloc_append(stralloc *,char *); /* beware: this takes a pointer to 1 char */ +extern int stralloc_starts(stralloc *,char *); + +#define stralloc_0(sa) stralloc_append(sa,"") + +extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); +extern int stralloc_catlong0(stralloc *,long,unsigned int); + +#define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) +#define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) +#define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) +#define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0)) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/prot.h +++ qmail-1.03/contrib/checkpassword-0.90/prot.h @@ -0,0 +1,7 @@ +#ifndef PROT_H +#define PROT_H + +extern int prot_gid(int); +extern int prot_uid(int); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/choose.sh +++ qmail-1.03/contrib/checkpassword-0.90/choose.sh @@ -0,0 +1,18 @@ + +result="$4" + +case "$1" in + *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *r*) ./$2 >/dev/null 2>&1 || result="$3" ;; +esac + +rm -f $2.o $2 + +exec cat "$result" --- qmail-1.03.orig/contrib/checkpassword-0.90/README +++ qmail-1.03/contrib/checkpassword-0.90/README @@ -0,0 +1,7 @@ +checkpassword 0.90, gamma. +20001222 +Copyright 2000 +D. J. Bernstein + +checkpassword home page: http://cr.yp.to/checkpwd.html +Installation instructions: http://cr.yp.to/checkpwd/install.html --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer_2.c +++ qmail-1.03/contrib/checkpassword-0.90/buffer_2.c @@ -0,0 +1,6 @@ +#include "readwrite.h" +#include "buffer.h" + +char buffer_2_space[256]; +static buffer it = BUFFER_INIT(write,2,buffer_2_space,sizeof buffer_2_space); +buffer *buffer_2 = ⁢ --- qmail-1.03.orig/contrib/checkpassword-0.90/strerr.h +++ qmail-1.03/contrib/checkpassword-0.90/strerr.h @@ -0,0 +1,78 @@ +#ifndef STRERR_H +#define STRERR_H + +struct strerr { + struct strerr *who; + char *x; + char *y; + char *z; +} ; + +extern struct strerr strerr_sys; +extern void strerr_sysinit(void); + +extern char *strerr(struct strerr *); +extern void strerr_warn(char *,char *,char *,char *,char *,char *,struct strerr *); +extern void strerr_die(int,char *,char *,char *,char *,char *,char *,struct strerr *); + +#define STRERR(r,se,a) \ +{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } + +#define STRERR_SYS(r,se,a) \ +{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } +#define STRERR_SYS3(r,se,a,b,c) \ +{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } + +#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_warn5(x1,x2,x3,x4,x5,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_warn4(x1,x2,x3,x4,se) \ +strerr_warn((x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_warn3(x1,x2,x3,se) \ +strerr_warn((x1),(x2),(x3),0,0,0,(se)) +#define strerr_warn2(x1,x2,se) \ +strerr_warn((x1),(x2),0,0,0,0,(se)) +#define strerr_warn1(x1,se) \ +strerr_warn((x1),0,0,0,0,0,(se)) + +#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_die5(e,x1,x2,x3,x4,x5,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_die4(e,x1,x2,x3,x4,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_die3(e,x1,x2,x3,se) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,(se)) +#define strerr_die2(e,x1,x2,se) \ +strerr_die((e),(x1),(x2),0,0,0,0,(se)) +#define strerr_die1(e,x1,se) \ +strerr_die((e),(x1),0,0,0,0,0,(se)) + +#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) +#define strerr_die5sys(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys) +#define strerr_die4sys(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys) +#define strerr_die3sys(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys) +#define strerr_die2sys(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys) +#define strerr_die1sys(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,&strerr_sys) + +#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0) +#define strerr_die5x(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0) +#define strerr_die4x(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,0) +#define strerr_die3x(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,0) +#define strerr_die2x(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,0) +#define strerr_die1x(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,0) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/str_len.c +++ qmail-1.03/contrib/checkpassword-0.90/str_len.c @@ -0,0 +1,14 @@ +#include "str.h" + +unsigned int str_len(char *s) +{ + register char *t; + + t = s; + for (;;) { + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/alloc_re.c +++ qmail-1.03/contrib/checkpassword-0.90/alloc_re.c @@ -0,0 +1,17 @@ +#include "alloc.h" +#include "byte.h" + +int alloc_re(x,m,n) +char **x; +unsigned int m; +unsigned int n; +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + alloc_free(*x); + *x = y; + return 1; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/x86cpuid.c +++ qmail-1.03/contrib/checkpassword-0.90/x86cpuid.c @@ -0,0 +1,38 @@ +#include + +void nope() +{ + exit(1); +} + +main() +{ + unsigned long x[4]; + unsigned long y[4]; + int i; + int j; + char c; + + signal(SIGILL,nope); + + x[0] = 0; + x[1] = 0; + x[2] = 0; + x[3] = 0; + + asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) ); + if (!x[0]) return 0; + asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) ); + + for (i = 1;i < 4;++i) + for (j = 0;j < 4;++j) { + c = x[i] >> (8 * j); + if (c < 32) c = 32; + if (c > 126) c = 126; + putchar(c); + } + + printf("-%08x-%08x\n",y[0],y[3]); + + return 0; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer_copy.c +++ qmail-1.03/contrib/checkpassword-0.90/buffer_copy.c @@ -0,0 +1,16 @@ +#include "buffer.h" + +int buffer_copy(buffer *bout,buffer *bin) +{ + int n; + char *x; + + for (;;) { + n = buffer_feed(bin); + if (n < 0) return -2; + if (!n) return 0; + x = buffer_PEEK(bin); + if (buffer_put(bout,x,n) == -1) return -3; + buffer_SEEK(bin,n); + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/exit.h +++ qmail-1.03/contrib/checkpassword-0.90/exit.h @@ -0,0 +1,6 @@ +#ifndef EXIT_H +#define EXIT_H + +extern void _exit(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_cats.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_cats.c @@ -0,0 +1,8 @@ +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_cats(stralloc *sa,char *s) +{ + return stralloc_catb(sa,s,str_len(s)); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/tryshsgr.c +++ qmail-1.03/contrib/checkpassword-0.90/tryshsgr.c @@ -0,0 +1,14 @@ +main() +{ + short x[4]; + + x[0] = x[1] = 1; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 1) _exit(1); + x[1] = 2; + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 2) _exit(1); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/Makefile +++ qmail-1.03/contrib/checkpassword-0.90/Makefile @@ -0,0 +1,304 @@ +# Don't edit Makefile! Use conf-* for configuration. + +SHELL=/bin/sh + +default: it + +alloc.o: \ +compile alloc.c alloc.h error.h + ./compile alloc.c + +alloc_re.o: \ +compile alloc_re.c alloc.h byte.h + ./compile alloc_re.c + +auto-str: \ +load auto-str.o unix.a byte.a + ./load auto-str unix.a byte.a + +auto-str.o: \ +compile auto-str.c buffer.h readwrite.h exit.h + ./compile auto-str.c + +auto_home.c: \ +auto-str conf-home + ./auto-str auto_home `head -1 conf-home` > auto_home.c + +auto_home.o: \ +compile auto_home.c + ./compile auto_home.c + +buffer.o: \ +compile buffer.c buffer.h + ./compile buffer.c + +buffer_2.o: \ +compile buffer_2.c readwrite.h buffer.h + ./compile buffer_2.c + +buffer_copy.o: \ +compile buffer_copy.c buffer.h + ./compile buffer_copy.c + +buffer_get.o: \ +compile buffer_get.c buffer.h byte.h error.h + ./compile buffer_get.c + +buffer_put.o: \ +compile buffer_put.c buffer.h str.h byte.h error.h + ./compile buffer_put.c + +byte.a: \ +makelib byte_copy.o byte_cr.o byte_diff.o str_chr.o str_len.o \ +str_start.o + ./makelib byte.a byte_copy.o byte_cr.o byte_diff.o \ + str_chr.o str_len.o str_start.o + +byte_copy.o: \ +compile byte_copy.c byte.h + ./compile byte_copy.c + +byte_cr.o: \ +compile byte_cr.c byte.h + ./compile byte_cr.c + +byte_diff.o: \ +compile byte_diff.c byte.h + ./compile byte_diff.c + +check: \ +it instcheck + ./instcheck + +checkpassword: \ +load checkpassword.o prot.o unix.a byte.a shadow.lib crypt.lib s.lib + ./load checkpassword prot.o unix.a byte.a `cat \ + shadow.lib` `cat crypt.lib` `cat s.lib` + +checkpassword.o: \ +compile checkpassword.c error.h pathexec.h prot.h hasspnam.h \ +hasuserpw.h + ./compile checkpassword.c + +chkshsgr: \ +load chkshsgr.o + ./load chkshsgr + +chkshsgr.o: \ +compile chkshsgr.c exit.h + ./compile chkshsgr.c + +choose: \ +warn-auto.sh choose.sh conf-home + cat warn-auto.sh choose.sh \ + | sed s}HOME}"`head -1 conf-home`"}g \ + > choose + chmod 755 choose + +compile: \ +warn-auto.sh conf-cc systype print-cc.sh trycpp.c + sh print-cc.sh > compile + chmod 755 compile + +crypt.lib: \ +trycrypt.c compile load + ( ( ./compile trycrypt.c && \ + ./load trycrypt -lcrypt ) >/dev/null 2>&1 \ + && echo -lcrypt || exit 0 ) > crypt.lib + rm -f trycrypt.o trycrypt + +env.o: \ +compile env.c str.h env.h + ./compile env.c + +error.o: \ +compile error.c error.h + ./compile error.c + +error_str.o: \ +compile error_str.c error.h + ./compile error_str.c + +hasshsgr.h: \ +choose compile load tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr \ +warn-shsgr + ./chkshsgr || ( cat warn-shsgr; exit 1 ) + ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h + +hasspnam.h: \ +tryspnam.c compile load + ( ( ./compile tryspnam.c && ./load tryspnam ) >/dev/null \ + 2>&1 \ + && echo \#define HASGETSPNAM 1 || exit 0 ) > hasspnam.h + rm -f tryspnam.o tryspnam + +hasuserpw.h: \ +tryuserpw.c s.lib compile load + ( ( ./compile tryuserpw.c \ + && ./load tryuserpw `cat s.lib` ) >/dev/null 2>&1 \ + && echo \#define HASGETUSERPW 1 || exit 0 ) > hasuserpw.h + rm -f tryuserpw.o tryuserpw + +hier.o: \ +compile hier.c auto_home.h + ./compile hier.c + +install: \ +load install.o hier.o auto_home.o unix.a byte.a + ./load install hier.o auto_home.o unix.a byte.a + +install.o: \ +compile install.c buffer.h strerr.h error.h open.h readwrite.h exit.h + ./compile install.c + +instcheck: \ +load instcheck.o hier.o auto_home.o unix.a byte.a + ./load instcheck hier.o auto_home.o unix.a byte.a + +instcheck.o: \ +compile instcheck.c strerr.h error.h readwrite.h exit.h + ./compile instcheck.c + +it: \ +prog install instcheck + +load: \ +warn-auto.sh conf-ld + ( cat warn-auto.sh; \ + echo 'main="$$1"; shift'; \ + echo exec "`head -1 conf-ld`" \ + '-o "$$main" "$$main".o $${1+"$$@"}' \ + ) > load + chmod 755 load + +makelib: \ +warn-auto.sh systype + ( cat warn-auto.sh; \ + echo 'main="$$1"; shift'; \ + echo 'rm -f "$$main"'; \ + echo 'ar cr "$$main" $${1+"$$@"}'; \ + case "`cat systype`" in \ + sunos-5.*) ;; \ + unix_sv*) ;; \ + irix64-*) ;; \ + irix-*) ;; \ + dgux-*) ;; \ + hp-ux-*) ;; \ + sco*) ;; \ + *) echo 'ranlib "$$main"' ;; \ + esac \ + ) > makelib + chmod 755 makelib + +open_read.o: \ +compile open_read.c open.h + ./compile open_read.c + +open_trunc.o: \ +compile open_trunc.c open.h + ./compile open_trunc.c + +pathexec_env.o: \ +compile pathexec_env.c stralloc.h gen_alloc.h alloc.h str.h byte.h \ +env.h pathexec.h + ./compile pathexec_env.c + +pathexec_run.o: \ +compile pathexec_run.c error.h stralloc.h gen_alloc.h str.h env.h \ +pathexec.h + ./compile pathexec_run.c + +prog: \ +checkpassword + +prot.o: \ +compile prot.c hasshsgr.h prot.h + ./compile prot.c + +s.lib: \ +tryslib.c compile load + ( ( ./compile tryslib.c && \ + ./load tryslib -ls ) >/dev/null 2>&1 \ + && echo -ls || exit 0 ) > s.lib + rm -f tryslib.o tryslib + +setup: \ +it install + ./install + +shadow.lib: \ +tryshadow.c compile load + ( ( ./compile tryshadow.c && \ + ./load tryshadow -lshadow ) >/dev/null 2>&1 \ + && echo -lshadow || exit 0 ) > shadow.lib + rm -f tryshadow.o tryshadow + +str_chr.o: \ +compile str_chr.c str.h + ./compile str_chr.c + +str_len.o: \ +compile str_len.c str.h + ./compile str_len.c + +str_start.o: \ +compile str_start.c str.h + ./compile str_start.c + +stralloc_cat.o: \ +compile stralloc_cat.c byte.h stralloc.h gen_alloc.h + ./compile stralloc_cat.c + +stralloc_catb.o: \ +compile stralloc_catb.c stralloc.h gen_alloc.h byte.h + ./compile stralloc_catb.c + +stralloc_cats.o: \ +compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h + ./compile stralloc_cats.c + +stralloc_eady.o: \ +compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h + ./compile stralloc_eady.c + +stralloc_opyb.o: \ +compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h + ./compile stralloc_opyb.c + +stralloc_opys.o: \ +compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h + ./compile stralloc_opys.c + +stralloc_pend.o: \ +compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \ +gen_allocdefs.h + ./compile stralloc_pend.c + +strerr_die.o: \ +compile strerr_die.c buffer.h exit.h strerr.h + ./compile strerr_die.c + +strerr_sys.o: \ +compile strerr_sys.c error.h strerr.h + ./compile strerr_sys.c + +systype: \ +find-systype.sh trycpp.c x86cpuid.c + sh find-systype.sh > systype + +unix.a: \ +makelib alloc.o alloc_re.o buffer.o buffer_2.o buffer_copy.o \ +buffer_get.o buffer_put.o env.o error.o error_str.o open_read.o \ +open_trunc.o pathexec_env.o pathexec_run.o prot.o stralloc_cat.o \ +stralloc_catb.o stralloc_cats.o stralloc_eady.o stralloc_opyb.o \ +stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o + ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_2.o \ + buffer_copy.o buffer_get.o buffer_put.o env.o error.o \ + error_str.o open_read.o open_trunc.o pathexec_env.o \ + pathexec_run.o prot.o stralloc_cat.o stralloc_catb.o \ + stralloc_cats.o stralloc_eady.o stralloc_opyb.o \ + stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o + +clean: + rm -rf rm auto-str checkpassword chkshsgr compile install instcheck load makelib *o *a checkpassword.0 systype auto_home.c choose crypt.lib hasshsgr.h hasspnam.h hasuserpw.h s.lib shadow.lib systype --- qmail-1.03.orig/contrib/checkpassword-0.90/str_chr.c +++ qmail-1.03/contrib/checkpassword-0.90/str_chr.c @@ -0,0 +1,17 @@ +#include "str.h" + +unsigned int str_chr(register char *s,int c) +{ + register char ch; + register char *t; + + ch = c; + t = s; + for (;;) { + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + } + return t - s; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/VERSION +++ qmail-1.03/contrib/checkpassword-0.90/VERSION @@ -0,0 +1 @@ +checkpassword 0.90 --- qmail-1.03.orig/contrib/checkpassword-0.90/checkpassword.8 +++ qmail-1.03/contrib/checkpassword-0.90/checkpassword.8 @@ -0,0 +1,119 @@ +.TH checkpassword 8 +.SH NAME +checkpassword \- check a password +.SH SYNOPSIS +.B checkpassword +.I subprogram +[ +.I args ... +] +.SH DESCRIPTION +.B checkpassword +reads descriptor 3 through end of file +and then closes descriptor 3. +There must be at most 512 bytes of data before end of file. + +The information supplied on descriptor 3 +is a login name terminated by \e0, +a password terminated by \e0, +a timestamp terminated by \e0, +and possibly more data. +There are no other restrictions on +the form of the login name, password, and timestamp. + +If the password is unacceptable, +.B checkpassword +exits 1. +If +.B checkpassword +is misused, +it may instead exit 2. +If there is a temporary problem checking the password, +.B checkpassword +exits 111. + +If the password is acceptable, +.B checkpassword +uses +.B execvp +to run +.B subprogram +with the given arguments. +.SH "CHECKPASSWORD-COMPATIBLE TOOLS" +There are other tools that offer the same interface as +.BR checkpassword . +Applications that use +.B checkpassword +are encouraged to take the +.B checkpassword +name as an argument, +so that they can be used with different +.BR checkpassword -compatible +tools. + +Note that these tools do not follow the +.B getopt +interface. +Optional features are controlled through +(1) the tool name and +(2) environment variables. +.SH "THE PASSWORD DATABASE" +.B checkpassword +checks the login name and password against +.BR /etc/passwd , +using the operating system's +.B getpwnam +and +.B crypt +functions. +It rejects accounts with empty passwords. +It ignores the timestamp. + +Other +.BR checkpassword -compatible +tools have different interpretations of +login names, passwords, and timestamps. +Both the login name and the password +should be treated as secrets by the application calling +.BR checkpassword ; +the only distinction is for administrative convenience. +The timestamp should include any other information +that the password is based on; +for example, the challenge in a challenge-response system such as APOP. + +.B WARNING: +.B getpwnam +is inherently unreliable. +It fails to distinguish between temporary errors and nonexistent users. +Future versions of +.B getpwnam +should return ETXTBSY to indicate temporary errors +and ESRCH to indicate nonexistent users. +.SH "PROCESS-STATE CHANGES" +Before invoking +.BR subprogram , +.B checkpassword +sets up +.BR $USER , +.BR $HOME , +.BR $SHELL , +its supplementary groups, +its gid, +its uid, +and its working directory. + +Other +.BR checkpassword -compatible +tools may make different changes to the process state. +These effects must be documented; +applications will differ in their requirements. +.SH "VERSION" +This documentation describes +.B checkpassword +version 0.80. +See +.B http://pobox.com/~djb/checkpwd.html +for updates. +.SH "SEE ALSO" +getpwnam(3), +crypt(3) --- qmail-1.03.orig/contrib/checkpassword-0.90/readwrite.h +++ qmail-1.03/contrib/checkpassword-0.90/readwrite.h @@ -0,0 +1,7 @@ +#ifndef READWRITE_H +#define READWRITE_H + +extern int read(); +extern int write(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/stralloc_pend.c +++ qmail-1.03/contrib/checkpassword-0.90/stralloc_pend.c @@ -0,0 +1,5 @@ +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) --- qmail-1.03.orig/contrib/checkpassword-0.90/auto-str.c +++ qmail-1.03/contrib/checkpassword-0.90/auto-str.c @@ -0,0 +1,41 @@ +#include "buffer.h" +#include "readwrite.h" +#include "exit.h" + +char bspace[256]; +buffer b = BUFFER_INIT(write,1,bspace,sizeof bspace); + +void puts(char *s) +{ + if (buffer_puts(&b,s) == -1) _exit(111); +} + +main(int argc,char **argv) +{ + char *name; + char *value; + unsigned char ch; + char octal[4]; + + name = argv[1]; + if (!name) _exit(100); + value = argv[2]; + if (!value) _exit(100); + + puts("const char "); + puts(name); + puts("[] = \"\\\n"); + + while (ch = *value++) { + puts("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); + puts(octal); + } + + puts("\\\n\";\n"); + if (buffer_flush(&b) == -1) _exit(111); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer.h +++ qmail-1.03/contrib/checkpassword-0.90/buffer.h @@ -0,0 +1,56 @@ +#ifndef BUFFER_H +#define BUFFER_H + +typedef struct buffer { + char *x; + unsigned int p; + unsigned int n; + int fd; + int (*op)(); +} buffer; + +#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } +#define BUFFER_INSIZE 8192 +#define BUFFER_OUTSIZE 8192 + +extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int); + +extern int buffer_flush(buffer *); +extern int buffer_put(buffer *,char *,unsigned int); +extern int buffer_putalign(buffer *,char *,unsigned int); +extern int buffer_putflush(buffer *,char *,unsigned int); +extern int buffer_puts(buffer *,char *); +extern int buffer_putsalign(buffer *,char *); +extern int buffer_putsflush(buffer *,char *); + +#define buffer_PUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : buffer_put((s),&(c),1) \ + ) + +extern int buffer_get(buffer *,char *,unsigned int); +extern int buffer_bget(buffer *,char *,unsigned int); +extern int buffer_feed(buffer *); + +extern char *buffer_peek(buffer *); +extern void buffer_seek(buffer *,unsigned int); + +#define buffer_PEEK(s) ( (s)->x + (s)->n ) +#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) + +#define buffer_GETC(s,c) \ + ( ((s)->p > 0) \ + ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ + : buffer_get((s),(c),1) \ + ) + +extern int buffer_copy(buffer *,buffer *); + +extern buffer *buffer_0; +extern buffer *buffer_0small; +extern buffer *buffer_1; +extern buffer *buffer_1small; +extern buffer *buffer_2; + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer_put.c +++ qmail-1.03/contrib/checkpassword-0.90/buffer_put.c @@ -0,0 +1,88 @@ +#include "buffer.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +static int allwrite(int (*op)(),int fd,char *buf,unsigned int len) +{ + int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +int buffer_flush(buffer *s) +{ + int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int buffer_putalign(buffer *s,char *buf,unsigned int len) +{ + unsigned int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (buffer_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_put(buffer *s,char *buf,unsigned int len) +{ + unsigned int n; + + n = s->n; + if (len > n - s->p) { + if (buffer_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_putflush(buffer *s,char *buf,unsigned int len) +{ + if (buffer_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int buffer_putsalign(buffer *s,char *buf) +{ + return buffer_putalign(s,buf,str_len(buf)); +} + +int buffer_puts(buffer *s,char *buf) +{ + return buffer_put(s,buf,str_len(buf)); +} + +int buffer_putsflush(buffer *s,char *buf) +{ + return buffer_putflush(s,buf,str_len(buf)); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/conf-cc +++ qmail-1.03/contrib/checkpassword-0.90/conf-cc @@ -0,0 +1,3 @@ +gcc -O2 + +This will be used to compile .c files. --- qmail-1.03.orig/contrib/checkpassword-0.90/pathexec_run.c +++ qmail-1.03/contrib/checkpassword-0.90/pathexec_run.c @@ -0,0 +1,46 @@ +#include "error.h" +#include "stralloc.h" +#include "str.h" +#include "env.h" +#include "pathexec.h" + +static stralloc tmp; + +void pathexec_run(char *file,char **argv,char **envp) +{ + char *path; + unsigned int split; + int savederrno; + + if (file[str_chr(file,'/')]) { + execve(file,argv,envp); + return; + } + + path = env_get("PATH"); + if (!path) path = "/bin:/usr/bin"; + + savederrno = 0; + for (;;) { + split = str_chr(path,':'); + if (!stralloc_copyb(&tmp,path,split)) return; + if (!split) + if (!stralloc_cats(&tmp,".")) return; + if (!stralloc_cats(&tmp,"/")) return; + if (!stralloc_cats(&tmp,file)) return; + if (!stralloc_0(&tmp)) return; + + execve(tmp.s,argv,envp); + if (errno != error_noent) { + savederrno = errno; + if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; + } + + if (!path[split]) { + if (savederrno) errno = savederrno; + return; + } + path += split; + path += 1; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/str_start.c +++ qmail-1.03/contrib/checkpassword-0.90/str_start.c @@ -0,0 +1,13 @@ +#include "str.h" + +int str_start(register char *s,register char *t) +{ + register char x; + + for (;;) { + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/warn-shsgr +++ qmail-1.03/contrib/checkpassword-0.90/warn-shsgr @@ -0,0 +1,3 @@ +Oops. Your getgroups() returned 0, and setgroups() failed; this means +that I can't reliably do my shsgr test. Please either ``make'' as root +or ``make'' while you're in one or more supplementary groups. --- qmail-1.03.orig/contrib/checkpassword-0.90/env.h +++ qmail-1.03/contrib/checkpassword-0.90/env.h @@ -0,0 +1,8 @@ +#ifndef ENV_H +#define ENV_H + +extern char **environ; + +extern /*@null@*/char *env_get(char *); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/TARGETS +++ qmail-1.03/contrib/checkpassword-0.90/TARGETS @@ -0,0 +1,60 @@ +load +systype +compile +hasspnam.h +s.lib +hasuserpw.h +checkpassword.o +choose +chkshsgr.o +chkshsgr +hasshsgr.h +prot.o +makelib +alloc.o +alloc_re.o +buffer.o +buffer_2.o +buffer_copy.o +buffer_get.o +buffer_put.o +env.o +error.o +error_str.o +open_read.o +open_trunc.o +pathexec_env.o +pathexec_run.o +stralloc_cat.o +stralloc_catb.o +stralloc_cats.o +stralloc_eady.o +stralloc_opyb.o +stralloc_opys.o +stralloc_pend.o +strerr_die.o +strerr_sys.o +unix.a +byte_copy.o +byte_cr.o +byte_diff.o +str_chr.o +str_len.o +str_start.o +byte.a +shadow.lib +crypt.lib +checkpassword +prog +install.o +hier.o +auto-str.o +auto-str +auto_home.c +auto_home.o +install +instcheck.o +instcheck +it +setup +check --- qmail-1.03.orig/contrib/checkpassword-0.90/pathexec_env.c +++ qmail-1.03/contrib/checkpassword-0.90/pathexec_env.c @@ -0,0 +1,68 @@ +#include "stralloc.h" +#include "alloc.h" +#include "str.h" +#include "byte.h" +#include "env.h" +#include "pathexec.h" + +static stralloc plus; +static stralloc tmp; + +int pathexec_env(char *s,char *t) +{ + if (!s) return 1; + if (!stralloc_copys(&tmp,s)) return 0; + if (t) { + if (!stralloc_cats(&tmp,"=")) return 0; + if (!stralloc_cats(&tmp,t)) return 0; + } + if (!stralloc_0(&tmp)) return 0; + return stralloc_cat(&plus,&tmp); +} + +void pathexec(char **argv) +{ + char *path; + char **e; + unsigned int elen; + unsigned int i; + unsigned int j; + unsigned int split; + unsigned int t; + + if (!stralloc_cats(&plus,"")) return; + + elen = 0; + for (i = 0;environ[i];++i) + ++elen; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) + ++elen; + + e = (char **) alloc((elen + 1) * sizeof(char *)); + if (!e) return; + + elen = 0; + for (i = 0;environ[i];++i) + e[elen++] = environ[i]; + + j = 0; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) { + split = str_chr(plus.s + j,'='); + for (t = 0;t < elen;++t) + if (byte_equal(plus.s + j,split,e[t])) + if (e[t][split] == '=') { + --elen; + e[t] = e[elen]; + break; + } + if (plus.s[j + split]) + e[elen++] = plus.s + j; + j = i + 1; + } + e[elen] = 0; + + pathexec_run(*argv,argv,e); + alloc_free(e); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/byte_cr.c +++ qmail-1.03/contrib/checkpassword-0.90/byte_cr.c @@ -0,0 +1,16 @@ +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} --- qmail-1.03.orig/contrib/checkpassword-0.90/open.h +++ qmail-1.03/contrib/checkpassword-0.90/open.h @@ -0,0 +1,10 @@ +#ifndef OPEN_H +#define OPEN_H + +extern int open_read(char *); +extern int open_excl(char *); +extern int open_append(char *); +extern int open_trunc(char *); +extern int open_write(char *); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/install.c +++ qmail-1.03/contrib/checkpassword-0.90/install.c @@ -0,0 +1,149 @@ +#include "buffer.h" +#include "strerr.h" +#include "error.h" +#include "open.h" +#include "readwrite.h" +#include "exit.h" + +extern void hier(); + +#define FATAL "install: fatal: " + +int fdsourcedir = -1; + +void h(home,uid,gid,mode) +char *home; +int uid; +int gid; +int mode; +{ + if (mkdir(home,0700) == -1) + if (errno != error_exist) + strerr_die4sys(111,FATAL,"unable to mkdir ",home,": "); + if (chown(home,uid,gid) == -1) + strerr_die4sys(111,FATAL,"unable to chown ",home,": "); + if (chmod(home,mode) == -1) + strerr_die4sys(111,FATAL,"unable to chmod ",home,": "); +} + +void d(home,subdir,uid,gid,mode) +char *home; +char *subdir; +int uid; +int gid; +int mode; +{ + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (mkdir(subdir,0700) == -1) + if (errno != error_exist) + strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": "); + if (chown(subdir,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": "); + if (chmod(subdir,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": "); +} + +char inbuf[BUFFER_INSIZE]; +char outbuf[BUFFER_OUTSIZE]; +buffer ssin; +buffer ssout; + +void c(home,subdir,file,uid,gid,mode) +char *home; +char *subdir; +char *file; +int uid; +int gid; +int mode; +{ + int fdin; + int fdout; + + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); + + fdin = open_read(file); + if (fdin == -1) + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + buffer_init(&ssin,read,fdin,inbuf,sizeof inbuf); + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf); + + switch(buffer_copy(&ssout,&ssin)) { + case -2: + strerr_die4sys(111,FATAL,"unable to read ",file,": "); + case -3: + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + } + + close(fdin); + if (buffer_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); +} + +void z(home,subdir,file,len,uid,gid,mode) +char *home; +char *subdir; +char *file; +int len; +int uid; +int gid; +int mode; +{ + int fdout; + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); + if (chdir(subdir) == -1) + strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); + + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf); + + while (len-- > 0) + if (buffer_put(&ssout,"",1) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (buffer_flush(&ssout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (fsync(fdout) == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + if (close(fdout) == -1) /* NFS silliness */ + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); + + if (chown(file,uid,gid) == -1) + strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); + if (chmod(file,mode) == -1) + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); +} + +main() +{ + fdsourcedir = open_read("."); + if (fdsourcedir == -1) + strerr_die2sys(111,FATAL,"unable to open current directory: "); + + umask(077); + hier(); + _exit(0); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/SYSDEPS +++ qmail-1.03/contrib/checkpassword-0.90/SYSDEPS @@ -0,0 +1,9 @@ +VERSION +systype +crypt.lib +shadow.lib +s.lib +hasspnam.h +hasuserpw.h +hasshsgr.h +hasshsgr.h --- qmail-1.03.orig/contrib/checkpassword-0.90/TODO +++ qmail-1.03/contrib/checkpassword-0.90/TODO @@ -0,0 +1 @@ +check portability --- qmail-1.03.orig/contrib/checkpassword-0.90/open_read.c +++ qmail-1.03/contrib/checkpassword-0.90/open_read.c @@ -0,0 +1,6 @@ +#include +#include +#include "open.h" + +int open_read(char *fn) +{ return open(fn,O_RDONLY | O_NDELAY); } --- qmail-1.03.orig/contrib/checkpassword-0.90/open_trunc.c +++ qmail-1.03/contrib/checkpassword-0.90/open_trunc.c @@ -0,0 +1,6 @@ +#include +#include +#include "open.h" + +int open_trunc(char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } --- qmail-1.03.orig/contrib/checkpassword-0.90/str.h +++ qmail-1.03/contrib/checkpassword-0.90/str.h @@ -0,0 +1,14 @@ +#ifndef STR_H +#define STR_H + +extern unsigned int str_copy(char *,char *); +extern int str_diff(char *,char *); +extern int str_diffn(char *,char *,unsigned int); +extern unsigned int str_len(char *); +extern unsigned int str_chr(char *,int); +extern unsigned int str_rchr(char *,int); +extern int str_start(char *,char *); + +#define str_equal(s,t) (!str_diff((s),(t))) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/byte.h +++ qmail-1.03/contrib/checkpassword-0.90/byte.h @@ -0,0 +1,13 @@ +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/hasshsgr.h2 +++ qmail-1.03/contrib/checkpassword-0.90/hasshsgr.h2 @@ -0,0 +1,2 @@ +/* sysdep: +shortsetgroups */ +#define HASSHORTSETGROUPS 1 --- qmail-1.03.orig/contrib/checkpassword-0.90/gen_alloc.h +++ qmail-1.03/contrib/checkpassword-0.90/gen_alloc.h @@ -0,0 +1,7 @@ +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +#define GEN_ALLOC_typedef(ta,type,field,len,a) \ + typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/trycrypt.c +++ qmail-1.03/contrib/checkpassword-0.90/trycrypt.c @@ -0,0 +1,4 @@ +main() +{ + ; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/buffer_get.c +++ qmail-1.03/contrib/checkpassword-0.90/buffer_get.c @@ -0,0 +1,67 @@ +#include "buffer.h" +#include "byte.h" +#include "error.h" + +static int oneread(int (*op)(),int fd,char *buf,unsigned int len) +{ + int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == error_intr) continue; + return r; + } +} + +static int getthis(buffer *s,char *buf,unsigned int len) +{ + if (len > s->p) len = s->p; + s->p -= len; + byte_copy(buf,len,s->x + s->n); + s->n += len; + return len; +} + +int buffer_feed(buffer *s) +{ + int r; + + if (s->p) return s->p; + r = oneread(s->op,s->fd,s->x,s->n); + if (r <= 0) return r; + s->p = r; + s->n -= r; + if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); + return r; +} + +int buffer_bget(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +int buffer_get(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *buffer_peek(buffer *s) +{ + return s->x + s->n; +} + +void buffer_seek(buffer *s,unsigned int len) +{ + s->n += len; + s->p -= len; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/gen_allocdefs.h +++ qmail-1.03/contrib/checkpassword-0.90/gen_allocdefs.h @@ -0,0 +1,34 @@ +#ifndef GEN_ALLOC_DEFS_H +#define GEN_ALLOC_DEFS_H + +#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ +int ta_ready(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ +int ta_rplus(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ +int ta_append(register ta *x,register type *i) \ +{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/error_str.c +++ qmail-1.03/contrib/checkpassword-0.90/error_str.c @@ -0,0 +1,267 @@ +#include +#include "error.h" + +#define X(e,s) if (i == e) return s; + +char *error_str(int i) +{ + X(0,"no error") + X(error_intr,"interrupted system call") + X(error_nomem,"out of memory") + X(error_noent,"file does not exist") + X(error_txtbsy,"text busy") + X(error_io,"input/output error") + X(error_exist,"file already exists") + X(error_timeout,"timed out") + X(error_inprogress,"operation in progress") + X(error_again,"temporary failure") + X(error_wouldblock,"input/output would block") + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") + X(error_nodevice,"device not configured") + X(error_proto,"protocol error") + X(error_isdir,"is a directory") + X(error_connrefused,"connection refused") +#ifdef ESRCH + X(ESRCH,"no such process") +#endif +#ifdef E2BIG + X(E2BIG,"argument list too long") +#endif +#ifdef ENOEXEC + X(ENOEXEC,"exec format error") +#endif +#ifdef EBADF + X(EBADF,"file descriptor not open") +#endif +#ifdef ECHILD + X(ECHILD,"no child processes") +#endif +#ifdef EDEADLK + X(EDEADLK,"operation would cause deadlock") +#endif +#ifdef EFAULT + X(EFAULT,"bad address") +#endif +#ifdef ENOTBLK + X(ENOTBLK,"not a block device") +#endif +#ifdef EBUSY + X(EBUSY,"device busy") +#endif +#ifdef EXDEV + X(EXDEV,"cross-device link") +#endif +#ifdef ENODEV + X(ENODEV,"device does not support operation") +#endif +#ifdef ENOTDIR + X(ENOTDIR,"not a directory") +#endif +#ifdef EINVAL + X(EINVAL,"invalid argument") +#endif +#ifdef ENFILE + X(ENFILE,"system cannot open more files") +#endif +#ifdef EMFILE + X(EMFILE,"process cannot open more files") +#endif +#ifdef ENOTTY + X(ENOTTY,"not a tty") +#endif +#ifdef EFBIG + X(EFBIG,"file too big") +#endif +#ifdef ENOSPC + X(ENOSPC,"out of disk space") +#endif +#ifdef ESPIPE + X(ESPIPE,"unseekable descriptor") +#endif +#ifdef EROFS + X(EROFS,"read-only file system") +#endif +#ifdef EMLINK + X(EMLINK,"too many links") +#endif +#ifdef EDOM + X(EDOM,"input out of range") +#endif +#ifdef ERANGE + X(ERANGE,"output out of range") +#endif +#ifdef EALREADY + X(EALREADY,"operation already in progress") +#endif +#ifdef ENOTSOCK + X(ENOTSOCK,"not a socket") +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ,"destination address required") +#endif +#ifdef EMSGSIZE + X(EMSGSIZE,"message too long") +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE,"incorrect protocol type") +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT,"protocol not available") +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT,"protocol not supported") +#endif +#ifdef ESOCKTNOSUPPORT + X(ESOCKTNOSUPPORT,"socket type not supported") +#endif +#ifdef EOPNOTSUPP + X(EOPNOTSUPP,"operation not supported") +#endif +#ifdef EPFNOSUPPORT + X(EPFNOSUPPORT,"protocol family not supported") +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT,"address family not supported") +#endif +#ifdef EADDRINUSE + X(EADDRINUSE,"address already used") +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL,"address not available") +#endif +#ifdef ENETDOWN + X(ENETDOWN,"network down") +#endif +#ifdef ENETUNREACH + X(ENETUNREACH,"network unreachable") +#endif +#ifdef ENETRESET + X(ENETRESET,"network reset") +#endif +#ifdef ECONNABORTED + X(ECONNABORTED,"connection aborted") +#endif +#ifdef ECONNRESET + X(ECONNRESET,"connection reset") +#endif +#ifdef ENOBUFS + X(ENOBUFS,"out of buffer space") +#endif +#ifdef EISCONN + X(EISCONN,"already connected") +#endif +#ifdef ENOTCONN + X(ENOTCONN,"not connected") +#endif +#ifdef ESHUTDOWN + X(ESHUTDOWN,"socket shut down") +#endif +#ifdef ETOOMANYREFS + X(ETOOMANYREFS,"too many references") +#endif +#ifdef ELOOP + X(ELOOP,"symbolic link loop") +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG,"file name too long") +#endif +#ifdef EHOSTDOWN + X(EHOSTDOWN,"host down") +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH,"host unreachable") +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY,"directory not empty") +#endif +#ifdef EPROCLIM + X(EPROCLIM,"too many processes") +#endif +#ifdef EUSERS + X(EUSERS,"too many users") +#endif +#ifdef EDQUOT + X(EDQUOT,"disk quota exceeded") +#endif +#ifdef ESTALE + X(ESTALE,"stale NFS file handle") +#endif +#ifdef EREMOTE + X(EREMOTE,"too many levels of remote in path") +#endif +#ifdef EBADRPC + X(EBADRPC,"RPC structure is bad") +#endif +#ifdef ERPCMISMATCH + X(ERPCMISMATCH,"RPC version mismatch") +#endif +#ifdef EPROGUNAVAIL + X(EPROGUNAVAIL,"RPC program unavailable") +#endif +#ifdef EPROGMISMATCH + X(EPROGMISMATCH,"program version mismatch") +#endif +#ifdef EPROCUNAVAIL + X(EPROCUNAVAIL,"bad procedure for program") +#endif +#ifdef ENOLCK + X(ENOLCK,"no locks available") +#endif +#ifdef ENOSYS + X(ENOSYS,"system call not available") +#endif +#ifdef EFTYPE + X(EFTYPE,"bad file type") +#endif +#ifdef EAUTH + X(EAUTH,"authentication error") +#endif +#ifdef ENEEDAUTH + X(ENEEDAUTH,"not authenticated") +#endif +#ifdef ENOSTR + X(ENOSTR,"not a stream device") +#endif +#ifdef ETIME + X(ETIME,"timer expired") +#endif +#ifdef ENOSR + X(ENOSR,"out of stream resources") +#endif +#ifdef ENOMSG + X(ENOMSG,"no message of desired type") +#endif +#ifdef EBADMSG + X(EBADMSG,"bad message type") +#endif +#ifdef EIDRM + X(EIDRM,"identifier removed") +#endif +#ifdef ENONET + X(ENONET,"machine not on network") +#endif +#ifdef ERREMOTE + X(ERREMOTE,"object not local") +#endif +#ifdef ENOLINK + X(ENOLINK,"link severed") +#endif +#ifdef EADV + X(EADV,"advertise error") +#endif +#ifdef ESRMNT + X(ESRMNT,"srmount error") +#endif +#ifdef ECOMM + X(ECOMM,"communication error") +#endif +#ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +#endif +#ifdef EREMCHG + X(EREMCHG,"remote address changed") +#endif + return "unknown error"; +} --- qmail-1.03.orig/contrib/checkpassword-0.90/tryuserpw.c +++ qmail-1.03/contrib/checkpassword-0.90/tryuserpw.c @@ -0,0 +1,9 @@ +#include + +void main() +{ + struct userpw *upw; + + upw = getuserpw(""); + puts(upw->upw_passwd); +} --- qmail-1.03.orig/contrib/checkpassword-0.90/error.h +++ qmail-1.03/contrib/checkpassword-0.90/error.h @@ -0,0 +1,27 @@ +#ifndef ERROR_H +#define ERROR_H + +#include + +extern int error_intr; +extern int error_nomem; +extern int error_noent; +extern int error_txtbsy; +extern int error_io; +extern int error_exist; +extern int error_timeout; +extern int error_inprogress; +extern int error_wouldblock; +extern int error_again; +extern int error_pipe; +extern int error_perm; +extern int error_acces; +extern int error_nodevice; +extern int error_proto; +extern int error_isdir; +extern int error_connrefused; + +extern char *error_str(int); +extern int error_temp(int); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/alloc.h +++ qmail-1.03/contrib/checkpassword-0.90/alloc.h @@ -0,0 +1,8 @@ +#ifndef ALLOC_H +#define ALLOC_H + +extern /*@null@*//*@out@*/char *alloc(); +extern void alloc_free(); +extern int alloc_re(); + +#endif --- qmail-1.03.orig/contrib/checkpassword-0.90/conf-home +++ qmail-1.03/contrib/checkpassword-0.90/conf-home @@ -0,0 +1,4 @@ +/ + +This is the checkpassword home directory. The checkpassword program will +be installed in the bin subdirectory. --- qmail-1.03.orig/contrib/checkpassword-0.90/hasshsgr.h1 +++ qmail-1.03/contrib/checkpassword-0.90/hasshsgr.h1 @@ -0,0 +1 @@ +/* sysdep: -shortsetgroups */ --- qmail-1.03.orig/error.3 +++ qmail-1.03/error.3 @@ -3,8 +3,7 @@ error \- syscall error codes .SH SYNTAX .B #include - -extern int \fBerrno\fP; +.B #include extern int \fBerror_intr\fP; .br --- qmail-1.03.orig/hier.c +++ qmail-1.03/hier.c @@ -76,6 +76,7 @@ c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); --- qmail-1.03.orig/ipme.c +++ qmail-1.03/ipme.c @@ -46,6 +46,11 @@ 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; } if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; len = 256; --- qmail-1.03.orig/datemail.sh +++ qmail-1.03/datemail.sh @@ -1 +1 @@ -exec QMAIL/bin/predate QMAIL/bin/sendmail ${1+"$@"} +exec /usr/sbin/predate /usr/sbin/sendmail ${1+"$@"} --- qmail-1.03.orig/qmail-queue.c +++ qmail-1.03/qmail-queue.c @@ -1,5 +1,6 @@ #include #include +#include #include "readwrite.h" #include "sig.h" #include "exit.h" @@ -155,6 +156,7 @@ { unsigned int len; char ch; + int fd; sig_blocknone(); umask(033); @@ -183,7 +185,7 @@ todofn = fnnum("todo/",0); intdfn = fnnum("intd/",0); - if (link(pidfn,messfn) == -1) die(64); + if (link(pidfn,messfn) == -1) die(64); if (unlink(pidfn) == -1) die(63); flagmademess = 1; @@ -248,6 +250,8 @@ if (fsync(intdfd) == -1) die_write(); if (link(intdfn,todofn) == -1) die(66); + if ((fd = open(todofn, O_RDONLY)) < 0 || + fsync(fd) < 0 || close(fd) < 0) die(66); triggerpull(); die(0); --- qmail-1.03.orig/qmail-lspawn.c +++ qmail-1.03/qmail-lspawn.c @@ -139,7 +139,7 @@ } if (pipe(pi) == -1) _exit(QLX_SYS); - args[0] = "bin/qmail-getpw"; + args[0] = "/usr/sbin/qmail-getpw"; args[1] = local; args[2] = 0; switch(gpwpid = vfork()) @@ -191,7 +191,7 @@ x = nughde.s; xlen = nughde.len; - args[0] = "bin/qmail-local"; + args[0] = "/usr/sbin/qmail-local"; args[1] = "--"; args[2] = x; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; --- qmail-1.03.orig/qmail-smtpd.8 +++ qmail-1.03/qmail-smtpd.8 @@ -37,11 +37,26 @@ even though such messages violate the SMTP protocol. .SH "CONTROL FILES" .TP 5 +.I badhelo +Unacceptable HELO/EHLO host names. +.B qmail-smtpd +will reject every recipient address for a message if +the host name is listed in, +or matches a POSIX regular expression pattern listed in, +.IR badhelo . +If the +.B NOBADHELO +environment variable is set, then the contents of +.IR badhelo +will be ignored. +For more information, please have a look at doc/README.qregex. +.TP 5 .I badmailfrom Unacceptable envelope sender addresses. .B qmail-smtpd will reject every recipient address for a message -if the envelope sender address is listed in +if the envelope sender address is listed in, or matches a POSIX regular expression +pattern listed in, .IR badmailfrom . A line in .I badmailfrom @@ -49,6 +64,32 @@ .BR @\fIhost , meaning every address at .IR host . +For more information, please have a look at doc/README.qregex. +.TP 5 +.I badmailfromnorelay +Functions the same as the +.IR badmailfrom +control file but is read only if the +.B RELAYCLIENT +environment variable is not set. +For more information, please have a look at doc/README.qregex. +.TP 5 +.I badmailto +Unacceptable envelope recipient addresses. +.B qmail-smtpd +will reject every recipient address for a message if the recipient address +is listed in, +or matches a POSIX regular expression pattern listed in, +.IR badmailto . +For more information, please have a look at doc/README.qregex. +.TP 5 +.I badmailtonorelay +Functions the same as the +.IR badmailto +control file but is read only if the +.B RELAYCLIENT +environment variable is not set. +For more information, please have a look at doc/README.qregex. .TP 5 .I databytes Maximum number of bytes allowed in a message, --- qmail-1.03.orig/binm1+df.sh +++ qmail-1.03/binm1+df.sh @@ -5,7 +5,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|dot-forward .forward |preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/qmail-local.c +++ qmail-1.03/qmail-local.c @@ -1,5 +1,6 @@ #include #include +#include #include "readwrite.h" #include "sig.h" #include "env.h" @@ -128,6 +129,9 @@ if (close(fd) == -1) goto fail; /* NFS dorks */ if (link(fntmptph,fnnewtph) == -1) goto fail; + if ((fd = open(fnnewtph, O_RDONLY)) < 0 || + fsync(fd) < 0 || close(fd) < 0) goto fail; + /* if it was error_exist, almost certainly successful; i hate NFS */ tryunlinktmp(); _exit(0); @@ -645,7 +649,7 @@ { cmds.s[j] = 0; k = j; - while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')) + while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))) cmds.s[--k] = 0; switch(cmds.s[i]) { --- qmail-1.03.orig/pinq.sh +++ qmail-1.03/pinq.sh @@ -1 +1 @@ -QMAIL/bin/maildir2mbox && exec pine ${1+"$@"} +/usr/bin/maildir2mbox && exec pine ${1+"$@"} --- qmail-1.03.orig/binm2.sh +++ qmail-1.03/binm2.sh @@ -4,7 +4,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using SVR4 binmail interface: /bin/mail -r -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start \ '|preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/proc+df.sh +++ qmail-1.03/proc+df.sh @@ -4,6 +4,6 @@ # Using dot-forward to support sendmail-style ~/.forward files. # Using procmail to deliver messages to /var/spool/mail/$USER by default. -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|dot-forward .forward |preline procmail' splogger qmail --- qmail-1.03.orig/qmail-pop3d.c +++ qmail-1.03/qmail-pop3d.c @@ -66,14 +66,14 @@ void die_scan() { err("unable to scan $HOME/Maildir"); die(); } void err_syntax() { err("syntax error"); } -void err_unimpl() { err("unimplemented"); } +void err_unimpl(arg) char *arg; { err("unimplemented"); } void err_deleted() { err("already deleted"); } void err_nozero() { err("messages are counted from 1"); } void err_toobig() { err("not that many messages"); } void err_nosuch() { err("unable to open that message"); } void err_nounlink() { err("unable to unlink all deleted messages"); } -void okay() { puts("+OK \r\n"); flush(); } +void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } void printfn(fn) char *fn; { @@ -146,7 +146,7 @@ } } -void pop3_stat() +void pop3_stat(arg) char *arg; { int i; unsigned long total; @@ -161,15 +161,15 @@ flush(); } -void pop3_rset() +void pop3_rset(arg) char *arg; { int i; for (i = 0;i < numm;++i) m[i].flagdeleted = 0; last = 0; - okay(); + okay(0); } -void pop3_last() +void pop3_last(arg) char *arg; { puts("+OK "); put(strnum,fmt_uint(strnum,last)); @@ -177,7 +177,7 @@ flush(); } -void pop3_quit() +void pop3_quit(arg) char *arg; { int i; for (i = 0;i < numm;++i) @@ -192,7 +192,7 @@ if (!stralloc_0(&line)) die_nomem(); rename(m[i].fn,line.s); /* if it fails, bummer */ } - okay(); + okay(0); die(); } @@ -214,7 +214,7 @@ if (i == -1) return; m[i].flagdeleted = 1; if (i + 1 > last) last = i + 1; - okay(); + okay(0); } void list(i,flaguidl) @@ -238,7 +238,7 @@ list(i,flaguidl); } else { - okay(); + okay(0); for (i = 0;i < numm;++i) if (!m[i].flagdeleted) list(i,flaguidl); @@ -267,7 +267,11 @@ 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); @@ -299,7 +303,7 @@ getlist(); - okay(); + okay(0); commands(&ssin,pop3commands); die(); } --- qmail-1.03.orig/qmail-control.9 +++ qmail-1.03/qmail-control.9 @@ -20,7 +20,11 @@ Comments are allowed in +.IR badhelo , .IR badmailfrom , +.IR badmailfromnorelay , +.IR badmailto , +.IR badmailtonorelay , .IR locals , .IR percenthack , .IR qmqpservers , @@ -40,7 +44,11 @@ .ta 5c 10c control default used by +.I badhelo \fR(none) \fRqmail-smtpd .I badmailfrom \fR(none) \fRqmail-smtpd +.I badmailfromnorelay \fR(none) \fRqmail-smtpd +.I badmailto \fR(none) \fRqmail-smtpd +.I badmailtonorelay \fR(none) \fRqmail-smtpd .I bouncefrom \fRMAILER-DAEMON \fRqmail-send .I bouncehost \fIme \fRqmail-send .I concurrencylocal \fR10 \fRqmail-send --- qmail-1.03.orig/patches/usr-doc.patch +++ qmail-1.03/patches/usr-doc.patch @@ -0,0 +1,95 @@ +diff -u qmail-1.03/debian/README.debian qmail-1.03/debian/README.debian +--- qmail-1.03/debian/README.debian ++++ qmail-1.03/debian/README.debian +@@ -67,7 +67,8 @@ + file to prevent another process from accessing it at the same time, and + thus corrupting your mail file. + +-For reasons explained in /usr/doc/qmail/INSTALL.mbox, qmail does not do this. ++For reasons explained in /usr/share/doc/qmail/INSTALL.mbox, qmail does ++not do this. + + The default setup uses /usr/sbin/qmail-procmail to perform the final + delivery of mail with appropriate dot-locking to prevent loss of mail. +@@ -90,7 +91,7 @@ + open to mail loss. + + Personally, I'd recommend moving to Maildir/ format if you can. Read +-the files in /usr/doc/qmail to find out more. ++the files in /usr/share/doc/qmail to find out more. + + --- + +@@ -125,7 +126,7 @@ + 127.0.0.1:allow,RELAYCLIENT="" + + which permits clients on the local machine to use this as a mail relay. For +-more information, look at question 5.5 of the FAQ (/usr/doc/qmail/FAQ.gz) ++more information, look at question 5.5 of the FAQ (/usr/share/doc/qmail/FAQ.gz) + + --- + Postmaster mail: +diff -u qmail-1.03/debian/preinst qmail-1.03/debian/preinst +--- qmail-1.03/debian/preinst ++++ qmail-1.03/debian/preinst +@@ -244,24 +244,6 @@ + } + } elsif ($action eq 'upgrade') { + $old_version = shift; +- if ($old_version =~ /1.02/ ) { +- debug("You are upgrading from version 1.02 \n"); +- debug("Moving /var/qmail/users to /etc/qmail/users\n"); +- `mkdir -p /etc/qmail/users`; +- `tar -cSpf - -C /var/qmail/users . | tar -xvSpf - -C /etc/qmail/users && rm -rf /var/qmail/users`; +- debug("Moving /var/qmail/alias to /var/lib/qmail/alias\n"); +- `mkdir -p /var/lib/qmail/alias`; +- `touch /var/qmail/alias/tmp`; +- `tar -cSpf - -C /var/qmail/alias . | tar -xvSpf - -C /var/lib/qmail/alias && rm -rf /var/qmail/alias`; +- `rm -rf /var/lib/qmail/alias/tmp`; +- debug("Moving /var/qmail/doc to /usr/share/doc/qmail\n"); +- `mkdir -p /usr/share/doc/qmail`; +- `tar -cSpf - -C /var/qmail/doc . | tar -xvSpf - -C /usr/doc/qmail && rm -rf /var/qmail/doc`; +- debug("Moving /var/qmail/boot to /usr/doc/qmail/examples/boot\n"); +- `mkdir -p /usr/share/doc/qmail/examples`; +- `tar -cSpf - -C /var/qmail/boot . | tar -xvSpf - -C /usr/share/doc/qmail/examples && rm -rf /var/qmail/boot`; +- } +- + if ($old_version =~ /1.03/ ) { + debug("You are upgrading from version 1.03 \n"); + debug("Checking control files ... \n"); +diff -u qmail-1.03/debian/rules qmail-1.03/debian/rules +--- qmail-1.03/debian/rules ++++ qmail-1.03/debian/rules +@@ -42,7 +42,6 @@ + $(INSTALL) -d debian/tmp/DEBIAN \ + debian/tmp/etc/init.d \ + debian/tmp/usr/share/doc/qmail \ +- debian/tmp/usr/doc \ + debian/tmp/usr/share/doc/qmail/examples \ + debian/tmp/var/qmail \ + debian/tmp/etc/qmail \ +@@ -73,7 +72,6 @@ + (cd debian/tmp/var/qmail && ln -s /usr/share/doc/qmail/examples/boot boot) + (cd debian/tmp/var/qmail && ln -s /var/lib/qmail/alias alias) + (cd debian/tmp/var/qmail && ln -s /etc/qmail/users users) +- (cd debian/tmp/usr/doc && ln -s /usr/share/doc/qmail qmail) + mv debian/tmp/var/qmail/man debian/tmp/usr/man && \ + rm -r debian/tmp/usr/man/cat? + # Move /var/qmail/bin programs to either /usr/bin or /usr/sbin +diff -u qmail-1.03/debian/src.postinst qmail-1.03/debian/src.postinst +--- qmail-1.03/debian/src.postinst ++++ qmail-1.03/debian/src.postinst +@@ -3,12 +3,6 @@ + # Source the debconf library + . /usr/share/debconf/confmodule + +-if [ "$1" = "configure" ]; then +- if [ -d /usr/doc -a ! -e /usr/doc/qmail-src -a -d /usr/share/doc/qmail-src ]; then +- ln -sf ../share/doc/qmail-src /usr/doc/qmail-src +- fi +-fi +- + # Previous informational message removed in favor of debconf + + # Code snippet courtesy of Wichert Akkerman + --- qmail-1.03.orig/patches/qmail-smtpd-usint.patch +++ qmail-1.03/patches/qmail-smtpd-usint.patch @@ -0,0 +1,11 @@ +--- qmail-smtpd.c 1998-06-15 06:53:16.000000000 -0400 ++++ qmail-smtpd-fixed.c 2004-01-16 11:55:43.000000000 -0500 +@@ -296,7 +296,7 @@ + char ch; + int state; + int flaginheader; +- int pos; /* number of bytes since most recent \n, if fih */ ++ unsigned int pos; /* number of bytes since most recent \n, if fih */ + int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ + int flagmaybey; /* 1 if this line might match \r\n, if fih */ + int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ --- qmail-1.03.orig/patches/qmail-date-localtime.patch +++ qmail-1.03/patches/qmail-date-localtime.patch @@ -0,0 +1,75 @@ +This patch causes the various qmail programs to generate date stamps in +the local timezone. I find GMT too annoying to convert from/to. I make +no warranties that it will work in your timezone, however it works for me. + +Works with qmail 1.01 to 1.03. + +To apply this patch, cd into the qmail source directory and type... + patch -s -p1 < patch-to-patch-file + +--- qmail-1.03.orig/date822fmt.c Tue Apr 15 15:05:23 1997 ++++ qmail-1.03/date822fmt.c Fri Apr 18 00:39:41 1997 +@@ -1,3 +1,4 @@ ++#include + #include "datetime.h" + #include "fmt.h" + #include "date822fmt.h" +@@ -12,18 +13,51 @@ + { + unsigned int i; + unsigned int len; ++ time_t now; ++ datetime_sec utc; ++ datetime_sec local; ++ struct tm *tm; ++ struct datetime new_dt; ++ int minutes; ++ ++ utc = datetime_untai(dt); ++ now = (time_t)utc; ++ tm = localtime(&now); ++ new_dt.year = tm->tm_year; ++ new_dt.mon = tm->tm_mon; ++ new_dt.mday = tm->tm_mday; ++ new_dt.hour = tm->tm_hour; ++ new_dt.min = tm->tm_min; ++ new_dt.sec = tm->tm_sec; ++ local = datetime_untai(&new_dt); ++ + len = 0; +- i = fmt_uint(s,dt->mday); len += i; if (s) s += i; ++ i = fmt_uint(s,new_dt.mday); len += i; if (s) s += i; + i = fmt_str(s," "); len += i; if (s) s += i; +- i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i; ++ i = fmt_str(s,montab[new_dt.mon]); len += i; if (s) s += i; + i = fmt_str(s," "); len += i; if (s) s += i; +- i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i; ++ i = fmt_uint(s,new_dt.year + 1900); len += i; if (s) s += i; + i = fmt_str(s," "); len += i; if (s) s += i; +- i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i; ++ i = fmt_uint0(s,new_dt.hour,2); len += i; if (s) s += i; + i = fmt_str(s,":"); len += i; if (s) s += i; +- i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i; ++ i = fmt_uint0(s,new_dt.min,2); len += i; if (s) s += i; + i = fmt_str(s,":"); len += i; if (s) s += i; +- i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i; +- i = fmt_str(s," -0000\n"); len += i; if (s) s += i; ++ i = fmt_uint0(s,new_dt.sec,2); len += i; if (s) s += i; ++ ++ if (local < utc) { ++ minutes = (utc - local + 30) / 60; ++ i = fmt_str(s," -"); len += i; if (s) s += i; ++ i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i; ++ i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i; ++ } ++ else { ++ minutes = (local - utc + 30) / 60; ++ i = fmt_str(s," +"); len += i; if (s) s += i; ++ i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i; ++ i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i; ++ } ++ ++ i = fmt_str(s,"\n"); len += i; if (s) s += i; ++ + return len; + } --- qmail-1.03.orig/patches/qmail-1.03.qmail_local.patch +++ qmail-1.03/patches/qmail-1.03.qmail_local.patch @@ -0,0 +1,12 @@ +diff -u qmail-1.03.old/qmail-local.c qmail-1.03/qmail-local.c +--- qmail-1.03.old/qmail-local.c 1998-06-15 05:52:55.000000000 -0500 ++++ qmail-1.03/qmail-local.c 2003-01-09 14:22:48.000000000 -0600 +@@ -645,7 +645,7 @@ + { + cmds.s[j] = 0; + k = j; +- while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')) ++ while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))) + cmds.s[--k] = 0; + switch(cmds.s[i]) + { --- qmail-1.03.orig/patches/pop3-supplementarygroups.patch +++ qmail-1.03/patches/pop3-supplementarygroups.patch @@ -0,0 +1,65 @@ +diff -ru qmail-1.03.orig/contrib/checkpassword-0.76/Makefile qmail-1.03/contrib/checkpassword-0.76/Makefile +--- qmail-1.03.orig/contrib/checkpassword-0.76/Makefile Thu Oct 14 16:51:32 1999 ++++ qmail-1.03/contrib/checkpassword-0.76/Makefile Thu Oct 14 17:09:27 1999 +@@ -6,7 +6,7 @@ + SHADOWLIBS=-lcrypt + SHADOWOPTS=-DPW_SHADOW + +-CC=cc $(SHADOWOPTS) ++CC=cc $(SHADOWOPTS) -DALL_GROUPS + LD=cc -s + + all: checkpassword +Only in qmail-1.03/contrib/checkpassword-0.76: checkpassword +diff -ru qmail-1.03.orig/contrib/checkpassword-0.76/checkpassword.c qmail-1.03/contrib/checkpassword-0.76/checkpassword.c +--- qmail-1.03.orig/contrib/checkpassword-0.76/checkpassword.c Thu Oct 14 16:51:32 1999 ++++ qmail-1.03/contrib/checkpassword-0.76/checkpassword.c Thu Oct 14 17:50:26 1999 +@@ -1,4 +1,5 @@ + #include ++#include + #ifdef PW_SHADOW + #include + #endif +@@ -36,6 +37,12 @@ + #ifdef AIX + struct userpw *spw; + #endif ++#ifdef ALL_GROUPS ++#define MAX_GROUPS 32 ++ int groups[MAX_GROUPS]; ++ int num_groups = 0; ++ struct group *gr; ++#endif + char *login; + char *password; + char *stored; +@@ -86,6 +93,27 @@ + #endif + + encrypted = crypt(password,stored); ++ ++#ifdef ALL_GROUPS ++ groups[0] = pw->pw_gid; ++ num_groups = 1; ++ setgrent(); ++ while( (gr = getgrent()) ) ++ { ++ for(i = 0; gr->gr_mem[i]; i++) ++ { ++ if(!strcmp(gr->gr_mem[i], login)) ++ { ++ if(gr->gr_gid != groups[0] && num_groups < MAX_GROUPS) ++ { ++ groups[num_groups] = gr->gr_gid; ++ num_groups++; ++ } ++ } ++ } ++ } ++ if (setgroups(num_groups, groups) == -1) _exit(1); ++#endif + + for (i = 0;i < sizeof(up);++i) up[i] = 0; + + + --- qmail-1.03.orig/patches/qmailqueue-patch +++ qmail-1.03/patches/qmailqueue-patch @@ -0,0 +1,49 @@ +diff -u qmail-1.03-orig/Makefile qmail-1.03/Makefile +--- qmail-1.03-orig/Makefile Mon Jun 15 04:53:16 1998 ++++ qmail-1.03/Makefile Tue Jan 19 10:52:24 1999 +@@ -1483,12 +1483,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 +diff -u qmail-1.03-orig/qmail.c qmail-1.03/qmail.c +--- qmail-1.03-orig/qmail.c Mon Jun 15 04:53:16 1998 ++++ qmail-1.03/qmail.c Tue Jan 19 09:57:36 1999 +@@ -6,14 +6,25 @@ + #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; + { + 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; } + --- qmail-1.03.orig/patches/qmail-smtpd-bmtpatch.patch +++ qmail-1.03/patches/qmail-smtpd-bmtpatch.patch @@ -0,0 +1,80 @@ +*** /usr/src/qmail-1.03/qmail-smtpd.c.bak Mon Jun 15 05:53:16 1998 +--- qmail-smtpd.c Mon Jan 4 10:50:12 1999 +*************** void die_ipme() { out("421 unable to fig +*** 50,55 **** +--- 50,56 ---- + void straynewline() { 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_bmt() { out("553 sorry, your envelope sender is in my badmailto 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() { out("502 unimplemented (#5.5.1)\r\n"); } + void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } +*************** stralloc liphost = {0}; +*** 96,101 **** +--- 97,105 ---- + int bmfok = 0; + stralloc bmf = {0}; + struct constmap mapbmf; ++ int bmtok = 0; ++ stralloc bmt = {0}; ++ struct constmap mapbmt; + + void setup() + { +*************** void setup() +*** 117,122 **** +--- 121,131 ---- + if (bmfok) + if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + ++ bmtok = control_readfile(&bmt,"control/badmailto",0); ++ if (bmtok == -1) die_control(); ++ if (bmtok) ++ if (!constmap_init(&mapbmt,bmt.s,bmt.len,0)) die_nomem(); ++ + if (control_readint(&databytes,"control/databytes") == -1) die_control(); + x = env_get("DATABYTES"); + if (x) { scan_ulong(x,&u); databytes = u; } +*************** int bmfcheck() +*** 208,213 **** +--- 217,233 ---- + return 0; + } + ++ int bmtcheck() ++ { ++ int j; ++ if (!bmtok) return 0; ++ if (constmap(&mapbmt,addr.s,addr.len - 1)) return 1; ++ j = byte_rchr(addr.s,addr.len,'@'); ++ if (j < addr.len) ++ if (constmap(&mapbmt,addr.s + j,addr.len - j - 1)) return 1; ++ return 0; ++ } ++ + int addrallowed() + { + int r; +*************** int addrallowed() +*** 219,224 **** +--- 239,245 ---- + + int seenmail = 0; + int flagbarf; /* defined if seenmail */ ++ int bmtbarf; /* defined if seenmail */ + stralloc mailfrom = {0}; + stralloc rcptto = {0}; + +*************** void smtp_mail(arg) char *arg; +*** 250,256 **** +--- 271,279 ---- + void smtp_rcpt(arg) char *arg; { + if (!seenmail) { err_wantmail(); return; } + if (!addrparse(arg)) { err_syntax(); return; } ++ bmtbarf = bmtcheck(); + if (flagbarf) { err_bmf(); return; } ++ if (bmtbarf) { err_bmt(); return; } + if (relayclient) { + --addr.len; + if (!stralloc_cats(&addr,relayclient)) die_nomem(); --- qmail-1.03.orig/patches/qmail-1.03.errno.patch +++ qmail-1.03/patches/qmail-1.03.errno.patch @@ -0,0 +1,47 @@ +diff -u qmail-1.03.old/cdb_seek.c qmail-1.03/cdb_seek.c +--- qmail-1.03.old/cdb_seek.c 1998-06-15 05:52:55.000000000 -0500 ++++ qmail-1.03/cdb_seek.c 2003-01-08 15:55:53.000000000 -0600 +@@ -1,6 +1,5 @@ + #include + #include +-extern int errno; + #include "cdb.h" + + #ifndef SEEK_SET +diff -u qmail-1.03.old/dns.c qmail-1.03/dns.c +--- qmail-1.03.old/dns.c 1998-06-15 05:52:55.000000000 -0500 ++++ qmail-1.03/dns.c 2003-01-08 16:00:32.000000000 -0600 +@@ -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" +diff -u qmail-1.03.old/error.3 qmail-1.03/error.3 +--- qmail-1.03.old/error.3 1998-06-15 05:52:55.000000000 -0500 ++++ qmail-1.03/error.3 2003-01-08 15:58:13.000000000 -0600 +@@ -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 -u qmail-1.03.old/error.h qmail-1.03/error.h +--- qmail-1.03.old/error.h 1998-06-15 05:52:55.000000000 -0500 ++++ qmail-1.03/error.h 2003-01-08 15:59:13.000000000 -0600 +@@ -1,7 +1,7 @@ + #ifndef ERROR_H + #define ERROR_H + +-extern int errno; ++#include + + extern int error_intr; + extern int error_nomem; --- qmail-1.03.orig/patches/qregex-20040725.patch +++ qmail-1.03/patches/qregex-20040725.patch @@ -0,0 +1,680 @@ +qregex-20040725.patch + +Changelog +2004 07 25 +Added the badmailfromnorelay and badmailtonorelay control files. + +Surrounded addresses in log messages with '<' and '>' to make picking them +out of log files with scripts easier. + +2004 06 01 +Updated README.qregex. + +2004 03 17 +Added the badhelo control file. This allows qregex to do pattern matching +againt the HELO host name presented by the smtp client. + +Plugged a memory leak. The two stralloc structures in the bmcheck function in +qmail-smtpd have been made static. This prevents the structures from +allocating new memory every time the bmcheck function is called. + +2004 02 07 +Qregex now ignores empty envelope senders ('mail from' command). Empty envelope +senders will not be compared to any regular expressions in the badmailfrom +control file and will always be accepted by qregex. Prior to this version it +was possible to write regular expressions that would reject mail with empty +envelope senders. + +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/hier.c ./netqmail-1.05/netqmail-1.05/hier.c +--- ./netqmail-1.05.orig/netqmail-1.05/hier.c 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/hier.c 2004-07-25 09:25:06.000000000 -0400 +@@ -76,6 +76,7 @@ + c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/install-big.c ./netqmail-1.05/netqmail-1.05/install-big.c +--- ./netqmail-1.05.orig/netqmail-1.05/install-big.c 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/install-big.c 2004-07-25 09:25:06.000000000 -0400 +@@ -76,6 +76,7 @@ + c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/Makefile ./netqmail-1.05/netqmail-1.05/Makefile +--- ./netqmail-1.05.orig/netqmail-1.05/Makefile 2004-06-04 21:51:58.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/Makefile 2004-07-25 09:25:06.000000000 -0400 +@@ -1532,16 +1532,16 @@ + ./compile qmail-showctl.c + + qmail-smtpd: \ +-load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ ++load qmail-smtpd.o rcpthosts.o qregex.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 alloc.a strerr.a substdio.a error.a str.a \ + fs.a auto_qmail.o socket.lib +- ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ ++ ./load qmail-smtpd qregex.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 `cat \ ++ alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ + socket.lib` + + qmail-smtpd.0: \ +@@ -1681,6 +1681,10 @@ + constmap.h stralloc.h gen_alloc.h rcpthosts.h + ./compile rcpthosts.c + ++qregex.o: \ ++compile qregex.c qregex.h ++ ./compile qregex.c ++ + readsubdir.o: \ + compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \ + auto_split.h +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-control.9 ./netqmail-1.05/netqmail-1.05/qmail-control.9 +--- ./netqmail-1.05.orig/netqmail-1.05/qmail-control.9 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/qmail-control.9 2004-07-25 09:25:06.000000000 -0400 +@@ -20,7 +20,11 @@ + + Comments are allowed + in ++.IR badhelo , + .IR badmailfrom , ++.IR badmailfromnorelay , ++.IR badmailto , ++.IR badmailtonorelay , + .IR locals , + .IR percenthack , + .IR qmqpservers , +@@ -40,7 +44,11 @@ + .ta 5c 10c + control default used by + ++.I badhelo \fR(none) \fRqmail-smtpd + .I badmailfrom \fR(none) \fRqmail-smtpd ++.I badmailfromnorelay \fR(none) \fRqmail-smtpd ++.I badmailto \fR(none) \fRqmail-smtpd ++.I badmailtonorelay \fR(none) \fRqmail-smtpd + .I bouncefrom \fRMAILER-DAEMON \fRqmail-send + .I bouncehost \fIme \fRqmail-send + .I concurrencylocal \fR10 \fRqmail-send +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-showctl.c ./netqmail-1.05/netqmail-1.05/qmail-showctl.c +--- ./netqmail-1.05.orig/netqmail-1.05/qmail-showctl.c 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/qmail-showctl.c 2004-07-25 09:25:06.000000000 -0400 +@@ -214,7 +214,11 @@ + _exit(111); + } + +- do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM."); ++ do_lst("badhelo","Any HELO host name is allowed.",""," HELO host name denied if it matches this pattern."); ++ do_lst("badmailfrom","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern."); ++ do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set."); ++ do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern."); ++ do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set."); + do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); + do_str("bouncehost",1,"bouncehost","Bounce host name is "); + do_int("concurrencylocal","10","Local concurrency is ",""); +@@ -267,7 +271,11 @@ + if (str_equal(d->d_name,"..")) continue; + if (str_equal(d->d_name,"bouncefrom")) continue; + if (str_equal(d->d_name,"bouncehost")) continue; ++ if (str_equal(d->d_name,"badhelo")) continue; + if (str_equal(d->d_name,"badmailfrom")) continue; ++ if (str_equal(d->d_name,"badmailfromnorelay")) continue; ++ if (str_equal(d->d_name,"badmailto")) continue; ++ if (str_equal(d->d_name,"badmailtonorelay")) continue; + if (str_equal(d->d_name,"bouncefrom")) continue; + if (str_equal(d->d_name,"bouncehost")) continue; + if (str_equal(d->d_name,"concurrencylocal")) continue; +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-smtpd.8 ./netqmail-1.05/netqmail-1.05/qmail-smtpd.8 +--- ./netqmail-1.05.orig/netqmail-1.05/qmail-smtpd.8 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/qmail-smtpd.8 2004-07-25 09:25:06.000000000 -0400 +@@ -37,11 +37,26 @@ + even though such messages violate the SMTP protocol. + .SH "CONTROL FILES" + .TP 5 ++.I badhelo ++Unacceptable HELO/EHLO host names. ++.B qmail-smtpd ++will reject every recipient address for a message if ++the host name is listed in, ++or matches a POSIX regular expression pattern listed in, ++.IR badhelo . ++If the ++.B NOBADHELO ++environment variable is set, then the contents of ++.IR badhelo ++will be ignored. ++For more information, please have a look at doc/README.qregex. ++.TP 5 + .I badmailfrom + Unacceptable envelope sender addresses. + .B qmail-smtpd + will reject every recipient address for a message +-if the envelope sender address is listed in ++if the envelope sender address is listed in, or matches a POSIX regular expression ++pattern listed in, + .IR badmailfrom . + A line in + .I badmailfrom +@@ -49,6 +64,32 @@ + .BR @\fIhost , + meaning every address at + .IR host . ++For more information, please have a look at doc/README.qregex. ++.TP 5 ++.I badmailfromnorelay ++Functions the same as the ++.IR badmailfrom ++control file but is read only if the ++.B RELAYCLIENT ++environment variable is not set. ++For more information, please have a look at doc/README.qregex. ++.TP 5 ++.I badmailto ++Unacceptable envelope recipient addresses. ++.B qmail-smtpd ++will reject every recipient address for a message if the recipient address ++is listed in, ++or matches a POSIX regular expression pattern listed in, ++.IR badmailto . ++For more information, please have a look at doc/README.qregex. ++.TP 5 ++.I badmailtonorelay ++Functions the same as the ++.IR badmailto ++control file but is read only if the ++.B RELAYCLIENT ++environment variable is not set. ++For more information, please have a look at doc/README.qregex. + .TP 5 + .I databytes + Maximum number of bytes allowed in a message, +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-smtpd.c ./netqmail-1.05/netqmail-1.05/qmail-smtpd.c +--- ./netqmail-1.05.orig/netqmail-1.05/qmail-smtpd.c 2004-06-04 21:51:58.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/qmail-smtpd.c 2004-07-25 22:25:59.000000000 -0400 +@@ -23,6 +23,15 @@ + #include "timeoutread.h" + #include "timeoutwrite.h" + #include "commands.h" ++#include "qregex.h" ++#include "strerr.h" ++ ++#define BMCHECK_BMF 0 ++#define BMCHECK_BMFNR 1 ++#define BMCHECK_BMT 2 ++#define BMCHECK_BMTNR 3 ++#define BMCHECK_BHELO 4 ++ + + #define MAXHOPS 100 + unsigned int databytes = 0; +@@ -49,7 +58,9 @@ + 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 err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } ++void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); } ++void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); } ++void err_bhelo() { out("553 sorry, your HELO host name has been denied (#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"); } +@@ -93,9 +104,21 @@ + + int liphostok = 0; + stralloc liphost = {0}; ++ + int bmfok = 0; + stralloc bmf = {0}; +-struct constmap mapbmf; ++ ++int bmfnrok = 0; ++stralloc bmfnr = {0}; ++ ++int bmtok = 0; ++stralloc bmt = {0}; ++ ++int bmtnrok = 0; ++stralloc bmtnr = {0}; ++ ++int bhelook = 0; ++stralloc bhelo = {0}; + + void setup() + { +@@ -114,8 +137,19 @@ + + bmfok = control_readfile(&bmf,"control/badmailfrom",0); + if (bmfok == -1) die_control(); +- if (bmfok) +- if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); ++ ++ bmfnrok = control_readfile(&bmfnr,"control/badmailfromnorelay",0); ++ if (bmfnrok == -1) die_control(); ++ ++ bmtok = control_readfile(&bmt,"control/badmailto",0); ++ if (bmtok == -1) die_control(); ++ ++ bmtnrok = control_readfile(&bmtnr,"control/badmailtonorelay",0); ++ if (bmtnrok == -1) die_control(); ++ ++ bhelook = control_readfile(&bhelo, "control/badhelo",0); ++ if (bhelook == -1) die_control(); ++ if (env_get("NOBADHELO")) bhelook = 0; + + if (control_readint(&databytes,"control/databytes") == -1) die_control(); + x = env_get("DATABYTES"); +@@ -197,14 +231,48 @@ + return 1; + } + +-int bmfcheck() ++int bmcheck(which) int which; + { +- int j; +- if (!bmfok) return 0; +- if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1; +- j = byte_rchr(addr.s,addr.len,'@'); +- if (j < addr.len) +- if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1; ++ int i = 0; ++ int j = 0; ++ int x = 0; ++ int negate = 0; ++ static stralloc bmb = {0}; ++ static stralloc curregex = {0}; ++ ++ if (which == BMCHECK_BMF) { ++ if (!stralloc_copy(&bmb,&bmf)) die_nomem(); ++ } else if (which == BMCHECK_BMFNR) { ++ if (!stralloc_copy(&bmb,&bmfnr)) die_nomem(); ++ } else if (which == BMCHECK_BMT) { ++ if (!stralloc_copy(&bmb,&bmt)) die_nomem(); ++ } else if (which == BMCHECK_BMTNR) { ++ if (!stralloc_copy(&bmb,&bmtnr)) die_nomem(); ++ } else if (which == BMCHECK_BHELO) { ++ if (!stralloc_copy(&bmb,&bhelo)) die_nomem(); ++ } else { ++ die_control(); ++ } ++ ++ while (j < bmb.len) { ++ i = j; ++ while ((bmb.s[i] != '\0') && (i < bmb.len)) i++; ++ if (bmb.s[j] == '!') { ++ negate = 1; ++ j++; ++ } ++ if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem(); ++ if (!stralloc_0(&curregex)) die_nomem(); ++ if (which == BMCHECK_BHELO) { ++ x = matchregex(helohost.s, curregex.s); ++ } else { ++ x = matchregex(addr.s, curregex.s); ++ } ++ if ((negate) && (x == 0)) return 1; ++ if (!(negate) && (x > 0)) return 1; ++ j = i + 1; ++ negate = 0; ++ } + return 0; + } + +@@ -218,7 +286,9 @@ + + + int seenmail = 0; +-int flagbarf; /* defined if seenmail */ ++int flagbarfbmf; /* defined if seenmail */ ++int flagbarfbmt; ++int flagbarfbhelo; + stralloc mailfrom = {0}; + stralloc rcptto = {0}; + +@@ -226,11 +296,13 @@ + { + smtp_greet("250 "); out("\r\n"); + seenmail = 0; dohelo(arg); ++ if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO); + } + void smtp_ehlo(arg) char *arg; + { + smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); + seenmail = 0; dohelo(arg); ++ if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO); + } + void smtp_rset(arg) char *arg; + { +@@ -240,7 +312,11 @@ + void smtp_mail(arg) char *arg; + { + if (!addrparse(arg)) { err_syntax(); return; } +- flagbarf = bmfcheck(); ++ flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */ ++ if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF); ++ if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) { ++ flagbarfbmf = bmcheck(BMCHECK_BMFNR); ++ } + seenmail = 1; + if (!stralloc_copys(&rcptto,"")) die_nomem(); + if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); +@@ -250,7 +326,25 @@ + void smtp_rcpt(arg) char *arg; { + if (!seenmail) { err_wantmail(); return; } + if (!addrparse(arg)) { err_syntax(); return; } +- if (flagbarf) { err_bmf(); return; } ++ if (flagbarfbhelo) { ++ strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0); ++ err_bhelo(); ++ return; ++ } ++ if (flagbarfbmf) { ++ strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0); ++ err_bmf(); ++ return; ++ } ++ if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT); ++ if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) { ++ flagbarfbmt = bmcheck(BMCHECK_BMTNR); ++ } ++ if (flagbarfbmt) { ++ strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0); ++ err_bmt(); ++ return; ++ } + if (relayclient) { + --addr.len; + if (!stralloc_cats(&addr,relayclient)) die_nomem(); +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qregex.c ./netqmail-1.05/netqmail-1.05/qregex.c +--- ./netqmail-1.05.orig/netqmail-1.05/qregex.c 1969-12-31 19:00:00.000000000 -0500 ++++ ./netqmail-1.05/netqmail-1.05/qregex.c 2004-07-25 09:25:06.000000000 -0400 +@@ -0,0 +1,57 @@ ++/* ++ * qregex (v2) ++ * $Id: qregex.c,v 2.1 2001/12/28 07:05:21 evan Exp $ ++ * ++ * Author : Evan Borgstrom (evan at unixpimps dot org) ++ * Created : 2001/12/14 23:08:16 ++ * Modified: $Date: 2001/12/28 07:05:21 $ ++ * Revision: $Revision: 2.1 $ ++ * ++ * Do POSIX regex matching on addresses for anti-relay / spam control. ++ * It logs to the maillog ++ * See the qregex-readme file included with this tarball. ++ * If you didn't get this file in a tarball please see the following URL: ++ * http://www.unixpimps.org/software/qregex ++ * ++ * qregex.c is released under a BSD style copyright. ++ * See http://www.unixpimps.org/software/qregex/copyright.html ++ * ++ * Note: this revision follows the coding guidelines set forth by the rest of ++ * the qmail code and that described at the following URL. ++ * http://cr.yp.to/qmail/guarantee.html ++ * ++ */ ++ ++#include ++#include ++#include "qregex.h" ++ ++#define REGCOMP(X,Y) regcomp(&X, Y, REG_EXTENDED|REG_ICASE) ++#define REGEXEC(X,Y) regexec(&X, Y, (size_t)0, (regmatch_t *)0, (int)0) ++ ++int matchregex(char *text, char *regex) { ++ regex_t qreg; ++ int retval = 0; ++ ++ ++ /* build the regex */ ++ if ((retval = REGCOMP(qreg, regex)) != 0) { ++ regfree(&qreg); ++ return(-retval); ++ } ++ ++ /* execute the regex */ ++ if ((retval = REGEXEC(qreg, text)) != 0) { ++ /* did we just not match anything? */ ++ if (retval == REG_NOMATCH) { ++ regfree(&qreg); ++ return(0); ++ } ++ regfree(&qreg); ++ return(-retval); ++ } ++ ++ /* signal the match */ ++ regfree(&qreg); ++ return(1); ++} +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qregex.h ./netqmail-1.05/netqmail-1.05/qregex.h +--- ./netqmail-1.05.orig/netqmail-1.05/qregex.h 1969-12-31 19:00:00.000000000 -0500 ++++ ./netqmail-1.05/netqmail-1.05/qregex.h 2004-07-25 09:25:06.000000000 -0400 +@@ -0,0 +1,5 @@ ++/* simple header file for the matchregex prototype */ ++#ifndef _QREGEX_H_ ++#define _QREGEX_H_ ++int matchregex(char *text, char *regex); ++#endif +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/README.qregex ./netqmail-1.05/netqmail-1.05/README.qregex +--- ./netqmail-1.05.orig/netqmail-1.05/README.qregex 1969-12-31 19:00:00.000000000 -0500 ++++ ./netqmail-1.05/netqmail-1.05/README.qregex 2004-07-25 09:25:06.000000000 -0400 +@@ -0,0 +1,196 @@ ++QREGEX (v2) 20040725 - README July 25, 2004 ++A Regular Expression matching patch for qmail 1.03 and netqmail ++ ++ ++OVERVIEW: ++ ++qregex adds the ability to match address evelopes via Regular Expressions (REs) ++in the qmail-smtpd process. It has the abiltiy to match `helo/ehlo` (host name), ++`mail from` (envelope sender), and `rcpt to` (envelope recipient) commands. ++It follows all the base rules that are set out with qmail (ie using control ++files) so it makes for easy integretion into an existing setup (see the ++install instructions for more info). The v2 is specified because qregex was ++re-written to better conform to the security guarantee set forth by the author ++of qmail. The original version used stdio.h and stdlib.h for reading the ++control files whereas v2 now uses all stralloc functions which are much more ++regulated against buffer overruns and the like. ++See: http://cr.yp.to/qmail/guarantee.html ++ ++ ++FEATURES: ++ ++Features of qregex include: ++ ++1. Performs pattern matching on envelope senders and envelope ++ recipients against REs in the badmailfrom and badmailto control ++ files. Two additional control files, badmailfromnorelay and ++ badmailtonorelay, are used for pattern matching when the ++ RELAYCLIENT environment variable is not set. ++ ++2. Performs pattern matching on the helo/ehlo host name. Setting the ++ NOBADHELO environment variable prevents the host name from being ++ compared to the patterns in the badhelo control file. ++ ++3. Matches to patterns are logged ++ ++4. Matching is case insensitive. ++ ++5. qregex ignores empty envelope senders. An empty envelope sender is not ++ compared to the patterns in the badmailfrom and badmailfromnorelay ++ control files and is always accepted. ++ ++ ++PLATFORMS: ++ ++qregex has been built and tested on the following platforms. I'm sure it won't ++have any problems on any platform that qmail will run on (providing they have ++a regex interface) but if you run into problems let me know. ++ ++ - OpenBSD 3.x ++ - FreeBSD 4.x ++ - Mandrake Linux 9.x ++ - SuSE Linux 8.x ++ ++ ++ ++INSTALLATION INSTRUCTIONS: ++ ++Installation is very simple, there is only one requirement. You need to use the ++GNU version of the patch utility (http://www.gnu.org/software/patch/patch.html). ++(For Solaris 8 users it is installed as 'gpatch') ++ ++- If this is a new setup. ++Unpack the qmail archive, cd into the qmail-1.03 directory and run ++"patch < /path/to/qregex-.patch". Follow the instructions as per the ++included qmail INSTALL file. Once you are done come back to this file and read ++the section on the control files. ++ ++If you are using netqmail, then unpack the netqmail archive. Run the collate.sh ++script and cd into the resulting netqmail- directory. From there, run ++"patch < /path/to/qregex-.patch". Complete the netqmail installation ++normally. Once you are done, come back to this file and read the section on the ++control files. ++ ++- If this is an existing setup. ++FIRST: create your control files (see below). ++cd into your existing qmail or netqmail source directory. Run ++"patch < /path/to/qregex-.patch" then "make qmail-smtpd". Now run ++./qmail-smtpd and test your new rules to make sure they work as expected. ++ ++Install the new binary by cd'ing to /var/qmail/bin and as root (in one command) ++copy the existing binary to 'qmail-smtpd.old' and copy the new binary from the ++source directory to 'qmail-smtpd'. ++(ex. cp qmail-smtpd qmail-smtpd.old && cp ~/qmail-1.03/qmail-smtpd qmail-smtpd) ++ ++You can also optionally just run "make setup check" as it will install the ++updated documentation and man pages provided with this patch. Stopping qmail ++before doing the "make setup check" is always a good idea. ++ ++ ++LOGGING: ++ ++qregex will log matches to the patterns in the various control files. Log ++messages will take these three forms depending on which control file was ++matched: ++ ++badhelo ++qmail-smtpd: badhelo: at ++ ++badmailfrom and badmailfromnorelay ++qmail-smtpd: badmailfrom: at ++ ++badmailto and badmailtonorelay ++qmail-smtpd: badmailto: at ++ ++ ++CONTROL FILES: ++ ++qregex provides you with five control files. None of these control files ++is mandatory and you can use them in any combination you choose in your setup. ++ ++The "control/badmailfrom" and "control/badmailto" files contain your REs for ++matching against the 'mail from' (envelope sender) and 'rcpt to' (envelope ++recipient) smtp commands respectively. ++The "control/badmailfromnorelay" and "control/badmailtonorelay" match against ++the same commands but are read only when the RELAYCLIENT environment variable ++is not set. ++The "control/badhelo" file matches against the 'helo/ehlo' smtp command. ++ ++If you prefer you can symlink the badmailfrom and badmailto control files ++(ln -s badmailfrom badmailto) and maintain fewer sets of rules. Beware ++this might cause problems in certain setups. ++ ++ Here's an example "badhelo" file. ++ ----------------------------------- ++ # block host strings with no dot (not a FQDN) ++ !\. ++ ----------------------------------- ++ ++ An example "badmailfrom" file. ++ ----------------------------------- ++ # this will drop everything containing the string ++ # bad.domain.com or Bad.Domain.Com or BAD.domain.COM ++ bad\.domain\.com ++ # force users to fully qualify themselves ++ # (i.e. deny "user", accept "user@domain") ++ !@ ++ ----------------------------------- ++ ++ And "badmailto" (a little more interesting) ++ ----------------------------------- ++ # must not contain invalid characters, brakets or multiple @'s ++ [!%#:*^(){}] ++ @.*@ ++ ----------------------------------- ++ ++You can use the non-RE character '!' to start an RE as a signal to qregex to ++negate the action. As used above in the badmailfrom file, by negating the '@' ++symbol qregex will signal qmail-smtpd to deny the 'mail from' command whenever ++the address doesn't contain an @ symbol. When used inside a bracket expression, ++the '!' character looses this special meaning. This is shown in the badmailto ++example. ++ ++The norelay control files follow the same rules as the other control files but ++are intended to address two specific scenarios. ++The badmailfromnorelay file can be used to block mail trying to spoof a domain ++hosted on your mail server. It prevents a mail client that is not allowed to ++relay email through your server from using one of your hosted domains as its ++envelope sender. ++The badmailtonorelay file can be used to create email addresses that cannot ++receive mail from any source not allowed to relay email through your server. ++This is handy for creating email addresses for use only within your own ++domain(s) that can't receive spam from the world at large. ++ ++ ++INTERNALS: ++ ++qregex (or regexmatch as the function is called) will be called during the ++`helo/ehlo`, `rcpt to` and `mail from` handling routines in "qmail-smtpd.c". ++When called, it will read the proper control file then one by one compile and ++execute the regex on the string passed into qmail-smtpd. If the regex matches ++it returns TRUE (1) and the qmail-smtpd process will deny the user the ability ++to continue. If you change anything and think it betters this patch please ++send me a new diff file so I can take a peek. ++ ++ ++CONTACT: ++qregex is maintained by: ++ Andrew St. Jean ++ andrew@arda.homeunix.net ++ www.arda.homeunix.net/store/qmail/ ++ ++Contributers to qregex: ++ Jeremy Kitchen ++ kitchen at scriptkitchen dot com ++ http://www.scriptkitchen.com/qmail ++ ++ Alex Pleiner ++ alex@zeitform.de ++ zeitform Internet Dienste ++ http://www.zeitform.de/ ++ ++ Thanos Massias ++ ++Original qregex patch written by: ++ Evan Borgstrom ++ evan at unixpimps dot org +diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/TARGETS ./netqmail-1.05/netqmail-1.05/TARGETS +--- ./netqmail-1.05.orig/netqmail-1.05/TARGETS 1998-06-15 06:53:16.000000000 -0400 ++++ ./netqmail-1.05/netqmail-1.05/TARGETS 2004-07-25 09:25:06.000000000 -0400 +@@ -252,6 +252,7 @@ + qmail-qmtpd + qmail-smtpd.o + qmail-smtpd ++qregex.o + sendmail.o + sendmail + tcp-env.o --- qmail-1.03.orig/patches/netscape-progress.patch +++ qmail-1.03/patches/netscape-progress.patch @@ -0,0 +1,48 @@ +From: Scott Moorhouse +To: qmail@list.cr.yp.to +Subject: Re: qmail-pop3d and Netscape +Date: Tue, 27 Jul 1999 11:16:59 -0500 + + +After taking a look at qmail-pop3d.c, it looked easy to write a patch +to make Messenger's progress meter work again, so I took the initiative +to do so. The diff is so tiny (1 pg with context), I'll just include +it here for anybody to use. + +Thanks for pointing me in the right direction. + +*** qmail-pop3d.c.orig Tue Jul 27 11:07:33 1999 +--- qmail-pop3d.c Tue Jul 27 10:50:39 1999 +*************** +*** 267,273 **** + + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } +! okay(); + substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); + blast(&ssmsg,limit); + close(fd); +--- 267,277 ---- + + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } +! /* 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); + +On Tue, Jul 27, 1999 at 09:29:34AM +0300, Anand Buddhdev wrote: +> On Mon, Jul 26, 1999 at 09:04:09AM -0500, Scott Moorhouse wrote: +> +> I believe this is a Netscape problem. It doesn't use the message size +> value from the LIST command, but instead expects the message size to be +> given after the OK to the RETR command, like this: +> +> ... +> RETR 1 +> +OK 345 octets +[...] --- qmail-1.03.orig/patches/qmail-0.0.0.0.patch +++ qmail-1.03/patches/qmail-0.0.0.0.patch @@ -0,0 +1,14 @@ +--- qmail-1.03/ipme.c Mon Jun 15 06:53:16 1998 ++++ qmail-1.03-sg/ipme.c Mon Jan 29 02:27:38 2001 +@@ -46,6 +46,11 @@ + 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; } + if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; + + len = 256; --- qmail-1.03.orig/patches/qmail-1.03.isoc.patch +++ qmail-1.03/patches/qmail-1.03.isoc.patch @@ -0,0 +1,362 @@ +This patch is Copyright (C) 2004 by James Craig Burley. License +below. + +2004-01-19 0040 EST James Craig Burley + +This patch improves ISO C conformance of qmail code -- specifically, +of qmail-lspawn, qmail-newmrh, qmail-newu, qmail-pop3d, qmail-popup, +qmail-rspawn, and qmail-smtpd. This fixes two known bugs: + + - qmail-smtpd can be crashed by a client sending a sufficiently + long (e.g. 2GB) header line in an email. + + - qmail_lspawn, qmail-newmrh, qmail-newu, and qmail-rspawn might + crash or otherwise misbehave on hosts with a smaller "int" type + than "char *" type, e.g. 64-bit hosts with 32-bit "int"s. + +The other changes are unlikely to have any effect, except possibly on +unusual architectures and/or in the presence of rare optimizations. + +This is Version 1 of this patch. It adds the changes to +cdbmake_add.c, spawn.c, and, correspondingly, Makefile, which pertain +to the second bug listed above. + +See all my qmail patches at . + +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. + + +*** qmail-1.03/cdbmake_add.c Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/cdbmake_add.c Mon Jan 19 00:35:38 2004 +*************** +*** 1,2 **** +--- 1,3 ---- ++ #include "alloc.h" + #include "cdbmake.h" + +*** qmail-1.03/Makefile Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/Makefile Mon Jan 19 00:35:35 2004 +*************** makelib cdbmake_pack.o cdbmake_hash.o cd +*** 264,268 **** + + cdbmake_add.o: \ +! compile cdbmake_add.c cdbmake.h uint32.h + ./compile cdbmake_add.c + +--- 264,268 ---- + + cdbmake_add.o: \ +! compile cdbmake_add.c cdbmake.h alloc.h uint32.h + ./compile cdbmake_add.c + +*************** trylsock.c compile load +*** 1893,1897 **** + spawn.o: \ + compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ +! stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \ + auto_qmail.h auto_uids.h auto_spawn.h + ./chkspawn +--- 1893,1897 ---- + spawn.o: \ + compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ +! stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \ + auto_qmail.h auto_uids.h auto_spawn.h + ./chkspawn +*** qmail-1.03/qmail-pop3d.c Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/qmail-pop3d.c Thu Jan 15 22:08:57 2004 +*************** void die_scan() { err("unable to scan $H +*** 67,71 **** + + void err_syntax() { err("syntax error"); } +! void err_unimpl() { err("unimplemented"); } + void err_deleted() { err("already deleted"); } + void err_nozero() { err("messages are counted from 1"); } +--- 67,71 ---- + + void err_syntax() { err("syntax error"); } +! void err_unimpl(arg) char *arg; { err("unimplemented"); } + void err_deleted() { err("already deleted"); } + void err_nozero() { err("messages are counted from 1"); } +*************** void err_nosuch() { err("unable to open +*** 74,78 **** + void err_nounlink() { err("unable to unlink all deleted messages"); } + +! void okay() { puts("+OK \r\n"); flush(); } + + void printfn(fn) char *fn; +--- 74,78 ---- + void err_nounlink() { err("unable to unlink all deleted messages"); } + +! void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } + + void printfn(fn) char *fn; +*************** void getlist() +*** 147,151 **** + } + +! void pop3_stat() + { + int i; +--- 147,151 ---- + } + +! void pop3_stat(arg) char *arg; + { + int i; +*************** void pop3_stat() +*** 162,174 **** + } + +! void pop3_rset() + { + int i; + for (i = 0;i < numm;++i) m[i].flagdeleted = 0; + last = 0; +! okay(); + } + +! void pop3_last() + { + puts("+OK "); +--- 162,174 ---- + } + +! void pop3_rset(arg) char *arg; + { + int i; + for (i = 0;i < numm;++i) m[i].flagdeleted = 0; + last = 0; +! okay(0); + } + +! void pop3_last(arg) char *arg; + { + puts("+OK "); +*************** void pop3_last() +*** 178,182 **** + } + +! void pop3_quit() + { + int i; +--- 178,182 ---- + } + +! void pop3_quit(arg) char *arg; + { + int i; +*************** void pop3_quit() +*** 193,197 **** + rename(m[i].fn,line.s); /* if it fails, bummer */ + } +! okay(); + die(); + } +--- 193,197 ---- + rename(m[i].fn,line.s); /* if it fails, bummer */ + } +! okay(0); + die(); + } +*************** void pop3_dele(arg) char *arg; +*** 215,219 **** + m[i].flagdeleted = 1; + if (i + 1 > last) last = i + 1; +! okay(); + } + +--- 215,219 ---- + m[i].flagdeleted = 1; + if (i + 1 > last) last = i + 1; +! okay(0); + } + +*************** void dolisting(arg,flaguidl) char *arg; +*** 239,243 **** + } + else { +! okay(); + for (i = 0;i < numm;++i) + if (!m[i].flagdeleted) +--- 239,243 ---- + } + else { +! okay(0); + for (i = 0;i < numm;++i) + if (!m[i].flagdeleted) +*************** void pop3_top(arg) char *arg; +*** 268,272 **** + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } +! okay(); + substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); + blast(&ssmsg,limit); +--- 268,272 ---- + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } +! okay(0); + substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); + blast(&ssmsg,limit); +*************** char **argv; +*** 300,304 **** + getlist(); + +! okay(); + commands(&ssin,pop3commands); + die(); +--- 300,304 ---- + getlist(); + +! okay(0); + commands(&ssin,pop3commands); + die(); +*** qmail-1.03/qmail-popup.c Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/qmail-popup.c Thu Jan 15 22:09:21 2004 +*************** void die_badauth() { err("authorization +*** 65,72 **** + void err_syntax() { err("syntax error"); } + void err_wantuser() { err("USER first"); } +! void err_authoriz() { err("authorization first"); } + +! void okay() { puts("+OK \r\n"); flush(); } +! void pop3_quit() { okay(); die(); } + + +--- 65,72 ---- + void err_syntax() { err("syntax error"); } + void err_wantuser() { err("USER first"); } +! void err_authoriz(arg) char *arg; { err("authorization first"); } + +! void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } +! void pop3_quit(arg) char *arg; { okay(0); die(); } + + +*************** void pop3_user(arg) char *arg; +*** 137,141 **** + { + if (!*arg) { err_syntax(); return; } +! okay(); + seenuser = 1; + if (!stralloc_copys(&username,arg)) die_nomem(); +--- 137,141 ---- + { + if (!*arg) { err_syntax(); return; } +! okay(0); + seenuser = 1; + if (!stralloc_copys(&username,arg)) die_nomem(); +*** qmail-1.03/qmail-smtpd.c Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/qmail-smtpd.c Thu Jan 15 22:12:02 2004 +*************** void straynewline() { out("451 See http: +*** 52,61 **** + 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() { 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() { out("250 ok\r\n"); } +! void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } + void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } + +--- 52,61 ---- + 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 smtp_greet(code) char *code; +*** 68,76 **** + substdio_put(&ssout,greeting.s,greeting.len); + } +! void smtp_help() + { + out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); + } +! void smtp_quit() + { + smtp_greet("221 "); out("\r\n"); flush(); _exit(0); +--- 68,76 ---- + substdio_put(&ssout,greeting.s,greeting.len); + } +! void smtp_help(arg) char *arg; + { + out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); + } +! void smtp_quit(arg) char *arg; + { + smtp_greet("221 "); out("\r\n"); flush(); _exit(0); +*************** void smtp_ehlo(arg) char *arg; +*** 233,237 **** + seenmail = 0; dohelo(arg); + } +! void smtp_rset() + { + seenmail = 0; +--- 233,237 ---- + seenmail = 0; dohelo(arg); + } +! void smtp_rset(arg) char *arg; + { + seenmail = 0; +*************** int *hops; +*** 317,322 **** + if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; + if (flagmaybey) if (pos == 1) flaginheader = 0; + } +- ++pos; + if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } + } +--- 317,322 ---- + if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; + if (flagmaybey) if (pos == 1) flaginheader = 0; ++ ++pos; + } + if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } + } +*************** void acceptmessage(qp) unsigned long qp; +*** 366,370 **** + } + +! void smtp_data() { + int hops; + unsigned long qp; +--- 366,370 ---- + } + +! void smtp_data(arg) char *arg; { + int hops; + unsigned long qp; +*** qmail-1.03/spawn.c Mon Jun 15 06:53:16 1998 +--- qmail-1.03.0/spawn.c Mon Jan 19 00:35:38 2004 +*************** +*** 6,9 **** +--- 6,10 ---- + #include "byte.h" + #include "str.h" ++ #include "alloc.h" + #include "stralloc.h" + #include "select.h" --- qmail-1.03.orig/patches/qmail-link-sync.patch +++ qmail-1.03/patches/qmail-link-sync.patch @@ -0,0 +1,54 @@ +--- ../qmail-1.03.orig/qmail-local.c Mon Jun 15 12:53:16 1998 ++++ qmail-local.c Sun Jul 16 16:19:04 2000 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "readwrite.h" + #include "sig.h" + #include "env.h" +@@ -128,6 +129,9 @@ + if (close(fd) == -1) goto fail; /* NFS dorks */ + + if (link(fntmptph,fnnewtph) == -1) goto fail; ++ if ((fd = open(fnnewtph, O_RDONLY)) < 0 || ++ fsync(fd) < 0 || close(fd) < 0) goto fail; ++ + /* if it was error_exist, almost certainly successful; i hate NFS */ + tryunlinktmp(); _exit(0); + +--- ../qmail-1.03.orig/qmail-queue.c Mon Jun 15 12:53:16 1998 ++++ qmail-queue.c Sun Jul 16 16:19:33 2000 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "readwrite.h" + #include "sig.h" + #include "exit.h" +@@ -155,6 +156,7 @@ + { + unsigned int len; + char ch; ++ int fd; + + sig_blocknone(); + umask(033); +@@ -183,7 +185,7 @@ + todofn = fnnum("todo/",0); + intdfn = fnnum("intd/",0); + +- if (link(pidfn,messfn) == -1) die(64); ++ if (link(pidfn,messfn) == -1) die(64); + if (unlink(pidfn) == -1) die(63); + flagmademess = 1; + +@@ -248,6 +250,8 @@ + if (fsync(intdfd) == -1) die_write(); + + if (link(intdfn,todofn) == -1) die(66); ++ if ((fd = open(todofn, O_RDONLY)) < 0 || ++ fsync(fd) < 0 || close(fd) < 0) die(66); + + triggerpull(); + die(0); --- qmail-1.03.orig/patches/qmail-ldap-1.03-20041201.patch +++ qmail-1.03/patches/qmail-ldap-1.03-20041201.patch @@ -0,0 +1,38486 @@ +Common subdirectories: qmail-1.03/CVS and qmail-ldap/CVS +diff -upN qmail-1.03/EXTTODO qmail-ldap/EXTTODO +--- qmail-1.03/EXTTODO Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/EXTTODO Wed May 5 17:42:11 2004 +@@ -0,0 +1,112 @@ ++EXTTODO by Claudio Jeker and ++Andre Oppermann ++(c) 2002-2004 Internet Business Solutions Ltd. ++ ++The EXTTODO patch is a part of the qmail-ldap patch. ++This patches for qmail come with NO WARRANTY. ++ ++RELEASE: 5. Jan. 2003 ($Date: 2004/04/16 13:24:16 $) ++ ++EXTTODO: ++====================== ++ ++TOC: ++ WHAT DOES IT DO ++ INSTALL ++ CONFIG FILES ++ SETUP ++ BIG PICTURE ++ ++NEWS: ++ ++ This is the first release of the EXTTODO patch. ++ ++================================================================================ ++ ++WHAT DOES IT DO ++ ++ The exttodo patch addresses a problem known as the silly qmail (queue) ++ problem. This problem is found only on system with high injection rates. ++ ++ qmail with a big local and remote concurrency could deliver a tremendous ++ amount of messages but normally this can not be achieved because qmail-send ++ becomes a bottleneck on those high volumes servers. ++ qmail-send preprocesses all new messages before distributing them for local ++ or remote delivering. In one run qmail-send does one todo run but has the ++ ability to close multiple jobs. Because of this layout qmail-send can not ++ feed all the new available (local/remote) delivery slots and therefor it is ++ not possible to achieve the maximum throughput. ++ This would be a minor problem if one qmail-send run could be done in extreme ++ short time but because of many file system calls (fsync and (un)link) a todo ++ run is expensive and throttles the throughput. ++ ++ The exttodo patch tries to solve the problem by moving the todo routine into ++ an external program. This reduces the run time in qmail-send. ++ ++ exttodo adds a new program to qmail called qmail-todo. qmail-todo prepares ++ incoming messages for local and remote delivering (by creating info/ ++ local/ and remote/ and removing todo/). See also ++ INTERNALS. As next qmail-todo transmits the to qmail-send which will ++ add this message into the priority queue which schedules the message for ++ delivery. ++ ++INSTALL ++ ++ To enable the exttodo patch you need to define EXTERNAL_TODO while compiling ++ qmail(-ldap) this can be done with the -D flag of cc (e.g. cc -DEXTERNAL_TODO). ++ ++ NOTE: the exttodo patch can also be used on qmail systems without the ++ qmail-ldap patch. ++ ++================================================================================ ++ ++CONFIG FILES ++ ++ No additional control files are used or needed. ++ ++================================================================================ ++ ++SETUP ++ ++ qmail-todo will be started by qmail-start and therefor no additional setup ++ is needed. ++ ++ To verify that exttodo is running just check if qmail-todo is running. ++ ++================================================================================ ++ ++BIG PICTURE ++ ++ +-------+ +-------+ ++ | clean | | clean | ++ +--0-1--+ +--0-1--+ +-----------+ ++ trigger ^ | ^ | +->0,1 lspawn | ++ | | v | v / +-----------+ ++ +-------+ v +--2-3--+ +--5-6--+ / ++ | | | | 0<--7 1,2<-+ ++ | queue |--+--| todo | | send | ++ | | | | 1-->8 3,4<-+ ++ +-------+ +-------+ +---0---+ \ ++ | \ +-----------+ ++ v +->0,1 rspwan | ++ +---0---+ +-----------+ ++ | logger| ++ +-------+ ++ ++Communication between qmail-send and qmail-todo ++ ++todo -> send: ++ D[LRB]\0 ++ Start delivery for new message with id . ++ the character L, R or B defines the type ++ of delivery, local, remote or both respectively. ++ L\0 ++ Dump string to the logger without adding additional \n or similar. ++send -> todo: ++ H Got a SIGHUP reread ~/control/locals and ~/control/virtualdomains ++ X Quit ASAP. ++ ++qmail-todo sends "\0" terminated messages whereas qmail-send just send one ++character to qmail-todo. ++ ++ +diff -upN qmail-1.03/FILES qmail-ldap/FILES +--- qmail-1.03/FILES Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/FILES Wed May 5 17:42:11 2004 +@@ -227,16 +227,11 @@ case_lowerb.c + case_lowers.c + case_starts.c + cdb.3 ++cdb.c + cdb.h + cdb_hash.c +-cdb_seek.c +-cdb_unpack.c +-cdbmake.h +-cdbmake_add.c +-cdbmake_hash.c +-cdbmake_pack.c +-cdbmss.h +-cdbmss.c ++cdb_make.c ++cdb_make.h + coe.3 + coe.h + coe.c +@@ -431,3 +426,103 @@ maildir.c + tcp-environ.5 + constmap.h + constmap.c ++EXTTODO ++Makefile.cdb ++POPBEFORESMTP ++QLDAPGROUP ++QLDAPINSTALL ++QLDAPNEWS ++QLDAPPICTURE ++QLDAPTODO ++TLS.readme ++auth_imap.c ++auth_mod.c ++auth_mod.h ++auth_pop.c ++auth_smtp.c ++auto_userl.h ++base64.c ++base64.h ++byte_repl.c ++case_startb.c ++check.c ++check.h ++checkpassword.c ++checkpassword.h ++condwrite.c ++digest.c ++digest_md4.c ++digest_md4.h ++digest_md5.c ++digest_md5.h ++digest_rmd160.c ++digest_rmd160.h ++digest_sha1.c ++digest_sha1.h ++dirmaker ++dirmaker.c ++dirmaker.h ++endian.c ++execcheck.c ++execcheck.h ++localdelivery.c ++localdelivery.h ++locallookup.c ++locallookup.h ++maildir++.c ++maildir++.h ++mailmagic.c ++mailmagic.h ++mailmaker.c ++mailmaker.h ++output.c ++output.h ++passwd.c ++passwd.h ++pbsadd.c ++pbscheck.c ++pbsdbd.c ++pbsexec.c ++pbsexec.h ++popfetch.pl ++qldap-cluster.c ++qldap-cluster.h ++qldap-debug.c ++qldap-debug.h ++qldap-errno.c ++qldap-errno.h ++qldap-filter.c ++qldap-profile.c ++qldap-profile.h ++qldap.c ++qldap.h ++qmail-cdb.c ++qmail-forward.c ++qmail-group.c ++qmail-imapd-ssl.sh ++qmail-imapd.rules ++qmail-imapd.sh ++qmail-ldap.h ++qmail-ldaplookup.c ++qmail-pop3d-ssl.sh ++qmail-pop3d.rules ++qmail-pop3d.sh ++qmail-qmqpd.rules ++qmail-qmqpd.sh ++qmail-quotawarn.c ++qmail-reply.c ++qmail-secretary.c ++qmail-smtpd.rules ++qmail-smtpd.sh ++qmail-todo.c ++qmail-verify.c ++qmail.schema ++qmail.sh ++rbl.c ++rbl.h ++read-ctrl.c ++read-ctrl.h ++readwrite.c ++signatures ++smtpcall.c ++smtpcall.h +diff -upN qmail-1.03/LICENSE qmail-ldap/LICENSE +--- qmail-1.03/LICENSE Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/LICENSE Wed May 5 17:42:11 2004 +@@ -0,0 +1,40 @@ ++ ++This copyright notice applies to the qmail-ldap patch. It does not apply ++to the original qmail-1.03 by Dan Bernstein. It also partly applies to ++the resulting source and object code. In that Dan Bernsteins copyright ++remains intact and is enhanced with ours as derivative work. ++ ++/* ++ * Copyright (c) 1998-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ +diff -upN qmail-1.03/Makefile qmail-ldap/Makefile +--- qmail-1.03/Makefile Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/Makefile Thu Jul 1 16:28:30 2004 +@@ -1,8 +1,101 @@ ++# Edit this few lines to configure your ldap stuff ++ ++# to enable some additional for qmail-ldap stuff put it on the LDAPFLAGS line ++# ++# -DALTQUEUE to use a diffrent qmail-queue programm on runtime ++# -DBIGBROTHER to use the control/bigbrother file to forward all mails comming ++# from a specified account to another (swiss bigbrother law) ++# -DBIGTODO to enable the big todo patch (this can be used together with ++# EXTERNAL_TODO). Useful for servers with very many non-preprocessed mails ++# -DBIND_8_COMPAT need if the compile fails building dns.c because of ++# undeclared defines. This is necessary on MacOS X 10.3. ++# -DCLEARTEXTPASSWD to use cleartext passwords (bad idea on production systems) ++# -DDASH_EXT to enable the dash_ext patch for extended mail addresses ++# -DDATA_COMPRESS to use the smtp on the fly DATA compression ++# -DEXTERNAL_TODO to use the external high-performance todo processing (this ++# avoids the silly qmail syndrome with high injection rates) ++# -DIGNOREVERISIGN to disallow dns wildchar matches on gtlds, thanks verisign. ++# -DQLDAP_CLUSTER for enabling cluster support ++# -DQMQP_COMPRESS to use the QMQP on the fly compression (for clusters) ++# -DQUOTATRASH to include the Trash in the quota calculation (normaly it is not) ++# -DSMTPEXECCHECK to enable smtp DOS/Windows executable detection ++#LDAPFLAGS=-DQLDAP_CLUSTER -DEXTERNAL_TODO -DDASH_EXT -DDATA_COMPRESS -DQMQP_COMPRESS -DSMTPEXECCHECK ++ ++# Perhaps you have different ldap libraries, change them here ++LDAPLIBS=-L/usr/local/lib -lldap -llber ++# and change the location of the include files here ++LDAPINCLUDES=-I/usr/local/include ++# on Slowaris you need -lresolv and probably a LD_RUN_PATH added like this: ++#LDAPLIBS=-L/opt/OpenLDAP/lib -lldap -llber -lresolv -R/opt/OpenLDAP/lib ++# for example on my Linux box I use: ++#LDAPLIBS=-L/opt/OpenLDAP/lib -lldap -llber ++# if you need a special include-directory for ldap headers enable this ++#LDAPINCLUDES=-I/opt/OpenLDAP/include ++ ++# ZLIB needed for -DDATA_COMPRESS and -DQMQP_COMPRESS ++#ZLIB=-lz ++# or you installed zlib in a different path you can use something like this ++#ZLIB=-L/opt/zlib/lib -lz ++#ZINCLUDES=-I/opt/zlib/include ++ ++# TLS (SMTP encryption) in qmail-smtpd and qmail-remote, see TLS.readme ++# You need OpenSSL for this ++# use -DTLS_REMOTE to enable tls support in qmail-remote ++# use -DTLS_SMTPD to enable tls support in qmail-smtpd ++# use -DTLSDEBUG to enable additional tls debug information in qmail-remote ++#TLS=-DTLS_REMOTE -DTLS_SMTPD ++# Path to OpenSSL includes ++#TLSINCLUDES=-I/usr/local/include ++# Path to OpenSSL libraries ++#TLSLIBS=-L/usr/local/lib -lssl -lcrypto ++# Path to OpenSSL binary ++#OPENSSLBIN=/usr/local/bin/openssl ++#OPENSSLBIN=openssl ++ ++# to make the Netscape download progress bar work with qmail-pop3d ++# uncomment the next line (allready done) ++MNW=-DMAKE_NETSCAPE_WORK ++ ++# to enable the auto-maildir-make feature uncomment the next line ++#MDIRMAKE=-DAUTOMAILDIRMAKE ++ ++# to enable the auto-homedir-make feature uncomment the next line ++#HDIRMAKE=-DAUTOHOMEDIRMAKE ++ ++# on most systems we need this to make auth_pop and auth_imap ++#SHADOWLIBS=-lcrypt ++# OpenBSD and other Systems do not have libcrypt, so comment the line out ++# if you get linking problems. ++# To use shadow passwords under some Linux OS, uncomment the next two lines. ++#SHADOWLIBS=-lcrypt -lshadow ++#SHADOWOPTS=-DPW_SHADOW ++# To use shadow passwords under Solaris, uncomment the SHADOWOPTS line. ++ ++# to enable the possibility to log and debug imap and pop uncoment the ++# next line ++#DEBUG=-DDEBUG ++# WARNING: you need a NONE DEBUG auth_* to run with inetd ++ ++# for profiling ... ++#INCTAI=../libtai-0.60 ++#LIBTAI=../libtai-0.60 ++ ++# Just for me, make from time to time a backup ++BACKUPPATH=/backup/qmail-backup/qmail-ldap.`date "+%Y%m%d-%H%M"`.tar ++# STOP editing HERE !!! ++ + # Don't edit Makefile! Use conf-* for configuration. + + SHELL=/bin/sh + +-default: it ++default: it ldap ++ ++ldap: qmail-quotawarn qmail-reply auth_pop auth_imap auth_smtp digest \ ++qmail-ldaplookup pbsadd pbscheck pbsdbd qmail-todo qmail-forward \ ++qmail-secretary qmail-group qmail-verify condwrite qmail-cdb \ ++qmail-imapd.run qmail-pbsdbd.run qmail-pop3d.run qmail-qmqpd.run \ ++qmail-smtpd.run qmail.run qmail-imapd-ssl.run qmail-pop3d-ssl.run \ ++Makefile.cdb-p + + addresses.0: \ + addresses.5 +@@ -20,6 +113,75 @@ alloc_re.o: \ + compile alloc_re.c alloc.h byte.h + ./compile alloc_re.c + ++auth_imap: \ ++load auth_imap.o auth_mod.o checkpassword.o passwd.o digest_md4.o \ ++digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o getopt.a \ ++control.o dirmaker.o mailmaker.o qldap.a localdelivery.o locallookup.o \ ++pbsexec.o constmap.o getln.a strerr.a substdio.a stralloc.a env.a wait.a \ ++dns.o ip.o ipalloc.o ipme.o alloc.a str.a case.a fs.a error.a timeoutconn.o \ ++timeoutread.o ndelay.a open.a sig.a prot.o auto_uids.o auto_qmail.o \ ++dns.lib socket.lib ++ ./load auth_imap auth_mod.o checkpassword.o passwd.o digest_md4.o \ ++ digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \ ++ getopt.a control.o dirmaker.o mailmaker.o qldap.a localdelivery.o \ ++ locallookup.o pbsexec.o constmap.o getln.a strerr.a substdio.a \ ++ stralloc.a env.a wait.a dns.o ip.o ipalloc.o ipme.o alloc.a str.a \ ++ case.a fs.a error.a timeoutconn.o timeoutread.o ndelay.a open.a \ ++ sig.a prot.o auto_uids.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) \ ++ `cat dns.lib` `cat socket.lib` ++ ++auth_imap.o: \ ++compile auth_imap.c alloc.h byte.h env.h error.h exit.h fmt.h pbsexec.h \ ++qldap-debug.h qldap-errno.h qmail-ldap.h readwrite.h scan.h sgetopt.h \ ++sig.h str.h stralloc.h substdio.h timeoutread.h auth_mod.h ++ ./compile $(LDAPFLAGS) $(DEBUG) auth_imap.c ++ ++auth_mod.o: \ ++compile auth_mod.c auth_mod.h checkpassword.h byte.h localdelivery.h \ ++locallookup.h output.h qldap.h qldap-debug.h qldap-errno.h stralloc.h \ ++read-ctrl.h dirmaker.h qldap-cluster.h select.h ++ ./compile $(LDAPFLAGS) $(DEBUG) $(HDIRMAKE) $(MDIRMAKE) auth_mod.c ++ ++auth_pop: \ ++load auth_pop.o auth_mod.o checkpassword.o passwd.o digest_md4.o \ ++digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o getopt.a \ ++control.o dirmaker.o mailmaker.o qldap.a localdelivery.o locallookup.o \ ++pbsexec.o constmap.o getln.a strerr.a substdio.a stralloc.a env.a wait.a \ ++dns.o ip.o ipalloc.o ipme.o alloc.a str.a case.a fs.a error.a timeoutconn.o \ ++timeoutread.o ndelay.a open.a prot.o auto_uids.o auto_qmail.o \ ++dns.lib socket.lib ++ ./load auth_pop auth_mod.o checkpassword.o passwd.o digest_md4.o \ ++ digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \ ++ getopt.a control.o qldap.a dirmaker.o mailmaker.o localdelivery.o \ ++ locallookup.o pbsexec.o constmap.o getln.a strerr.a substdio.a \ ++ stralloc.a env.a wait.a dns.o ip.o ipalloc.o ipme.o alloc.a str.a \ ++ case.a fs.a error.a timeoutconn.o timeoutread.o ndelay.a open.a \ ++ prot.o auto_uids.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) \ ++ `cat dns.lib` `cat socket.lib` ++ ++auth_pop.o: \ ++compile auth_pop.c byte.h env.h error.h exit.h pbsexec.h qldap-debug.h \ ++qldap-errno.h qmail-ldap.h readwrite.h sgetopt.h str.h stralloc.h substdio.h \ ++timeoutread.h auth_mod.h ++ ./compile $(LDAPFLAGS) $(DEBUG) auth_pop.c ++ ++auth_smtp: \ ++load auth_smtp.o checkpassword.o passwd.o digest_md4.o digest_md5.o \ ++digest_rmd160.o digest_sha1.o base64.o read-ctrl.o control.o qldap.a \ ++constmap.o getln.a strerr.a substdio.a stralloc.a env.a alloc.a str.a \ ++case.a fs.a error.a open.a prot.o auto_uids.o auto_qmail.o ++ ./load auth_smtp checkpassword.o passwd.o digest_md4.o \ ++ digest_md5.o digest_rmd160.o digest_sha1.o base64.o read-ctrl.o \ ++ control.o qldap.a constmap.o getln.a strerr.a substdio.a stralloc.a \ ++ env.a alloc.a str.a case.a fs.a error.a open.a prot.o auto_uids.o \ ++ auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) ++ ++auth_smtp.o: \ ++compile auth_smtp.c byte.h env.h error.h exit.h output.h qldap.h \ ++qldap-debug.h qldap-errno.h qmail-ldap.h read-ctrl.h str.h stralloc.h \ ++substdio.h checkpassword.h auth_mod.h ++ ./compile $(LDAPFLAGS) $(DEBUG) auth_smtp.c ++ + auto-ccld.sh: \ + conf-cc conf-ld warn-auto.sh + ( cat warn-auto.sh; \ +@@ -136,6 +298,18 @@ auto_usera.o: \ + compile auto_usera.c + ./compile auto_usera.c + ++auto_userl.c: \ ++auto-str conf-users ++ ./auto-str auto_userl `head -3 conf-users | tail -1` > auto_userl.c ++ ++auto_userl.o: \ ++compile auto_userl.c ++ ./compile auto_userl.c ++ ++base64.o: \ ++compile base64.c base64.h str.h ++ ./compile $(LDAPFLAGS) base64.c ++ + binm1: \ + binm1.sh conf-qmail + cat binm1.sh \ +@@ -211,15 +385,19 @@ byte_rchr.o: \ + compile byte_rchr.c byte.h + ./compile byte_rchr.c + ++byte_repl.o: \ ++compile byte_repl.c byte.h ++ ./compile byte_repl.c ++ + byte_zero.o: \ + compile byte_zero.c byte.h + ./compile byte_zero.c + + case.a: \ + makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \ +-case_starts.o ++case_startb.o case_starts.o + ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \ +- case_lowers.o case_starts.o ++ case_lowers.o case_startb.o case_starts.o + + case_diffb.o: \ + compile case_diffb.c case.h +@@ -237,52 +415,50 @@ case_lowers.o: \ + compile case_lowers.c case.h + ./compile case_lowers.c + ++case_startb.o: \ ++compile case_startb.c case.h ++ ./compile case_startb.c ++ + case_starts.o: \ + compile case_starts.c case.h + ./compile case_starts.c + + cdb.a: \ +-makelib cdb_hash.o cdb_unpack.o cdb_seek.o +- ./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o ++makelib cdb_hash.o cdb.o ++ ./makelib cdb.a cdb_hash.o cdb.o ++ ++cdb.o: \ ++compile cdb.c cdb.h byte.h error.h seek.h uint32.h ++ ./compile cdb.c + + cdb_hash.o: \ + compile cdb_hash.c cdb.h uint32.h + ./compile cdb_hash.c + +-cdb_seek.o: \ +-compile cdb_seek.c cdb.h uint32.h +- ./compile cdb_seek.c +- +-cdb_unpack.o: \ +-compile cdb_unpack.c cdb.h uint32.h +- ./compile cdb_unpack.c ++cdb_make.o: \ ++compile cdb_make.c cdb.h readwrite.h seek.h error.h alloc.h uint32.h ++ ./compile cdb_make.c + + cdbmake.a: \ +-makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o +- ./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \ +- cdbmake_add.o +- +-cdbmake_add.o: \ +-compile cdbmake_add.c cdbmake.h uint32.h +- ./compile cdbmake_add.c +- +-cdbmake_hash.o: \ +-compile cdbmake_hash.c cdbmake.h uint32.h +- ./compile cdbmake_hash.c +- +-cdbmake_pack.o: \ +-compile cdbmake_pack.c cdbmake.h uint32.h +- ./compile cdbmake_pack.c +- +-cdbmss.o: \ +-compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \ +-uint32.h substdio.h +- ./compile cdbmss.c ++makelib cdb_make.o cdb_hash.o ++ ./makelib cdbmake.a cdb_make.o cdb_hash.o + + check: \ +-it man ++it man ldap + ./instcheck + ++check.o: \ ++compile check.c check.h str.h str_len.c ++ ./compile $(LDAPFLAGS) check.c ++ ++checkpassword.o: \ ++compile checkpassword.c auth_mod.h auto_uids.h byte.h check.h env.h \ ++error.h fmt.h localdelivery.h passwd.h pbsexec.h prot.h \ ++qldap.h qldap-debug.h qldap-errno.h qmail-ldap.h scan.h str.h stralloc.h \ ++dns.h ipalloc.h ipme.h ndelay.h qldap-cluster.h readwrite.h select.h \ ++timeoutconn.h dirmaker.h mailmaker.h ++ ./compile $(LDAPFLAGS) $(LDAPINCLUDES) $(DEBUG) checkpassword.c ++ + chkshsgr: \ + load chkshsgr.o + ./load chkshsgr +@@ -334,6 +510,20 @@ compile condredirect.c sig.h readwrite.h + wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h + ./compile condredirect.c + ++condwrite: \ ++load condwrite.o maildir++.o getln.a stralloc.a alloc.a env.a wait.a \ ++seek.a strerr.a substdio.a error.a gfrom.o str.a now.o fs.a mailmaker.o \ ++open.a sig.a lock.a auto_qmail.o ++ ./load condwrite maildir++.o getln.a stralloc.a alloc.a env.a \ ++ wait.a seek.a strerr.a substdio.a error.a gfrom.o str.a now.o \ ++ fs.a mailmaker.o open.a sig.a lock.a auto_qmail.o ++ ++condwrite.o: \ ++compile condwrite.c auto_qmail.h byte.h env.h error.h fmt.h getln.h gfrom.h \ ++lock.h maildir++.h now.h open.h qmail-ldap.h seek.h sig.h str.h stralloc.h \ ++strerr.h subfd.h substdio.h wait.h mailmaker.h qldap-errno.h ++ ./compile $(MDIRMAKE) condwrite.c ++ + config: \ + warn-auto.sh config.sh conf-qmail conf-break conf-split + cat warn-auto.sh config.sh \ +@@ -386,12 +576,47 @@ datetime_un.o: \ + compile datetime_un.c datetime.h + ./compile datetime_un.c + ++digest: \ ++load digest.o passwd.o digest_md4.o digest_md5.o digest_rmd160.o \ ++digest_sha1.o base64.o qldap-debug.o output.o getopt.a strerr.a \ ++substdio.a case.a env.a stralloc.a str.a fs.a alloc.a error.a ++ ./load digest passwd.o digest_md4.o digest_md5.o digest_rmd160.o \ ++ digest_sha1.o base64.o qldap-debug.o output.o getopt.a strerr.a \ ++ substdio.a case.a env.a stralloc.a str.a fs.a alloc.a error.a \ ++ $(SHADOWLIBS) ++ ++digest.o: \ ++compile digest.c base64.h error.h passwd.h qldap-errno.h \ ++sgetopt.h stralloc.h ++ ./compile $(LDAPFLAGS) digest.c ++ ++digest_md4.o: \ ++compile endian digest_md4.c byte.h digest_md4.h uint32.h ++ ./compile $(LDAPFLAGS) `./endian` digest_md4.c ++ ++digest_md5.o: \ ++compile endian digest_md5.c byte.h digest_md5.h uint32.h ++ ./compile $(LDAPFLAGS) `./endian` digest_md5.c ++ ++digest_rmd160.o: \ ++compile endian digest_rmd160.c byte.h digest_rmd160.h uint32.h ++ ./compile $(LDAPFLAGS) `./endian` digest_rmd160.c ++ ++digest_sha1.o: \ ++compile endian digest_sha1.c byte.h digest_sha1.h uint32.h ++ ./compile $(LDAPFLAGS) `./endian` digest_sha1.c ++ + direntry.h: \ + compile trydrent.c direntry.h1 direntry.h2 + ( ./compile trydrent.c >/dev/null 2>&1 \ + && cat direntry.h2 || cat direntry.h1 ) > direntry.h + rm -f trydrent.o + ++dirmaker.o: \ ++compile dirmaker.c dirmaker.h control.h qldap-debug.h qldap-errno.h \ ++stralloc.h wait.h ++ ./compile $(HDIRMAKE) $(DEBUG) dirmaker.c ++ + dns.lib: \ + tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \ + alloc.a error.a fs.a str.a +@@ -404,7 +629,7 @@ alloc.a error.a fs.a str.a + dns.o: \ + compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \ + stralloc.h gen_alloc.h dns.h case.h +- ./compile dns.c ++ ./compile $(LDAPFLAGS) dns.c + + dnscname: \ + load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \ +@@ -492,6 +717,14 @@ warn-auto.sh elq.sh conf-qmail conf-brea + > elq + chmod 755 elq + ++endian: \ ++load endian.o ++ ./load endian ++ ++endian.o: \ ++compile endian.c ++ ./compile $(LDAPFLAGS) endian.c ++ + env.a: \ + makelib env.o envread.o + ./makelib env.a env.o envread.o +@@ -536,6 +769,10 @@ except.o: \ + compile except.c fork.h strerr.h wait.h error.h exit.h + ./compile except.c + ++execcheck.o: \ ++compile execcheck.c execcheck.h case.h env.h qmail.h str.h stralloc.h ++ ./compile $(LDAPFLAGS) execcheck.c ++ + fd.a: \ + makelib fd_copy.o fd_move.o + ./makelib fd.a fd_copy.o fd_move.o +@@ -703,7 +940,7 @@ compile hfield.c hfield.h + + hier.o: \ + compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h +- ./compile hier.c ++ ./compile $(LDAPFLAGS) $(DEBUG) hier.c + + home: \ + home.sh conf-qmail +@@ -741,21 +978,22 @@ seek.h fork.h + + install: \ + load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ +-strerr.a substdio.a open.a error.a str.a fs.a ++auto_userl.o strerr.a substdio.a open.a error.a str.a fs.a + ./load install fifo.o hier.o auto_qmail.o auto_split.o \ +- auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a ++ auto_uids.o auto_userl.o strerr.a substdio.a open.a error.a \ ++ str.a fs.a + + install-big: \ + load install-big.o fifo.o install.o auto_qmail.o auto_split.o \ +-auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a ++auto_uids.o auto_userl.o strerr.a substdio.a open.a error.a str.a fs.a + ./load install-big fifo.o install.o auto_qmail.o \ +- auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \ +- str.a fs.a ++ auto_split.o auto_uids.o auto_userl.o strerr.a substdio.a \ ++ open.a error.a str.a fs.a + + install-big.o: \ + compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \ + fifo.h +- ./compile install-big.c ++ ./compile $(LDAPFLAGS) $(DEBUG) install-big.c + + install.o: \ + compile install.c substdio.h strerr.h error.h open.h readwrite.h \ +@@ -764,9 +1002,9 @@ exit.h + + instcheck: \ + load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ +-strerr.a substdio.a error.a str.a fs.a ++auto_userl.o strerr.a substdio.a error.a str.a fs.a + ./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \ +- auto_uids.o strerr.a substdio.a error.a str.a fs.a ++ auto_uids.o auto_userl.o strerr.a substdio.a error.a str.a fs.a + + instcheck.o: \ + compile instcheck.c strerr.h error.h readwrite.h exit.h +@@ -783,7 +1021,7 @@ gen_alloc.h + + ipme.o: \ + compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \ +-stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h ++stralloc.h gen_alloc.h ipme.h ip.h + ./compile ipme.c + + ipmeprint: \ +@@ -794,7 +1032,7 @@ error.a str.a fs.a socket.lib + + ipmeprint.o: \ + compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \ +-ipalloc.h ip.h gen_alloc.h exit.h ++ip.h gen_alloc.h exit.h + ./compile ipmeprint.c + + it: \ +@@ -806,15 +1044,24 @@ qmail-pop3d qmail-popup qmail-qmqpc qmai + qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ + 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 ++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 + + load: \ + make-load warn-auto.sh systype + ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load + chmod 755 load + ++localdelivery.o: \ ++compile localdelivery.c localdelivery.h control.h qldap-debug.h ++ ./compile $(DEBUG) localdelivery.c ++ ++locallookup.o: \ ++compile locallookup.c locallookup.h checkpassword.h error.h getln.h \ ++localdelivery.h open.h passwd.h substdio.h ++ ./compile $(DEBUG) $(SHADOWOPTS) locallookup.c ++ + lock.a: \ + makelib lock_ex.o lock_exnb.o lock_un.o + ./makelib lock.a lock_ex.o lock_exnb.o lock_un.o +@@ -841,6 +1088,12 @@ gen_alloc.h direntry.h datetime.h now.h + strerr.h + ./compile maildir.c + ++maildir++.o: \ ++compile maildir++.c maildir++.h readwrite.h stralloc.h error.h str.h \ ++open.h substdio.h getln.h error.h strerr.h fmt.h scan.h now.h seek.h \ ++sig.h direntry.h ++ ./compile $(LDAPFLAGS) maildir++.c ++ + maildir2mbox: \ + load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \ + getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \ +@@ -890,6 +1143,15 @@ datetime.h gen_alloc.h stralloc.h gen_al + readwrite.h open.h headerbody.h maildir.h strerr.h + ./compile maildirwatch.c + ++mailmagic.o: \ ++compile mailmagic.c mailmagic.h byte.h case.h error.h getln.h \ ++stralloc.h substdio.h qmail-ldap.h ++ ./compile $(LDAPFLAGS) mailmagic.c ++ ++mailmaker.o: \ ++compile mailmaker.c mailmaker.h error.h open.h qldap-errno.h ++ ./compile $(MDIRMAKE) mailmaker.c ++ + mailsubj: \ + warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split + cat warn-auto.sh mailsubj.sh \ +@@ -918,6 +1180,13 @@ make-makelib.sh auto-ccld.sh + cat auto-ccld.sh make-makelib.sh > make-makelib + chmod 755 make-makelib + ++Makefile.cdb-p: \ ++Makefile.cdb conf-qmail ++ cat Makefile.cdb \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > Makefile.cdb-p ++ chmod 644 Makefile.cdb-p ++ + makelib: \ + make-makelib warn-auto.sh systype + ( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \ +@@ -992,6 +1261,59 @@ open_write.o: \ + compile open_write.c open.h + ./compile open_write.c + ++output.o: \ ++compile output.c output.h stralloc.h substdio.h fmt.h str.h scan.h \ ++readwrite.h ++ ./compile output.c ++ ++passwd.o: \ ++compile passwd.c base64.h byte.h case.h digest_md4.h digest_md5.h \ ++digest_rmd160.h digest_sha1.h qldap-debug.h qldap-errno.h str.h \ ++stralloc.h uint32.h passwd.h ++ ./compile $(LDAPFLAGS) $(DEBUG) passwd.c ++ ++pbsadd: \ ++load pbsadd.o control.o now.o ip.o getln.a open.a env.a stralloc.a \ ++alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o socket.lib ++ ./load pbsadd control.o now.o ip.o getln.a open.a env.a \ ++ stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \ ++ auto_qmail.o `cat socket.lib` ++ ++pbsadd.o: \ ++compile pbsadd.c alloc.h auto_qmail.h byte.h control.h env.h error.h \ ++exit.h fmt.h ip.h now.h readwrite.h stralloc.h substdio.h ++ ./compile pbsadd.c ++ ++pbscheck: \ ++load pbscheck.o control.o now.o timeoutread.o timeoutwrite.o \ ++ip.o getln.a open.a env.a stralloc.a alloc.a strerr.a substdio.a \ ++error.a str.a fs.a auto_qmail.o socket.lib ++ ./load pbscheck control.o now.o timeoutread.o timeoutwrite.o \ ++ ip.o getln.a open.a env.a stralloc.a alloc.a strerr.a substdio.a \ ++ error.a str.a fs.a auto_qmail.o `cat socket.lib` ++ ++pbscheck.o: \ ++compile pbscheck.c alloc.h auto_qmail.h byte.h control.h env.h error.h \ ++exit.h fmt.h ip.h now.h readwrite.h str.h stralloc.h substdio.h timeoutread.h \ ++timeoutwrite.h ++ ./compile pbscheck.c ++ ++pbsdbd: \ ++load pbsdbd.o control.o now.o ip.o ndelay.a getln.a open.a stralloc.a \ ++alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o socket.lib ++ ./load pbsdbd control.o now.o ip.o ndelay.a getln.a open.a \ ++ stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \ ++ auto_qmail.o `cat socket.lib` ++ ++pbsdbd.o: \ ++compile pbsdbd.c alloc.h auto_qmail.h byte.h control.h ip.h ndelay.h \ ++now.h stralloc.h strerr.h substdio.h uint32.h ++ ./compile pbsdbd.c ++ ++pbsexec.o: \ ++compile pbsexec.c pbsexec.h open.h qldap-debug.h wait.h ++ ./compile $(DEBUG) pbsexec.c ++ + pinq: \ + warn-auto.sh pinq.sh conf-qmail conf-break conf-split + cat warn-auto.sh pinq.sh \ +@@ -1074,6 +1396,53 @@ compile qbiff.c readwrite.h stralloc.h g + substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h + ./compile qbiff.c + ++qldap.a: \ ++makelib check.o output.o qldap.o qldap-cluster.o qldap-filter.o \ ++qldap-debug.o qldap-errno.o auto_break.o ++ ./makelib qldap.a check.o output.o qldap.o qldap-cluster.o \ ++ qldap-filter.o qldap-debug.o qldap-errno.o auto_break.o ++ ++qldap.o: \ ++compile qldap.c qldap.h alloc.h byte.h case.h check.h control.h error.h \ ++fmt.h qldap-debug.h qldap-errno.h qmail-ldap.h scan.h str.h stralloc.h ++ ./compile $(LDAPFLAGS) $(LDAPINCLUDES) $(DEBUG) qldap.c ++ ++qldap-cluster.o: \ ++compile qldap-cluster.c qldap-cluster.h constmap.h control.h qldap-debug.h \ ++stralloc.h ++ ./compile $(LDAPFLAGS) $(DEBUG) qldap-cluster.c ++ ++qldap-debug.o: \ ++compile qldap-debug.c output.h stralloc.h substdio.h fmt.h str.h readwrite.h \ ++error.h qldap-errno.h env.h scan.h qldap-debug.h ++ ./compile $(LDAPFLAGS) $(DEBUG) qldap-debug.c ++ ++qldap-errno.o: \ ++compile qldap-errno.c qldap-errno.h error.h ++ ./compile $(LDAPFLAGS) qldap-errno.c ++ ++qldap-filter.o: \ ++compile qldap-filter.c auto_break.h qldap.h qmail-ldap.h str.h stralloc.h ++ ./compile $(LDAPFLAGS) qldap-filter.c ++ ++profile: qldap-profile.o ++ ++qldap-profile.o: \ ++compile qldap-profile.c qldap-profile.h qldap-debug.h ++ ./compile $(INCTAI) $(DEBUG) qldap-profile.c ++ ++qmail-cdb: \ ++load qmail-cdb.o getln.a open.a cdbmake.a seek.a case.a \ ++stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o ++ ./load qmail-cdb getln.a open.a cdbmake.a seek.a \ ++ case.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ ++ auto_qmail.o ++ ++qmail-cdb.o: \ ++compile qmail-cdb.c auto_qmail.h case.h cdb_make.h exit.h getln.h \ ++open.h readwrite.h stralloc.h strerr.h substdio.h uint32.h ++ ./compile qmail-cdb.c ++ + qmail-clean: \ + load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \ + substdio.a error.a str.a fs.a auto_qmail.o auto_split.o +@@ -1089,7 +1458,7 @@ qmail-clean.o: \ + compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \ + direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \ + substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h +- ./compile qmail-clean.c ++ ./compile $(LDAPFLAGS) qmail-clean.c + + qmail-command.0: \ + qmail-command.8 +@@ -1107,6 +1476,18 @@ qmail-control.9 conf-break conf-spawn + | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + > qmail-control.5 + ++qmail-forward: \ ++load qmail-forward.o qmail.o control.o now.o env.a fd.a wait.a open.a getln.a \ ++seek.a stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o ++ ./load qmail-forward qmail.o control.o now.o env.a fd.a wait.a \ ++ open.a getln.a seek.a strerr.a stralloc.a alloc.a substdio.a \ ++ error.a str.a fs.a auto_qmail.o ++ ++qmail-forward.o: \ ++compile qmail-forward.c auto_qmail.h control.h error.h fmt.h getln.h now.h \ ++qmail.h seek.h str.h stralloc.h strerr.h substdio.h ++ ./compile $(LDAPFLAGS) qmail-forward.c ++ + qmail-getpw: \ + load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \ + auto_usera.o +@@ -1131,10 +1512,40 @@ error.h exit.h byte.h str.h case.h fmt.h + qlx.h + ./compile qmail-getpw.c + ++qmail-group: \ ++load qmail-group.o qmail.o now.o control.o case.a getln.a sig.a open.a \ ++seek.a fd.a wait.a env.a qldap.a read-ctrl.o stralloc.a alloc.a strerr.a \ ++substdio.a error.a fs.a str.a coe.o auto_qmail.o ++ ./load qmail-group qmail.o now.o control.o case.a getln.a sig.a \ ++ open.a seek.a fd.a wait.a env.a qldap.a read-ctrl.o stralloc.a \ ++ alloc.a fs.a strerr.a substdio.a error.a str.a coe.o auto_qmail.o \ ++ $(LDAPLIBS) ++ ++qmail-group.o: \ ++compile qmail-group.c alloc.h auto_break.h byte.h case.h coe.h control.h \ ++env.h error.h fd.h fmt.h getln.h ndelay.h now.h open.h qldap.h qldap-errno.h \ ++qmail.h qmail-ldap.h read-ctrl.h seek.h sig.h str.h stralloc.h strerr.h \ ++substdio.h wait.h ++ ./compile $(LDAPFLAGS) qmail-group.c ++ + qmail-header.0: \ + qmail-header.5 + nroff -man qmail-header.5 > qmail-header.0 + ++qmail-imapd-ssl.run: \ ++qmail-imapd-ssl.sh conf-qmail ++ cat qmail-imapd-ssl.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-imapd-ssl.run ++ chmod 755 qmail-imapd-ssl.run ++ ++qmail-imapd.run: \ ++qmail-imapd.sh conf-qmail ++ cat qmail-imapd.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-imapd.run ++ chmod 755 qmail-imapd.run ++ + qmail-inject: \ + load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \ + control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \ +@@ -1171,15 +1582,16 @@ qmail-limits.9 conf-break conf-spawn + > qmail-limits.7 + + qmail-local: \ +-load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ ++load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o mailmaker.o \ + slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ + wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ +-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib +- ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \ +- slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \ +- lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ +- substdio.a error.a str.a fs.a datetime.a auto_qmail.o \ +- auto_patrn.o `cat socket.lib` ++fs.a datetime.a auto_qmail.o auto_patrn.o control.o socket.lib \ ++maildir++.o qldap-errno.o ++ ./load qmail-local qmail.o quote.o maildir++.o now.o gfrom.o \ ++ myctime.o mailmaker.o slurpclose.o case.a getln.a getopt.a sig.a \ ++ open.a seek.a lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ ++ substdio.a qldap-errno.o error.a str.a fs.a datetime.a auto_qmail.o \ ++ auto_patrn.o `cat socket.lib` + + qmail-local.0: \ + qmail-local.8 +@@ -1188,23 +1600,47 @@ qmail-local.8 + qmail-local.o: \ + compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \ + open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \ +-substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \ +-gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \ +-substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h +- ./compile qmail-local.c ++sgetopt.h subgetopt.h alloc.h error.h stralloc.h gen_alloc.h fmt.h \ ++str.h now.h case.h quote.h qmail.h slurpclose.h myctime.h gfrom.h \ ++auto_patrn.h qmail-ldap.h qldap-errno.h auto_qmail.h scan.h maildir++.h \ ++mailmaker.h ++ ./compile $(LDAPFLAGS) $(MDIRMAKE) qmail-local.c + + qmail-log.0: \ + qmail-log.5 + nroff -man qmail-log.5 > qmail-log.0 + ++qmail-ldaplookup: \ ++load qmail-ldaplookup.o qldap.a passwd.o digest_md4.o digest_md5.o \ ++digest_rmd160.o digest_sha1.o base64.o constmap.o localdelivery.o \ ++dirmaker.o wait.a read-ctrl.o control.o env.a getopt.a getln.a stralloc.a \ ++alloc.a strerr.a error.a substdio.a open.a fs.a str.a case.a auto_usera.o \ ++auto_qmail.o ++ ./load qmail-ldaplookup qldap.a passwd.o digest_md4.o digest_md5.o \ ++ digest_rmd160.o digest_sha1.o base64.o constmap.o localdelivery.o \ ++ dirmaker.o wait.a read-ctrl.o control.o env.a getopt.a getln.a \ ++ stralloc.a alloc.a strerr.a error.a substdio.a open.a fs.a str.a \ ++ case.a auto_usera.o auto_qmail.o $(LDAPLIBS) $(SHADOWLIBS) ++ ++qmail-ldaplookup.o: \ ++compile qmail-ldaplookup.c alloc.h auto_usera.h byte.h case.h env.h error.h \ ++localdelivery.h output.h passwd.h qldap.h qldap-cluster.h qldap-debug.h \ ++qldap-errno.h qmail-ldap.h read-ctrl.h scan.h sgetopt.h str.h stralloc.h \ ++strerr.h subfd.h substdio.h dirmaker.h ++ ./compile $(LDAPFLAGS) $(SHADOWOPTS) $(HDIRMAKE) $(DEBUG) \ ++ qmail-ldaplookup.c ++ + qmail-lspawn: \ +-load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \ +-case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \ +-fs.a auto_qmail.o auto_uids.o auto_spawn.o +- ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \ +- sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \ +- substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \ +- auto_spawn.o ++load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o control.o \ ++sig.a strerr.a getln.a wait.a case.a cdb.a fd.a open.a stralloc.a \ ++alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \ ++auto_spawn.o auto_usera.o env.a qldap.a dirmaker.o read-ctrl.o \ ++localdelivery.o seek.a constmap.o ++ ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o control.o \ ++ qldap.a sig.a strerr.a constmap.o getln.a wait.a case.a cdb.a \ ++ fd.a seek.a open.a dirmaker.o read-ctrl.o localdelivery.o env.a \ ++ stralloc.a alloc.a substdio.a str.a error.a fs.a auto_qmail.o \ ++ auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS) + + qmail-lspawn.0: \ + qmail-lspawn.8 +@@ -1213,15 +1649,19 @@ qmail-lspawn.8 + qmail-lspawn.o: \ + compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \ + gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \ +-slurpclose.h auto_qmail.h auto_uids.h qlx.h +- ./compile qmail-lspawn.c ++slurpclose.h auto_qmail.h auto_uids.h qlx.h \ ++auto_break.h auto_usera.h byte.h check.h env.h fmt.h localdelivery.h \ ++open.h qldap.h qldap-debug.h qldap-errno.h qmail-ldap.h read-ctrl.h \ ++sig.h str.h qldap-cluster.h getln.h seek.h dirmaker.h ++ ./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) $(DEBUG) \ ++ qmail-lspawn.c + + qmail-newmrh: \ +-load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \ ++load qmail-newmrh.o getln.a open.a cdbmake.a seek.a case.a \ + stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o +- ./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \ +- seek.a case.a stralloc.a alloc.a strerr.a substdio.a \ +- error.a str.a auto_qmail.o ++ ./load qmail-newmrh getln.a open.a cdbmake.a seek.a \ ++ case.a stralloc.a alloc.a strerr.a substdio.a error.a \ ++ str.a auto_qmail.o + + qmail-newmrh.0: \ + qmail-newmrh.8 +@@ -1237,14 +1677,14 @@ qmail-newmrh.9 conf-break conf-spawn + + qmail-newmrh.o: \ + compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \ +-getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \ +-uint32.h substdio.h ++getln.h exit.h readwrite.h open.h auto_qmail.h cdb_make.h uint32.h \ ++substdio.h + ./compile qmail-newmrh.c + + qmail-newu: \ +-load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \ ++load qmail-newu.o getln.a open.a seek.a cdbmake.a case.a \ + stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o +- ./load qmail-newu cdbmss.o getln.a open.a seek.a cdbmake.a \ ++ ./load qmail-newu getln.a open.a cdbmake.a seek.a \ + case.a stralloc.a alloc.a substdio.a error.a str.a \ + auto_qmail.o + +@@ -1262,18 +1702,26 @@ qmail-newu.9 conf-break conf-spawn + + qmail-newu.o: \ + compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \ +-getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \ +-readwrite.h open.h error.h case.h auto_qmail.h ++getln.h substdio.h cdb_make.h uint32.h substdio.h exit.h readwrite.h \ ++open.h error.h case.h auto_qmail.h + ./compile qmail-newu.c + ++qmail-pbsdbd.run: \ ++qmail-pbsdbd.sh conf-qmail ++ cat qmail-pbsdbd.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-pbsdbd.run ++ chmod 755 qmail-pbsdbd.run ++ + qmail-pop3d: \ + load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ +-maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ +-stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib +- ./load qmail-pop3d commands.o case.a timeoutread.o \ ++maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a str.a \ ++stralloc.a alloc.a substdio.a error.a fs.a socket.lib maildir++.o \ ++seek.a ++ ./load qmail-pop3d commands.o maildir++.o case.a timeoutread.o \ + timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \ + open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \ +- fs.a `cat socket.lib` ++ fs.a seek.a `cat socket.lib` + + qmail-pop3d.0: \ + qmail-pop3d.8 +@@ -1283,8 +1731,22 @@ qmail-pop3d.o: \ + compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \ + substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \ + str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \ +-timeoutwrite.h +- ./compile qmail-pop3d.c ++timeoutwrite.h maildir++.h ++ ./compile $(LDAPFLAGS) $(MNW) qmail-pop3d.c ++ ++qmail-pop3d-ssl.run: \ ++qmail-pop3d-ssl.sh conf-qmail ++ cat qmail-pop3d-ssl.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-pop3d-ssl.run ++ chmod 755 qmail-pop3d-ssl.run ++ ++qmail-pop3d.run: \ ++qmail-pop3d.sh conf-qmail ++ cat qmail-pop3d.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-pop3d.run ++ chmod 755 qmail-pop3d.run + + qmail-popup: \ + load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \ +@@ -1302,7 +1764,7 @@ qmail-popup.o: \ + compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \ + substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \ + readwrite.h timeoutread.h timeoutwrite.h +- ./compile qmail-popup.c ++ ./compile $(DEBUG) qmail-popup.c + + qmail-pw2u: \ + load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \ +@@ -1334,11 +1796,13 @@ auto_usera.h + qmail-qmqpc: \ + load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \ + timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \ +-getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib ++getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib \ ++dns.lib + ./load qmail-qmqpc slurpclose.o timeoutread.o \ + timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \ + sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \ +- error.a str.a fs.a `cat socket.lib` ++ error.a fs.a dns.o str.a ipalloc.o `cat dns.lib` `cat socket.lib` \ ++ $(ZLIB) + + qmail-qmqpc.0: \ + qmail-qmqpc.8 +@@ -1347,15 +1811,15 @@ qmail-qmqpc.8 + qmail-qmqpc.o: \ + compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \ + stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \ +-timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h +- ./compile qmail-qmqpc.c ++timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h ipalloc.h ++ ./compile $(LDAPFLAGS) $(ZINCLUDES) qmail-qmqpc.c + + qmail-qmqpd: \ + load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \ + env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a + ./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \ + auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \ +- str.a datetime.a fs.a ++ str.a datetime.a fs.a $(ZLIB) + + qmail-qmqpd.0: \ + qmail-qmqpd.8 +@@ -1364,17 +1828,24 @@ qmail-qmqpd.8 + qmail-qmqpd.o: \ + compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \ + sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h +- ./compile qmail-qmqpd.c ++ ./compile $(LDAPFLAGS) $(ZINCLUDES) qmail-qmqpd.c ++ ++qmail-qmqpd.run: \ ++qmail-qmqpd.sh conf-qmail ++ cat qmail-qmqpd.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-qmqpd.run ++ chmod 755 qmail-qmqpd.run + + qmail-qmtpd: \ + load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \ +-date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \ +-getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \ +-str.a fs.a auto_qmail.o ++date822fmt.o now.o qmail.o cdb.a fd.a seek.a wait.a datetime.a \ ++open.a getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a \ ++error.a str.a fs.a auto_qmail.o + ./load qmail-qmtpd rcpthosts.o control.o constmap.o \ +- received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ +- datetime.a open.a getln.a sig.a case.a env.a stralloc.a \ +- alloc.a substdio.a error.a str.a fs.a auto_qmail.o ++ received.o date822fmt.o now.o qmail.o cdb.a fd.a seek.a \ ++ wait.a datetime.a open.a getln.a sig.a case.a env.a \ ++ stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o + + qmail-qmtpd.0: \ + qmail-qmtpd.8 +@@ -1421,11 +1892,12 @@ qmail-qstat.8 + qmail-queue: \ + load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \ + datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \ +-str.a fs.a auto_qmail.o auto_split.o auto_uids.o +- ./load qmail-queue triggerpull.o fmtqfn.o now.o \ +- date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \ +- alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ +- auto_split.o auto_uids.o ++str.a fs.a auto_qmail.o auto_split.o auto_uids.o control.o constmap.o \ ++stralloc.a case.a getln.a ++ ./load qmail-queue triggerpull.o fmtqfn.o now.o control.o \ ++ constmap.o date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \ ++ stralloc.a getln.a case.a alloc.a substdio.a error.a str.a fs.a \ ++ auto_qmail.o auto_split.o auto_uids.o + + qmail-queue.0: \ + qmail-queue.8 +@@ -1435,18 +1907,36 @@ qmail-queue.o: \ + compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \ + alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \ + auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h +- ./compile qmail-queue.c ++ ./compile $(LDAPFLAGS) qmail-queue.c ++ ++qmail-quotawarn: \ ++load qmail-quotawarn.o newfield.o now.o date822fmt.o mailmagic.o case.a \ ++control.o fd.a wait.a open.a myctime.o case.a getln.a sig.a open.a seek.a \ ++lock.a datetime.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ ++fs.a auto_qmail.o ++ ./load qmail-quotawarn newfield.o now.o date822fmt.o mailmagic.o \ ++ case.a control.o fd.a wait.a open.a myctime.o case.a getln.a sig.a \ ++ open.a seek.a lock.a datetime.a env.a stralloc.a alloc.a strerr.a \ ++ substdio.a error.a str.a fs.a auto_qmail.o ++ ++qmail-quotawarn.o: \ ++compile qmail-quotawarn.c auto_qmail.h byte.h case.h control.h date822fmt.h \ ++datetime.h env.h error.h exit.h fmt.h getln.h mailmagic.h myctime.h \ ++newfield.h now.h open.h qmail-ldap.h seek.h sig.h str.h strerr.h substdio.h \ ++wait.h lock.h ++ ./compile qmail-quotawarn.c + + qmail-remote: \ + load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \ +-timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \ ++timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o base64.o \ + ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \ +-substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib ++strerr.a substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib + ./load qmail-remote control.o constmap.o timeoutread.o \ + timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \ +- ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ +- lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ +- str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` ++ ipalloc.o ipme.o quote.o base64.o ndelay.a case.a sig.a \ ++ open.a lock.a seek.a getln.a stralloc.a alloc.a strerr.a \ ++ substdio.a error.a str.a fs.a auto_qmail.o \ ++ `cat dns.lib` `cat socket.lib` $(TLSLIBS) $(ZLIB) + + qmail-remote.0: \ + qmail-remote.8 +@@ -1458,7 +1948,24 @@ subfd.h substdio.h scan.h case.h error.h + alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \ + gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \ + tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h +- ./compile qmail-remote.c ++ ./compile $(LDAPFLAGS) $(TLS) $(TLSINCLUDES) $(ZINCLUDES) \ ++ qmail-remote.c ++ ++qmail-reply: \ ++load qmail-reply.o mailmagic.o case.a control.o constmap.o getln.a \ ++sig.a newfield.o now.o date822fmt.o datetime.a open.a seek.a env.a \ ++qmail.o getopt.a fd.a wait.a digest_md5.o base64.o stralloc.a alloc.a \ ++strerr.a substdio.a error.a str.a fs.a auto_qmail.o ++ ./load qmail-reply mailmagic.o case.a control.o constmap.o \ ++ getln.a sig.a newfield.o now.o date822fmt.o datetime.a open.a \ ++ seek.a env.a qmail.o getopt.a fd.a wait.a digest_md5.o base64.o \ ++ stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o ++ ++qmail-reply.o: \ ++compile qmail-reply.c byte.h case.h control.h constmap.h direntry.h env.h \ ++error.h exit.h getln.h newfield.h now.h open.h qmail.h qmail-ldap.h \ ++readwrite.h seek.h sgetopt.h strerr.h stralloc.h substdio.h uint32.h ++ ./compile $(LDAPFLAGS) qmail-reply.c + + qmail-rspawn: \ + load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \ +@@ -1478,17 +1985,33 @@ compile qmail-rspawn.c fd.h wait.h subst + tcpto.h + ./compile qmail-rspawn.c + ++qmail-secretary: \ ++load qmail-secretary.o base64.o digest_sha1.o control.o newfield.o now.o \ ++date822fmt.o datetime.a mailmaker.o mailmagic.o case.a getln.a qmail.o \ ++getopt.a seek.a fd.a wait.a sig.a open.a stralloc.a env.a alloc.a strerr.a \ ++substdio.a error.a str.a fs.a auto_qmail.o ++ ./load qmail-secretary base64.o digest_sha1.o control.o newfield.o \ ++ now.o date822fmt.o datetime.a mailmaker.o mailmagic.o case.a getln.a \ ++ qmail.o getopt.a seek.a fd.a wait.a sig.a open.a stralloc.a env.a \ ++ alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o ++ ++qmail-secretary.o: \ ++compile qmail-secretary.c uint32.h base64.h byte.h case.h digest_sha1.h \ ++env.h error.h fmt.h getln.h mailmagic.h now.h open.h seek.h sgetopt.h \ ++sig.h str.h stralloc.h strerr.h substdio.h qldap-errno.h mailmaker.h ++ ./compile $(LDAPFLAGS) $(MDIRMAKE) qmail-secretary.c ++ + qmail-send: \ + load qmail-send.o 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 ++datetime.a case.a ndelay.a getln.a wait.a cdb.a seek.a fd.a sig.a \ ++open.a lock.a stralloc.a env.a alloc.a substdio.a error.a str.a fs.a \ ++auto_qmail.o auto_split.o + ./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 ++ wait.a cdb.a seek.a fd.a sig.a open.a lock.a stralloc.a env.a \ ++ alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_split.o + + qmail-send.0: \ + qmail-send.8 +@@ -1508,8 +2031,8 @@ open.h seek.h exit.h lock.h ndelay.h now + substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \ + scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \ + qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \ +-fmtqfn.h readsubdir.h direntry.h +- ./compile qmail-send.c ++fmtqfn.h readsubdir.h direntry.h cdb.h uint32.h ++ ./compile $(LDAPFLAGS) qmail-send.c + + qmail-showctl: \ + load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \ +@@ -1532,17 +2055,18 @@ auto_split.h + ./compile qmail-showctl.c + + qmail-smtpd: \ +-load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ ++load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o rbl.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 +- ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ ++date822fmt.o now.o qmail.o execcheck.o cdb.a smtpcall.o coe.o fd.a \ ++seek.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 dns.lib socket.lib ++ ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o rbl.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` ++ received.o date822fmt.o now.o qmail.o execcheck.o cdb.a \ ++ smtpcall.o coe.o fd.a seek.a wait.a datetime.a getln.a \ ++ open.a sig.a case.a env.a stralloc.a alloc.a substdio.a \ ++ error.a fs.a auto_qmail.o dns.o str.a \ ++ `cat dns.lib` `cat socket.lib` $(TLSLIBS) $(ZLIB) + + qmail-smtpd.0: \ + qmail-smtpd.8 +@@ -1553,8 +2077,16 @@ compile qmail-smtpd.c sig.h readwrite.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 +- ./compile qmail-smtpd.c ++exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h rbl.h ++ ./compile $(LDAPFLAGS) $(TLS) $(TLSINCLUDES) $(ZINCLUDES) \ ++ qmail-smtpd.c ++ ++qmail-smtpd.run: \ ++qmail-smtpd.sh conf-qmail ++ cat qmail-smtpd.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail-smtpd.run ++ chmod 755 qmail-smtpd.run + + qmail-start: \ + load qmail-start.o prot.o fd.a auto_uids.o +@@ -1574,7 +2106,7 @@ qmail-start.9 conf-break conf-spawn + + qmail-start.o: \ + compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h +- ./compile qmail-start.c ++ ./compile $(LDAPFLAGS) qmail-start.c + + qmail-tcpok: \ + load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \ +@@ -1606,6 +2138,20 @@ compile qmail-tcpto.c substdio.h subfd.h + fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h + ./compile qmail-tcpto.c + ++qmail-todo: \ ++load qmail-todo.o control.o constmap.o trigger.o fmtqfn.o now.o \ ++readsubdir.o case.a ndelay.a getln.a sig.a cdb.a open.a stralloc.a \ ++alloc.a substdio.a error.a str.a seek.a fs.a auto_qmail.o auto_split.o ++ ./load qmail-todo control.o constmap.o trigger.o fmtqfn.o now.o \ ++ readsubdir.o case.a ndelay.a getln.a sig.a cdb.a open.a stralloc.a \ ++ alloc.a substdio.a error.a str.a seek.a fs.a auto_qmail.o auto_split.o ++ ++qmail-todo.o: \ ++compile qmail-todo.c alloc.h auto_qmail.h byte.h cdb.h constmap.h control.h \ ++direntry.h error.h exit.h fmt.h fmtqfn.h getln.h open.h ndelay.h now.h \ ++readsubdir.h scan.h select.h sig.h str.h stralloc.h substdio.h trigger.h ++ ./compile $(LDAPFLAGS) qmail-todo.c ++ + qmail-upq: \ + warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split + cat warn-auto.sh qmail-upq.sh \ +@@ -1627,6 +2173,19 @@ qmail-users.9 conf-break conf-spawn + | sed s}SPAWN}"`head -1 conf-spawn`"}g \ + > qmail-users.5 + ++qmail-verify: \ ++load qmail-verify.o qldap.a read-ctrl.o control.o getln.a substdio.a \ ++stralloc.a env.a alloc.a error.a open.a fs.a case.a str.a timeoutread.o \ ++auto_qmail.o ++ ./load qmail-verify qldap.a read-ctrl.o control.o getln.a \ ++ substdio.a stralloc.a env.a alloc.a error.a open.a fs.a case.a \ ++ str.a timeoutread.o auto_qmail.o $(LDAPLIBS) ++ ++qmail-verify.o: \ ++compile qmail-verify.c error.h getln.h qldap.h qldap-errno.h qmail-ldap.h \ ++read-ctrl.h stralloc.h subfd.h substdio.h timeoutread.h ++ ./compile $(LDAPFLAGS) $(DEBUG) qmail-verify.c ++ + qmail.0: \ + qmail.7 + nroff -man qmail.7 > qmail.0 +@@ -1634,7 +2193,14 @@ qmail.7 + qmail.o: \ + compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \ + qmail.h substdio.h auto_qmail.h +- ./compile qmail.c ++ ./compile $(LDAPFLAGS) qmail.c ++ ++qmail.run: \ ++qmail.sh conf-qmail ++ cat qmail.sh \ ++ | sed s}%QMAIL%}"`head -1 conf-qmail`"}g \ ++ > qmail.run ++ chmod 755 qmail.run + + qreceipt: \ + load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \ +@@ -1676,6 +2242,10 @@ quote.o: \ + compile quote.c stralloc.h gen_alloc.h str.h quote.h + ./compile quote.c + ++rbl.o: \ ++compile rbl.c dns.h env.h ipalloc.h qmail.h rbl.h stralloc.h ++ ./compile rbl.c ++ + rcpthosts.o: \ + compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \ + constmap.h stralloc.h gen_alloc.h rcpthosts.h +@@ -1686,6 +2256,14 @@ compile readsubdir.c readsubdir.h dirent + auto_split.h + ./compile readsubdir.c + ++readwrite.o: \ ++compile readwrite.c readwrite.h ++ ./compile readwrite.c ++ ++read-ctrl.o: \ ++compile read-ctrl.c auto_qmail.h error.h open.h read-ctrl.h ++ ./compile read-ctrl.c ++ + received.o: \ + compile received.c fmt.h qmail.h substdio.h now.h datetime.h \ + datetime.h date822fmt.h received.h +@@ -1743,7 +2321,7 @@ substdio.h alloc.h auto_qmail.h exit.h e + ./compile sendmail.c + + setup: \ +-it man ++it man ldap + ./install + + sgetopt.o: \ +@@ -1795,9 +2373,8 @@ make-makelib.sh trycpp.c warn-auto.sh au + auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \ + install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \ + case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \ +-cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \ +-cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \ +-coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \ ++cdb.3 cdb.c cdb.h cdb_hash.c cdb_make.c cdb_make.h coe.3 coe.h \ ++coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \ + fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \ + open.h open_append.c open_excl.c open_read.c open_trunc.c \ + open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \ +@@ -1883,6 +2460,11 @@ compile slurpclose.c stralloc.h gen_allo + error.h + ./compile slurpclose.c + ++smtpcall.o: \ ++compile smtpcall.c auto_qmail.h coe.h fd.h substdio.h str.h stralloc.h \ ++timeoutread.h timeoutwrite.h wait.h smtpcall.h ++ ./compile smtpcall.c ++ + socket.lib: \ + trylsock.c compile load + ( ( ./compile trylsock.c && \ +@@ -1895,7 +2477,7 @@ compile chkspawn spawn.c sig.h wait.h su + stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \ + auto_qmail.h auto_uids.h auto_spawn.h + ./chkspawn +- ./compile spawn.c ++ ./compile $(DEBUG) spawn.c + + splogger: \ + load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib +@@ -1914,10 +2496,10 @@ scan.h fmt.h + str.a: \ + makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \ + str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \ +-byte_cr.o byte_zero.o ++byte_cr.o byte_zero.o byte_repl.o + ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \ + str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \ +- byte_diff.o byte_copy.o byte_cr.o byte_zero.o ++ byte_diff.o byte_copy.o byte_cr.o byte_zero.o byte_repl.o + + str_chr.o: \ + compile str_chr.c str.h +@@ -2036,10 +2618,10 @@ compile substdi.c substdio.h byte.h erro + + substdio.a: \ + makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \ +-subfdouts.o subfdin.o subfdins.o substdio_copy.o ++subfdouts.o subfdin.o subfdins.o substdio_copy.o readwrite.o + ./makelib substdio.a substdio.o substdi.o substdo.o \ + subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \ +- substdio_copy.o ++ substdio_copy.o readwrite.o + + substdio.o: \ + compile substdio.c substdio.h +@@ -2139,3 +2721,24 @@ compile wait_nohang.c haswaitp.h + wait_pid.o: \ + compile wait_pid.c error.h haswaitp.h + ./compile wait_pid.c ++ ++cert: ++ $(OPENSSLBIN) req -new -x509 -nodes \ ++ -out `head -1 conf-qmail`/control/cert.pem -days 366 \ ++ -keyout `head -1 conf-qmail`/control/cert.pem ++ chmod 640 `head -1 conf-qmail`/control/cert.pem ++ chown qmaild:qmail `head -1 conf-qmail`/control/cert.pem ++ ++cert-req: ++ $(OPENSSLBIN) req -new -nodes \ ++ -out req.pem \ ++ -keyout `head -1 conf-qmail`/control/cert.pem ++ chmod 640 `head -1 conf-qmail`/control/cert.pem ++ chown qmaild:qmail `head -1 conf-qmail`/control/cert.pem ++ @echo ++ @echo "Send req.pem to your CA to obtain signed_req.pem, and do:" ++ @echo "cat signed_req.pem >> `head -1 conf-qmail`/control/cert.pem" ++ ++backup: \ ++clean ++ tar cf $(BACKUPPATH) . +diff -upN qmail-1.03/Makefile.cdb qmail-ldap/Makefile.cdb +--- qmail-1.03/Makefile.cdb Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/Makefile.cdb Wed May 5 17:42:11 2004 +@@ -0,0 +1,60 @@ ++# ++# Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker, ++# Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# 1. Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# 2. Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# 3. All advertising materials mentioning features or use of this software ++# must display the following acknowledgement: ++# This product includes software developed by Internet Business ++# Solutions AG and its contributors. ++# 4. Neither the name of the author nor the names of its contributors ++# may be used to endorse or promote products derived from this software ++# without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++# SUCH DAMAGE. ++# ++ ++ ++# Simple Makefile to keep cdb databases up to date ++# This Makefile assumes that tcprules and qmail-cdb are in your $PATH ++# if not edit the next two lines. ++TCPRULES=tcprules ++QMAILRULES="%QMAIL%/bin/qmail-cdb" ++ ++FILES= locals.cdb rcpthosts.cdb qmail-smtpd.cdb qmail-qmqpd.cdb \ ++ qmail-pop3d.cdb qmail-imapd.cdb ++ ++TMPFILE=rules.tmp ++ ++.SUFFIXES: .cdb .rules ++ ++all: $(FILES) ++ @rm -f $(TMPFILE) ++ ++# locals and rcpthosts are special cases... ++locals.cdb: locals ++ $(QMAILRULES) locals.cdb $(TMPFILE) < locals ++ ++rcpthosts.cdb: rcpthosts ++ $(QMAILRULES) rcpthosts.cdb $(TMPFILE) < rcpthosts ++ ++.rules.cdb: ++ $(TCPRULES) $@ $(TMPFILE) < $< ++ +diff -upN qmail-1.03/POPBEFORESMTP qmail-ldap/POPBEFORESMTP +--- qmail-1.03/POPBEFORESMTP Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/POPBEFORESMTP Wed May 5 17:42:11 2004 +@@ -0,0 +1,194 @@ ++POPBEFORESMTP by Claudio Jeker and ++Andre Oppermann ++(c) 2002-2004 Internet Business Solutions Ltd. ++ ++The POPBEFORESMTP tools are a part of the qmail-ldap patch. ++This patch for qmail comes with NO WARRANTY. ++ ++RELEASE: current ($Date: 2004/04/16 13:24:16 $) ++ ++POP-Before-SMTP: ++====================== ++ ++TOC: ++ HOW DOES IT WORK ++ INSTALL ++ CONFIG FILES ++ SETUP ++ - pbsadd ++ - pbscheck ++ - pbsdbd ++ EXAMPLES ++ ++================================================================================ ++ ++HOW DOES IT WORK ++ ++ From http://www.lifewithqmail.org/ldap: ++ As we all know, SMTP does not contain any authentication mechanisms by ++ default. So in practice you are allowing relaying through your server only ++ for some IP addresses, normally your corporate network. If your users are ++ coming from various, dynamic IP addresses they can't use your mailserver ++ for sending :-(( ++ ++ To overcome this limitation there are 3 possibilities: ++ ++ - relaying based on the envelope sender - a really bad idea, easy to abuse. ++ - SMTP AUTH - great, but your clients need to support it. For a patch see ++ http://www.lifewithqmail.org/ldap ++ - POP-before-SMTP - when the user gets his mail through pop3 or imap, his ++ IP address is recorded and the permission to relay is given for this IP ++ for a defined time. ++ ++ SMTP AUTH would be the best solution as username and password are supplied ++ when sending, but as long as too many clients are lacking support for it, ++ this is not an option for most of us. ++ ++ Most POP-before-SMTP solutions use the tcpserver tcprules cdb file to ++ store the allowed IP addresses. This does not work in a clustered setup. ++ Our solution uses two clients pbsadd and pbscheck and a server pbsdbd which ++ stores the IP addresses in a database. ++ pbsadd has to be added just after auth_pop or auth_imap and will add new ++ allowed IP addresses to the cache. ++ pbscheck runs before qmail-smtpd and sets the RELAYCLIENT environment if the ++ IP address is allowed to relay. ++ pbsdbd is the Pop-Before-Smtp DataBase Daemon. pbsdbd uses a similar cache ++ algorithm as djbdns' dnscache daemon. ++ pbsadd and pbscheck communicate over UDP with the pbsdbd server. ++ ++================================================================================ ++ ++INSTALL ++ ++ The Tools pbsadd, pbscheck and pbsdbd are installed in the qmail binary ++ directory, normally /var/qmail/bin. ++ ++ NOTE: the tools can also be used on qmail systems without the qmail-ldap patch. ++ ++================================================================================ ++ ++CONFIG FILES ++ ++~control/pbsservers ++ ++ A list of IP addresses of running pbsdbd servers. ++ This file is only used by the clients pbsadd and pbscheck. ++ Required ++ Example: ++ 127.0.0.1 ++ 10.0.1.1 ++ 10.0.2.1 ++ ++~control/pbsip ++ ++ The pbsdbd server's address is given through this control file. ++ This file is only needed for the pbsdbd server. ++ Default: 0.0.0.0 ++ Example: 127.0.0.1 ++ ++~control/pbsport ++ ++ The port where all pbsdbd servers are listening on. ++ This file if used is needed by all pbs tools and has to be in sync on all ++ cluster machines. ++ Default: 2821 ++ Example: 6666 ++ Note: Ports > 1024 should be used so that the pbsdbd server can be run ++ unprivileged. ++ ++~control/pbssecret ++ ++ Shared secret used by pbsadd and pbsdbd to authenticate the client. ++ Required for pbsdbd and pbsadd. ++ Example: mekmitasdigoat ++ ++~control/pbscachesize ++ ++ Size in bytes used for the cache. Normally you do not need to set this ++ because the default value is big enough. ++ Default: 1048576 /* equal to 1 MB */ ++ ++~control/pbstimeout ++ ++ Timeout in seconds until entries in the cache are invalidated. ++ Only used by the pbsdbd server. ++ Default: 600 ++ Example: 900 ++ ++~control/pbsenv ++ ++ Additional environment variables to include. ++ pbscheck will set these variables to the values pbsadd returned. ++ It is possible to rewrite the variables. A line like ++ USER=TCPREMOTEINFO will cause pbscheck to set the environment TCPREMOTEINFO ++ to the value set as USER in pbsadd. If you like to prepend some identifier ++ in front of the value you can this like this: ++ USER=TCPREMOTEINFO=[pbs] this will add [pbs] in front of the value returned ++ by pbsadd. ++ Multiline. ++ Default: none ++ Example: HOST ++ TCPREMOTEIP=FROMIP ++ USER=TCPREMOTEINFO=[pbs] ++ ++ ++================================================================================ ++ ++SETUP ++ ++pbsadd: ++ usage: pbsadd subprogram ... ++ ++ pbsadd will try to add the IP address $TCPREMOTEIP to all pbsdbd servers ++ listed in ~control/pbsservers. Afterward the subprogram with its arguments ++ is started. ++ On non fatal errors the subprogram will be started without successfully ++ update the database on the pbsdbd servers. ++ ++pbscheck: ++ usage: pbscheck subprogram ... ++ ++ pbscheck checks if the IP address $TCPREMOTEIP is allowed to relay. ++ It will send queries to the pbsdbd servers listed in ~control/pbsservers. ++ The first query will be sent to a randomly chosen server, if this timeouts ++ all servers will be tried one after another. ++ If the IP is allowed to relay the environment $RELAYCLIENT is set. ++ On non fatal errors the subprogram will be started without setting ++ $RELAYCLIENT. ++ ++pbsdbd: ++ usage: pbsdbd ++ ++ pbsdbd will listen on address specified in ~control/pbsip and the port ++ specified in ~control/pbsport (default 2821). ++ IP addresses will only be added to the cache if the secret specified in ++ ~control/pbssecret is included in the add request. ++ ++================================================================================ ++ ++EXAMPLES ++ ++ First create all necessary ~control files. ++ ++ NOTE: the following shell scripts are not finished. You have to edit them to ++ modify them for your needs. ++ ++ The pbsdbd should be run as unprivileged user, this can be done with setuidgid. ++ ++ #!/bin/sh ++ setuidgid qmaild pbsdbd ++ ++ pbsadd has to be run after auth_pop, auth_imap or checkpassword in the pop3 or ++ imap tool chain. ++ ++ #!/bin/sh ++ tcpserver 0 110 qmail-popup $HOST auth_pop pbsadd qmail-pop3d ./Maildir/ ++ ++ ++ pbscheck has to be run before qmail-smtpd. ++ ++ #!/bin/sh ++ tcpserver -x $SMTPRULES -v -u qmaild -g nofiles 0 25 pbscheck qmail-smtpd ++ ++ ++END :-) +diff -upN qmail-1.03/QLDAPGROUP qmail-ldap/QLDAPGROUP +--- qmail-1.03/QLDAPGROUP Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/QLDAPGROUP Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,170 @@ ++QMAILGROUP by Claudio Jeker ++(c) 2004 Internet Business Solutions Ltd. ++ ++ ++RELEASE: $Date: 2004/12/01 14:19:49 $ ($Revision: 1.3 $) ++ ++qmail-group and qmail-secretary: ++==================================== ++ ++While it is possible to implement simple mail distributors via multiple ++mailFrowarding entries in qmail-ldap it is not possible to do more complex or ++dynamic mail distributors. qmail-group adds this capability -- with the help of ++qmail-secretary -- to qmail-ldap. ++ ++qmail-group extends the basic qmailUser object with a new LDAP objectclass ++qmailGroup. The new object adds fields to specify members, senders and ++moderators for the list together with some standard settings. To define a ++mailing group both qmailUser and qmailGroup objects are necessary. ++ ++LDAP Schema: ++ ++In addition to the qmailUser attributes the following additional attributes are ++defined by qmailGroup: ++ ++senderconfirm: ++ If this boolean attribute is set to true than an incomming mail needs to be ++ approved by the sender. This ensures that the sender is aware that he is ++ sending to a list and makes it almost impossible to send forged mails, spam, ++ mail viruses and other junk to be distributed to list. If sender confirmation ++ is used a confirmation message is sent to the sender. This needs to reply to ++ that message if he does not do that the mail will be deleted after 1 week. ++ By default senderconfirmation is turned off. ++ ++membersonly: ++ If this boolean attribute is set to true than an incomming mail needs to come ++ from a member of the list. Only the envelope sender address is used for the ++ check. Because it is easy to forge the envelope sender address sender- ++ confirmation should be enabled too. ++ ++dnmember: ++filtermember: ++rfc822member: ++ Members of the group are specified by these attributes. It is possible to ++ specify a member by a LDAP distinguish name, a LDAP filter definiton or by ++ a rfc822 email address. ++ Example: ++ dnmember: uid=joe,ou=example,o=qmail-ldap,c=CH ++ filetrmember: ((objectclass=qmailUser)(employeeType=accountant)) ++ rfc822member: alice@qmail-ldap.org ++ ++dnsender: ++filtersender: ++rfc822sender: ++ It is possible to limit the allowed users to send to the list. If membersonly ++ is set to true and one of the sender attributes is set, mails to the list are ++ enforced to come form on of the specified senders. See also membersonly. ++ ++dnmoderator: ++rfc822moderator: ++ The mail group can be moderated -- mails need to be approved by one of the ++ specified moderators. An approval message is sent t each specified moderator. ++ Again to approve a message on of the moderators needs to reply the approval ++ message. If no approval was sent in one week the mail is deleted. ++ ++confirmtext: ++ This attribute can be used to specify a own confirm text used if sender- ++ confirmation is used. The usual %HEADER% magic of qmail-reply et al. can be ++ used here. ++ ++moderatortext: ++ This attribute can be used to specify a own approval text used if the list ++ is moderated. The usual %HEADER% magic of qmail-reply et al. can be used ++ here too. ++ ++bounceadmin: ++ Bounceadmin can be set to one or multiple rfc822 email addresses. Mail ++ delivery errors are then forwarded to these addresses instead of the sender ++ of the original mail. ++ ++To enable a mail-group at least following qmailUser attributes need to be set ++too: ++ ++mail: main mailaddress of the list ++mailalternateaddress: needs to be set to list-catchall@domain.tld, this is used ++ for moderation and sender confirmation but also for bounce handling. ++mailmessagestore: A valid messagestore for sender confirmation and moderation ++ is needed. ++ ++ ++qmail-secretary: ++ ++qmail-secretary is a helper program for qmail-group and ezmlm. It implements ++both moderation and sender confirmation. qmail-group calls qmail-secretary ++internally but for ezmlm the .qmail files need to be adapted. ++ ++usage (non ezmlm mode): ++qmail-secretary [ -Z ] [ -c | -C ] [[ -m addr ] ... ] [ -M file ] maildir ++ ++usage (ezmlm mode): ++qmail-secretary -z ezmlmdir [ -c | -C ] [[ -m addr ] ... ] [ -M file ] ++ maildir [ ezmlm-send ... ] ++ ++Options: ++-C Disable sender confirmation (default) ++-M file Use file as a list of moderators. One per line. ++-Z Non ezmlm mode (default). ++-c Enable sender confirmation ++-m addr Add addr to the list of moderators ++-z ezmlmdir Enable ezmlm mode and use ezmlmdir as base directory for ++ configuration. ++ ++qmail-secretary uses the secified Maildir to store the messages that need ++approval. Messages that need to be confirmed are stored in maildir/new and ++messages waiting for moderation approval are stored in maildir/cur. ++ ++In ezmlm mode following files from ezmlmdir are read: ++mailinglist Address of the mailing list ++inhost Incomming Host ++inlocal Incomming Local Address part ++outhost Outgoing Host ++outlocal outgoing Local Address part ++text/approve The moderation approve request text ++text/confirm The sender confirmation request text ++ ++In non ezmlm mode the information are extraceted from the environment. Mainly ++from: ++$LOCAL ++$SENDER ++$HOST ++$EXT ++$APPROVEMESS ++$CONFIRMMESS ++ ++LOCAL, SENDER, HOST and EXT are set by qmail-local but APPROVEMESS and ++CONFIRMMESS can be set by the caller. ++ ++Mails are tagged with a cryptographic hash. Sender confirmations are received ++by $LOCAL-confirm-@$HOST and bounces end in $LOCAL-reject-@$HOST. ++Moderation messages are received by $LOCAL-approve-@$HOST and bounces ++end in $LOCAL-bounce-@$HOST. ++ ++Simple setup: ++Following qmail files should be set for sender confirmation.. ++ ++.qmail ++|qmail-secretary -c ./Maildir/secretary ++ ++ ++.qmail-confirm-default ++|qmail-secretary -c ./Maildir/secretary ++ ++.qmail-reject-default ++|qmail-secretary -c ./Maildir/secretary ++ ++It is possible to just add a .qmail-default instead of .qmail-confirm-default ++and .qmail-reject-default. ++ ++Simple ezmlm setup: ++.qmail ++|qmail-secretary -c -z ezmlmdir ezmlmdir/secretary/ ezmlm-send ezmlmdir ++|ezmlm-send ezmlmdir ++|ezmlm-warn ezmlmdir || exit 0 ++ ++.qmail-default ++|qmail-secretary -c -z ezmlmdir ezmlmdir/secretary/ ezmlm-send ezmlmdir ++|ezmlm-manage ezmlmdir ++|ezmlm-warn ezmlmdir || exit 0 ++ ++The other .qmail files don't need to be modified. ++ +diff -upN qmail-1.03/QLDAPINSTALL qmail-ldap/QLDAPINSTALL +--- qmail-1.03/QLDAPINSTALL Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/QLDAPINSTALL Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,1267 @@ ++QMAIL_LDAP by Andre Oppermann , ++Claudio Jeker and Boris Lutz ++(c) 1998-2004 Internet Business Solutions AG ++ ++The qmail-ldap patch for qmail comes with NO WARRANTY. ++ ++This patch is under the BSD license. See LICENSE. ++ ++RELEASE: current ($Date: 2004/12/01 14:19:49 $) ++ ++TOC: ++ INSTALL how to install the patch ++ CONFIG FILES all about the extra config file ++ DEFAULT LDAP FIELDS all about the fields in ldap ++ EXAMPLES example ldif and slapd.conf ++ MAILINGLIST, BUGS & PROBLEMS How to help us helping you ++ ++TODO: ++ ++ see QLDAPTODO ++ ++NEWS: ++ ++ see QLDAPNEWS ++ ++IMPORTANT NEWS: ++ ++ - From release 20030901 on we broke certain backwards compatibility with ++ release 20030801 and prior releases for clarity and cleanup reasons!! ++ ++ - New qmailGroup attribute "bounceadmin", see QLDAPGROUP for more info ++ ++ - and as always a lot of smaller patches see QLDAPNEWS ++ ++================================================================================ ++ ++INSTALL: ++ ++1. Make sure you have fairly good knowledge of qmail and LDAP ++ READ THEIR FAQs. PLEASE. ++ ++2. Read this document. THIS IS IMPORTANT, this is no ++ ./configure; make; make install software. ++ If you are not familiar with compiling software you should definitifly ++ read http://www.lifewithqmail.org/ldap/ first. ++ ++3. You need the following compiled and installed ++ - OpenLDAP 2.x or higher (others might also work) ++ OpenLDAP releases < 2.0 should no longer be used (you have been warned). ++ and ++ - OpenSSL 0.9.4 or higher if you want TLS SMTP encrytion ++ ++ We recommend also using Dan Bernstein's toolset daemontools-0.76, ++ ucspi-tcp-0.88 and djbdns-1.05 to run qmail. ++ ++ If you have problems with OpenLDAP look into their FAQ. The same for ++ OpenSSL. ++ You NEED knowledge of LDAP so READ their FAQ and/or man pages. ++ ++4. Apply the qmail-ldap patches to a clean qmail-1.03 source tree ++ normaly "cd qmail-1.03_source_tree; patch -p1 < location_of_patch" ++ works ;-). There seems to be a problem with the original patch utility ++ on Solaris based systems, use the gnu patch utility instead. ++ A pre-compiled binary should be available at http://www.sunfreeware.com/ ++ or on many mirrors around the world. ++ ++5. Edit the conf-* files and the top of the Makefile (only the top ;-) ) ++ You can set/change: ++ - LDAPFLAGS= ++ -DALTQUEUE (to enable alternate queue selection via environment ++ variable QMAILQUEUE. Also known as qmailqueue patch.) ++ -DBIGBROTHER (turn on per address queue extra feature see the ++ section about the ~control/bigbrother control file) ++ -DBIGTODO (to enable the big todo patch, can be used together ++ with EXTERNAL_TODO) ++ -DBIND_8_COMPAT needed on system with new incompatible ++ bind9 header files. Currently this is necessary on MacOS X 10.3. ++ -DCLEARTEXTPASSWD (for cleartext passwords in ldap, bad idea) ++ -DDASH_EXT (turn on dash_ext support see 5.3) ++ -DDATA_COMPRESS (to enable smtp on the fly data compression. ++ It is needed to set ZLIB accordingly.) ++ -DEXTERNAL_TODO (to use the external high-performancer ++ -DQLDAP_CLUSTER (turns the cluster support on) ++ todo processing) ++ -DQMQP_COMPRESS (to enable QMQP on the fly data compression. ++ Can be used in clusters. It is needed to set ZLIB accordingly. ++ IMPORTANT: this breaks compatibility with the stock qmqp ++ protocol. So either all qmail-qmqpc/-qmqpd use the on the fly ++ compression or non.) ++ -DSMTPEXECCHECK (to enable Russell Nelsons antivirus patch ++ for qmail-smtpd. To turn it on set the REJECTEXEC env-var.) ++ -DDUPEALIAS (to make migration from some X.400 messaging ++ systems easier. See QLDAPNEWS 20031101 for more information.) ++ ++ - LDAPLIBS: the libraries you need for ldap, e.g. -lldap -llber ++ NOTE: on Solaris Systems you probably need also -lnsl -lsocket ++ newer OpenLDAP libs my need also -lresolv (DNS support). ++ It is also good to set the ld runpath with the -R switch ++ for more info ld(1) or gcc(1) and ++ http://www.lifewithqmail.org/ldap/. ++ - LDAPINCLUDES: perhaps you need a special include-path for ldap ++ NOTE: if you need this you may run into shared library problems ++ see http://www.lifewithqmail.org/ldap/. ++ ++ - ZLIB is used when DATA_COMPRESS and QMAP_COMPRESS is defined. Normaly ++ -lz should work, if libz is installed in a different location use ++ -L/path/to/zlibdir -lz ++ - MNW=-DMAKE_NETSCAPE_WORK (turns on the patch that fixes the problem ++ with the Netscape download progress bar and qmail-pop3d) ++ ++ - MDIRMAKE=-DAUTOMAILDIRMAKE (turns the auto-MAILdir-make-patch on) ++ - HDIRMAKE=-DAUTOHOMEDIRMAKE (compiles the auto-HOMEdir-make-patch ++ into the release, you need the ~control/dirmaker file to turn the ++ patch on, see CONFIG FILES) ++ ++ - SHADOWLIBS=-lcrypt is needed on most systems (except my OpenBSD box :-) ) ++ SHADOWLIBS=-lcrypt -lshadow , SHADOWOPTS=-DPW_SHADOW are needed on some ++ Systems (Solaris, Linux) for local password lookups ++ (just like the original djb-checkpassword. See Makefile.) ++ - DEBUG=-DDEBUG (compiles debugging into the auth modules and qmail-ldap, ++ see also 10.) ++ - TLS* stuff for TLS (SMTP encryption) mostly self explaining ++ ++5.1 Have a look at qmail-ldap.h, perhaps you want to change something there. ++ LDAP_CATCH_ALL: used for catching mails for a specific domain. ++ Also used for extension nameing with DASH_EXT. ++ QUOTA_WARNING_LEVEL: triger level for quotawarning in percent. ++ *ID_{MAX,MIN}: upper and lower limit for uid's and gid's. ++ RESTRICT_PROG: restrict delivery programm pathes to non special shell ++ characters. See also next section 5.2 ++ ALIASDEVNULL: replacement for the std. aliasempty for user with ++ neither homeDirectory nor mailMessageStore defined. ++ QLDAP_TIMEOUT: Default ldap search timeout. In seconds. ++ LDAP_*: Names of the ldap fields used for lookups. ++ DOTMODE_*: Names for the different dot modes. ++ MODE_*: Names for the different delivery modes. ++ ISACTIVE_*: Names for the account status. ++ ++5.2 Have a look at check.c if you want to change the ldap field check behaviour ++ In the standart patch we check for this (in regexp form): ++ user: [a-zA-Z0-9@_.][a-zA-Z0-9@_.-]* (for the LDAP_UID field) ++ path: [a-zA-Z0-9@_./:=][a-zA-Z0-9@_.-/:=]* ++ (for LDAP_MAILSTORE and LDAP_HOMEDIR) ++ prog: [a-zA-Z0-9@_./:=\\\t\n "'+,][a-zA-Z0-9@_.-/:=\\\t\n "'+,]* ++ (for LDAP_PROGRAM with RESTRICT_PROG on, if RESTRICT_PROG is 0 ++ then most shell escape characters are also allowed. e.g [$#!%&()*;]) ++ ++5.3 Note on DASH_EXT: ++ Finally we added a variation of Henning Brauer's dash-ext patch. The main ++ difference is the way it handels the extensions. ++ Example lookup scheme: ++ aaaa-bbbb-cccc@domain.tld ++ aaaa-bbbb-CATCHALL@domain.tld ++ aaaa-CATCHALL@domain.tld ++ CATCHALL@domain.tld ++ where CATCHALL is replaced with the value of LDAP_CATCH_ALL defined ++ in qmail-ldap.h. If CATCHALL is set to "default" instead of the standart ++ "catchall" it is almost stock qmails behaviour. ++ Note: Only up to four levels of dash extensions are checked to prevent ++ DoS attacks. You can change that in qmail-ldap.h via DASH_EXT_LEVELS. ++ ++6. Compile and install the stuff (it's the same as in standard qmail ++ install -> HINT: read the INSTALL and the FAQ file!!! :) ). ++ Now everything should be installed with correct permissions. ++ ++6.1 If "make setup check" fails with an error like this: ++ /usr/local/lib/libldap.so: undefined reference to `res_query' ++ /usr/local/lib/libldap.so: undefined reference to `dn_expand' ++ collect2: ld returned 1 exit status ++ make: *** [qmail-lspawn] Error 1 ++ You have forgotten to add -lresolv to LDAPLIBS. ++ ++6.2 If using TLS you can use 'make cert' or 'make cert-req' to create TLS ++ certificates ++ ++7. Create the LDAP user database and start the LDAP server ++ See qmail.schema for definition of all fields for OpenLDAP 2.x ++ ++8. Create the proper ~control/ldap* files for qmail-ldap ++ At least ldapserver and ldapbasedn must exist (and also 'me') ++ ++9. Test and Enjoy! ++ ++10. Debugging: as said befor you can compile qmail-lspawn and the auth modules ++ with a flexible debugging facility (option DEBUG). ++ The debug output gets logged through splogger or your favorite logging tool ++ connected to stderr for tcpserver-pop/imap chain. ++ To turn on debugging you need only to define the LOGLEVEL environment ++ variable (e.g. with env, env LOGLEVEL=3 qmail-start ...) ++ There are these LOGLEVEL: ++ LOGLEVEL=1 -> Errors ++ LOGLEVEL=2 -> Warnings ++ LOGLEVEL=4 -> Info ++ LOGLEVEL=8 -> Info^2 ++ LOGLEVEL=16 -> Debug ++ LOGLEVEL=32 -> Debug^2 ++ LOGLEVEL=64 -> LDAP Debug ++ LOGLEVEL=128 -> LDAP Debug^2 ++ LOGLEVEL=256 -> PASSWD, this level is normaly off because it shows ++ critical data (unencrypted and crypted passwords). To ++ turn it on edit checkpassword.c and increase the level ++ for init_debug(). ++ ++ WARNING: on production machines don't use levels higher 3 or you will get ++ incredible huge logfiles. ++ NOTE: too high debuglevels are reduced to the maximum allowed debug level ++ if the level parameter in init_debug() is smaler. ++ The LOGLEVEL is compare with a bit mask, so that ++ LOGLEVEL=3 will report warnings and errors but LOGLEVEL=2 will ++ only report warnings. ++ With the new log support the environment variable is LOGLEVEL but ++ the old DEBUGLEVEL is still supported. ++ The new log support will no longer add the log output to bounce ++ messages. ++ ++11. NOTE ABOUT POP/IMAP services ++ The stock qmail recomends that you use a program by the name 'checkpassword' ++ to do the authentication, like this: ++ ++ pop3 stream tcp nowait root \ ++ /var/qmail/bin/qmail-popup qmail-popup \ ++ YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir ++ ++ With the use of the LDAP patch, this have been slightly altered. We now use ++ a program by the name 'auth_pop' instead... Something like this (replacement ++ inetd.conf line): ++ ++ pop3 stream tcp nowait root \ ++ /var/qmail/bin/qmail-popup qmail-popup \ ++ YOURHOST /var/qmail/bin/auth_pop /var/qmail/bin/qmail-pop3d Maildir ++ ++ ++ Same goes for the command 'auth_imap' if your IMAP server can use an ++ external program for authentication. auth_imap was designed for ++ courier-IMAP and should work with it out of the box. ++ There is also a auth_ldap modul in courier-imap that should work too. ++ You can get courier-imap from http://www.inter7.com ++ ++ auth_pop and auth_imap are part of this patch and will be installed with the ++ other qmail programs. ++ ++================================================================================ ++ ++CONFIG FILES: ++ ++~control/aliasempty ++OR ++~control/defaultdelivery ++ ++ Default delivery mode used by and only by the startup scripts. ++ Default: ./Maildir/ ++ Example: ./ ++ Note: If you have a more complex default delivery you need to edit the ++ runscripts because qmail-pop3d and the imapd do not understand this ++ complex format. ++ ++~control/locals.cdb ++ ++ Replaces locals and is read by qmail-local and qmail-smtpd on the fly. ++ Default: locals ++ Note: You don't have to -HUP qmail-send for changes in locals.cdb to ++ take effect. As soon as you regenerate locals.cdb it will become ++ active. Use bin/qmail-cdb to create the locals.cdb file. ++ Alternatively you can do "make" in ~control/ directory. See the ++ Makefile for more information. ++ If this file exists locals is ignored. ++ ++~control/rcpthosts.cdb ++ ++ Replaces rcpthosts and morercpthosts.cdb and is read by qmail-smtpd on the fly. ++ Default: rcpthosts and morercpthosts.cdb ++ Note: qmail-smtpd reads locals(.cdb) as well and there is no need anymore ++ to replicate all domains here too. Only domains you are doing queueing ++ for must be listed here. As soon as you regenerate rcpthosts.cdb it will ++ become active. Use bin/qmail-cdb to create the rcpthosts.cdb file. ++ Alternatively you can do "make" in ~control/ directory. See the ++ Makefile for more information. ++ If this file exists rcpthosts and morercpthosts.cdb are ignored. ++ ++~control/ldapserver ++ ++ List of Hostnames or IP addresses of LDAP servers. One per line. ++ An additional port can be supplied with the host:port notation. ++ Required ++ Example: ++ ldap.nrg4u.com ++ ldap2.nrg4u.com ++ ldap3.nrg4u.com:1234 ++ ++~control/ldapbasedn ++ ++ The base DN from where the search in the LDAP tree begins ++ Normaly required ++ Default: NULL ++ Example: o=Internet Pipeline, c=CH ++ Note: Referrals are ignored ++ ++~control/ldapobjectclass ++ ++ The ldap objectclass the search will be limited to ++ Default: NULL, will search all objectclasses ++ Example: qmailUser ++ Note: Can specify more than one, must then be written in ldap search syntax ++ ++~control/ldaplogin ++ ++ Username for the LDAP server connection ++ Default: NULL ++ Example: cn=qmail-ldap, o=Internet Pipeline, c=CH ++ Note: The user must have enough rights to lookup all user information ++ ++~control/ldappassword ++ ++ Password for the LDAP server connection ++ Default: NULL ++ Note: The password is in clear text. The file should be owned by root and ++ mode (600) rw-------. If rcpt verify or auth_smtp is used then the ++ permissions must be adjusted so that the qmail-smtpd user -- normaly ++ qmaild -- has read access. ++ ++~control/ldapgrouplogin ++ ++ Username for the qmail-group LDAP server connection. ++ Default: use the login specified in ~control/ldaplogin ++ Example: cn=qmail-group, o=Internet Pipeline, c=CH ++ Note: The user must have enough rights to lookup the mail attribute. ++ Also the ldap limit used for this user must be enough high. ++ ++~control/ldapgrouppassword ++ ++ Password for the qmail-group LDAP server connection. ++ Default: NULL only if ~control/ldapgrouplogin is present else fall back to ++ ~control/ldappassword ++ Note: The password is in clear text. The file should not be readable for ++ all. ++ ++~control/ldaplocaldelivery ++ ++ To lookup the local passwd file if the LDAP lookup finds no match. This ++ affects qmail-lspawn and auth_* if the LDAP lookup returns nothing. ++ Default: enabled ++ Example: 1 ++ Note: boolean, use 0 (zero) or 1 (one) ++ ++~control/ldaprebind ++ ++ Use the possibility of rebinding to the ldap-server to compare pop3 ++ and imap passwords. So you can make your acl more restrictive. ++ Default: disabled ++ Example: 1 ++ Note: boolean, use 0 (zero) or 1 (one) ++ ++~control/ldapcluster ++ ++ Turn clustering on and off. Needs a qmail-ldap compiled with ++ -DQLDAP_CLUSTER or nothing will happen. Also don't forget to set up ++ qmail-qmqpd on all servers in the cluster. ++ Default: disabled ++ Example: 1 ++ Note: boolean, use 0 (zero) or 1 (one) ++ ATTN: the control files me, rcpthosts and locals have to be set carfully ++ or you will have big problems. ++ ++~control/ldapclusterhosts ++ ++ ldapclusterhosts contains a number of hostnames (FQDM) to check togehter ++ with ~control/me when clustering is on. This file is useful if you want to ++ run multiple instances of qmail-ldap on one machine. ++ Default: none, in other words just check with ~control/me ++ Example: customersmtp.nrg4u.com ++ Note: multiline ++ ++~control/defaultquotasize ++ ++ The default amount of disk space the user can use until all further messages ++ get bounced back to the sender. Size is a byte count. ++ Default: unlimited ++ Example: 1000000 (max 1000000 bytes size) ++ Note: is overridden by mailQuota*, make sure to have set ~control/quotowarning ++ otherwise you will not get quota warning messages ++ ++~control/defaultquotacount ++ ++ The default maximum amount of messages the user can have until all further ++ messages get bounced back to the sender. Count is a file count. ++ Default: unlimited ++ Example: 1000 (max 1000 Mails) ++ Note: is overridden by mailQuota*, make sure to have set ~control/quotowarning ++ otherwise you will not get quota warning messages ++ ++~control/ldapdefaultdotmode ++ ++ The default interpretation of .qmail files ++ Default: ldaponly ++ Example: both ++ Values: both, dotonly, ldaponly, ldapwithprog ++ Note: Works only for deliveries based on LDAP lookups. ++ Local mails use dotonly like in normal qmail. ++ ++~control/ldapmessagestore ++ ++ The default prefix for non absolute path's in mailMessageStore, without ++ heading '/'. ++ Default: NULL ++ Example: /maildisk ++ Note: Used in virtual users environments ++ ++~control/ldapuid ++ ++ The default UID used in virtual users environments. This value will be ++ used for ldap entries with no LDAP_QMAILUID (see below) field ++ Default: NULL ++ Example: 1010 ++ Note: should be a real UID, must be above 100 ++ ++~control/ldapgid ++ ++ The default GID used in virtual users environments. This value will be ++ used for ldap entries with no LDAP_QMAILGID (see below) field ++ Default: NULL ++ Example: 1010 ++ Note: should be a real GID, must be above 100 ++ ++~control/ldaptimeout ++ ++ The time the ldap search waits for a response from the ldap server ++ Default: 30 seconds ++ Example: 60 ++ Note: in seconds, if it gets no response within this time it will ++ continue either with the next specified ldap server or it will ++ defer the delivery and try again later. ++ ++~control/custombouncetext ++ ++ Additional custom text in bounce messages, e.g. for providing contact ++ information of your ISP or messages in your language ++ Default: NULL ++ Example: You can contact us at (555) 555 5555 ++ Note: Multiline ++ It MUST NOT contain a blank line ("\n\n") anywhere otherwise you ++ break qsmbf. Use a line with one or more spaces ("\n \n") instead. ++ See http://cr.yp.to/proto/qsbmf.txt for more info. ++ ++~control/quotawarning ++ ++ Custom text in quota warning message, e.g. for providing contact information ++ of your ISP ++ Default: NULL ++ Example: You can contact us at (555) 555 5555 ++ Note: Multiline. Needs to be present to make qmail-quotawarn work. ++ Supports the %HEADER% magic similar to qmail-reply. The headers From:, ++ Subject:, the content type headers and headers starting with X- can be ++ set. The value of the To: header is forced to the recipient address. ++ The %SUBJECT% magic of qmail-reply is not useful for a quotawarning and ++ therefor disabled. ++ ++~control/dirmaker ++ ++ Absolute path to your program/script that creates missing homedirs ++ Default: none (off) ++ Example: /var/qmail/bin/create_homedir ++ Note: the script is executeded after the setuid/gid, it isn't running ++ under root for security reasons. ++ The command is executed with execve not system ++ (so mkdir --mode=700 -p does not work!) use a shell script. ++ $1 is the homedir-path and $2 is aliasempty. ++ If you use $2 have a look at the first and last char to ensure that ++ it is a path to the maildir and not a pipe or mailbox delivery. ++ Possible very simple shell script: ++ ++ -cut- ++ #!/bin/sh ++ mkdir -m 700 -p $1 ++ #EOF ++ -cut- ++ ++~control/relaymailfrom ++ ++ This file contains envelope sender addresses that are allowed to relay through ++ this server. ++ Default: none ++ Example: user@domain or @domain ++ Note: Use with care, the envelope senders address can easily be spoofed and ++ then you are an open relay again. It is better to use a scheme like ++ POP before SMTP. ++ ++~control/rbllist ++ ++ Rbllist contains a number of RBL's to check for the given senders IP address. ++ The file consists of four tab or space separated fields. ++ basedomain: base domain address to lookup (e.g. relays.ordb.org) ++ action: one of addheader or reject. ++ addheader will just create a X-RBL: header whereas ++ reject will reject the smtp connection instantly with a 553 error. ++ matchon: any or IP-Address, if a IP-Address is specified the action is only ++ taken if the returned address form basedomain is equal to ++ IP-Address. With any all returned IP-Address will match. ++ message: message to be included in X-RBL: headers and 553 errors. ++ ++ Possible example: ++ # baseaddress action matchon Message ++ #======================================================================== ++ sbl.spamhaus.org reject 127.0.0.2 See http://www.spamhaus.org/SBL ++ relays.ordb.org addheader 127.0.0.2 See http://www.ordb.org/faq/ ++ list.dsbl.org addheader 127.0.0.2 See http://dsbl.org/main ++ bl.spamcop.net addheader 127.0.0.2 See http://spamcop.net/ ++ relays.ordb.org reject any see http://ordb.org ++ spamguard.leadmon.net addheader 127.0.0.2 address is a dialup address ++ ++ Default: none ++ Note: Multiline. To activate RBL checks you have to set RBL in qmail-smtpd's ++ environment (with tcpserver). See this website for more information on ++ available RBLs: http://www.declude.com/JunkMail/Support/ip4r.htm ++ The environment variable RBLONLYHEADER overrides any rejects and only ++ adds headers. This can be set by ip-range with tcpserver. ++ ++~control/goodmailaddr ++ ++ This file contains local recipient addresses that are always accepted in ++ conjunction with sender or recipient verify checks. ++ Default: none ++ Example: user@domain or @domain ++ Note: This is useful for things like and other ++ addresses you always want to accept, even if they are not in the ++ ldap directory or when a lookup temporarly fails. See RCPTCHECK ++ and SENDERCHECK. ++ ++~control/badrcptto ++ ++ This file contains local recipient addresses that are rejected. ++ Default: none ++ Example: user@domain or @domain ++ Note: This can be useful if a spammer sends lots of messages to a ++ nonexistant user from an invalid address as otherwise postmaster ++ will get lots of double bounces. ++ ++~control/badmailfrom-unknown ++ ++ This file contains blocked addresses for server without a PTR RR. ++ This is useful to stop some spammer that use fake hotmail or yahoo ++ addresses but mail from home-pc without a PTR RR dns record. ++ Example: @hotmail.com ++ Note: Syntax as in ~control/badmailfrom. ++ ++~control/bouncemaxbytes ++ ++ This file contains the maximal number of bytes to be included in a bounce ++ message. ++ Default: 0 (off) ++ Example: 102400 (equivalent to 10kB) ++ ++~control/smtpclustercookie ++ ++ This file contains a cookie (random string) that is the same on all ++ smtp MX clusters. It is to prevent outgoing mails looping back because ++ of incorrect or faked MX records pointing to some external ip address ++ which qmail-remote does not recognise as in reality 'itself' (as seen ++ from the cluster perspective). The external ip address can be for example ++ a load balancer or a NAT device. ++ Default: none ++ Example: cvkmd9078923hjv4nkd890q3g ++ Note: String will be truncated after 32 characters. If qmail-remote ++ sees the same string advertised in qmail-smtpd greeting it will ++ abort the delivery attempt, bounce the message and report a smtp ++ loop error. ++ ++~control/cert.pem ++ ++ Certificate for qmail-smtp tls option. This file can be generated via "make ++ cert" or "make cert-req". The file needs to be readable for qmail-smtpd -- in ++ other words it needs to be readable for user qmaild. ++ ++~control/outgoingip ++ ++ This file contains the IP qmail-remote should bind to. ++ Default: 0.0.0.0 ++ Example: 192.168.12.88 ++ ++~control/qmqpcip ++ ++ This file contains the IP qmail-qmqpc should bind to. ++ Default: 0.0.0.0 ++ Example: 192.168.12.88 ++ ++~control/bigbrother ++ ++ This file is only used if BIGBROTHER was defined in the Makefile. ++ For ISP that need to implement some surveillance method because of some ++ beloved authoroties (like here in switzerland), you can enable a per ++ address queue extra feature. To automatically forward all mail to and from ++ badguy@badplace.ch to bigbrother@admin.ch you need to add followong line to ++ ~control/bigbrother: badguy@badplace.ch:bigbrother@admin.ch. ++ bigbrother@admin.ch can be a local, ldap or remote address. ++ Default: none (off) ++ Example: badguy@badplace.ch:bigbrother@admin.ch ++ Note: An extra recipient will be added in qmail-send. If the bigbrother ++ address causes a bounce the sender will see this bounce. ++ ++~control/signatures ++ ++ This file contains content signatures for the REJECTEXEC functionality. ++ Default: none ++ Example: TVqQAAMAA (block some windows executables, exe|com|pif|scr) ++ Example: UEsDBAoAAAAAA*****DKJx+eAFgAAABYAA**AAAA (block MyDoom) ++ Note: These signatures are matched for in the first line of mime ++ attachments. Be sure to make them as specific as possible ++ to avoid to have a too broad filter and matching valid ++ content. The asterisk (*) is a single placeholder that will ++ match any single character at that position. The signature ++ is litteraly matches and no decoding of mime attachments is ++ being done. Normally the signature contains the base64 ++ encoded version of the string you want to match. Lines ++ starting with a hash sign (#) are ignored and can be used ++ for comments. ++ The default file contains signatures of Windows executable ++ files (exe|com|pif|scr, etc) and common email Virii at the ++ time of the current release. ++ ++~control/smtpcert ++ ++ This file contains the location of the SSL certificate used for smtps STARTTLS ++ feature. The path may be relative to /var/qmail or whatever was specified in ++ conf-qmail. ++ Default: none ++ Example: control/cert.pem ++ ++~control/remotecert ++ ++ This file contains the location of the OPTIONAL SSL certificate used for ++ outgoing SMTP sessions. The path may be relative to /var/qmail or whatever ++ was specified in conf-qmail. ++ Default: none ++ Example: control/cert.pem ++ Note: Unlike ~control/smtpcert this file is completle optional for encrypion. ++ qmail-remote will use STARTTLS and SSL encryption even without a cert ++ file, as it is not neccessary for the client. ++ ++~control/tarpitcount ++~control/tarpitdelay ++~control/maxrcptcount ++~control/rblonlyheader ++~control/ldapdefaultquota ++~control/ldapusername ++~control/ldappasswdappend ++ NO LONGER USED, PLEASE REMOVE THESE FILES ++ ++================================================================================ ++ ++Environment variables setable via tcpserver, envdir or plain old env/sh: ++ ++AUTHPREPEND ++ ++ String that is prepended to the login in the received line. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "Authenticated user: " ++ Note: Just for additional information in the received line. You can use this ++ to make tracking of (ab)users easier. ++ ++AUTHREQUIRED ++ ++ Allow sending of messages (for this host and relaying) only to authenticated ++ senders. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Use this only if all clients support AMTP-AUTH. Be careful not to block ++ remote mail servers sending messages for local users. This is only useful ++ if you want to restrict certain IP ranges (for example you dial-up or ++ other customers) to be able to send only as existing and valid users. ++ ++BLOCKRELAYPROBE ++ ++ Rejects recipients with and "!", "%" or double-"@" ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: This is quite useful to stop so called anti-spam probes of clueless ++ and overzealus wannabe RBL operators. These probes try to exploit ++ some ancient sendwhale bugs never existent in qmail. Unfortunatly ++ qmail accepts such stuff even if it doesn't relays it and bounces ++ it later. "!" is the old UUCP bang path. "%" is a sendwhale relaying ++ hack and double-"@" a sendwhale bug. ++ Beware if you actually use the qmail percent-hack! Then this can't ++ be used obviously! ++ ++LDAPSOFTOK ++ ++ Treat ldap soft errors (ldap server unavailable, etc) as if the check was ++ successful and continue. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Normally qmail-smtp will give a 450 temporary error if the ldap server ++ could not be successfuly queried. This changes to treat such errors as ++ if they had been successful. This is useful when it is more important ++ to keep the service available, even if the ldap server can't be queried ++ for some reason (down, unreachable, insufficient query rights, etc). ++ ++LOGLEVEL ++ ++ Level of log verbosity in qmail-smtpd. ++ Default: 0 (NULL) ++ Affects: qmail-smtpd ++ Example: 3 ++ Levels: ++ 0 = no logging ++ 1 = fatal errors ++ 2 = accounting ++ 3 = connection setup and smtp errors ++ 4 = verbose ++ Note: integer value, everything will be logged through tcpserver ++ ++POP3_LOGLEVEL ++ ++ Level of log verbosity in qmail-pop3d. ++ Default: 0 (NULL) ++ Affects: qmail-pop3d ++ Example: 3 ++ Levels: ++ 0 = no logging ++ 1 = fatal errors ++ 2 = login/logout accounting ++ 3 = session errors ++ 4 = verbose ++ Note: integer value, everything will be logged through tcpserver ++ Note2: this is a hack so that this log level does not interfere with the one ++ of auth_pop. ++ ++LOGLEVEL or DEBUGLEVEL ++ ++ Level of log verbosity in qmail-lspawn, auth_* ++ Default: 0 (NULL) ++ Levels: ++ LOGLEVEL=1 -> Errors ++ LOGLEVEL=2 -> Warnings ++ LOGLEVEL=4 -> Info ++ LOGLEVEL=8 -> Info^2 ++ LOGLEVEL=16 -> Debug ++ LOGLEVEL=32 -> Debug^2 ++ LOGLEVEL=64 -> LDAP Debug ++ LOGLEVEL=128 -> LDAP Debug^2 ++ LOGLEVEL=256 -> PASSWD, this level is normaly off because it shows ++ critical data (unencrypted and crypted passwords). To ++ turn it on edit checkpassword.c and increase the level ++ for init_debug(). ++ WARNING: on production machines don't use levels higher 3 or you will get ++ incredible huge logfiles. ++ NOTE: too high debuglevels are reduced to the maximum allowed debug level ++ if the level parameter in init_debug() is smaler. ++ The LOGLEVEL is compare with a bit mask, so that ++ LOGLEVEL=3 will report warnings and errors but LOGLEVEL=2 will ++ only report warnings. ++ Both names are supported with LOGLEVEL having the higher priority. ++ ++MAXRCPTCOUNT ++ ++ Maxrcptcount is the maximum number of RCPT TOs you accept before permanently ++ rejecting this delivery attempt. ++ Default: 0 (which means no unlimited) ++ Affects: qmail-smtpd ++ Example: 5 ++ Note: This is a hard limit. If you just want to give some pain for smaller ++ recipient numbers consider tarpit use as well. ++ ++NOBOUNCE ++ ++ Rejects null sender bounces ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Use only in extreme cases and only for certain IP ranges. Blocking ++ bounces is considered harmful and strictly prohibited by RFC2821. ++ This can be useful if a spammer used your domain as sender and you ++ get all the bounces. Otherwise don't enable this! You want to get ++ bounces! ++ ++NOCOMPRESS ++ ++ Disables the dynamoc data compression in qmail-qmqpd. ++ Default: off ++ Affects: qmail-qmqpd ++ Example: "" (any value will do) ++ ++NOPBS ++ ++ Disable adding of pbs data. NOPBS disables the execution of pbsadd in auth_*. ++ Default: off ++ Affects: auth_pop, auth_imap & pbsadd ++ Example: "" (any value will do) ++ Note: this is manly useful to hinder adding informations of forwarder sessions. ++ ++QMAILQUEUE ++ ++ Use this queueing program instead of the default qmail-queue program. ++ Default: off ++ Affects: qmail-smtpd, qmail-qmtpd, qmail-qmqpd, qmail-inject, ++ but also qmail-local, qmail-reply, qmail-send, qreceipt, ++ condredirect, forward ++ Example: /var/scanner/bin/qmail-scanner-queue.pl ++ Note: Using this for something different than the mail incomming daemons ++ is dissuaded. ++ ++RBL ++ ++ If set turns on rbl checking. See also section about the ~control/rbllist ++ control file. ++ Default: none ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ ++RBLONLYHEADER ++ ++ Rblonlyheader causes qmail-smtpd not to reject the message in any case but ++ just to add a line with it's findings to the mail header. ++ Default: none ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Add's a ++ "X-RBL: (relays.ordb.org) matches with 127.0.0.2 and tells us go home" ++ header to the message for later filtering. ++ ++RCPTCHECK ++ ++ Check if the recipient (envelope "rcpt to:") of a message really exists. If not ++ give a 550 reject right now instead of bouncing later in qmail-lspawn. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Only applies to recipients whose domain is listed in ~control/locals. ++ Recipients domains listed in ~control/rcpthosts are allowed without ++ further checks. If RELAYCLIENT is set, all other recipients are allowed ++ as well. Addresses or domains listed in ~control/goodmailaddr are ++ unconditionally allowed in all cases. ++ ++REJECTEXEC ++ ++ Reject DOS/Windows executables in mail attachements. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: This patch does not distinguish between valid applications and ++ evil viruses and trojans so handle with care. It is not a 100% ++ guaranteed protection but it handles a lot of unwanted stuff. ++ The file ~control/signatures contains signatures for matching ++ of mime attachments. ++ ++RETURNMXCHECK ++ ++ Rejects senders if they don't have a valid return MX ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: This is quite useful even though it doesn't stops many spammers ++ today. But it ensures that you can send an email or a bounce ++ back to the sender. It is also useful for your own users/customers ++ because if they type a nonexistent sender into their "from" field ++ (typos!) it'll stop them the first time instead of getting help- ++ desk calls when nobody can reply to them. ++ ++SANITYCHECK ++ ++ Rejects senders without an @, no . in domain part or too long/short TLD ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: Rejects stuff which you probably don't want on your mailserver ++ because it's highly likely that it'll bounce later. ++ ++SENDERCHECK ++ ++ Check if the sender (envelope "mail from:") of a message really exists (in the ++ ldap directory). If not give a 550 reject right now. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" or "LOOSE" or "STRICT" ++ Note: Only applies to senders whose domain is listed in ~control/locals. ++ Everything else is assumed to be an external message with a foreign ++ sender coming in, so no check applied. This is normal mode. ++ Setting to "LOOSE" will allow only senders which are listed either in ++ ~control/locals or ~control/rcpthosts. Setting to "STRICT" will only ++ allow senders which are listed in ~control/locals. With this you can ++ enforce for example that people from certain ip ranges can only send ++ if they have a valid existing email address with you. ++ Addresses or domains listed in ~control/goodmailaddr are unconditionally ++ allowed in all cases. ++ ++SSLCERT ++ ++ Path to the SSL certificate qmail-smtpd should use for STARTTLS. Overrides ++ ~control/smtpcert. ++ Default: none, ~control/smtpcert will be used ++ Example: /var/qmail/boot/qmail-smtpd/cert.pem ++ ++SMTPAUTH ++ ++ Enables SMTP-AUTH for remote clients. Authenticated clients are allowed to ++ relay through this server and their login is being recorded in the received ++ line. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "TLSREQUIRED" or "" (any value will do) ++ Note: With SMTP-AUTH remote users can use this mail server for relaying. ++ SMTP is unencrypted and auth passwords are in clear text equivalent ++ base64 encoding. With TLSREQUIRED enabled SMTP-AUTH is only accepted ++ when the SMTP session is TLS encrypted to prevent password sniffing. ++ TLSREQUIRED requires TLS option to be compiled into qmail-ldap. ++ ++SMTP550DISCONNECT ++ ++ Disconnect the SMTP session if a 5xx is produced by the sender ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" (any value will do) ++ Note: This is useful if you have a spammer trying different senders or ++ recipients in the same session separated by rset's. ++ ++TARPITCOUNT ++ ++ Tarpitcount is the number of RCPT TOs you accept before you start tarpitting. ++ Default: 0 (which means no tarpitting) ++ Affects: qmail-smtpd ++ Example: 5 ++ Note: This number should be smaller than MAXRCPTCOUNT to have any effect. ++ ++TARPITDELAY ++ ++ Tarpitdelay is the number of seconds of delay to introduce after each ++ subsequent RCPT TO. ++ Default: 5 ++ Affects: qmail-smtpd ++ Example: 10 ++ Note: Connection which are tarpitted take a long time to finish. Be aware ++ that this ties up the available qmail-smtpd slots. Raise connection ++ limits with tcpserver if neccessary. ++ ++421GREETING ++ ++ Rejects a connection right away with a 421 in the greeting line and ++ starts in a dummy mode where only QUIT works unless 421GREETING is set -- in ++ that case the connection will closed immediatly after printing the greeting. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" ++ Example: "Go away!" ++ Note: You can set this in tcpserver if you want to reject messages from ++ an ip address temporarily. If no string is given it will default ++ to "Service temporarily not available (#4.3.2)". ++ The timeout is reduced to 20 seconds to prevent starvation. ++ ++550GREETING ++ ++ Rejects a connection right away with a 550 in the greeting line and ++ starts in a dummy mode where only QUIT works unless 421GREETING is set -- in ++ that case the connection will closed immediatly after printing the greeting. ++ Default: off ++ Affects: qmail-smtpd ++ Example: "" ++ Example: "Go away!" ++ Note: You can set this in tcpserver if you want to reject messages from ++ an ip address permanently. If no string is given it will default ++ to "Sorry, your message has been administratively denied. (#5.7.1)". ++ The timeout is reduced to 20 seconds to prevent starvation. ++ 550GREETING has precedence over 421GREETING. ++ ++ ++================================================================================ ++ ++DEFAULT LDAP PARAMETER FIELDS: ++NOTE: keywords have to match exactly, so pay attention. ++ All fieldnames and keywords can be changed at compile time. ++ Just have a look at qmail-ldap.h. ++ ++LDAP_MAIL (default: "mail") ++ ++ The users email address ++ Required ++ Example: jdoe@foo.bar ++ ++ ++LDAP_MAILALTERNATE (default: "mailAlternateAddress") ++ ++ Secondary (alias) mailaddresses for the same user ++ Example: jd@foo.bar ++ Note: multifield ++ ++ ++LDAP_UID (default: "uid") ++ ++ The username for POP3 and IMAP delivery ++ Required ++ Example: jdoe ++ Note: this name will also be set as $USER for qmail-local and program delivery. ++ ++ ++LDAP_QMAILUID (default: "qmailUID") ++ ++ UID of the user on the mailsystem ++ Example: 1010 ++ Note: Can be omitted in a virtual users environment ++ but only if it is defined via the control file ~control/ldapuid ++ ++LDAP_QMAILGID (default: "qmailGID") ++ ++ GID of the user on the mailsystem ++ Example: 1010 ++ Note: Can be omitted in a virtual users environment ++ but only if it is defined via the control file ~control/ldapgid ++ ++ ++LDAP_PASSWD (default: "userPassword") ++ ++ The password for POP3/IMAP authentication ++ Example: {MD5}uSI59Zyfa5lapBLGfJrD+g== ++ Note: Can be encrypted with {SHA}, {SSHA}, {MD5}, {SMD5}, {MD4}, {RMD160}, ++ {RMD160}, {NS-MTA-MD5}, ++ {crypt} crypt (without {crypt} prefix) or cleartext (only if compiled ++ with -DCLEARTEXTPASSWD (a bad idea on production systems)). ++ If you rebind to the ldapserver don't use {NS-MTA-MD5}, {RMD160} and ++ probably {MD4}. These algorithms are sometimes not supported by the ++ ldap servers, so check with their documentation. ++ To generate passwords you can use the included tool 'digest'. ++ ++ ++LDAP_MAILSTORE (default: "mailMessageStore") ++and ++LDAP_HOMEDIR (default: "homeDirectory") ++ ++ Path to the maildir/mbox on the mail system is extracted from those fields. ++ If LDAP_HOMEDIR is found this field is used as $HOME, using aliasempty or ++ mailMessagestore if defined as default delivery method. ++ If only LDAP_MAILSTORE is defined this will be used as $HOME and aliasempty ++ as default delivery method. ++ If neither LDAP_MAILSTORE nor LDAP_HOMEDIR is defined, ~alias (qmails alias ++ user homedir) will be used as $HOME and ALIASDEVNULL (defined in qmail-ldap.h) ++ as default delivery method. Also the delivery mode is set to ldap only and ++ forward only (LDAP_DOTMODE and LDAP_MODE). ++ Example: /home/jdoe/ ++ Note: LDAP_MAILSTORE can be written relative in a virtual users environment ++ ldapmailstore will be prefixed to make the path absolute. ++ For more info have a look at the QLDAPNEWS file. ++ If you use "homeDirectory" in an incompatible way then redefine it in ++ qldap-ldap.h to something not used, like "noHomeDirectory". ++ ++ ++LDAP_QUOTA_SIZE (default: "mailQuotaSize") ++LDAP_QUOTA_COUNT (default: "mailQuotaCount") ++ ++ The amount of space the user can use until all further messages get bounced. ++ There are two possible limits, size (a byte count) and count (a file count). ++ Example: max 1000000 bytes size and max 1000 Mails ++ mailQuotaSize: 1000000 ++ mailQuotaCount: 1000 ++ Note: a value of 0 means unlimited quota for that limit (count or size). ++ Note2: overrides defaultquotasize and defaultquotacount per user. ++ the old string forma (1000000S,1000C) is no longer supported. ++ ++LDAP_MAXMSIZE (default: "mailSizeMax") ++ ++ The maximum size (in bytes) that a single message may have. Everything over ++ this size gets bounced. ++ Example: 102400 ++ Note: mailSizeMax has no influence on the datasize control file for the ++ smtp daemon. The mailSizeMax decision is not take until the mail is ++ delivered localy (by qmail-lspawn). ++ ++ ++LDAP_FORWARDS (default: "mailForwardingAddress") ++ ++ Address(es) to forward all incoming messages for this user to. ++ Example: jdoe@new.place ++ Note: multifield. Forwards are done in addition to local (maildir/mbox) ++ delivery. Forwardings can be disabled without having to remove ++ the entries. See deliveryMode for more information on both. ++ ++ ++LDAP_PROGRAM (default: "deliveryProgramPath") ++ ++ Program to execute for all incoming mails. Gets the message as input on stdin. ++ Example: /usr/bin/program -c -s ++ Note: multifield. The same as |/usr/bin/program -c -s in .qmail ++ Works only with qmailDotMode set to ldapwithprog or both. ++ With ldaponly set deliveryProgramPath is silently ignored. ++ Before using it have a look at QLDAPNEWS, qmail-ldap.h, check.c and ++ see also 5.2. ++ Program delivery is done in addition to local (maildir/mbox) delivery. ++ Program delivery can be disabled without having to remove the ++ entries. See deliveryMode for more information on both. ++ A valid home-directory is needed so either LDAP_MAILSTORE or ++ LDAP_HOMEDIR needs to be defined. ++ ++LDAP_MODE (default: "deliveryMode") ++ ++ multi field entries of these keywords ++ - (no entry): default delivery, put message into maildir/mbox (localdelivery), ++ plus forward and program delivery if specified. ++ - noforward: do not forward (ignores forwarding entries in ldap and .qmail) ++ - nolocal: do not put message into maildir/mbox (ignores also .qmail) ++ - noprogram: do not do program deliveries (ignores deliveryprogrampath, .qmail) ++ - reply: send an auto_reply mail with text from mailReplyText ++ Default: no entry -> default ++ Example: noforward ++ noprogram ++ Note: The behaviour changed compared with previous qmail-ldap versions ++ (20030801 and earlier)! ++ Setting a mailForwardingAddress no longer disables local delivery. ++ This is the most important change. ++ ++ Normal is no longer a real mode. It is just a placeholder for the ++ default behaviour. ++ Local delivery is now always done, except when explicitly disabled ++ with nolocal. ++ ++ Noforward and noprogram disable forwardings and program deliveries ++ even if mailForwardingsAddress or deliveryProgramPath attributes ++ exist. This way you can keep programs and forwards but turn them ++ off if you don't need them, instead of removing their attributes. ++ ++ If no mode to the contrary set, forwards, program deliveries, local ++ deliveries are all done if existent. Reply is not automatic and has ++ to be enabled explicitly. ++ ++ ++LDAP_REPLYTEXT (default: "mailReplyText") ++ ++ A reply text for every incoming message (multiline) ++ Example: I'm on vacation until next monday ++ Example2: multiline base64 ++ SGkgcW1haWwtbGRhcCBmYW5zLAoKaWYgSSBjb3VsZCBJIHdvdWxkIGJlIGlu ++ IHRoZSBtb3VudGFpbnMgc2tpaW5nIGJ1dCBJJ20gYXQgaG9tZQp3cml0aW5n ++ IHRoaXMgbWVzc2FnZSBmb3IgdGhlIFFMREFQSU5TVEFMTCBmaWxlLgpUbyBi ++ ZSBob25lc3QsIHRoZXJlIGlzIG5vdCBlbm91Z2ggc25vdyBhcm91bmQgdG8g ++ ZW5qb3kgc2tpaW5nLgoKdGhhbmtzIGZvciByZWFkaW5nIHRoZSBRTERBUElO ++ U1RBTEwgZmlsZQoKLS0KOndxIENsYXVkaW8K ++ Note: used only if deliveryMode is set to reply. ++ To use multiline text in ldap it has to be base64 in the ldif. ++ GUI tools like GQ are doing this correct, ldapadd can handle base64 ++ inputs or a path to a file containing the reply text (man ldapadd). ++ Note2: It is now possible to add a header section to the reply. ++ If the replytext starts with a %HEADER% line all lines following until ++ the next empty line are treated as header. The fields From:, Subject:, ++ the content type headers and most X- headers can be set. To:, X-Mailer: ++ and Precedence: are ignored and set by qmail-reply. If %SUBJECT% ++ is used in the Subject field it is expanded with the Subject of the sent ++ mail. This expansion will only work for the first line of a multiline ++ Subject header. ++ ++LDAP_DOTMODE (default: "qmailDotMode") ++ ++ The default interpretation of .qmail files ++ Values: both, dotonly, ldaponly, ldapwithprog, none (just Maildir/box delivery) ++ Default: set by file ~control/ldapdefaultdotmode ++ Note: Works only for deliveries based on LDAP lookups, ++ overrides ~control/ldapdefaultdotmode. ++ ++ ++LDAP_MAILHOST (default: "mailHost") ++ ++ On which qmail server the messagestore of this user is located ++ Example: qmail3.nrg4u.com ++ Note: Must be the same as the ~control/me hostname on the homeserver ++ of the user. ++ ++ ++LDAP_ISACTIVE (default: "accountStatus") ++ ++ The status of a user account. ++ Values: active (no restrictions), ++ noaccess (only mail delivery but no pop/imap access), ++ disabled (bounce incoming messages) ++ deleted (bounce incoming messages and mark for deletion, ++ see LDAP_PURGE) ++ Default: no accountStatus is equal to active. ++ ++ ++LDAP_PURGE (default: "qmailAccountPurge") ++ ++ If accountStatus set to 'deleted', the earliest date when the mailMessageStore ++ including all remaining content will be deleted from the filesystem. ++ Values: date and time in seconds since Jan. 1, 1970 (the epoch) ++ Default: not set ++ Note: This deletion has to be done by an external helper program, for example ++ periodically run from cron. A sample script is included under the name ++ qmailAccountPurge.sh. Handle automatic deletions with care! ++ ++ ++LDAP_QMAILUSER (default: "qmailUser") ++ NO LONGER USED, REMOVE IT SOMEWHEN FROM YOUR DATABASE ++ Replaced by LDAP_UID ++ ++================================================================================ ++ ++EXAMPLE QLDAP LDIF FILE: ++ ++dn: cn=Andre Oppermann, o=Internet Pipeline, c=CH ++cn: Andre Oppermann ++sn: Oppermann ++objectClass: top ++objectClass: person ++objectClass: inetOrgPerson ++objectClass: qmailUser ++mail: opi@opi.flirtbox.ch ++mailAlternateAddress: andre@opi.flirtbox.ch ++mailHost: opi.flirtbox.ch ++mailMessageStore: /usr/home/opi/Maildir/ ++mailForwardingAddress: opi@nrg4u.com ++deliveryProgramPath: /usr/home/opi/bin/smsinformer -q ++deliveryMode: noprogram ++mailQuotaSize: 1000000 ++mailQuotaCount: 1000 ++qmailUID: 1001 ++qmailGID: 1001 ++uid: opi ++userPassword: {SMD5}b28a87511da157f147ed4766b0474a8a ++accountStatus: active ++ ++================================================================================ ++ ++EXAMPLE SLAPD.CONF FILE: ++ ++####################################################################### ++# ldbm database definitions ++####################################################################### ++ ++database ldbm ++suffix "o=Internet Pipeline, c=CH" ++directory /var/qmail/users ++rootdn "cn=root, o=Internet Pipeline, c=CH" ++rootpw secret ++index objectclass,mail,mailAlternateAddress,uid eq,sub ++index accountStatus,mailHost,deliveryMode eq ++index default sub ++ ++================================================================================ ++ ++FOR OpenLDAP 2.x DO THIS: ++ ++Copy qmail.schema to your OpenLDAP installation location and add this ++to your slapd.conf: ++ ++ include /path/to/your/OpenLDAP/qmail.schema ++ ++================================================================================ ++ ++MAILINGLIST, BUGS & PROBLEMS ++ ++There is a qmail-ldap specific mailinglist at qmail-ldap@qmail-ldap.org. ++To subscribe just write a mail to qmail-ldap-subscribe@qmail-ldap.org. ++ ++The qmail-ldap mailinglist archive can be found at ++http://www.suares.com/qmail-ldap/archive ++ ++There is also a life with qmail-ldap homepage at: ++http://www.lifewithqmail.org/ldap ++ ++If you have a problem with the patch or there seems to be a bug in the code ++please add some output of qmail-ldap with LOGLEVEL set to something higher ++then 2 (255 is a good setting to see all possible problems). ++It is impossible to know where the problem is when somebody writes a mail like: ++I have a problem with the patch. No mail gets send to the user in the ldap db. ++ ++Normaly you get also a better response if you specify your problem in detail. ++It seems that often a "RTFM" is enough, but when you have read until here you ++are probably not such a candidate. ++ ++END :-) ++ +diff -upN qmail-1.03/QLDAPNEWS qmail-ldap/QLDAPNEWS +--- qmail-1.03/QLDAPNEWS Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/QLDAPNEWS Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,1276 @@ ++QMAIL_LDAP by Andre Oppermann , ++Claudio Jeker and Boris Lutz ++(c) 1999-2004 Internet Business Solutions AG ++ ++RELEASE: $Date: 2004/12/01 14:19:50 $ ($Revision: 1.208 $) ++ ++ ++This is the NEWS FILE, so the QLDAPINSTALL file gets a bit cleaner. ++This file is NOT structured!! ++ ++TODO: ++ ++ see QLDAPTODO ++ ++WARNING: If you are upgrading from 20030801a or earlier make sure that ++ you have read the news section for 20030901. ++ ++NEWS for current stuff: ++ ++ Introduce a better extension handling to qmail-group. Qmail-group will now ++ only deliver mails if they are sent to the main address. This should fix ++ possible mail-loops. Also the extension -moderators is now supported and ++ mails to that email will be sent to all moderators. ++ ++ Introduce the new qmailGroup ldap attribute "bounceadmin". Bounceadmin is a ++ list of rfc822 mail addresses where delivery errors are sent to. If no ++ bounceadmin is specified then the original sender of the mail will be used. ++ ++ qmail-reply sends mail with empty envelope sender as it does not make sense ++ to get bounces for automatic replies. Prodded by Andre who had over 1000 ++ failure notices after his vacation. ++ ++ Only update the qmail-reply recent sent db if we would send a mail to this ++ user. Before every sender was added to the db and caused massive trashing. ++ ++ Bugfix in qmail-group to make filtermember/filtersender work when ++ membersonly is turned on. Previously users specified via a filter where ++ always considered not member of the group. Reported by Flavio Fonseca. ++ ++ Fix qmail-group so that senderconfirm and moderation can be used togehter. ++ This fixes a problem where qmail-secretary detected a mail loop when both ++ options where used. Reported by George Lekatsas. ++ ++ Source ~control/{aliasempty,defaultdelivery} with cat instead of head -1 ++ so it is possible to define more than just a simple ./Maildir/ delivery ++ as default. Found by Michel H. ++ ++NEWS for current 20041101: ++ ++ Don't forget to check also for accountStatus deleted in the auth tools and ++ deny access in this case. ++ ++ Only send the AUTH option in MAIL FROM: if the session is authenticated. ++ Fixes a problem seen with some obscure mail server. ++ ++NEWS for current 20040801: ++ ++ In qmail-smtpd if SSLCERT is set use this as the path to the certificate and ++ not as the path to a file containing the path to the certificate. Noticed by ++ Zachary Kotlarek. ++ ++ Fix a security bug in the startup scripts. qmail-smtpd is run under the ++ user $USER. If $USER was set on invocation of the script, the value was not ++ reset to the default qmaild. In the worst-case qmail-smtpd was running as ++ root. Yikes! To install the new script you need to remove the old one before ++ make setup check. Also affected are the qmail-pbsdbd and qmail-qmqpd ++ run-scripts. ++ ++ Fix a bug in smtp_auth handling where empty password caused a disconnect. ++ Noticed by Fabio Gomes. ++ ++ Fix multiple bugs in qmail-smtps starttls handling. Noticed by Ted Zlatanov. ++ ++NEWS for 20040701 stuff: ++ ++ qmail-smtpd log level cleanup. Add a additional level for accounting and ++ remove some redundant messages. ++ ++ Fix a bug in checkpassword.c that caused auth_pop and auth_imap to ignore ++ the per user quota if rebind was used. Reported by nbari at unixmexico.com ++ ++ Add ~control/remotecert for qmail-remote similar to ~control/smtpcert ++ for qmail-smtpd. The big difference is that qmail-remote will use STARTTLS ++ and SSL encryption even without this file as a certificate is optional for ++ the client side. ++ ++ To enable SMTP STARTTLS the path to the cert file needs to be set in ++ ~control/smtpcert or set via the env var SSLCERT. ++ ++ If the defaultdelivery aka aliasempty is not a local delivery qmail-local ++ may start additional programs while running qmail-reply. Reported by ++ Florian Pflug. ++ ++ Fix the SIGHUP handling between qmail-send and qmail-local. ++ ++ Messages sent from a moderator to a group only need to be approved by the ++ moderator himself. ++ ++ qmail-todo started to spin if qmail-send exited non nicely (aka crashed). ++ ++ Fix some path and 'sh' issues in the run scripts reported by Toni Mueller ++ and Ted Zlatanov. While doing that add some ssl run scripts. ++ ++ Fix QUOTATRASH option by including LDAPFLAGS to the maildir++.o target. ++ Reported by Zachary Denison. ++ ++ Replaced the cdb functions with the public domain mmaped version from ++ tcpserver. This makes it possible to keep the file open and do extremly ++ fast searches. ++ ++ Add license to files that are under our (Andre or mine) copyright. At least ++ it is now clear what is our stuff and what is coming from djb. ++ ++NEWS for 20040401 stuff: ++ ++ Added some qmail-group docu. See QLDAPGROUP. ++ ++ Better 550GREETING support and added an additional 421GREETING mode to ++ qmail-smtpd. ++ ++ Qmail-secretary should ignore mails with precedence set to list, junk or bulk. ++ ++ Added Bruce Guenters qmail-qmqpc connect timeout patch. ++ ++ Add SMTP AUTH support to qmail-remote. A user can be specified via ++ ~control/smtproutes. To authenticate all mails to inside.af.mil with ++ user joe-user something like this can be used. ++ inside.af.mil:firewall.af.mil joe-user eat@joe's ++ ++ Don't let qmail-group or qmail-secretary inject mails with no recipients. ++ ++ Print remote IP address in error messages for RBL rejects and denied ++ relaying attempts to make debugging based on the bounce messages far ++ easier. Requested by Jason Eggleston. ++ ++NEWS for 20040301 stuff: ++ ++ Fix buffer overflow noticed by Georgi Guninski in qmail-qmtpd.c. ++ There is no easy way to exploit it. Additionally the same issue is ++ patched in qmail-qmqpd.c. ++ ++ Fix an issue in qmail-remote.c with TLSDEBUG defined. Noticed by ++ Oskar Eyb and Rainer Hartenthaler. ++ ++ Fix bugs in qmail-group. The moderation feature was broken and in some ++ header fields a char of the local address was chopped of. Noticed by ++ different people. ++ ++ Fix endless loop in qmail-ldaplookup noticed by Tomas Kuliavas. ++ ++ Fix bug in substdio_feed noticed by Stefan Paletta. ++ ++ Fix qmail-inject -f "" bug noticed by Mesa de Ayuda. ++ ++ Added LDAPFLAG -DBIND_8_COMPAT needed on systems with new incompatible ++ bind9 header files. Currently this is necessary on MacOS X 10.3. ++ ++ Disable the too generic zip blocker signature in the example signature file. ++ ++NEWS for 20040201 stuff: ++ ++ Yet another bug fix in the maildirmake code of auth_mod.c. The previous fix ++ was definitifly not strong enough, ++ ++ Bug fix in condwrite. The maildir child should not exit 99 on finish the ++ parent should exit 99 and the child 0. ++ ++ In qmail-smtpd limit the accepted text line lenght to 10000 characters. ++ The RFC proposes a maximum of a 1000 but be nice to broken MTA/MUAs and it ++ does not really hurt us. ++ ++ Enhanced qmail-smtpd execcheck. Basic idea is form Russel Nelsons ++ qmail-smtpd-viruscan-1.3 patch. MIME signatrues are now stored in the control ++ file ~control/signatures. Two enhancements where done to Russels patch. ++ First MIME forwarded messages are also completly scanned and secondly it is ++ possible to use a '*' in the signature as a anymatch character. This makes ++ the signatures more powerful. ++ ++ It is now possible to limit the allowed senders to a qmail-group with ++ dnsender, rfc822sender and filtersender similar to dnmember, rfc822member ++ and filtermember. If membersonly is enabled and one of those sender attributes ++ is used only mails comming form this list of senders are passed to the group. ++ ++ Ensure qmail-remote does not print the DDC percentage in error messages. ++ ++ Add auto maildirmake capability to qmail-secretary. ++ ++ qmail-verify, auth_smtp, qmail-group and qmail-ldaplookup only try to read ++ ~control/ldaplogin and ~control/ldappassword. If one of the files can not be ++ read use anonymous login or the alternate login credentials in case of ++ qmail-group and qmail-ldaplookup. ++ ++ Yet another cleanup round through the whole code. Fix many issues with integer ++ overflows inclusive the qmail-smtpd crash found by Georgi Guninski. ++ While doing that rename puts and log to putstr and logit so that it does not ++ conflict with gcc internals. ++ ++ Bugfix in auth_mod.c reported by em (at) cmla.ens-cachan.fr ++ ++ Yet another run script update. $ALIASEMPTY fix from Jo Geraerts and correct ++ $QMAIL idea from Ace Suares. ++ ++ Do the same game in Makefile.cdb. Prepend %QMAIL%/bin infront of qmail-cdb. ++ ++ Fix typo in qmail-secretary. Reported by Beni Schoedler. ++ ++NEWS for 20040101 stuff: ++ ++ Never fdcopy STDOUT with STDERR in qmail-popup. The copy was only skipped if ++ DEBUG was set. So it was not possible to use qmail-pop3d accounting/logging ++ if a non-DEBUG version was compiled. Report by Henning Brauer. ++ ++ Once again I missed something in the run scripts. It would be good to run ++ awk scripts with awk. Remember to remove the old run scripts before a ++ make setup check. ++ ++ Kill the qmail-verify zombies in qmail-smtps call infrastructure. Reported ++ by Kevin J. McCarthy. ++ ++ auth_pop and auth_imap used always the default quota settings because ++ the quota attributes for the ldap search where missing. Thanks to Ricardo ++ Cerqueira for the report. ++ ++ The envdir parsing in the runscripts was absolutly broken. First of ++ all I used a C-Style comentary in a shell script and then the simple ++ eval `env - envdir ./env env` does not work with environments with ++ spaces. So this was exchanged through a simple awk script. Fixed some ++ other runscript bogons too. ++ To install the new run scripts the old ones need to be removed `rm ++ /var/qmail/boot/*/run` ++ ++NEWS for 20031201 stuff: ++ ++ Do not overwrite rules file on new install (make setup check). ++ ++ Make it possible to specify the number of concurrent connection of tcpserver ++ controlled daemons (qmail-smtpd, qmail-qmqpd, qmail-pop3d, qmail-imapd). ++ This can be achived by setting the CONCURRENCY environment variable. ++ ++ qmail-reply does no longer reply to messages tagged with a spamassassin ++ "X-Spam-Status: Yes" header. ++ ++ The dynamic data compression done in qmail-qmqpd can be explicitly disabled. ++ If the environment variable NOCOMPRESS is set the feature is disabled. ++ ++ Sending a SIGHUP reloads now also the qmail-lspawn config. Sending a ++ SIGHUP directly to qmail-lspawn is no longer supported. qmail-send sends ++ upon receipt of a SIGHUP a empty message with delivery number 0xBEEF (48879) ++ to the qmail-lspawn process. This may cause trouble if you have a concurrency ++ bigger than this. The code should work even with higher values but I'm not ++ able to test this. ++ ++ qmail-reply should clear the database if the reply text changes. So that ++ you get a new message after the change. ++ ++ Fix in check.c:sanitypathcheckb(). Until now .. where not allowed in a ++ path. Now we check for the real thing(tm) "/../" and "^../". ++ ++ Case sensitivity bug fix when using locals.cdb. While constmap uses case ++ insensitive compares cdb doesn't, this will cause trouble when using local.cdb ++ and the envelope recipient has uppercase letters in the domain part. ++ Thanks to Doug Council for the report. ++ ++ Do not touch "down" files in service dirs on install else we would disable a ++ already enabled service without the knowledge of the user. ++ ++NEWS for 20031101a stuff: ++ ++ Nasty bugfix in qmail-qmqpd with compression turned on. On slow links large ++ mails could cause a transmission error. ++ ++ Minor bug fixes in passwd.c, qmail-remote.c, qmail-smtpd.c and rcpthosts.c. ++ Thanks Toni Mueller, Vicente Aguilar and Neil Sequeira for the reports. ++ ++NEWS for 20031101 stuff: ++ ++ Basic daemontool run scripts installed in ~/boot. qmail-ldap installs now ++ daemontools run script for most services in ~/boot. A Makefile for cdb ++ updating is installed in ~control. ++ ++ locals and rcpthosts can now be stored as cdb. This makes morercpthost.cdb ++ superfluous, also the hupping of qmail-send if the locals.cdb file changes ++ is no longer neccesary. If locals.cdb is present locals is ignored respectively ++ if rcpthosts.cdb is present rcpthosts and morercpthosts.cdb are ignored. ++ ++ Important bug fix: if you removed rcpthosts, qmail-ldap became a open relay. ++ This is stock qmail behaviour but since we include locals in our rcpthost ++ check this old assumption is wrong. We also consider the stock qmail behaviour ++ as a design flaw because a mta should never be a open relay unless the ++ luser want's so. ++ ++ readwrite cleanup. Similar to other djb ware we wrap read() and write() ++ into the functions subread() and subwrite(). This solves the 64-bit troubles ++ with read and write. read() and write() should no longer be used together with ++ the substdio framework. ++ ++ Huge cleanup. Bring qmail into the 21st century. Define all prototypes ++ and include the needed system include files. This commit fixes about 99% ++ of all compiler warnings and makes code developing lesser error-prone. ++ The Makefile dependencies need to be updated to reflect reality. ++ A few errors are still in the tree which are either hard to solve or ++ considered harmless -- mainly return type of main() in a few helper apps. ++ This cleanup brought some strange bugs to light which are now fixed. ++ ++ Finally enabled the "send only one reply to each sender" feature ++ in qmail-reply. ++ ++ Critical bugfix in auth_imap.c. A bug in the function that should invoke ++ the next authmodule caused auth_imap to end up in one infinit loop. ++ ++ Add DUPEALIAS feature. When duplicate or overlapping mail or ++ mailAlternateAddress exist the mail will be forwarded to this local ++ user (like the alias user of qmail). It can be either bounced or ++ handled there with a script/program answering with some meaningful ++ reply. This compile time option is intended for migration of old ++ X.400 mail systems where a user was available under some short names ++ if nobody else had the same shortname. ++ ++ Add some more features to qmail-ldaplookup. Password compare works now. ++ It is now also possible to use a different binddn and bindpw. ++ What is missing are local /etc/passwd lookups and group handling. ++ ++ The objectclass of a group object can now be changed like all other ldap ++ values via qmail-ldap.h. ++ ++ Fix in the qmail schema definitions: a ')' was missing. ++ ++NEWS for 20031001 stuff: ++ ++ Change NOPOP in accountStatus to NOACCESS as it is not just disabling ++ pop access but also imap and possibly others. ++ ++ ~control/ldapserver is now read with control_readfile. Multiple servers ++ now have to be specified at one per line. Using # for comments is allowed ++ and empty lines are removed. ++ ++ qmail-smtpd now reads ~control/locals and merges this with ~control/rcpthosts. ++ It is no longer neccessary to list a domain in both files. Anything listed ++ in locals is now automatically accepted by qmail-smtpd. rcpthosts is only ++ used and needed for domains we have to do spooling for. ++ ++ New compile time option IGNOREVERISIGN to disable dns wildcard matches ++ on gtlds. With this the return mx check will work again with .com domains. ++ This version can also handle multiple A records. A big hurray to verisign ++ who added this broken feature to the internet. ++ ++ Added auth_smtp and AUTH capabilities to qmail-smtpd. Enabled via the ++ SMTPAUTH env var. If SMTPAUTH is set to TLSREQUIRED it is neccesairy to ++ do a STARTTLS before issuing an AUTH command. If AUTHREQUIRED is set any ++ user MUST successfully authenticate before issuing a MAIL FROM command. ++ The string in the env var AUTHPREPEND will be prepended to the userid in ++ the received line. ++ ++ New tool qmail-verify which is used for email address verification. See ++ next two new features. ++ ++ smtp recipient verify. This qmail-smtpd feature will look up every RCPT TO ++ address in ldap with qmail-verify to check the recipients existance. If it ++ does not exist, qmail-smtpd will answer directly with a 550 reply instead ++ of accepting the email and bouncing it later. Only addresses whose domain ++ part is listed in ~control/locals are checked (because only there we know ++ the definite answer). Relaying and rcpthosts works as before, recipient is ++ not checked for those. Addresses listed in new ~control/goodmailaddr will ++ be accepted in any case. This is very useful for important or special ++ (like postmaster or mail admin) addresses which must work under any ++ circumstances (or local addresses which are not in ldap). Enabled with ++ RCPTCHECK env var. ++ ++ smtp sender verify. This qmail-smtpd feature will look up every MAIL FROM ++ address in ldap with qmail-verify to check the senders existance. If it ++ does not exist, qmail-smtpd will reject with 550 reply. In normal mode ++ only (envelope) senders whose domain part is listed in ~control/locals ++ are checked. Otherwise no-one else from outside could send mail to local ++ users anymore. In mode LOOSE it will only allow verified sender plus any ++ sender with its domain listed in ~control/rcpthosts. In STRICT mode it ++ will allow only ldap verified senders. With this you can, for example, ++ enforce that users within your network must use a valid sender which ++ exists in ldap and no other. Addresses listed in new ~control/goodmailaddr ++ will be accepted in any case. This is very useful for important or special ++ (like postmaster or mail admin) addresses which must work under any circum- ++ stances (or local addresses which are not in ldap). Enabled with SENDERCHECK ++ env var. ++ ++ 550greeting to reject smtp connections right away in the smtp ++ greeting message. Use this to permanently reject all messages coming ++ from a particular ip address(range). ++ ++ smtpclustercookie feature for (large) smtp MX clusters behind load ++ balancers or NAT devices. The cookie is presentented in the smtp ++ greeting as last string before \r\n. qmail-remote compares the ++ cookie with it's own and if they match assumes that the message ++ is looping. Cookies are set in ~control/smtpclustercookie. Length ++ is limited to 32 characters. Fill with some random printable chars. ++ ++ qmail-smtpd now prints its hostname (~control/me) along with QP ++ when acking a message. Makes it easier to track which smtp MX cluster ++ member took the message. ++ ++ qmail-smtpd greeting restructured due to the above things. It now ++ prints "220 [~control/me] ESMTP [~control/smtpgreeting] [~control/ ++ smtpclustercookie]\r\n". You don't have to put the hostname of the ++ machine into smtpgreeting anymore. It is just a text. Can be empty. ++ ++ qmail-qmqpd supports now both clear and ZLIB compressed communications ++ for intra-cluster forwards. ++ ++ Added new tool condwrite. Works like condredirect but writes to a maildir ++ or mailfile instead of forwarding. The quota is respected and maildir are ++ created automatic if option is set. NOTE: The automatic maildir creation ++ is not capable to create valid IMAP subdirs (Maildir/.somedir). ++ ++ auth_* sets now the MAILDIRQUOTA and DATASIZE environment vars. ++ ++ New compile time option QUOTATRASH to include the Trash in the quota ++ calculation. The courier-imap secification tells explicitly to ignore ++ .Trash but in the last few weeks I had to find out that the courier ++ documentation should not be respected, because courier does not respect ++ it either. ++ ++ qmail-reply will no longer send replies to mails tagged with a X-RBL header. ++ This should dramaticaly reduce reply bounces if used with the proper RBL. ++ ++ Announce the EHLO STARTTLS option only if tls is compiled, enabled and ++ we have found a valid certificate in ~control/cert.pem for encryption. ++ ++ Modernize qmail startup infratructure. First step is to redo the ~boot ++ directory and to add ~log directory. Create subdirs for qmail, qmail-smtpd, ++ qmail-qmqpd, qmail-pop3d, qmail-imapd and qmail-pbsd for supervise and ++ multilog. Corresponding run files will come in the next release. ++ ++ Fix bug in qmail-smtp addrparse function. If "mail from" or "rcpt to" did ++ neither contain a '<' nor a ':' the function returned a nullsender (bounce) ++ or recipient instead of a syntax error. This bug is also present in stock ++ qmail-1.03. ++ ++ The copyloop used to forward pop3 and imap session can be simplified. ++ Neither pop3 nor imap are protocols which support half close so dump this ++ stuff. Half closing those forwarding sessions could be used as a DOS attack. ++ ++ qmail-todo could end in an infinite loop if qmail-send died before sending ++ the synchronization flag. This can happen if qmail-lspawn died because of ++ a missing control file. ++ ++ Print the dynamic data compression message in qmail-remote only if compressed ++ data was sent. Otherwise we get some junk number. ++ ++ Fixing clustering. The cluster forwarding was broken during the rewrite ++ (20030901). ++ ++ Fix error handling of qmail-quotawarning startup in qmail-local. ++ ++ Bug fix in qldap_get_status reported by . ++ ++ Removed some unneccesary verbositiy in qmail-secretary. ++ ++ Bug fix in the maildir string creation. A specified count value will over- ++ write any size settings. Thanks to Neil Sequeira for reporting this issue. ++ ++ SHADOWLIBS added in the digest link rule. ++ ++ bug fix in auth_imap. courier-imap login program which is invoking ++ auth_imap did not adhere to its own specs and sends too much stuff. ++ ++ ++NEWS for 20030901 stuff: ++ ++ WARNING: This release is NOT fully backwards compatible! We have made ++ certain changes for clarity and cleanup. ++ ++ qmail-group added. This tool handles mailing groups stored in ldap. Members ++ can be defined as rfc822 addresses, via dn entries and via ldap filters. ++ qmail-group can restrict mails togheter with qmail-secretary. So it is ++ possible to moderate a list, to restrict the sender to be a list member or ++ to confirm each message (qsecretary). ++ ++ qmail-ldaplookup has been rewritten. Not all functionality of the old tool ++ has been integrated yet. It is now possible to use search filters and to ++ show multiple entries. ++ ++ Removed some qmail-smtpd control files (tarpitcount/delay, maxrcptcount, ++ rblonlyheader). The only and right way to set them is environment variables ++ with tcpserver. ++ ++ Changed deliveryMode significantly. Before the setting of a forwarding ++ would have disabled local delivery. This is no longer the case. Each of ++ the modes has to be explicitly disabled (local, forward, program) or ++ enabled (reply). There are no longer contradicting modes which makes it ++ much more logical. ++ This change probably has a great impact on many administrative frontends! ++ ++ Quota definitions are new format only. ~control/ldapdefaultquota and mailQuota ++ serve no meaning anymore. Also the string quota format (10000S,100C) is no ++ longer supported. Use ~control/defaultquota[size|count] and mailQuotaSize ++ and mailQuotaCount instead. ++ ++ New tool qmail-secretary. This is the swiss army knife for mail group and ++ mailing list handling. It is used by the upcoming qmail-group tool but has ++ a compatibility modus for ezmlm (you may guess why ...). ++ ++ New tool qmail-forward. This tool forwards a mail via qmail-qmqpc in a ++ much nicer way than qmail-lspawn befor. Some more or less ugly hacks could ++ be removed. ++ ++ qmail-reply recent sender support finished. The code is still disabled ++ via NOTYET defines until I verified it. ++ ++ The mailheader magic of qmail-reply is now also supported by qmail-ldaplookup ++ and qmail-secretary. ++ ++ Fixed some problems with text control files, mainly quotawarning and ++ custombouncetext. Trailing white spaces and empty lines are no longer ++ cleared. ++ ++ Rewrite of the homedirmake and maildirmake feature. Finaly auth_imap will ++ create the maildir for courier. ++ ++ The environments passed between qmail-lspawn and qmail-local are now ':' ++ seperated and escaped. Nota bene the old csv stile definition of some ++ attributes mainly deliveryMode is still supported (the ',' are replaced ++ by ':' automagically). ++ ++ major cleanup in qmail-lspawn ldap handling and exit-code handling code. ++ Also the forwarding code has been moved out so that this code is no longer ++ run under root. ++ ++ NOPBS environment variable can now be used to disable pbsadd. This is useful ++ for nat-ed customers or if you have some local port forwarding and absolutly ++ neccessary for clusters (NOPBS set for all clusterhost IPs). ++ ++ Integration for pbs tools in cluster environments. auth_* has a switch -d ++ to specify pbsadd or a other tool that is executed in all success cases be ++ it local access or session forwarding. The old way via chaning the processes ++ still works for non cluster setups. ++ ++ new auth_pop, auth_imap and checkpassword implementation. The files are ++ now better seperated so that it should be possible to implement auth_smtp ++ without copying most of the auth* code. It is now possible to run the auth_* ++ tools without root priviledges and root priviledges are dropped as soon as ++ possible. ++ ++ Salted versions of SHA and MD5 (SSHA and SMD5) implemented and major cleanup ++ of the hole passwd compare functions. The digest tool has been rewritten to ++ support the new algorithms and to support passwd verifying. Also the base64 ++ and digest_* implementations have been cleaned up and stripped. ++ ++ new and better structured ldap backend. This solves many issues we had ++ with the old hackish implementation. These are: functioning rebind, support ++ for multiple concurrent connections, more flexible support for ldap attribute ++ handling and upcomming filter functions that can handle mutliple results. ++ ++ compile time option to enable ZLIB compression for QMQP cluster communication. ++ This is useful when cluster hosts are in different locations and have slow ++ or metered connections between them. All QMQP client/servers need to be ++ support the dynamic data compression, stock QMQP and compressed QMQP are ++ unable to understand each other. This may change for the server but not for the ++ client. Enable in Makefile with -DQMQP_COMPRESSION switch. ++ ++ cleaned up qmail.schema and added qmailGroup objectclass for mail groups. ++ ++ major cleanup, actually a huge cleanup, currently over 75 modified, removed ++ or added files. The code is now much more modularized and protable. ++ ++NEWS for 20030801 stuff: ++ ++ Removed checking of client certificates from TLS in qmail-smtpd. It is ++ no longer possible to allow automatic relaying via TLS client certs. ++ TLS functionality for transport is not affected and continues to be ++ fully functional. ++ ++ Some cleanup and clarification in smtpd and rbl logging. ++ ++ Added Russell Nelsons antivirus patch for qmail-smtpd. ++ Compile qmail-ldap with the -DSMTPEXECCHECK option and turn it on with ++ the REJECTEXEC environment variable. ++ ++ Added qmail-queue patch. Compile-time option via -DALTQUEUE. ++ ++ On-the-fly SMTP session data compression via ESMTP DATAZ extension. ++ Saves a damn lot of bandwidth. This is currently draft. See ++ draft-oppermann-smtp-datacompression-00.txt. ++ ++ Bug fix in Makefile (qmail-todo dependencies). ++ ++ Better handling of SMTP mail-parameters mainly SIZE. Until now only the first ++ mail-parameter was used all others where ignored. Also specially escaped ++ or quoted mail addresses could result in strange outcomes. ++ ++ New control/rbllist parser, it is no longer needed to use one tab as ++ separator. Lines starting with a # are comments and will be ignored. ++ ++ New delivery mode noforward to disable all forwarding entries in ldap ++ and .qmail. The deliveryMode attributes need some major overhaul becasue ++ we have a few modes -- manly forwardonly, noforward, localdelivery, ++ normal and nombox -- that are exclusive. Anyway for now this should make ++ life a bit easier. ++ ++ qmail-remote tries now higher MX servers if the previous server temporary ++ fails in the HELO/EHLO command exchange. >=500 errors result in a delivery ++ error. ++ ++NEWS for 20030501 stuff: ++ ++ gcc bug fix for OpenBSD sparc64 in digest_sha.c ++ ++ Better copy loop in checkpasswords imap/pop3 forwarding this should solve ++ problems with large file downloads over imap. ++ ++ Remove duplicate entries from pbsdbd cache, this should solve the "hash ++ flodding" error message. ++ ++ Bug fix in rbl.c from Sami Farin. ++ ++ Bad handling of return values. Per RFC a EHLO may return a 500, 502 or ++ perhaps a 504. In this case retry with HELO. ++ Update: Some servers send some non RFC compliant error code so retry ++ with HELO in all cases. ++ ++NEWS for 20030401 stuff: ++ ++ Added big todo patch. Enable with -DBIGTODO in Makefile. ++ ++ qmail-remote has a better look at the return codes of the helo/ehlo command. ++ This gives a better error handling in case of server that refuse the ++ connection with a >500 error in the begining. ++ ++ qmail-local bug fix in .qmail parser (missing () around a ||). ++ ++ Be more careful with closedir(). It is possible that the dirp is NULL. ++ ++ Nasty bug fix in qmail-qmqpc.c. Due to this it was impossible to use ++ qmail-qmqpc. ++ ++NEWS for 20030301 stuff: ++ ++ qmail-showctl updated so that all new control files are listed. ++ ++ qmail-remote and qmail-qmqpc are now capable to bind to a specified port ++ for outgoing connections. You can use control/outgoingip and control/qmqpcip ++ to set the ip. ++ ++ For ISP that need to implement some surveillance method because of some ++ beloved authoroties (like here in switzerland), we added the ++ BIGBROTHER switch. This enables a per address queue extra feature. ++ Just put a key pair like badguy@badplace.ch:bigbrother@admin.ch in ++ ~control/bigbrother to automaticaly forward all mail to or from ++ badguy to bigbrother. bigbrother can be a local, ldap or remote address. ++ ++ Bug fix in qmail-local: flagforwardonly was set to 0 instead of 1 if ++ deliverymode was forwardonly. ++ ++ Bug fix in maildir++ code: At two places a closedir was missing. Thanks to ++ Reinin Oyama. ++ ++ Bug fix because of a gratuitous recycling of a var in qmail-quotawarn if ++ the DOTMODE_NONE was used. Thanks to Chris Maxwell. ++ ++ Don't print extended received header if the needed infos are not available. ++ This is for qmtp receives. Idea by Chris L. Mason. ++ ++ Many bug fixes and enhancements in the NOTYET code of qmail-reply, inspired ++ by Neil Sequeira. ++ ++NEWS for 20030101 stuff: ++ ++ Retry the ldap_bind with LDAPv2 if ldap_bind fails with LDAP_PROTOCOL_ERROR. ++ This solves a problem with OpenLDAP > 2.0 client libs and a OpenLDAP 1.2 ++ Server. Inspired by Henning Brauer. ++ ++ New qmail-reply program. Now it is possible to define a header section ++ with %HEADER%. With this change it is possible to define special Content-type ++ and Content-Transfer-Encodings. ++ ++ Bug fix in qmail-lspawn: LDAP_MAXMSIZE = 0 should be eq unlimited. ++ Thanks to Henning Brauer. ++ ++ Finally added pop3d logging similar to the smtpd logging. ++ ++ Added the badmailfrom-unkown feature from Maex (via Henning Brauer). ++ ++ Added a fix in qmail-ldaplookup.c. Thanks to Kosh Naranek for the report. ++ ++NEWS for 20021201a stuff: ++ ++ Hot fix in qmail-local. If no quota was specified accounts with mailforwarding ++ didn't work. ++ ++ Close directory file handle in pbsadd and pbscheck. ++ ++ Nicer exit behaviour in qmail-todo (exit 0 if no error encountered). ++ ++ Add caseIgnoreIA5SubstringsMatch for mailAlternateAddress in qmail.schema. ++ ++NEWS for 20021201 stuff: ++ ++ On exit qmail-todo behaves now like qmail-[rl]spawn and stays alive ++ until qmail-send exits. All zombies have been slayered. ++ ++ On a -HUP qmail-send rereads more ~control files. Now bouncemaxbytes, ++ custombouncetext, locals and virtualdomains are reloaded. ++ ++ There seems to be a tiny bug in qmail-1.03 qmail-clean program. Fixed. ++ ++ Renamed QMAILQUOTA to MAILDIRQUOTA to work better with maildrop. ++ ++ Bug fix in qldap-ldaplib.c, when the ldap lookup timed out the wrong error ++ was returned. ++ ++ Minor bug fixes in the pbs tools inspired by Junjiro Okajima. ++ ++ Don't use NULL in maildir++.c because it is often not defined. ++ ++NEWS for 20021101 stuff: ++ ++ New ldap fields added: ++ - mailQuotaSize and mailQuotaCount replace the cryptic mailQuota string. ++ mailQuotaSize specifies the maximum size in bytes and mailQuotaCount ++ is the maximum number of messages allowed. ++ Note: the old mailQuota string is still valid and used if neither ++ mailQuotaSize nor mailQuotaCount are set. ++ - mailSizeMax specifies the maximum size of a single message the user may ++ receive. e.g. Dial-up customer prefer a small mailSizeMax. ++ Note: mailSizeMax is used in qmail-lspawn whereas databytes sets the ++ SMTP DATA limit. Therefor having a mailSizeMax bigger than databytes ++ does not make much sense. ++ The old mailQuota way of doing things is still supported. ++ ++ Fixed some bugs and cleand up maildir++.c. The maildirsize parser is now ++ rock solid and does no longer freak out when lines start with spaces as in ++ the newer courier-imap releases. ++ ++ quota_check() returns now also percentages over 100% (if over quota) and ++ the percentages calculation does not overflow with sizes over 40MB. ++ NOTE: quotas with sizes of around 4GB may overflow if large mails are ++ delivered and so the maildir size may get far over quota. This is a bug ++ and will get fixed somewhen (switch to 64bit quota numbers). ++ ++ maildir++ quota API cleanup. quota_recalc() works now exactly like ++ quota_calc(). ++ ++ In qmail.schema 'ProgramDeliveryPath' was incorrectly specified as ++ SINGLE-VALUE. Thanks to for finding it. ++ ++NEWS for 20021001 stuff: ++ ++ Corrected qmail.schema contributed by Mike Jackson. ++ ++ Documentation bug in POPBEFORESMTP fixed. ++ ++ Add LDAPv3 protocol support. ++ ++ Synchronize the external processor qmail-todo with qmail-send on startup. ++ There was a race condition on startup which caused some mails to be deliverd ++ twice. ++ ++ In both auth_* tools the forwarding code was only sending a CR instead of ++ the needed CRLF. ++ ++ Little fixes in the pbs tools. ++ ++NEWS for 20020901 stuff: ++ ++ Fixed bugs in pbscheck and pbsadd which caused unexpected behaviour if ++ multiple servers where specified. ++ ++ Fixed multiple bugs in maildir++ quota handling. ++ bug in read5120(), if open failed it could cause a loop. ++ bug with handling of subdirectories (path concatenation). ++ bug with interpretation of quota strings for courier 0C means ++ no files allowed whereas for qmail-ldap it was unlimited. ++ ++ Fixed some spelling errors. ++ ++ Bugfix in auth_imap. The procedure for failed logons had a bug. ++ ++NEWS for 20020801 stuff: ++ ++ Fixed an error in the patch file. ++ ++NEWS for 20020701 stuff: ++ ++ Fix in qmail-reply: the wrong Return-Path was set because an interference of ++ qmail-locals environment and qmail-injects use of it. ($USER is used in ++ the Return-Path) ++ ++ In both auth_* tools the forwarding code was sending LFCR instead of CRLF. ++ ++ Fix buffer overflow in qmail-quotawarn.c. I changed the filename generation ++ without resizing the file name buffers, shame on me. ++ NOTE: This overflow can not be exlpoited. ++ ++ better handling of virtual/ldap .qmail handling. ++ The ldap .qmail arguments are now exected in the following way: ++ 1. reply (deliveryMode: reply) ++ 2. delivery programs (deliveryProgramPath) ++ 3. forwards (mailForwardingAddress) ++ 4. localdeliver (deliveryMode: localdelivery) ++ So it is possible to use a filter delivery program or other more complex ++ delivery options. ++ ++NEWS for 20020501a stuff: ++ ++ bounce messages are now qsbmf-compliant, wether custombouncetext is set or ++ not. Note that you may not have blank lines in custombouncetext. ++ Thanks to Henning Brauer for the patch and to Mike Jackson for ++ the report. ++ ++ The pop-before-smtp tools now support transaction of additional environment ++ variables. See POPBEFORESMTP for more info. ++ ++ Use real rfc822 timestamps and more Maildir stile filename in qmail-quotawarn. ++ This should fix order problems in mailclients. ++ ++NEWS for 20020501 stuff: ++ ++ ****** ATTENTION the format of ~control/rbllist has changed, see ****** ++ QLDAPINSTALL for information about the new rbllist file. ++ ++ Major overhaul of qmail-smtpd. Completely restructured anti-spam stuff and ++ replaced DENYMAIL environment variable (settable through tcpserver) with: ++ - SMTP550DISCONNECT to disconnect the smtp session immediatly after a fatal ++ 5xx error ++ - NOBOUNCE to reject null sender bounces ++ - SANITYCHECK to reject messages without @, no . in TLD, too short/long TLD ++ - RETURNMXCHECK to check if the sender has an MX ++ - BLOCKRELAYPROBE to block rcptto containing !%@ before @ from Russell Nelson ++ - RBL to check RBLs ++ - RBLONLYHEADER to only add a X-RBL header ++ ++ added bouncemaxbytes patch: ++ to turn it on write the amount of bytes to bounce in the file ++ ~control/bouncemaxbytes. ++ Work inspired and mostly copied from Frank DENIS aka Jedi/Sector One. ++ ++ Bug fix in qmail-send.c log handling: ++ If in one read a log entry and a delivery status notification was delivered the ++ status notification was dropped and therefor qmail-send did not close the job. ++ ++ qmail-remote supports the smtp size extension as specified by rfc 1870. ++ If the EHLO extension size is set qmail-remote sends size in the mail from ++ commando. It does not parse the EHLO size argument to check if the size is ++ OK, the remote smtp server should decide if it is OK. ++ ++ clean up in qmail-remote, the starttls option was not compared in a case ++ independend way as defined in rfc 2821. The tls debug option is now called ++ TLSDEBUG. ++ ++ added Russ Nelson patch to qmail-remote to send using QMTP. ++ From his patch: ++ This patch to qmail-remote causes it to attempt qmtp first if the MX priority ++ indicates so. Read http://cr.yp.to/proto/mxps.txt for more information. ++ If you want this qmail-remote to be able to send email to you using qmtp, ++ then you should be running a qmtpd on port 209, and you should have your ++ lowest MX priority be 12801. ++ ++ added pop-before-smtp tools (see POPBEFORESMTP for more info). ++ ++ reject any null sender (bounce) smtp session with more than one rcpt-to ++ (based on an idea of Charles Cazabon and some code of Henning Brauer) ++ ++ updated QLDAPINSTALL (more about those nasty -lresolv and ld.so problems) ++ ++ beautified the output of the recieved line (added an additional linebreak) ++ ++ Add a precedence bulk header when we forward a message to more than one ++ recipient. So auto-reply programs at the recipients will not answer such ++ mails. A message forwarded to more than one recipient is now considered ++ a mailing list email. ++ ++ Add an external TODO processor program. This moves the queue todo processing ++ out of qmail-send to avoid the silly qmail syndrome with high injection rates ++ (see EXTTODO for more info). Enable with -DEXTERNAL_TODO in Makefile. ++ ++NEWS for 20011001 stuff: ++ ++ added a variation of Henning Brauer's alternate mailhost patch. ++ For more info: mailto: ++ ++ added a variation of Henning Brauer's dash-ext patch. The main ++ difference is the way it handels the extensions. ++ Example lookup scheme: ++ aaaa-bbbb-cccc@domain.tld ++ aaaa-bbbb-CATCHALL@domain.tld ++ aaaa-CATCHALL@domain.tld ++ CATCHALL@domain.tld ++ where CATCHALL is replaced with the value of LDAP_CATCH_ALL defined ++ in qmail-ldap.h. If CATCHALL is set to "default" instead of the standart ++ "catchall" it is allmost stock qmails behaviour. ++ The dash-ext stuff can be turned on with the -DDASH_EXT option in Makefile. ++ ++ some rewrite of qmail-ldaplookup. See qmail-ldaplookup -h. ++ ++ Makefile bug fixed, spawn.c was compiled without -DDEBUG. Not in 0802i. ++ ++ Changes in qldap-ldaplib.*: ++ added qldap_open to open the ldap connection ++ added qldap_close to close the ldap connection ++ renamed ldap_lookup to qldap_lookup ++ Now it is possible to use one ldap (TCP) connection for multiple queries, so ++ the connection overhead with DASH_EXT is drastically reduced. ++ ++ new debug/log handling. In qmail-lspawn the debug output is no ++ longer added to bounce mails. ++ ++ bug fix in the cleaned up NS-MTA code. ++ ++ bugfix in catchall search string generation. Hopefully the last one. ++ ++ bugfix in qmail-ldaplookup (ldap_value_free). Thanks to Sascha Gresk. ++ ++ better handling of deliverymode in qmail-lspawn.c ++ ++NEWS for 20010501 stuff: ++ ++ bugfix in qmail-local.c by Mark Belnap. Problems with deliverymode reply. ++ ++ disallow null passwords in auth_pop and auth_imap. ++ ++ added RBLONLYHEADER logging control file and variable. With this it will ++ no longer reject a mail upon a RBL match but it will mark it with a "X-RBL:" ++ header. ++ ++ major cleanup in digest_* and base64 to make the code more djb style. ++ Minor cleanup in some other files. compatibility.h is no longer needed. YES! ++ ++ string fix in digest_md5.c (NS_MTA handling) ++ ++ bugfix in catchall search string generation. ++ ++ bugfixes in maildir++ support. Thanks to Franky Van Liedekerke. ++ ++ bugfixes in qmail-reply ++ ++ new attribute qmailAccountPurge for automatic purging of maildirs from ++ deleted accounts ++ ++NEWS for 20010301 ++ ++ added 0.0.0.0 patch ++ ++ some fixes for misc. stuff from Chris Noe ++ - with DEBUGLEVEL set, the default ldapGID is printed incorrectly ++ - The line above says 'without trailing slash' but the example has one :) ++ - Permanet -> Permanent ++ - Programm -> Program ++ - fix qmail-lspawn 'Out of memory' error when attempting local delivery ++ to a nonexistant user. ++ ++ fix for qmail-reply.c from Jamie Blondin ++ - handle precedence flag in the right way ++ ++ fix for qmail.schema mailReplyText from David E. Storey ++ ++ fix for ldaptimeout to just defer message delivery instead of bouncing ++ sometimes ++ ++NEWS for 20010201: ++ ++ fix for ldapobjectclass bugfix ++ ++ beautyfied qmail-reply.c. Now it should handel most messages in a correct ++ and nice way. ++ ++ bugfix for the new ldapobjectclass and ldaptimeout stuff ++ ++ bugfix in maildir++.c: algorithm has ignored all subdirs except .Trash ++ ++NEWS for 20010101: ++ ++ introduced ~control/objectclass to limit the ldap search to a specific ++ ldap objectclass as suggested in some recommended procedures. ++ ++ bugfix in maildir++: ++ files with sizes containig 0 or 9 where claclculated wrong ++ if only one of C or S type where declared the quota of the other was ignored ++ ++ changed ALIASEMPTY in qmail-ldap.h from /dev/null to |sh -c "cat > /dev/null" ++ direct writing to /dev/null resulted in a soft error. This shell call does the ++ same without an error. ++ ++ introduced ~control/ldaptimeout to limit the time and ldap search might ++ take until the delivery attempt is being deferred and tried again later. ++ The default is 30 seconds. ++ ++ works fine with OpenLDAP 2.x (2.0.7). ++ ++ included the OpenLDAP 2.x LDAPv3 Schema definition file created by ++ David E. Storey. This version is based on the original work by David ++ but modified quite a lot by Andre. Also qmail-ldap has got it's own ++ offcially IANA assigned OID. ++ ++NEWS for 20001201: ++ ++ cluster loop protection enhanced, now also the users mailaddress is added: ++ Delivered-To: CLUSTERHOST host.name.as.in.control.me users@e-mail.addr ++ ++ new maildir++ quota algorithm implemented. This one is simpler and should ++ therefor work much better. NOTE: The code was not tested under havy load. ++ ++ major enhancements in qmail-reply.c. Fixed a bug that could crash qmail-reply ++ if a bad mail was sent. The output of qmail-reply was also beautified. ++ ++ introduced MAXRCPTCOUNT to limit the maximum number of rcpt to's in one session. ++ ++ introduced RBL support to check the senders IP against a number of RBL's, see ++ ~control/rbllist. ++ ++ documented ~control/relaymailfrom to allow relaying based on the senders ++ mail address. ++ ++ documented LOGLEVEL and DENYMAIL environment variables to qmail-smtpd. ++ ++NEWS for 20001013: ++ ++ possible fix for newer gcc. Problems with va_arg and unsigned chars. ++ I don't have such a new gcc, so I don't know if this fixes the problem. ++ ++ bug fix for the problem mentioned by Aleksander Dzierzanowski (mail to deleted ++ mailfiles bounce if there is a quota set). ++ ++ cluster loop protection added. Now it should be impossible that mail loop ++ forever if the cluster was badly configured. It works via the Delivered-To line ++ and uses something like this: ++ Delivered-To: CLUSTERHOST host.name.as.in.control.me ++ ++ fixed multiple problems with suns cc. ++ ++ fixed multiple problems and bugs in TLS support. ++ ++ fixed a bug introduced with the bitmask support for debug outputs. ++ ++ cleanup at different locations to respect the signedness of variables ++ ++ added bitmask support for debug outputs, so DEBUGLEVEL=3 will print error and ++ warnings but DEBUGLEVEL=2 only warnings. Note: init_debug's 2nd argument has ++ changed, it's now a binary mask that is binary anded with the debuglevel. ++ e.g. to disable PASSWD outputs use something like -1^256 as 2nd argument. ++ ++ added some defines for better testing: ++ use -DPORT_SMTP="alternate smtp port", -DPORT_LDAP="alternate ldap port" and ++ -DPORT_QMQP="alternate qmqp port" to change those ports. ++ ++NEWS for 20000701 patch: ++ ++ if the LDAP server is down put the message back into the queue instead of ++ bouncing ++ ++ correct spelling errors in many files ++ ++ forcing forwardonly and ldaponly when neither LDAP_MAILSTORE nor LDAP_HOMEDIR ++ is defined ++ ++ bugfixes in hier.c and install-big.c to install qmail-ldaplookup with correct ++ 0700 permission, as told in the QLDAPINSTALL file ++ ++ bug fix in checkpassword.c and qmail-ldaplookup.c with wrong index to the ++ LDAP args array. Thanks to Ricardo Cerqueira ++ ++ small bug fix in qmail-ldaplookup, fixed a wrong output. ++ ++ added possible connection less LDAP support. Untested because slapd does not ++ support cladp until now. To turn it on use -DUSE_CLDAP as LDAPFLAGS ++ ++NEWS for 20000601 patch: ++ ++ update of the QLDAP* files ++ ++ bug fix in maildir++.c and qmail-local.c, now quota_add should add the correct ++ size of the mail. Until now only the message without DTLINE and RPLINE was ++ sized ++ ++ bugfixes in "empty file list :)" ++ ++ ++NEWS for 20000501 patch (and some also for 20000401): ++ ++ Add the new control files and their meaning to qmail-showctl ++ You can use qmail-showctl to check your setup. ++ ++ added new tool qmail-ldaplookup with this program you can check the ldap ++ db entries. Similar to the old checkpassword with debug support. ++ Usage: qmail-ldaplookup {-m mailaddress | -u userid [passwd]} ++ NOTE: because this tool could show critical data (like the hashed passwd) ++ it is installed with mode 000 (no rights for anybody) ++ You should only give root the permission to start it. ++ ++ new mailMessageStore/homeDirectory handling. ++ Because a lot of people requested it and because I was also unhappy with it ++ I have rewritten/enhanced the mailMessageStore handling. ++ Now the homedir and aliasempty are set via both ++ mailMessageStore (LDAP_MAILSTORE) and homeDirectory (LDAP_HOMEDIR). ++ It works like this: ++ IF LDAP_HOMEDIR exists it is used as $HOME (qmail-locals 3rd ARGV) ++ IF also LDAP_MAILSTORE exists LDAP_MAILSTORE is used as aliasempty ++ (last ARGV of qmail-local) ++ ELSE (no LDAP_MAILSTORE ) use the aliasempty specified ++ in /var/qmail/rc or similar ++ FI ++ ELSE IF LDAP_MAILSTORE exists but no LDAP_HOMEDIR exists ++ IF LDAP_MAILSTORE is absolute use LDAP_MAILSTORE as ++ $HOME and use standard aliasempty ++ ELSE (LDAP_MAILSTORE not absolute) use control/ldapmessagestore as ++ prefix to LDAP_MAILSTORE and use this as $HOME and use std. aliasempty ++ ELSE neither LDAP_MAILSTORE nor LDAP_HOMEDIR exists ++ use ~alias as $HOME and ALIASDEVNULL as aliasempty ++ FI ++ ++ NOTE: the case neither LDAP_MAILSTORE nor LDAP_HOMEDIR is a bit special ++ ~alias is installed as root.qmail mode 02755 (rwxr-sr-x) so no user ++ can write to this directory. ALIASDEVNULL is defined in qmail-ldap.h ++ normally /dev/null can be used (forward-only and ldaponly will be forced ++ in the next release) or a special alert tool can be used ++ ("|/var/qmail/bin/myalerttool") ++ NOTE2: if you use "homeDirectory" and "mailMessageStore" in an incompatible ++ way and you want the old behavior back define LDAP_HOMEDIR in ++ qmail-ldap.h as an nonexistent ldap db field like noHomeDirectory. ++ ++ new check algorithm, I think it's faster and better. ++ Have a look at check.c. At the end of the file there is a array with all ++ ASCII chars (7bit). You can allow or deny char by adding: ++ DENY_ALL: always deny this char ++ ALLOW_ALL: always allow this char ++ ALLOW_USER: allow this char for username checks (chck_user) ++ DENY_USER: deny this char for username checks (chck_user) ++ ALLOW_PATH: allow this char for path checks (chck_path) ++ DENY_PATH: deny this char for path checks (chck_path) ++ ALLOW_PROG: allow this char for program checks (chck_prog) ++ DENY_PROG: deny this char for program checks (chck_prog) ++ NOT_FIRST: deny this char at the beginning of a string ++ SPACE: alias to ALLOW_PROG ++ PARANOIA: deny most shell special chars like '|' or '*' for program checks ++ can be turned on or of in qmail-ldap.h ++ Example: ++ /* 7 \007 ^G */ DENY_ALL, /* deny control chars */ ++ /* 45 '-' */ ALLOW_ALL|NOT_FIRST, /* allowed but not first */ ++ /* 47 '/' */ ALLOW_ALL&DENY_USER, /* allowed only for path and prog */ ++ /* 58 ':' */ ALLOW_PROG|ALLOW_PATH, /* like before */ ++ ++ As you can see ALLOWs have to be ORed together whereas DENYs have to be ANDed ++ NOT_FIRST has to be ORed and PARANOIA has to be ANDed. ++ ++ getcwd and chdir no longer used in qldap-ldaplib.c init_ldap function. ++ ++ changed the connection forwarding under pop and imap. Now it should work ++ correctly, or at least better then before ;-) ++ ++ major cleanup in maildir++ support (mainly maildir++.c) ++ ++ bugfixes in qmail-lspawn.c, qmail-reply.c and checkpassword.c ++ ++ ++NEWS for previous releases: ++ ++ Added new debug facility that is usable for the auth tools and qmail-lspawn. ++ The debug-level can now be changed at runtime and everything gets logged via ++ splogger or any other logger connected to stderr of the execution chain. ++ You can set the debug level easily with the DEUBUGLEVEL environment variable. ++ ++ Created a new auth tool for pop3 and imap. The old checkpassword is not ++ needed anymore. The new programs are auth_pop and auth_imap. ++ To have the possibility to compare cleartextpasswords (password how are ++ stored clear text in ldap) define CLEARTEXTPASSWORD. Because this setting ++ is a security disaster it is normally off. All other modes (hashed MD4, MD5, ++ SHA and the standard DES crypt) are not affected. ++ ++ Rewritten qmail-lspawn and the auth tools. Both programs use now the same ++ debug and ldap functions, which are now moved to new files (qldap-*). ++ The complete ldap lookup is now more flexible, so you can easier add your ++ special stuff. ++ ++ The qmailUser ldap field and the corresponding conf file are no longer used, ++ they have been replaced with the uid field. ++ ++ Added maildir++ support, this means especially better quota support via the ++ maildir++ maildirsize file. For more info have a look at courier-imap ++ http://www.inter7.com/courierimap/ ++ ++ Added signal-handler for qmail-lspawn, now with a SIGHUP the qmail-lspawn ++ parent process reloads the his settings ( via the ~control files ) ++ ++ Added cluster support, use -DQLDAP_CLUSTER for enabling. ++ ++ Removed PWOPTS=-DLOOK_UP_PASSWD because it was only for checkpassword ++ and with ldaplocaldelivery you get the same result on the fly. ++ ++ Few minor bugfixes (qmail-qmqpd.c, qmail-qmtpd.c, receive.c) ++ ++ Updated QLDAPINSTALL and added new QLDAPNEWS because QLDAPINSTALL was ++ getting to long. ++ ++ Changed the make process, now with the make setup check also the qmail-ldap ++ parts are build and installed. Have fun ... ++ ++ Few minor bugfixes (accountStatus, AUTO_MAILDIRMAKE) ++ ++ Hack in the LDAP search filter escape function due to a bug in most LDAP ++ servers. Instead of escaping the wildchars we replace them with '_' as ++ long as -DLDAP_ESCAPE_BUG is present. (see Makefile) ++ ++ a catch all mail for one domain system is now available. The default ++ catchall account is "catchall@domain.com". You can change that to any ++ other sting in qmail-ldap.h at compile time. LDAP wildcards are not ++ allowed. ++ Due to a bug in the LDAP servers wildcards escaping does not work, so pay ++ attention. ++ ++ rewritten qmail-locals qldap code, now supports better support for different ++ dotModes. There are also some new settings. ++ ++ fixed some old bugs in qmail-local ++ ++ fixed already some bugs in new qmail-local code ;-) ++ ++ added a log facility to qmail-lspawn. ++ ++ added some experimental -extension support in qmail-lspawn. ++ ++ Added a headerfile qmail-ldap.h where all parameters are set. ++ This includes some changes in qmail-local.c qmail-lspawn.c and checkpassword.c ++ ++ qmail-lspawn checks no longer for "correct" mailaddresses, now the possible ++ mailaddress is escaped ('(', ')', '*') before added to the search filter. ++ ++ all the stuff that was fixed in the subpatches. (XXX double check that) ++ ++ Added some compile options in the Makefile for easier configuration (see 5.) ++ ++ Added Christopher K. Davis' patch to handle oversized dns packets. ++ ++ Added Chris Johnson's tarpitting patch. ++ ++ Added qmail-quotawarn and qmail-reply for better handling of quota-warnings ++ and auto reply ++ ++ deliveryMode is now a comma separated list see LDAP PARAMETER FIELDS ++ ++ Fixed a few things in qmail-local ++ ++ Supports OpenLDAP now ++ ++ WARNING: {SHA1} changed to {SHA} according to the standard ++ ++ Integrated Lindsay Haisley update to Rask Lambertsen's excellent ++ antispam patch for qmail v1.01, based on Lionel Widdifield's patch. ++ Please read ANTISPAM for more information. ++ ++ checkpassword now supports the password format used by Netscape ++ Mailserver pre-3.0 and Software.com's Post.Office (NS-MTA-MD5). ++ That string is hex encoded, the first 32 Octets are the MD5 hashed ++ password and the second 32 Octets are the salt to the MD5 function. ++ ++ Added automatic homedir and maildir maker to qmail-local. ++ This can be enabled with ~control/dirmaker ++ ++ qmail-smtpd does logging now. This can be set by an environment variable ++ in tcpserver: LOGLEVEL="X". "0" or not present = no logging, "1" = fatal ++ errors, "2" = connection setup and warnings, "3" = verbose. ++ ++ Added fix for qmail-pop3d stat command bug found by Aaron Nabil ++ . ++ ++ checkpassword compiled with QLDAPDEBUG now does complete LDAP debugging. ++ Usage: ./checkpassword POPLogin POPPassword ++ ++ digest computes MD4, MD5, RMD160 and SHA passwords (compatible to Netscape) ++ Usage: ./digest POPPassword ++ ++ solved a problem on big endian machines that caused wrong SHA, MD5, MD4, ++ RMD160 passwords. (Added an endian testprogram to solve those probs) ++ ++ added a working version of the "MAKE_NETSCAPE_WORK" patch under qmail-pop3d. ++ The download bar should now work correctly. ++ ++ Fixed the bugs in qmail-lspawn. Changed stralloc_catb to stralloc_cat. ++ Thanks to Franky Van Liedekerke ++ ++ +diff -upN qmail-1.03/QLDAPPICTURE qmail-ldap/QLDAPPICTURE +--- qmail-1.03/QLDAPPICTURE Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/QLDAPPICTURE Sun Jun 25 03:04:27 2000 +@@ -0,0 +1,29 @@ ++ 1. qmail-smtpd accepts connection ++ ++ Is relayclient set? ++ Yes -> accept it anyway. ++ No -> check if recipient domain is listed in rcpthosts else ++ deny ++ ++ Does sender's domain have a valid MX or A record? ++ Yes -> accept for data ++ No -> deny ++ ++ Now the message gets queued. ++ ++ 2. qmail-send takes a look at it ++ ++ Is the recipients domain in virtualhosts or locals (doesn't matter ++ with qmail-ldap)? ++ Yes -> feed it to qmail-lspawn for local delivery ++ No -> feed it to qmail-rspawn for remote delivery (relaying as ++ usual) ++ ++ 3. qmail-lspawn gets it for local delivery ++ ++ Is the recipients full email address found in the LDAP directory? ++ Yes -> check if all needed attributes are present ++ Yes -> deliver it to the maildir ++ No -> bounce ++ No -> try a standard qmail (UNIX user or ~users/assign) delivery ++ +diff -upN qmail-1.03/QLDAPTODO qmail-ldap/QLDAPTODO +--- qmail-1.03/QLDAPTODO Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/QLDAPTODO Wed Aug 18 11:27:12 2004 +@@ -0,0 +1,45 @@ ++QMAIL-LDAP by Andre Oppermann , ++Claudio Jeker and Boris Lutz ++(c) 2000-2004 Internet Business Solutions AG ++ ++RELEASE: $Date: 2004/08/03 20:27:44 $ ($Revision: 1.36 $) ++ ++This is the TODO FILE, so the QLDAPINSTALL file gets a bit cleaner. ++This file is NOT structured!! ++ ++NEWS: ++ ++ see QLDAPNEWS ++ ++TODO: ++ ++ongoing - Debugging and testing, testing, testing ++done - The big qmail-ldap picture ++ongoing - full code review by a third person ++planned - make it possible to have locals and rcpthosts in ldap ++ and perhaps also the rules for the tcpserver (certs?) ++ some people refer to this as ldap-control ++ ++PS: planned means we see the use of the idea but there are a lot more ++ important things that need to be done first. ++ ++ALSO ON THE LIST: (priority list) ++- update qmail-ldaplookup (mainly ldap login, passwd check and group handling) ++- cleanup the debug code, unify the debug levels ++- cleanup failures (hard vs. temporary) ++- use pbstools for enhanced tarpit idea ++- make full example for qmailaccountpurge.sh ++- docu cleanup ++- address rewriting (envelope only) ++ ++older stuff still on the list: ++- add more and clearer documentation. ++- benchmarking the code ++- better TLS support (better written??) (tls for pop???) ++- 64bit counters for quota handling code. ++ ++status unclear: ++- force to alias if only mail and mailforwardingaddress is set (no uid). (done) ++- test what happens if only uid and mail is defiend in ldap or similar uncommon ++ cases (seems to be no problem, or?) ++ +diff -upN qmail-1.03/TARGETS qmail-ldap/TARGETS +--- qmail-1.03/TARGETS Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/TARGETS Wed May 5 17:42:11 2004 +@@ -147,9 +147,8 @@ hasshsgr.h + prot.o + coe.o + cdb_hash.o +-cdb_unpack.o +-cdb_seek.o + cdb.a ++cdb.o + auto-uid.o + auto-uid + auto-gid.o +@@ -221,10 +220,7 @@ qmail-upq + qmail-showctl.o + qmail-showctl + qmail-newu.o +-cdbmss.o +-cdbmake_pack.o +-cdbmake_hash.o +-cdbmake_add.o ++cdb_make.o + cdbmake.a + qmail-newu + qmail-pw2u.o +@@ -385,3 +381,81 @@ forgeries.0 + man + setup + check ++auth_imap ++Makefile.cdb-p ++auth_imap.o ++auth_mod.o ++auth_pop ++auth_pop.o ++auth_smtp ++auth_smtp.o ++auto_userl.c ++auto_userl.o ++base64.o ++byte_repl.o ++case_startb.o ++check.o ++checkpassword.o ++condwrite ++condwrite.o ++digest ++digest.o ++digest_md4.o ++digest_md5.o ++digest_rmd160.o ++digest_sha1.o ++dirmaker.o ++endian ++endian.o ++execcheck.o ++localdelivery.o ++locallookup.o ++maildir++.o ++mailmagic.o ++mailmaker.o ++output.o ++passwd.o ++pbsadd ++pbsadd.o ++pbscheck ++pbscheck.o ++pbsdbd ++pbsdbd.o ++pbsexec.o ++qldap-cluster.o ++qldap-debug.o ++qldap-errno.o ++qldap-filter.o ++qldap-profile.o ++qldap.a ++qldap.o ++qmail-cdb ++qmail-cdb.o ++qmail-forward ++qmail-forward.o ++qmail-group ++qmail-group.o ++qmail-imapd-ssl.run ++qmail-imapd.run ++qmail-ldaplookup ++qmail-ldaplookup.o ++qmail-pbsdbd.run ++qmail-pop3d-ssl.run ++qmail-pop3d.run ++qmail-qmqpd.run ++qmail-quotawarn ++qmail-quotawarn.o ++qmail-reply ++qmail-reply.o ++qmail-secretary ++qmail-secretary.o ++qmail-smtpd.run ++qmail-todo ++qmail-todo.o ++qmail-verify ++qmail-verify.o ++qmail.run ++rbl.o ++read-ctrl.o ++readwrite.o ++smtpcall.o +diff -upN qmail-1.03/TLS.readme qmail-ldap/TLS.readme +--- qmail-1.03/TLS.readme Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/TLS.readme Sat Mar 29 12:00:02 2003 +@@ -0,0 +1,71 @@ ++Frederik Vermeulen 20000112 ++http://www.esat.kuleuven.ac.be/~vermeule/qmail/tls.patch ++ ++This patch implements RFC2487 in qmail. This means you can ++get SSL or TLS encrypted and authenticated SMTP between ++the MTAs and between MTA and an MUA like Netscape4.5. ++The code is considered experimental. ++ ++Usage: - install OpenSSL-0.9.4 http://www.openssl.org/ ++ - apply patch to qmail-1.03 http://www.qmail.org/ ++ Makefile and conf-cc were patched for appropriate ++ linking. Apart from that, the patches to qmail-remote.c ++ and qmail-smtpd.c can be applied separately. ++ - provide a certificate in /var/qmail/control/cert.pem. ++ "make cert" makes a self-signed certificate. ++ "make cert-req" makes a certificate request. ++ - replace qmail-smtpd and/or qmail-remote binary ++ - verify operation (header information should show ++ something like ++ "Received [..] with DES-CBC3-SHA encrypted SMTP;") ++ If you don't have a server to test with, you can test ++ by sending mail to ping@linux.student.kuleuven.ac.be, ++ which will bounce your mail. ++ ++Optional: - when TLSDEBUG is defined, some extra SSL info will be logged ++ - when a 512 RSA key is provided in /var/qmail/control/rsa512.pem, ++ this key will be used instead of on-the-fly generation by ++ qmail-smtpd. Daily replacement can be done by crontab: ++ 01 01 * * * /usr/local/ssl/bin/openssl genrsa \ ++ -out /var/qmail/control/rsa512.new 512 > /dev/null 2>&1;\ ++ chmod 600 /var/qmail/control/rsa512.new; chown qmaild.qmail \ ++ /var/qmail/control/rsa512.new; /bin/mv -f \ ++ /var/qmail/control/rsa512.new /var/qmail/control/rsa512.pem ++ - server authentication: ++ qmail-remote requires authentication from servers for which ++ /var/qmail/control/tlshosts/host.dom.ain.pem exists. ++ The .pem file contains the validating CA certificates ++ (or self-signed server certificate with openssl-0.9.5). ++ CommonName has to match. ++ WARNING: this option may cause mail to be delayed, bounced, ++ doublebounced, and lost. ++ - client authentication: ++ when relay rules would reject an incoming mail, ++ qmail-smtpd can allow the mail based on a presented cert. ++ Certs are verified against a CA list in ++ /var/qmail/control/clientca.pem (eg. http://www.modssl.org/ ++ source/cvs/exp/mod_ssl/pkg.mod_ssl/pkg.sslcfg/ca-bundle.crt) ++ and the cert email-address has to match a line in ++ /var/qmail/control/tlsclients. This email-address is logged ++ in the headers. ++ ++Copyright: Same terms as qmail ++ Links with OpenSSL ++ Inspiration and code from examples in SSLeay (E. Young ++ and T. Hudson ), ++ stunnel (M. Trojnara ), ++ Postfix/TLS (L. Jaenicke ), ++ and modssl (R. Engelschall ). ++ Debug code from Jean-Philippe Donnio ++ Openssl usage consulting from Bodo M"oller ++ ++ ++Interoperability: - Netscape 4.5 and higher ++ - Microsoft Outlook 5 ++ - Microsoft Exchange Internet Mail Server 5.5.2448.0 ++ - Postfix/TLS ++ http://www.aet.TU-Cottbus.DE/personen/jaenicke/pfixtls/ ++ - Sendmail-TLS http://opensource.3gi.com/sendmail-tls/ ++ ++Patches: mailto: ++ +diff -upN qmail-1.03/alloc.c qmail-ldap/alloc.c +--- qmail-1.03/alloc.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/alloc.c Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,6 @@ ++#include + #include "alloc.h" + #include "error.h" +-extern char *malloc(); +-extern void free(); + + #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ + #define SPACE 4096 /* must be multiple of ALIGNMENT */ +@@ -11,10 +10,10 @@ static aligned realspace[SPACE / ALIGNME + #define space ((char *) realspace) + static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +-/*@null@*//*@out@*/char *alloc(n) ++/*@null@*//*@out@*/void *alloc(n) + unsigned int n; + { +- char *x; ++ void *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); +@@ -23,10 +22,10 @@ unsigned int n; + } + + void alloc_free(x) +-char *x; ++void *x; + { +- if (x >= space) +- if (x < space + SPACE) ++ if ((char *)x >= space) ++ if ((char *)x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); + } +diff -upN qmail-1.03/alloc.h qmail-ldap/alloc.h +--- qmail-1.03/alloc.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/alloc.h Tue Oct 28 18:21:31 2003 +@@ -1,8 +1,8 @@ + #ifndef ALLOC_H + #define ALLOC_H + +-extern /*@null@*//*@out@*/char *alloc(); +-extern void alloc_free(); +-extern int alloc_re(); ++extern /*@null@*//*@out@*/void *alloc(unsigned int); ++extern void alloc_free(void *); ++extern int alloc_re(char **, unsigned int, unsigned int); + + #endif +diff -upN qmail-1.03/auth_imap.c qmail-ldap/auth_imap.c +--- qmail-1.03/auth_imap.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auth_imap.c Thu Jul 1 16:28:30 2004 +@@ -0,0 +1,353 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++/* auth_imap.c for courier-imap */ ++#include ++#include ++#include ++#include ++#include "alloc.h" ++#include "byte.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "pbsexec.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "readwrite.h" ++#include "scan.h" ++#include "sgetopt.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "timeoutread.h" ++ ++#include "auth_mod.h" ++ ++#ifndef PORT_IMAP /* this is for testing purposes */ ++#define PORT_IMAP 143 ++#endif ++ ++const unsigned int auth_port = PORT_IMAP; ++ ++#define UP_LEN 1024 ++static char auth_up[UP_LEN]; ++static unsigned int auth_uplen; ++static int auth_argc; ++static char **auth_argv; ++ ++void ++auth_init(int argc, char **argv, stralloc *login, stralloc *authdata) ++{ ++ char *a, *s, *t, *l, *p; ++ int waitstat; ++ int i, opt; ++ ++ while ((opt = getopt(argc, argv, "d:")) != opteof) { ++ switch (opt) { ++ case 'd': ++ pbstool = optarg; ++ break; ++ default: ++ auth_error(AUTH_CONF); ++ } ++ } ++ argc -= optind; ++ argv += optind; ++ ++ if (argc < 1) ++ auth_error(AUTH_CONF); ++ auth_argc = argc; ++ auth_argv = argv; ++ ++ a = env_get("AUTHENTICATED"); ++ if (a && *a) { /* Already a good guy */ ++ logit(8, "auth_init: allready authenticated\n"); ++ execvp(*argv, argv); ++ auth_error(AUTH_EXEC); ++ } ++ ++#if 1 ++ /* ++ * remove all zombies, why should I do that? ++ * Because courier makes zombies for breakfast ++ */ ++ sig_childdefault(); ++ while (wait(&waitstat) >= 0) ; ++#endif ++ for (auth_uplen = 0;;) { ++ do { ++ i = read(3, auth_up + auth_uplen, ++ sizeof(auth_up) - auth_uplen); ++ } while ((i == -1) && (errno == EINTR)); ++ if (i == -1) ++ auth_error(ERRNO); ++ if (i == 0) break; ++ auth_uplen += i; ++ if (auth_uplen >= sizeof(auth_up)) { ++ auth_error(PANIC); ++ } ++ } ++ close(3); ++ auth_up[auth_uplen] = '\0'; ++ ++ /* ++ * get the different fields: serviceAUTHTYPEAUTHDATA ++ */ ++ i = 0; ++ s = auth_up; /* ignore service field */ ++ while (auth_up[i] && auth_up[i] != '\n' ) i++; ++ if (i >= auth_uplen) ++ auth_error(NEEDED); ++ auth_up[i++] = '\0'; ++ t = auth_up + i; /* type has to be "login" else fail ... */ ++ while (auth_up[i] && auth_up[i] != '\n' ) i++; ++ if (i >= auth_uplen) ++ auth_error(NEEDED); ++ auth_up[i++] = '\0'; ++ if (str_diff("login", t)) { ++ /* ++ * this modul supports only "login"-type, ++ * fail with AUTH_TYPE, so the ++ * next modul is called, perhaps with greater success ++ */ ++ auth_fail("unknown", AUTH_TYPE); ++ } ++ l = auth_up + i; /* next login */ ++ while (auth_up[i] && auth_up[i] != '\n' ) i++; ++ if (i >= auth_uplen) ++ auth_error(NEEDED); ++ auth_up[i++] = '\0'; ++ p = auth_up + i; /* and the password */ ++ while (auth_up[i] && auth_up[i] != '\n' ) i++; ++ if (i >= auth_uplen) ++ auth_error(NEEDED); ++ auth_up[i++] = '\0'; ++ if (i > auth_uplen) /* paranoia */ ++ auth_error(NEEDED); ++ ++ /* copy the login and password into the coresponding structures */ ++ if (!stralloc_copys(login, l)) ++ auth_error(ERRNO); ++ if (!stralloc_0(login)) ++ auth_error(ERRNO); ++ ++ if (!stralloc_copys(authdata, p)) ++ auth_error(ERRNO); ++ if (!stralloc_0(authdata)) ++ auth_error(ERRNO); ++} ++ ++void ++auth_fail(const char *login, int reason) ++{ ++ int i; ++ int pi[2]; ++ char *t; ++ t = auth_up; ++ ++ logit(2, "warning: auth_fail: user %s failed\n", login); ++ if (reason == NOSUCH || reason == AUTH_TYPE) { ++ logit(4, "warning: auth_fail: %s\n", qldap_err_str(reason)); ++ if (!env_unset("AUTHENTICATED")) ++ auth_error(ERRNO); ++ for (i=0; i 0) ++ return auth_argv[auth_argc-1]; ++ return (char *)0; ++} ++ ++#ifdef QLDAP_CLUSTER ++static void get_ok(int , const char *); ++ ++static void ++get_ok(int fd, const char *tag) ++/* get the ok for the next command, wait for "[TAG] OK.*\r\n" */ ++/* This should work (Idea from RFC 1730 and fetchmail) */ ++{ ++#define AUTH_TIMEOUT 10 /* 10 sec timeout */ ++#define OK_LEN 8192+1 ++ char ok[OK_LEN]; ++ char *s; ++ unsigned char x; ++ int len; ++ int i; ++ ++ if (!tag) return; /* bad pointer */ ++ do { ++ len = timeoutread(AUTH_TIMEOUT, fd, ok, sizeof(ok) - 1); ++ if (len == -1) ++ auth_error(ERRNO); ++ ok[len] = '\0'; ++ /* upper case all */ ++ for (i = 0, s = ok; i < len; i++) { ++ x = *s - 'a'; ++ if ( x <= 'z' - 'a' ) *s = x + 'A'; ++ s++; ++ } ++ } while (str_diffn(ok, tag, str_len(tag))); ++ /* tag found, next check for OK */ ++ s = ok + str_len(tag); /* skip tag */ ++ while (*s == ' ' || *s == '\t') s++; /* skip all spaces */ ++ ++ if (str_diffn(s, "OK", 2) == 0 ) return; ++ else if (str_diffn(s, "BAD", 3) == 0 || str_diffn(s, "NO", 2) == 0) ++ /* other server not happy */ ++ auth_error(BADCLUSTER); ++ /* ARRG, this server talks not my dialect */ ++ auth_error(BADCLUSTER); ++} ++ ++void ++auth_forward(int fd, char *login, char *passwd) ++{ ++ char *tag; ++ substdio ss; ++ char buf[512]; ++ ++ tag = env_get("IMAPLOGINTAG"); ++ if (!(tag && *tag)) ++ /* UH OH, no imap tag, how could that be ? */ ++ auth_error(PANIC); ++ ++ get_ok(fd, "*"); ++ substdio_fdbuf(&ss,subwrite,fd,buf,sizeof(buf)); ++ substdio_puts(&ss, tag); ++ substdio_puts(&ss, " login "); ++ substdio_puts(&ss, login); ++ substdio_puts(&ss, " "); ++ substdio_puts(&ss, passwd); ++ substdio_puts(&ss, "\r\n"); ++ substdio_flush(&ss); ++} ++ ++#endif /* QLDAP_CLUSTER */ ++ +diff -upN qmail-1.03/auth_mod.c qmail-ldap/auth_mod.c +--- qmail-1.03/auth_mod.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auth_mod.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,365 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include "byte.h" ++#include "error.h" ++#include "localdelivery.h" ++#include "locallookup.h" ++#include "output.h" ++#include "pbsexec.h" ++#include "qldap.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "read-ctrl.h" ++#include "readwrite.h" ++#include "stralloc.h" ++#ifdef QLDAP_CLUSTER ++#include ++#include "dns.h" ++#include "ipalloc.h" ++#include "ipme.h" ++#include "ndelay.h" ++#include "qldap-cluster.h" ++#include "select.h" ++#include "timeoutconn.h" ++#endif ++#ifdef AUTOHOMEDIRMAKE ++#include "dirmaker.h" ++#endif ++#ifdef AUTOMAILDIRMAKE ++#include "mailmaker.h" ++#endif ++ ++ ++#include "checkpassword.h" ++#include "auth_mod.h" ++ ++stralloc loginstr = {0}; ++stralloc authdatastr = {0}; ++ ++ctrlfunc ctrls[] = { ++ qldap_ctrl_login, ++ qldap_ctrl_generic, ++ localdelivery_init, ++#ifdef QLDAP_CLUSTER ++ cluster_init, ++#endif ++#ifdef AUTOHOMEDIRMAKE ++ dirmaker_init, ++#endif ++ 0 }; ++ ++checkfunc cfuncs[] = { ++ check_ldap, ++ check_passwd, ++ 0 ++}; ++ ++void chdir_or_make(char *, char *); ++ ++#ifdef QLDAP_CLUSTER ++void forward(char *, char *, struct credentials *); ++#endif ++ ++int ++main(int argc, char **argv) ++{ ++ struct credentials c; ++ int r; ++ ++ log_init(STDERR, ~256, 0); /* XXX limited so that it is not ++ possible to get passwords via ++ debug on production systems. ++ */ ++ if (read_controls(ctrls) == -1) ++ auth_error(AUTH_CONF); ++ ++ auth_init(argc, argv, &loginstr, &authdatastr); ++ logit(256, "auth_init: login=%s, authdata=%s\n", ++ loginstr.s, authdatastr.s); ++ ++ if (authdatastr.len <= 1) { ++ logit(1, "alert: null password.\n"); ++ auth_fail(loginstr.s, BADPASS); ++ } ++ ++ byte_zero(&c, sizeof(c)); ++ r = check(cfuncs, &loginstr, &authdatastr, &c, 0); ++ switch (r) { ++ case OK: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ change_uid(c.uid, c.gid); ++ setup_env(loginstr.s, &c); ++ chdir_or_make(c.home.s, c.maildir.s); ++ auth_success(loginstr.s); ++ case FORWARD: ++#ifdef QLDAP_CLUSTER ++ change_uid(-1, -1); ++ setup_env(loginstr.s, &c); ++ forward(loginstr.s, authdatastr.s, &c); ++ /* does not return */ ++#else ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ /* system error, now way out ... module likes to forward ++ but we don't have support for it. */ ++ auth_error(r); ++#endif ++ case NOSUCH: /* FALLTHROUGH */ ++ case BADPASS: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ auth_fail(loginstr.s, r); ++ default: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ /* system error, now way out ... */ ++ auth_error(r); ++ } ++ ++ auth_error(PANIC); ++ return 1; /* should never get here */ ++} ++ ++void ++chdir_or_make(char *home, char *maildir) ++{ ++ char *md; ++ ++ if (maildir == (char *)0 || *maildir == '\0') ++ md = auth_aliasempty(); ++ else ++ md = maildir; ++ ++ /* ... go to home dir and create it if needed */ ++ if (chdir(home) == -1) { ++#ifdef AUTOHOMEDIRMAKE ++ logit(8, "makeing homedir for %s %s\n", home, md); ++ ++ switch (dirmaker_make(home, md)) { ++ case OK: ++ break; ++ case MAILDIR_CRASHED: ++ logit(2, "warning: dirmaker failed: program crashed\n"); ++ auth_error(MAILDIR_FAILED); ++ case MAILDIR_FAILED: ++ logit(2, "warning: dirmaker failed: bad exit status\n"); ++ auth_error(MAILDIR_FAILED); ++ case MAILDIR_UNCONF: ++ logit(2, "warning: dirmaker failed: not configured\n"); ++ auth_error(MAILDIR_NONEXIST); ++ case MAILDIR_HARD: ++ logit(2, "warning: dirmaker failed: hard error\n"); ++ case ERRNO: ++ default: ++ logit(2, "warning: dirmaker failed (%s)\n", ++ error_str(errno)); ++ auth_error(MAILDIR_FAILED); ++ } ++ if (chdir(home) == -1) { ++ logit(2, "warning: 2nd chdir failed: %s\n", ++ error_str(errno)); ++ auth_error(MAILDIR_FAILED); ++ } ++ logit(32, "homedir successfully made\n"); ++#else ++ logit(2, "warning: chdir failed: %s\n", error_str(errno)); ++ auth_error(MAILDIR_NONEXIST); ++#endif ++ } ++#ifdef AUTOMAILDIRMAKE ++ switch (maildir_make(md)) { ++ case OK: ++ break; ++ case MAILDIR_CORRUPT: ++ logit(2, "warning: maildir_make failed (%s)\n", ++ "maildir seems to be corrupt"); ++ auth_error(MAILDIR_CORRUPT); ++ case ERRNO: ++ default: ++ logit(2, "warning: maildir_make failed (%s)\n", ++ error_str(errno)); ++ auth_error(MAILDIR_FAILED); ++ } ++#endif ++} ++ ++#ifdef QLDAP_CLUSTER ++static int allwrite(int (*)(),int, void *,int); ++static void copyloop(int, int, int); ++static char copybuf[4096]; ++ ++static int ++allwrite(int (*op)(),int fd, void *buf,int len) ++{ ++ int w; ++ ++ while (len) { ++ w = op(fd,buf,len); ++ if (w == -1) { ++ if (errno == error_intr) continue; ++ return -1; ++ } ++ if (w == 0) ; /* luser's fault */ ++ buf += w; ++ len -= w; ++ } ++ return 0; ++} ++ ++static void ++copyloop(int infd, int outfd, int timeout) ++{ ++ fd_set iofds; ++ struct timeval tv; ++ int maxfd; /* Maximum numbered fd used */ ++ int bytes, ret; ++ ++ ndelay_off(infd); ndelay_off(outfd); ++ while (1) { ++ /* file descriptor bits */ ++ FD_ZERO(&iofds); ++ maxfd = -1; ++ FD_SET(infd, &iofds); ++ if (infd > maxfd) ++ maxfd = infd; ++ FD_SET(outfd, &iofds); ++ if (outfd > maxfd) ++ maxfd = outfd; ++ ++ /* Set up timeout */ ++ tv.tv_sec = timeout; ++ tv.tv_usec = 0; ++ ++ ret = select(maxfd + 1, &iofds, (fd_set *)0, (fd_set *)0, &tv); ++ if (ret == -1) { ++ logit(1, "copyloop: select failed %s\n", ++ error_str(errno)); ++ break; ++ } else if (ret == 0) { ++ logit(32, "copyloop: select timeout\n"); ++ break; ++ } ++ if (FD_ISSET(infd, &iofds)) { ++ if ((bytes = read(infd, copybuf, ++ sizeof(copybuf))) < 0) { ++ logit(1, "copyloop: read failed: %s\n", ++ error_str(errno)); ++ break; ++ } ++ if (bytes == 0) ++ break; ++ if (allwrite(subwrite, outfd, copybuf, bytes) != 0) { ++ logit(1, "copyloop: write out failed: %s\n", ++ error_str(errno)); ++ break; ++ } ++ } ++ if (FD_ISSET(outfd, &iofds)) { ++ if ((bytes = read(outfd, copybuf, ++ sizeof(copybuf))) < 0) { ++ logit(1, "copyloop: read failed: %s\n", ++ error_str(errno)); ++ break; ++ } ++ logit(32, "copyloop: read in %i bytes read\n", bytes); ++ if (bytes == 0) ++ break; ++ if (allwrite(subwrite, infd, copybuf, bytes) != 0) { ++ logit(1, "copyloop: write in failed: %s\n", ++ error_str(errno)); ++ break; ++ } ++ } ++ } ++ close(infd); ++ close(outfd); ++ return; ++} ++ ++void ++forward(char *name, char *passwd, struct credentials *c) ++{ ++ struct ip_address outip; ++ ipalloc ip = {0}; ++ int ffd; ++ int timeout = 31*60; /* ~30 min timeout RFC1730 */ ++ int ctimeout = 30; ++ ++ /* pop befor smtp */ ++ pbsexec(); ++ ++ if (!ip_scan("0.0.0.0", &outip)) ++ auth_error(ERRNO); ++ ++ dns_init(0); ++ switch (dns_ip(&ip,&c->forwarder)) { ++ case DNS_MEM: ++ auth_error(ERRNO); ++ case DNS_SOFT: ++ case DNS_HARD: ++ auth_error(BADCLUSTER); ++ case 1: ++ if (ip.len <= 0) ++ auth_error(BADCLUSTER); ++ } ++ /* ++ 20010523 Don't check if only one IP is returned, so it is ++ possible to have a cluster node consisting of multiple machines. ++ XXX If your mailhost is bad (bad entries in ldap) you will get ++ bad loops, the only limit is the tcpserver concurrency limit. ++ 20030627 Could we use the ipme stuff of qmail-remote, to make ++ single hop loops impossible? Let's try it. ++ */ ++ if (ipme_is(&ip.ix[0].ip) == 1) ++ auth_error(BADCLUSTER); ++ ++ ffd = socket(AF_INET, SOCK_STREAM, 0); ++ if (ffd == -1) ++ auth_error(ERRNO); ++ ++ if (timeoutconn(ffd, &ip.ix[0].ip, &outip, auth_port, ctimeout) != 0) ++ auth_error(ERRNO); ++ ++ /* We have a connection, first send user and pass */ ++ auth_forward(ffd, name, passwd); ++ copyloop(0, ffd, timeout); ++ ++ _exit(0); /* all went ok, exit normaly */ ++} ++ ++#endif /* QLDAP_CLUSTER */ ++ +diff -upN qmail-1.03/auth_mod.h qmail-ldap/auth_mod.h +--- qmail-1.03/auth_mod.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auth_mod.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __AUTH_MOD_H__ ++#define __AUTH_MOD_H__ ++ ++#include "stralloc.h" ++ ++extern const unsigned int auth_port; ++ ++/* ++ * auth_init must return the 0-terminated strings login and authdata. ++ * possible arguments should be parsed and the argument for auth_success ++ * need to be stored if later needed. ++ */ ++void auth_init(int, char **, stralloc *, stralloc *); ++ ++/* ++ * Checks if it was a hard fail (bad password) or just a soft error ++ * (user not found). May start an other auth_module. MAY NOT return. ++ */ ++void auth_fail(const char *, int); ++ ++/* starts the next auth_module, or what ever (argv ... ) */ ++void auth_success(const char *); ++ ++/* ++ * Error handler, for this module, MAY NOT return. ++ * auth_error MAY be called befor auth_init so it is not possible to ++ * use the argument passed to auth_init in this function. ++ */ ++void auth_error(int); ++ ++/* ++ * for connection forwarding, makes the login part and returns after ++ * sending the latest command immidiatly ++ */ ++void auth_forward(int fd, char *login, char *passwd); ++ ++/* ++ * returns the default maildir if it is not defined, this is normally ++ * the last argument of the execution chain. ++ */ ++char *auth_aliasempty(void); ++ ++#endif +diff -upN qmail-1.03/auth_pop.c qmail-ldap/auth_pop.c +--- qmail-1.03/auth_pop.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auth_pop.c Thu Jul 1 16:28:30 2004 +@@ -0,0 +1,240 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include "byte.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "pbsexec.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "readwrite.h" ++#include "sgetopt.h" ++#include "str.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "timeoutread.h" ++ ++#include "auth_mod.h" ++ ++#ifndef PORT_POP3 /* this is for testing purposes */ ++#define PORT_POP3 110 ++#endif ++ ++const unsigned int auth_port = PORT_POP3; ++ ++#define UP_LEN 513 ++static char auth_up[UP_LEN]; ++static int auth_argc; ++static char **auth_argv; ++ ++void ++auth_init(int argc, char **argv, stralloc *login, stralloc *authdata) ++{ ++ char *l, *p; ++ int uplen; ++ int i, opt; ++ ++ while ((opt = getopt(argc, argv, "d:")) != opteof) { ++ switch (opt) { ++ case 'd': ++ pbstool = optarg; ++ break; ++ default: ++ auth_error(AUTH_CONF); ++ } ++ } ++ argc -= optind; ++ argv += optind; ++ ++ if (argc < 1) ++ auth_error(AUTH_CONF); ++ auth_argc = argc; ++ auth_argv = argv; ++ ++ for (uplen = 0;;) { ++ do { ++ i = subread(3, auth_up + uplen, ++ sizeof(auth_up) - uplen); ++ } while (i == -1 && errno == EINTR); ++ if (i == -1) ++ auth_error(ERRNO); ++ if (i == 0) break; ++ uplen += i; ++ if (uplen >= sizeof(auth_up)) ++ auth_error(PANIC); ++ } ++ close(3); ++ auth_up[uplen++] = '\0'; ++ ++ i = 0; ++ l = auth_up; ++ while (auth_up[i++]) ; ++ if (i == uplen) ++ auth_error(NEEDED); ++ p = auth_up + i; ++ while (auth_up[i++]) ; ++ if (i == uplen) ++ auth_error(NEEDED); ++ ++ if (!stralloc_copys(login, l)) ++ auth_error(ERRNO); ++ if (!stralloc_0(login)) ++ auth_error(ERRNO); ++ ++ if (!stralloc_copys(authdata, p)) ++ auth_error(ERRNO); ++ if (!stralloc_0(authdata)) ++ auth_error(ERRNO); ++ ++ /* up no longer needed so delete it */ ++ byte_zero(auth_up, sizeof(auth_up)); ++} ++ ++void ++auth_fail(const char *login, int reason) ++{ ++ /* in the qmail-pop3 chain it is not possible to have multiples ++ * authentication modules. So lets exit with the correct number ... */ ++ /* In this case we can use auth_error() */ ++ logit(2, "warning: auth_fail: user %s failed\n", login); ++ auth_error(reason); ++} ++ ++void ++auth_success(const char *login) ++{ ++ /* pop befor smtp */ ++ pbsexec(); ++ ++ /* start qmail-pop3d */ ++ execvp(*auth_argv,auth_argv); ++ ++ auth_error(AUTH_EXEC); ++ /* end */ ++} ++ ++void auth_error(int errnum) ++{ ++ /* ++ * See qmail-popup.c for exit codes meanings. ++ */ ++ logit(2, "warning: auth_error: authorization failed (%s)\n", ++ qldap_err_str(errnum)); ++ ++ if (errnum == AUTH_CONF) _exit(1); ++ if (errnum == TIMEOUT || errnum == LDAP_BIND_UNREACH) _exit(2); ++ if (errnum == BADPASS || errnum == NOSUCH) _exit(3); ++ if (errnum == NEEDED || errnum == ILLVAL || errnum == BADVAL) _exit(25); ++ if (errnum == ACC_DISABLED) _exit(4); ++ if (errnum == BADCLUSTER) _exit(5); ++ if (errnum == MAILDIR_CORRUPT) _exit(6); ++ if (errnum == MAILDIR_FAILED) _exit(61); ++ if (errnum == MAILDIR_NONEXIST) _exit(62); ++ if (errnum == AUTH_EXEC) _exit(7); ++ if (errnum == ERRNO && errno == error_nomem) _exit(8); ++ _exit(111); ++} ++ ++char * ++auth_aliasempty(void) ++{ ++ if (auth_argc > 0) ++ return auth_argv[auth_argc-1]; ++ return (char *)0; ++} ++ ++#ifdef QLDAP_CLUSTER ++static void get_ok(int); ++ ++static void get_ok(int fd) ++/* get the ok for the next command, wait for "+OK.*\r\n" */ ++/* This should be a mostly correct solution (adapted from fetchmail) */ ++{ ++#define AUTH_TIMEOUT 10 /* 10 sec timeout */ ++#define OK_LEN 512 /* max length of response (RFC1939) */ ++ char ok[OK_LEN]; ++ char *c; ++ int len; ++ int i; ++ ++ /* first get one single line from the other pop server */ ++ len = timeoutread(AUTH_TIMEOUT, fd, ok, OK_LEN); ++ if (len == -1) ++ auth_error(ERRNO); ++ if (len != 0) { ++ c = ok; ++ if (*c == '+' || *c == '-') ++ c++; ++ else ++ auth_error(BADCLUSTER); ++ for (i = 1; i < len /* paranoia */ && ++ ('A' < *c && *c < 'Z') ; ) { i++; c++; } ++ ++ if (i < len) { ++ *c = '\0'; ++ if (str_diff(ok, "+OK") == 0) ++ return; ++ else if (str_diffn(ok, "-ERR", 4)) ++ /* other server is not happy */ ++ auth_error(BADCLUSTER); ++ } ++ } ++ /* ARRG, very strange POP3 answer */ ++ auth_error(BADCLUSTER); ++} ++ ++void auth_forward(int fd, char *login, char *passwd) ++{ ++ char buf[512]; ++ substdio ss; ++ ++ substdio_fdbuf(&ss,subwrite,fd,buf,sizeof(buf)); ++ get_ok(fd); ++ substdio_puts(&ss, "user "); ++ substdio_puts(&ss, login); ++ substdio_puts(&ss, "\r\n"); ++ substdio_flush(&ss); ++ get_ok(fd); ++ substdio_puts(&ss, "pass "); ++ substdio_puts(&ss, passwd); ++ substdio_puts(&ss, "\r\n"); ++ substdio_flush(&ss); ++ ++} ++ ++#endif /* QLDAP_CLUSTER */ ++ +diff -upN qmail-1.03/auth_smtp.c qmail-ldap/auth_smtp.c +--- qmail-1.03/auth_smtp.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auth_smtp.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,213 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include "base64.h" ++#include "byte.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "getln.h" ++#include "output.h" ++#include "qldap.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "read-ctrl.h" ++#include "str.h" ++#include "stralloc.h" ++#include "subfd.h" ++#include "substdio.h" ++#include "timeoutread.h" ++ ++#include "checkpassword.h" ++ ++#include "auth_mod.h" ++ ++checkfunc cfuncs[] = { ++ check_ldap, ++ 0 ++}; ++ ++stralloc line = {0}; ++stralloc plain = {0}; ++ ++void ++auth_init(int argc, char **argv, stralloc *login, stralloc *authdata) ++{ ++ char *s, *smax; ++ int match; ++ ++ if (argc != 1) ++ auth_error(AUTH_CONF); ++ ++ if (getln(subfdin, &line, &match, '\0') != 0) ++ auth_error(ERRNO); ++ if (!match) auth_error(NEEDED); ++ if (!str_diff(line.s, "login")) { ++ if (getln(subfdin, &line, &match, '\0') != 0) ++ auth_error(ERRNO); ++ if (!match) auth_error(NEEDED); ++ if (b64_ptons(line.s, login) == -1) auth_error(BADVAL); ++ if (getln(subfdin, &line, &match, '\0') != 0) ++ auth_error(ERRNO); ++ if (!match) auth_error(NEEDED); ++ if (b64_ptons(line.s, authdata) == -1) auth_error(BADVAL); ++ /* XXX we should check if there is some bad ++ * data in both values */ ++ if (!stralloc_0(login)) auth_error(ERRNO); ++ if (!stralloc_0(authdata)) auth_error(ERRNO); ++ return; ++ } ++ if (!str_diff(line.s, "plain")) { ++ /* ++ * plain sends: [authorize-id]\0authenticate-id\0password ++ */ ++ if (!stralloc_copys(login, "")) auth_error(ERRNO); ++ if (!stralloc_copys(authdata, "")) auth_error(ERRNO); ++ if (getln(subfdin, &line, &match, '\0') != 0) ++ auth_error(ERRNO); ++ if (!match) auth_error(NEEDED); ++ if (b64_ptons(line.s, &plain) == -1) auth_error(BADVAL); ++ s = plain.s; smax = s + plain.len; ++ while (*s++ != '\0') if (s >= smax) auth_error(BADVAL); ++ do { ++ if (!stralloc_append(login, s)) auth_error(ERRNO); ++ if (s >= smax) auth_error(BADVAL); ++ } while (*s++ != '\0'); ++ while (*s && s < smax) { ++ if (!stralloc_append(authdata, s)) auth_error(ERRNO); ++ s++; ++ } ++ if (!stralloc_0(authdata)) auth_error(ERRNO); ++ return; ++ } ++ auth_error(AUTH_TYPE); ++} ++ ++void ++auth_fail(const char *login, int reason) ++{ ++ logit(2, "warning: auth_fail: user %s failed\n", login); ++ ++ if (substdio_putflush(subfdout, "D", 1) == -1) auth_error(ERRNO); ++ _exit(0); ++} ++ ++void ++auth_success(const char *login) ++{ ++ if (substdio_put(subfdout, "K", 1) == -1) auth_error(ERRNO); ++ if (substdio_puts(subfdout, login) == -1) auth_error(ERRNO); ++ if (substdio_putflush(subfdout, "", 1) == -1) auth_error(ERRNO); ++ _exit(0); ++} ++ ++void auth_error(int errnum) ++{ ++ logit(2, "warning: auth_error: authorization failed (%s)\n", ++ qldap_err_str(errnum)); ++ if (errnum == BADVAL || errnum == NEEDED || errnum == ILLVAL) { ++ if (substdio_putflush(subfdout, "Z", 1) == -1) ++ auth_error(ERRNO); ++ _exit(0); ++ } ++ ++ _exit(111); ++} ++ ++char * ++auth_aliasempty(void) ++{ ++ return (char *)0; ++} ++ ++stralloc loginstr = {0}; ++stralloc authdatastr = {0}; ++ ++ctrlfunc ctrls[] = { ++ qldap_ctrl_trylogin, ++ qldap_ctrl_generic, ++ 0 }; ++ ++int ++main(int argc, char **argv) ++{ ++ struct credentials c; ++ int r; ++ ++ log_init(STDERR, ~256, 0); /* XXX limited so that it is not ++ possible to get passwords via ++ debug on production systems. ++ */ ++ if (read_controls(ctrls) == -1) ++ auth_error(AUTH_CONF); ++ ++ auth_init(argc, argv, &loginstr, &authdatastr); ++ logit(256, "auth_init: login=%s, authdata=%s\n", ++ loginstr.s, authdatastr.s); ++ ++ if (authdatastr.len <= 1) { ++ logit(1, "alert: null password.\n"); ++ auth_fail(loginstr.s, BADPASS); ++ } ++ ++ byte_zero(&c, sizeof(c)); ++ r = check(cfuncs, &loginstr, &authdatastr, &c, 1); ++ /* XXX I'm not very happy with this solution but currently this ++ * is the easiest way. This file, auth_mod.c and checkpassword.c ++ * need some refactoring (: */ ++ switch (r) { ++ case OK: ++ case FORWARD: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ auth_success(loginstr.s); ++ case NOSUCH: /* FALLTHROUGH */ ++ case BADPASS: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ auth_fail(loginstr.s, r); ++ default: ++ /* authdata no longer needed */ ++ byte_zero(authdatastr.s, authdatastr.len); ++ /* system error, now way out ... */ ++ auth_error(r); ++ } ++ ++ auth_error(PANIC); ++ return 1; /* should never get here */ ++} ++ ++ +diff -upN qmail-1.03/auto-gid.c qmail-ldap/auto-gid.c +--- qmail-1.03/auto-gid.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto-gid.c Tue Oct 28 18:21:31 2003 +@@ -8,7 +8,7 @@ + #include "fmt.h" + + char buf1[256]; +-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); ++substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1)); + + void outs(s) + char *s; +@@ -16,7 +16,7 @@ char *s; + if (substdio_puts(&ss1,s) == -1) _exit(111); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -47,5 +47,5 @@ char **argv; + outs(strnum); + outs(";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/auto-int.c qmail-ldap/auto-int.c +--- qmail-1.03/auto-int.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto-int.c Tue Feb 17 15:31:30 2004 +@@ -5,15 +5,15 @@ + #include "fmt.h" + + char buf1[256]; +-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); ++substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1)); + +-void puts(s) ++void putstr(s) + char *s; + { + if (substdio_puts(&ss1,s) == -1) _exit(111); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -30,11 +30,11 @@ char **argv; + scan_ulong(value,&num); + strnum[fmt_ulong(strnum,num)] = 0; + +- puts("int "); +- puts(name); +- puts(" = "); +- puts(strnum); +- puts(";\n"); ++ putstr("unsigned int "); ++ putstr(name); ++ putstr(" = "); ++ putstr(strnum); ++ putstr(";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/auto-int8.c qmail-ldap/auto-int8.c +--- qmail-1.03/auto-int8.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto-int8.c Tue Feb 17 15:31:30 2004 +@@ -5,15 +5,15 @@ + #include "fmt.h" + + char buf1[256]; +-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); ++substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1)); + +-void puts(s) ++void putstr(s) + char *s; + { + if (substdio_puts(&ss1,s) == -1) _exit(111); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -30,11 +30,11 @@ char **argv; + scan_8long(value,&num); + strnum[fmt_ulong(strnum,num)] = 0; + +- puts("int "); +- puts(name); +- puts(" = "); +- puts(strnum); +- puts(";\n"); ++ putstr("int "); ++ putstr(name); ++ putstr(" = "); ++ putstr(strnum); ++ putstr(";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/auto-str.c qmail-ldap/auto-str.c +--- qmail-1.03/auto-str.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto-str.c Tue Feb 17 15:31:30 2004 +@@ -1,17 +1,17 @@ +-#include "substdio.h" + #include "readwrite.h" ++#include "substdio.h" + #include "exit.h" + + char buf1[256]; +-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); ++substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1)); + +-void puts(s) ++void putstr(s) + char *s; + { + if (substdio_puts(&ss1,s) == -1) _exit(111); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -25,20 +25,20 @@ char **argv; + value = argv[2]; + if (!value) _exit(100); + +- puts("char "); +- puts(name); +- puts("[] = \"\\\n"); ++ putstr("char "); ++ putstr(name); ++ putstr("[] = \"\\\n"); + +- while (ch = *value++) { +- puts("\\"); ++ while ((ch = *value++)) { ++ putstr("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); +- puts(octal); ++ putstr(octal); + } + +- puts("\\\n\";\n"); ++ putstr("\\\n\";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/auto-uid.c qmail-ldap/auto-uid.c +--- qmail-1.03/auto-uid.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto-uid.c Tue Oct 28 18:21:31 2003 +@@ -8,7 +8,7 @@ + #include "fmt.h" + + char buf1[256]; +-substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); ++substdio ss1 = SUBSTDIO_FDBUF(subwrite,1,buf1,sizeof(buf1)); + + void outs(s) /* was named puts, but Solaris pwd.h includes stdio.h. dorks. */ + char *s; +@@ -16,7 +16,7 @@ char *s; + if (substdio_puts(&ss1,s) == -1) _exit(111); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -47,5 +47,5 @@ char **argv; + outs(strnum); + outs(";\n"); + if (substdio_flush(&ss1) == -1) _exit(111); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/auto_patrn.h qmail-ldap/auto_patrn.h +--- qmail-1.03/auto_patrn.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto_patrn.h Thu Jan 29 16:48:14 2004 +@@ -1,6 +1,6 @@ + #ifndef AUTO_PATRN_H + #define AUTO_PATRN_H + +-extern int auto_patrn; ++extern unsigned int auto_patrn; + + #endif +diff -upN qmail-1.03/auto_spawn.h qmail-ldap/auto_spawn.h +--- qmail-1.03/auto_spawn.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto_spawn.h Thu Jan 29 16:48:14 2004 +@@ -1,6 +1,6 @@ + #ifndef AUTO_SPAWN_H + #define AUTO_SPAWN_H + +-extern int auto_spawn; ++extern unsigned int auto_spawn; + + #endif +diff -upN qmail-1.03/auto_split.h qmail-ldap/auto_split.h +--- qmail-1.03/auto_split.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/auto_split.h Thu Jan 29 16:48:14 2004 +@@ -1,6 +1,6 @@ + #ifndef AUTO_SPLIT_H + #define AUTO_SPLIT_H + +-extern int auto_split; ++extern unsigned int auto_split; + + #endif +diff -upN qmail-1.03/auto_userl.h qmail-ldap/auto_userl.h +--- qmail-1.03/auto_userl.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/auto_userl.h Thu Oct 30 10:13:02 2003 +@@ -0,0 +1,6 @@ ++#ifndef AUTO_USERL_H ++#define AUTO_USERL_H ++ ++extern char auto_userl[]; ++ ++#endif +diff -upN qmail-1.03/base64.c qmail-ldap/base64.c +--- qmail-1.03/base64.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/base64.c Tue Feb 17 15:31:30 2004 +@@ -0,0 +1,530 @@ ++/* base64.c for QLDAP modified to use only djb's qmail stuff */ ++ ++/* */ ++/* BASE64 */ ++/* */ ++ ++/* ++ * Copyright (c) 1996 by Internet Software Consortium. ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE ++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL ++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR ++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++ * SOFTWARE. ++ */ ++ ++/* ++ * Portions Copyright (c) 1995 by International Business Machines, Inc. ++ * ++ * International Business Machines, Inc. (hereinafter called IBM) grants ++ * permission under its copyrights to use, copy, modify, and distribute this ++ * Software with or without fee, provided that the above copyright notice and ++ * all paragraphs of this notice appear in all copies, and that the name of IBM ++ * not be used in connection with the marketing of any product incorporating ++ * the Software or modifications thereof, without specific, written prior ++ * permission. ++ * ++ * To the extent it has a right to do so, IBM grants an immunity from suit ++ * under its patents, if any, for the use, sale or manufacture of products to ++ * the extent that such products are used for performing Domain Name System ++ * dynamic updates in TCP/IP networks by means of the Software. No immunity is ++ * granted for any product per se or for any other function of any product. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, ++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, ++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN ++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. ++ */ ++ ++#include ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++ ++#define Assert(Cond) if (!(Cond)) strerr_die1x(111, "Abort: assert condition false in base64.") ++ ++static const char Base64[] = ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++static const char Pad64 = '='; ++ ++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) ++ The following encoding technique is taken from RFC 1521 by Borenstein ++ and Freed. It is reproduced here in a slightly edited form for ++ convenience. ++ ++ A 65-character subset of US-ASCII is used, enabling 6 bits to be ++ represented per printable character. (The extra 65th character, "=", ++ is used to signify a special processing function.) ++ ++ The encoding process represents 24-bit groups of input bits as output ++ strings of 4 encoded characters. Proceeding from left to right, a ++ 24-bit input group is formed by concatenating 3 8-bit input groups. ++ These 24 bits are then treated as 4 concatenated 6-bit groups, each ++ of which is translated into a single digit in the base64 alphabet. ++ ++ Each 6-bit group is used as an index into an array of 64 printable ++ characters. The character referenced by the index is placed in the ++ output string. ++ ++ Table 1: The Base64 Alphabet ++ ++ Value Encoding Value Encoding Value Encoding Value Encoding ++ 0 A 17 R 34 i 51 z ++ 1 B 18 S 35 j 52 0 ++ 2 C 19 T 36 k 53 1 ++ 3 D 20 U 37 l 54 2 ++ 4 E 21 V 38 m 55 3 ++ 5 F 22 W 39 n 56 4 ++ 6 G 23 X 40 o 57 5 ++ 7 H 24 Y 41 p 58 6 ++ 8 I 25 Z 42 q 59 7 ++ 9 J 26 a 43 r 60 8 ++ 10 K 27 b 44 s 61 9 ++ 11 L 28 c 45 t 62 + ++ 12 M 29 d 46 u 63 / ++ 13 N 30 e 47 v ++ 14 O 31 f 48 w (pad) = ++ 15 P 32 g 49 x ++ 16 Q 33 h 50 y ++ ++ Special processing is performed if fewer than 24 bits are available ++ at the end of the data being encoded. A full encoding quantum is ++ always completed at the end of a quantity. When fewer than 24 input ++ bits are available in an input group, zero bits are added (on the ++ right) to form an integral number of 6-bit groups. Padding at the ++ end of the data is performed using the '=' character. ++ ++ Since all base64 input is an integral number of octets, only the ++ ------------------------------------------------- ++ following cases can arise: ++ ++ (1) the final quantum of encoding input is an integral ++ multiple of 24 bits; here, the final unit of encoded ++ output will be an integral multiple of 4 characters ++ with no "=" padding, ++ (2) the final quantum of encoding input is exactly 8 bits; ++ here, the final unit of encoded output will be two ++ characters followed by two "=" padding characters, or ++ (3) the final quantum of encoding input is exactly 16 bits; ++ here, the final unit of encoded output will be three ++ characters followed by one "=" padding character. ++ */ ++ ++int ++b64_ntop(unsigned char const *src, size_t srclength, ++ char *target, size_t targsize) ++{ ++ size_t datalength = 0; ++ unsigned char input[3]; ++ unsigned char output[4]; ++ int i; ++ ++ while (2 < srclength) { ++ input[0] = *src++; ++ input[1] = *src++; ++ input[2] = *src++; ++ srclength -= 3; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ output[3] = input[2] & 0x3f; ++ Assert(output[0] < 64); ++ Assert(output[1] < 64); ++ Assert(output[2] < 64); ++ Assert(output[3] < 64); ++ ++ if (datalength + 4 > targsize) ++ return (-1); ++ target[datalength++] = Base64[output[0]]; ++ target[datalength++] = Base64[output[1]]; ++ target[datalength++] = Base64[output[2]]; ++ target[datalength++] = Base64[output[3]]; ++ } ++ ++ /* Now we worry about padding. */ ++ if (0 != srclength) { ++ /* Get what's left. */ ++ input[0] = input[1] = input[2] = '\0'; ++ for (i = 0; i < srclength; i++) ++ input[i] = *src++; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ Assert(output[0] < 64); ++ Assert(output[1] < 64); ++ Assert(output[2] < 64); ++ ++ if (datalength + 4 > targsize) ++ return (-1); ++ target[datalength++] = Base64[output[0]]; ++ target[datalength++] = Base64[output[1]]; ++ if (srclength == 1) ++ target[datalength++] = Pad64; ++ else ++ target[datalength++] = Base64[output[2]]; ++ target[datalength++] = Pad64; ++ } ++ if (datalength >= targsize) ++ return (-1); ++ target[datalength] = '\0'; /* Returned value doesn't count \0. */ ++ return (datalength); ++} ++ ++/* skips all whitespace anywhere. ++ converts characters, four at a time, starting at (or after) ++ src from base - 64 numbers into three 8 bit bytes in the target area. ++ it returns the number of data bytes stored at the target, or -1 on error. ++ */ ++ ++#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r') ++/* XXX ++ this is not the complete subset of ctypes.h isspace but for qmail-ldap ++ only space, tab, newline and carriage-return are useful (formfeed and ++ vertical tabs are normaly not used in network communications. ++ Claudio Jeker ++ */ ++ ++int ++b64_pton(char const *src, unsigned char *target, size_t targsize) ++{ ++ size_t tarindex; ++ int state, ch; ++ unsigned int pos; ++ ++ state = 0; ++ tarindex = 0; ++ ++ while ((ch = *src++) != '\0') { ++ if (ISSPACE(ch)) /* Skip whitespace anywhere. */ ++ continue; ++ ++ if (ch == Pad64) ++ break; ++ ++ pos = str_chr(Base64, ch); ++ if (pos > 63) /* A non-base64 character. */ ++ return (-1); ++ ++ switch (state) { ++ case 0: ++ if (target) { ++ if (tarindex >= targsize) ++ return (-1); ++ target[tarindex] = pos << 2; ++ } ++ state = 1; ++ break; ++ case 1: ++ if (target) { ++ if (tarindex + 1 >= targsize) ++ return (-1); ++ target[tarindex] |= pos >> 4; ++ target[tarindex+1] = (pos & 0x0f) << 4 ; ++ } ++ tarindex++; ++ state = 2; ++ break; ++ case 2: ++ if (target) { ++ if (tarindex + 1 >= targsize) ++ return (-1); ++ target[tarindex] |= pos >> 2; ++ target[tarindex+1] = (pos & 0x03) << 6; ++ } ++ tarindex++; ++ state = 3; ++ break; ++ case 3: ++ if (target) { ++ if (tarindex >= targsize) ++ return (-1); ++ target[tarindex] |= pos; ++ } ++ tarindex++; ++ state = 0; ++ break; ++ default: ++ strerr_die1x(111, "Abort: bad state in base64 decode."); ++ } ++ } ++ ++ /* ++ * We are done decoding Base-64 chars. Let's see if we ended ++ * on a byte boundary, and/or with erroneous trailing characters. ++ */ ++ ++ if (ch == Pad64) { /* We got a pad char. */ ++ ch = *src++; /* Skip it, get next. */ ++ switch (state) { ++ case 0: /* Invalid = in first position */ ++ case 1: /* Invalid = in second position */ ++ return (-1); ++ ++ case 2: /* Valid, means one byte of info */ ++ /* Skip any number of spaces. */ ++ for (; ch != '\0'; ch = *src++) ++ if (!ISSPACE(ch)) ++ break; ++ /* Make sure there is another trailing = sign. */ ++ if (ch != Pad64) ++ return (-1); ++ ch = *src++; /* Skip the = */ ++ /* Fall through to "single trailing =" case. */ ++ /* FALLTHROUGH */ ++ ++ case 3: /* Valid, means two bytes of info */ ++ /* ++ * We know this char is an =. Is there anything but ++ * whitespace after it? ++ */ ++ for (; ch != '\0'; ch = *src++) ++ if (!ISSPACE(ch)) ++ return (-1); ++ ++ /* ++ * Now make sure for cases 2 and 3 that the "extra" ++ * bits that slopped past the last full byte were ++ * zeros. If we don't check them, they become a ++ * subliminal channel. ++ */ ++ if (target && target[tarindex] != 0) ++ return (-1); ++ } ++ } else { ++ /* ++ * We ended by seeing the end of the string. Make sure we ++ * have no partial bytes lying around. ++ */ ++ if (state != 0) ++ return (-1); ++ } ++ ++ return (tarindex); ++} ++ ++int ++b64_ntops(unsigned char const *src, size_t srclength, stralloc *dest) ++{ ++ unsigned char input[3]; ++ unsigned char output[4]; ++ size_t i; ++ ++ if (!stralloc_copys(dest, "")) return -1; ++ while (2 < srclength) { ++ input[0] = *src++; ++ input[1] = *src++; ++ input[2] = *src++; ++ srclength -= 3; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ output[3] = input[2] & 0x3f; ++ Assert(output[0] < 64); ++ Assert(output[1] < 64); ++ Assert(output[2] < 64); ++ Assert(output[3] < 64); ++ output[0] = Base64[output[0]]; ++ output[1] = Base64[output[1]]; ++ output[2] = Base64[output[2]]; ++ output[3] = Base64[output[3]]; ++ ++ if (!stralloc_catb(dest, output, 4)) return -1; ++ } ++ ++ /* Now we worry about padding. */ ++ if (0 != srclength) { ++ /* Get what's left. */ ++ input[0] = input[1] = input[2] = '\0'; ++ for (i = 0; i < srclength; i++) ++ input[i] = *src++; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ Assert(output[0] < 64); ++ Assert(output[1] < 64); ++ Assert(output[2] < 64); ++ ++ if (!stralloc_append(dest, &Base64[output[0]])) return -1; ++ if (!stralloc_append(dest, &Base64[output[1]])) return -1; ++ if (srclength == 1) { ++ if (!stralloc_append(dest, &Pad64)) return -1; ++ } else { ++ if (!stralloc_append(dest, &Base64[output[2]])) ++ return -1; ++ } ++ if (!stralloc_catb(dest, &Pad64, 1)) return -1; ++ } ++ return 0; ++} ++ ++int ++b64_ptons(char const *src, stralloc *dest) ++{ ++ unsigned char out[3]; ++ int state, ch; ++ unsigned int pos; ++ ++ state = 0; ++ ++ if (!stralloc_copys(dest, "")) return -1; ++ while ((ch = *src++) != '\0') { ++ if (ISSPACE(ch)) /* Skip whitespace anywhere. */ ++ continue; ++ ++ if (ch == Pad64) ++ break; ++ ++ pos = str_chr(Base64, ch); ++ if (pos > 63) /* A non-base64 character. */ ++ return (-1); ++ ++ switch (state) { ++ case 0: ++ out[0] = pos << 2; ++ state = 1; ++ break; ++ case 1: ++ out[0] |= pos >> 4; ++ out[1] = (pos & 0x0f) << 4; ++ state = 2; ++ break; ++ case 2: ++ out[1] |= pos >> 2; ++ out[2] = (pos & 0x03) << 6; ++ state = 3; ++ break; ++ case 3: ++ out[2] |= pos; ++ if (!stralloc_catb(dest, out, 3)) return -1; ++ state = 0; ++ break; ++ default: ++ strerr_die1x(111, "Abort: bad state in base64 decode."); ++ } ++ } ++ ++ /* ++ * We are done decoding Base-64 chars. Let's see if we ended ++ * on a byte boundary, and/or with erroneous trailing characters. ++ */ ++ ++ if (ch == Pad64) { /* We got a pad char. */ ++ ch = *src++; /* Skip it, get next. */ ++ switch (state) { ++ case 0: /* Invalid = in first position */ ++ case 1: /* Invalid = in second position */ ++ return (-1); ++ ++ case 2: /* Valid, means one byte of info */ ++ /* Skip any number of spaces. */ ++ for (; ch != '\0'; ch = *src++) ++ if (!ISSPACE(ch)) ++ break; ++ /* Make sure there is another trailing = sign. */ ++ if (ch != Pad64) ++ return (-1); ++ ch = *src++; /* Skip the = */ ++ /* Fall through to "single trailing =" case. */ ++ /* FALLTHROUGH */ ++ ++ case 3: /* Valid, means two bytes of info */ ++ /* ++ * We know this char is an =. Is there anything but ++ * whitespace after it? ++ */ ++ for (; ch != '\0'; ch = *src++) ++ if (!ISSPACE(ch)) ++ return (-1); ++ ++ /* ++ * Now we need to write the one or two bytes of ++ * info to the stralloc. ++ */ ++ if (state == 2) { /* one byte */ ++ if (!stralloc_catb(dest, out, 1)) return -1; ++ } else { /* two bytes */ ++ if (!stralloc_catb(dest, out, 2)) return -1; ++ } ++ } ++ } else { ++ /* ++ * We ended by seeing the end of the string. Make sure we ++ * have no partial bytes lying around. ++ */ ++ if (state != 0) ++ return (-1); ++ } ++ ++ return 0; ++} ++ ++/* function for decoding and encoding hex strings */ ++static const char Hex[] = "0123456789abcdef"; ++/* static const char HexBig[] = "0123456789ABCDEF"; */ ++ ++int ++hex_ntops(unsigned char const *src, size_t srclength, stralloc *dest) ++{ ++ size_t i; ++ ++ if (!stralloc_copys(dest, "")) return -1; ++ for (i=0; i> 4])) return -1; ++ if (!stralloc_append(dest, &Hex[src[i] & 0x0f])) return -1; ++ } ++ return 0; ++} ++ ++int ++hex_ptons(char const *src, stralloc *dest) ++{ ++ int state; ++ unsigned char ch, out; ++ ++ state = 0; ++ if (!stralloc_copys(dest, "")) return -1; ++ while ((ch = *src++) != '\0') { ++ if (ISSPACE(ch)) /* Skip whitespace anywhere. */ ++ continue; ++ ++ if (ch >= '0' && ch <= '9') ++ ch -= '0'; ++ else if (ch >= 'a') ++ ch -= ('a' - 10); ++ else ++ ch -= ('A' - 10); ++ if (ch > 15) /* A non-Hex character. */ ++ return (-1); ++ ++ switch (state) { ++ case 0: ++ out = ch << 4; ++ state = 1; ++ break; ++ case 1: ++ out |= ch; ++ if (!stralloc_append(dest, &out)) return -1; ++ state = 0; ++ break; ++ default: ++ strerr_die1x(111, "Abort: bad state in hex decode."); ++ } ++ } ++ if (state != 0) ++ return -1; ++ return 0; ++} +diff -upN qmail-1.03/base64.h qmail-ldap/base64.h +--- qmail-1.03/base64.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/base64.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (c) 1999-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __BASE64_H__ ++#define __BASE64_H__ ++/* base64.h for QLDAP modified to use only djb's qmail stuff */ ++ ++#include "stralloc.h" ++ ++/* * ++ * BASE64 * ++ * */ ++ ++/* base63 encode */ ++int b64_ntop(unsigned char const *, size_t, char *, size_t); ++ ++/* base64 decode */ ++int b64_pton(char const *, unsigned char *, size_t); ++ ++/* the same as above but this time with a stralloc as destination */ ++int b64_ntops(unsigned char const *, size_t , stralloc *); ++ ++/* the same as above but this time with a stralloc as destination */ ++int b64_ptons(char const *, stralloc *); ++ ++int hex_ntops(unsigned char const *, size_t, stralloc *); ++int hex_ptons(char const *, stralloc *); ++ ++#endif +diff -upN qmail-1.03/bouncesaying.c qmail-ldap/bouncesaying.c +--- qmail-1.03/bouncesaying.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/bouncesaying.c Tue Oct 28 18:21:31 2003 +@@ -1,3 +1,4 @@ ++#include + #include "fork.h" + #include "strerr.h" + #include "error.h" +@@ -7,7 +8,7 @@ + + #define FATAL "bouncesaying: fatal: " + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -38,4 +39,6 @@ char **argv; + } + + strerr_die1x(100,argv[1]); ++ /* NOTREACHED */ ++ return 100; + } +diff -upN qmail-1.03/byte.h qmail-ldap/byte.h +--- qmail-1.03/byte.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte.h Tue Oct 28 18:21:31 2003 +@@ -1,12 +1,13 @@ + #ifndef BYTE_H + #define BYTE_H + +-extern unsigned int byte_chr(); +-extern unsigned int byte_rchr(); +-extern void byte_copy(); +-extern void byte_copyr(); +-extern int byte_diff(); +-extern void byte_zero(); ++extern unsigned int byte_chr(const char *, unsigned int, int); ++extern unsigned int byte_rchr(const char *, unsigned int, int); ++extern void byte_copy(void *, unsigned int, const void *); ++extern void byte_copyr(void *, unsigned int, const void *); ++extern int byte_diff(const void *, unsigned int, const void *); ++extern void byte_zero(void *, unsigned int); ++extern unsigned int byte_repl(char *, unsigned int, int, int); + + #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +diff -upN qmail-1.03/byte_chr.c qmail-ldap/byte_chr.c +--- qmail-1.03/byte_chr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_chr.c Tue Oct 28 18:21:31 2003 +@@ -1,12 +1,12 @@ + #include "byte.h" + + unsigned int byte_chr(s,n,c) +-char *s; ++const char *s; + register unsigned int n; + int c; + { + register char ch; +- register char *t; ++ register const char *t; + + ch = c; + t = s; +diff -upN qmail-1.03/byte_copy.c qmail-ldap/byte_copy.c +--- qmail-1.03/byte_copy.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_copy.c Tue Oct 28 18:21:31 2003 +@@ -1,14 +1,16 @@ + #include "byte.h" + + void byte_copy(to,n,from) +-register char *to; ++void *to; + register unsigned int n; +-register char *from; ++const void *from; + { ++ register char *t = (char *)to; ++ register const char *f = (const char *)from; + for (;;) { +- if (!n) return; *to++ = *from++; --n; +- if (!n) return; *to++ = *from++; --n; +- if (!n) return; *to++ = *from++; --n; +- if (!n) return; *to++ = *from++; --n; ++ if (!n) return; *t++ = *f++; --n; ++ if (!n) return; *t++ = *f++; --n; ++ if (!n) return; *t++ = *f++; --n; ++ if (!n) return; *t++ = *f++; --n; + } + } +diff -upN qmail-1.03/byte_cr.c qmail-ldap/byte_cr.c +--- qmail-1.03/byte_cr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_cr.c Tue Oct 28 18:21:31 2003 +@@ -1,16 +1,19 @@ + #include "byte.h" + + void byte_copyr(to,n,from) +-register char *to; ++void *to; + register unsigned int n; +-register char *from; ++const void *from; + { +- to += n; +- from += n; ++ register char *t = (char *)to; ++ register const char *f = (const char *)from; ++ ++ t += n; ++ f += n; + for (;;) { +- if (!n) return; *--to = *--from; --n; +- if (!n) return; *--to = *--from; --n; +- if (!n) return; *--to = *--from; --n; +- if (!n) return; *--to = *--from; --n; ++ if (!n) return; *--t = *--f; --n; ++ if (!n) return; *--t = *--f; --n; ++ if (!n) return; *--t = *--f; --n; ++ if (!n) return; *--t = *--f; --n; + } + } +diff -upN qmail-1.03/byte_diff.c qmail-ldap/byte_diff.c +--- qmail-1.03/byte_diff.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_diff.c Tue Oct 28 18:21:31 2003 +@@ -1,16 +1,19 @@ + #include "byte.h" + + int byte_diff(s,n,t) +-register char *s; ++const void *s; + register unsigned int n; +-register char *t; ++const void *t; + { ++ register const char *S = (const char *)s; ++ register const char *T = (const char *)t; ++ + for (;;) { +- if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; +- if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; +- if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; +- if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; ++ if (!n) return 0; if (*S != *T) break; ++S; ++T; --n; ++ if (!n) return 0; if (*S != *T) break; ++S; ++T; --n; ++ if (!n) return 0; if (*S != *T) break; ++S; ++T; --n; ++ if (!n) return 0; if (*S != *T) break; ++S; ++T; --n; + } +- return ((int)(unsigned int)(unsigned char) *s) +- - ((int)(unsigned int)(unsigned char) *t); ++ return ((int)(unsigned int)(unsigned char) *S) ++ - ((int)(unsigned int)(unsigned char) *T); + } +diff -upN qmail-1.03/byte_rchr.c qmail-ldap/byte_rchr.c +--- qmail-1.03/byte_rchr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_rchr.c Tue Oct 28 18:21:31 2003 +@@ -1,13 +1,13 @@ + #include "byte.h" + + unsigned int byte_rchr(s,n,c) +-char *s; ++const char *s; + register unsigned int n; + int c; + { + register char ch; +- register char *t; +- register char *u; ++ register const char *t; ++ register const char *u; + + ch = c; + t = s; +diff -upN qmail-1.03/byte_repl.c qmail-ldap/byte_repl.c +--- qmail-1.03/byte_repl.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/byte_repl.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2002-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "byte.h" ++ ++/* char replacement */ ++unsigned int byte_repl(char *s, unsigned int len, int f, int r) ++{ ++ register char *t; ++ int count = 0; ++ char fc; ++ char rc; ++ ++ t = s; fc = f; rc = r; ++ for(;;) { ++ if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len; ++ if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len; ++ if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len; ++ if (!len) return count; if (*t == fc) { *t=rc; count++; } ++t; --len; ++ } ++} ++ ++ +diff -upN qmail-1.03/byte_zero.c qmail-ldap/byte_zero.c +--- qmail-1.03/byte_zero.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/byte_zero.c Tue Oct 28 18:21:31 2003 +@@ -1,13 +1,14 @@ + #include "byte.h" + + void byte_zero(s,n) +-char *s; ++void *s; + register unsigned int n; + { ++ char *S = (char *)s; + for (;;) { +- if (!n) break; *s++ = 0; --n; +- if (!n) break; *s++ = 0; --n; +- if (!n) break; *s++ = 0; --n; +- if (!n) break; *s++ = 0; --n; ++ if (!n) break; *S++ = 0; --n; ++ if (!n) break; *S++ = 0; --n; ++ if (!n) break; *S++ = 0; --n; ++ if (!n) break; *S++ = 0; --n; + } + } +diff -upN qmail-1.03/case.h qmail-ldap/case.h +--- qmail-1.03/case.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/case.h Tue Oct 28 18:21:31 2003 +@@ -1,12 +1,12 @@ + #ifndef CASE_H + #define CASE_H + +-extern void case_lowers(); +-extern void case_lowerb(); +-extern int case_diffs(); +-extern int case_diffb(); +-extern int case_starts(); +-extern int case_startb(); ++extern void case_lowers(char *); ++extern void case_lowerb(char *, unsigned int); ++extern int case_diffs(const char *, const char *); ++extern int case_diffb(const char *, unsigned int, const char *); ++extern int case_starts(const char *, const char *); ++extern int case_startb(const char *, unsigned int, const char *); + + #define case_equals(s,t) (!case_diffs((s),(t))) + +diff -upN qmail-1.03/case_diffb.c qmail-ldap/case_diffb.c +--- qmail-1.03/case_diffb.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/case_diffb.c Tue Oct 28 18:21:31 2003 +@@ -1,9 +1,9 @@ + #include "case.h" + + int case_diffb(s,len,t) +-register char *s; ++register const char *s; + unsigned int len; +-register char *t; ++register const char *t; + { + register unsigned char x; + register unsigned char y; +diff -upN qmail-1.03/case_diffs.c qmail-ldap/case_diffs.c +--- qmail-1.03/case_diffs.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/case_diffs.c Tue Oct 28 18:21:31 2003 +@@ -1,8 +1,8 @@ + #include "case.h" + + int case_diffs(s,t) +-register char *s; +-register char *t; ++register const char *s; ++register const char *t; + { + register unsigned char x; + register unsigned char y; +diff -upN qmail-1.03/case_lowers.c qmail-ldap/case_lowers.c +--- qmail-1.03/case_lowers.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/case_lowers.c Tue Oct 28 18:21:31 2003 +@@ -4,7 +4,7 @@ void case_lowers(s) + char *s; + { + unsigned char x; +- while (x = *s) { ++ while ((x = *s)) { + x -= 'A'; + if (x <= 'Z' - 'A') *s = x + 'a'; + ++s; +diff -upN qmail-1.03/case_startb.c qmail-ldap/case_startb.c +--- qmail-1.03/case_startb.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/case_startb.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++/* based on case_starts.c by D.J. Bernstein */ ++#include "case.h" ++ ++int case_startb(const char *s, unsigned int len, const char *t) ++{ ++ unsigned char x; ++ unsigned char y; ++ ++ for (;;) { ++ y = *t++ - 'A'; ++ if (y <= 'Z' - 'A') ++ y += 'a'; ++ else ++ y += 'A'; ++ if (!y) ++ return (1); ++ if (!len) ++ return (0); ++ --len; ++ x = *s++ - 'A'; ++ if (x <= 'Z' - 'A') ++ x += 'a'; ++ else ++ x += 'A'; ++ if (x != y) ++ return (0); ++ } ++} ++ +diff -upN qmail-1.03/case_starts.c qmail-ldap/case_starts.c +--- qmail-1.03/case_starts.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/case_starts.c Tue Oct 28 18:21:31 2003 +@@ -1,8 +1,8 @@ + #include "case.h" + + int case_starts(s,t) +-register char *s; +-register char *t; ++register const char *s; ++register const char *t; + { + register unsigned char x; + register unsigned char y; +diff -upN qmail-1.03/cdb.c qmail-ldap/cdb.c +--- qmail-1.03/cdb.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/cdb.c Thu Jul 1 16:28:30 2004 +@@ -0,0 +1,164 @@ ++/* Public domain. */ ++ ++#include ++#include ++#include ++#include ++ ++#include "byte.h" ++#include "error.h" ++#include "seek.h" ++#include "uint32.h" ++ ++#include "cdb.h" ++ ++static void uint32_unpack(const unsigned char *buf, uint32 *u) ++{ ++ uint32 num; ++ num = buf[3]; num <<= 8; ++ num += buf[2]; num <<= 8; ++ num += buf[1]; num <<= 8; ++ num += buf[0]; ++ ++ *u = num; ++} ++ ++ ++ ++void cdb_free(struct cdb *c) ++{ ++ if (c->map) { ++ munmap(c->map,c->size); ++ c->map = 0; ++ } ++} ++ ++void cdb_findstart(struct cdb *c) ++{ ++ c->loop = 0; ++} ++ ++void cdb_init(struct cdb *c,int fd) ++{ ++ struct stat st; ++ char *x; ++ ++ cdb_free(c); ++ cdb_findstart(c); ++ c->fd = fd; ++ ++ if (fstat(fd,&st) == 0) ++ if (st.st_size <= 0xffffffff) { ++ x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0); ++ if (x + 1) { ++ c->size = st.st_size; ++ c->map = x; ++ } ++ } ++} ++ ++int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos) ++{ ++ if (c->map) { ++ if ((pos > c->size) || (c->size - pos < len)) goto FORMAT; ++ byte_copy(buf,len,c->map + pos); ++ } ++ else { ++ if (seek_set(c->fd,pos) == -1) return -1; ++ while (len > 0) { ++ int r; ++ do ++ r = read(c->fd,buf,len); ++ while ((r == -1) && (errno == error_intr)); ++ if (r == -1) return -1; ++ if (r == 0) goto FORMAT; ++ buf += r; ++ len -= r; ++ } ++ } ++ return 0; ++ ++ FORMAT: ++ errno = error_proto; ++ return -1; ++} ++ ++static int match(struct cdb *c,const char *key,unsigned int len,uint32 pos) ++{ ++ char buf[32]; ++ int n; ++ ++ while (len > 0) { ++ n = sizeof buf; ++ if (n > len) n = len; ++ if (cdb_read(c,buf,n,pos) == -1) return -1; ++ if (byte_diff(buf,n,key)) return 0; ++ pos += n; ++ key += n; ++ len -= n; ++ } ++ return 1; ++} ++ ++int cdb_findnext(struct cdb *c,const char *key,unsigned int len) ++{ ++ char buf[8]; ++ uint32 pos; ++ uint32 u; ++ ++ if (!c->loop) { ++ u = cdb_hash(key,len); ++ if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1; ++ uint32_unpack(buf + 4,&c->hslots); ++ if (!c->hslots) return 0; ++ uint32_unpack(buf,&c->hpos); ++ c->khash = u; ++ u >>= 8; ++ u %= c->hslots; ++ u <<= 3; ++ c->kpos = c->hpos + u; ++ } ++ ++ while (c->loop < c->hslots) { ++ if (cdb_read(c,buf,8,c->kpos) == -1) return -1; ++ uint32_unpack(buf + 4,&pos); ++ if (!pos) return 0; ++ c->loop += 1; ++ c->kpos += 8; ++ if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos; ++ uint32_unpack(buf,&u); ++ if (u == c->khash) { ++ if (cdb_read(c,buf,8,pos) == -1) return -1; ++ uint32_unpack(buf,&u); ++ if (u == len) ++ switch(match(c,key,len,pos + 8)) { ++ case -1: ++ return -1; ++ case 1: ++ uint32_unpack(buf + 4,&c->dlen); ++ c->dpos = pos + 8 + len; ++ return 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int cdb_find(struct cdb *c,const char *key,unsigned int len) ++{ ++ cdb_findstart(c); ++ return cdb_findnext(c,key,len); ++} ++ ++int cdb_seek(struct cdb *c,const char *key,unsigned int len,uint32 *dlen) ++{ ++ int rv; ++ ++ rv = cdb_find(c, key, len); ++ if (rv != 1) ++ return rv; ++ *dlen = cdb_datalen(c); ++ return rv; ++} ++ +diff -upN qmail-1.03/cdb.h qmail-ldap/cdb.h +--- qmail-1.03/cdb.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdb.h Wed May 5 17:42:11 2004 +@@ -1,12 +1,40 @@ ++/* Public domain. */ ++ + #ifndef CDB_H + #define CDB_H + + #include "uint32.h" + +-extern uint32 cdb_hash(); +-extern uint32 cdb_unpack(); ++#define CDB_HASHSTART 5381 ++extern uint32 cdb_hashadd(uint32,unsigned char); ++extern uint32 cdb_hash(const char *,unsigned int); ++ ++struct cdb { ++ char *map; /* 0 if no map is available */ ++ int fd; ++ uint32 size; /* initialized if map is nonzero */ ++ uint32 loop; /* number of hash slots searched under this key */ ++ uint32 khash; /* initialized if loop is nonzero */ ++ uint32 kpos; /* initialized if loop is nonzero */ ++ uint32 hpos; /* initialized if loop is nonzero */ ++ uint32 hslots; /* initialized if loop is nonzero */ ++ uint32 dpos; /* initialized if cdb_findnext() returns 1 */ ++ uint32 dlen; /* initialized if cdb_findnext() returns 1 */ ++} ; ++ ++extern void cdb_free(struct cdb *); ++extern void cdb_init(struct cdb *,int fd); ++ ++extern int cdb_read(struct cdb *,char *,unsigned int,uint32); ++ ++extern void cdb_findstart(struct cdb *); ++extern int cdb_findnext(struct cdb *,const char *,unsigned int); ++extern int cdb_find(struct cdb *,const char *,unsigned int); ++extern int cdb_seek(struct cdb *,const char *,unsigned int,uint32 *); + +-extern int cdb_bread(); +-extern int cdb_seek(); ++#define cdb_datapos(c) ((c)->dpos) ++#define cdb_datalen(c) ((c)->dlen) ++#define cdb_bread(c, b, l) \ ++ cdb_read((c), (b), (l), cdb_datapos(c)) + + #endif +diff -upN qmail-1.03/cdb_hash.c qmail-ldap/cdb_hash.c +--- qmail-1.03/cdb_hash.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdb_hash.c Wed May 5 17:42:11 2004 +@@ -1,16 +1,21 @@ ++/* Public domain. */ ++ + #include "cdb.h" + +-uint32 cdb_hash(buf,len) +-unsigned char *buf; +-unsigned int len; ++uint32 cdb_hashadd(uint32 h,unsigned char c) ++{ ++ h += (h << 5); ++ return h ^ c; ++} ++ ++uint32 cdb_hash(const char *buf,unsigned int len) + { + uint32 h; + +- h = 5381; ++ h = CDB_HASHSTART; + while (len) { ++ h = cdb_hashadd(h,*buf++); + --len; +- h += (h << 5); +- h ^= (uint32) *buf++; + } + return h; + } +diff -upN qmail-1.03/cdb_make.c qmail-ldap/cdb_make.c +--- qmail-1.03/cdb_make.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/cdb_make.c Fri Apr 16 20:32:45 2004 +@@ -0,0 +1,163 @@ ++/* Public domain. */ ++ ++#include "readwrite.h" ++#include "seek.h" ++#include "error.h" ++#include "alloc.h" ++#include "cdb.h" ++#include "cdb_make.h" ++ ++static void uint32_pack(char s[4],uint32 u) ++{ ++ s[0] = u & 255; ++ u >>= 8; ++ s[1] = u & 255; ++ u >>= 8; ++ s[2] = u & 255; ++ s[3] = u >> 8; ++} ++ ++int cdb_make_start(struct cdb_make *c,int fd) ++{ ++ c->head = 0; ++ c->split = 0; ++ c->hash = 0; ++ c->numentries = 0; ++ c->fd = fd; ++ c->pos = sizeof c->final; ++ substdio_fdbuf(&c->ss,subwrite,fd,c->ssbuf,sizeof c->ssbuf); ++ return seek_set(fd,c->pos); ++} ++ ++static int posplus(struct cdb_make *c,uint32 len) ++{ ++ uint32 newpos = c->pos + len; ++ if (newpos < len) { errno = error_nomem; return -1; } ++ c->pos = newpos; ++ return 0; ++} ++ ++int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h) ++{ ++ struct cdb_hplist *head; ++ ++ head = c->head; ++ if (!head || (head->num >= CDB_HPLIST)) { ++ head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist)); ++ if (!head) return -1; ++ head->num = 0; ++ head->next = c->head; ++ c->head = head; ++ } ++ head->hp[head->num].h = h; ++ head->hp[head->num].p = c->pos; ++ ++head->num; ++ ++c->numentries; ++ if (posplus(c,8) == -1) return -1; ++ if (posplus(c,keylen) == -1) return -1; ++ if (posplus(c,datalen) == -1) return -1; ++ return 0; ++} ++ ++int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen) ++{ ++ char buf[8]; ++ ++ if (keylen > 0xffffffff) { errno = error_nomem; return -1; } ++ if (datalen > 0xffffffff) { errno = error_nomem; return -1; } ++ ++ uint32_pack(buf,keylen); ++ uint32_pack(buf + 4,datalen); ++ if (substdio_put(&c->ss,buf,8) == -1) return -1; ++ return 0; ++} ++ ++int cdb_make_add(struct cdb_make *c,const char *key,unsigned int keylen,const char *data,unsigned int datalen) ++{ ++ if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1; ++ if (substdio_put(&c->ss,key,keylen) == -1) return -1; ++ if (substdio_put(&c->ss,data,datalen) == -1) return -1; ++ return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen)); ++} ++ ++int cdb_make_finish(struct cdb_make *c) ++{ ++ char buf[8]; ++ int i; ++ uint32 len; ++ uint32 u; ++ uint32 memsize; ++ uint32 count; ++ uint32 where; ++ struct cdb_hplist *x; ++ struct cdb_hp *hp; ++ ++ for (i = 0;i < 256;++i) ++ c->count[i] = 0; ++ ++ for (x = c->head;x;x = x->next) { ++ i = x->num; ++ while (i--) ++ ++c->count[255 & x->hp[i].h]; ++ } ++ ++ memsize = 1; ++ for (i = 0;i < 256;++i) { ++ u = c->count[i] * 2; ++ if (u > memsize) ++ memsize = u; ++ } ++ ++ memsize += c->numentries; /* no overflow possible up to now */ ++ u = (uint32) 0 - (uint32) 1; ++ u /= sizeof(struct cdb_hp); ++ if (memsize > u) { errno = error_nomem; return -1; } ++ ++ c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp)); ++ if (!c->split) return -1; ++ ++ c->hash = c->split + c->numentries; ++ ++ u = 0; ++ for (i = 0;i < 256;++i) { ++ u += c->count[i]; /* bounded by numentries, so no overflow */ ++ c->start[i] = u; ++ } ++ ++ for (x = c->head;x;x = x->next) { ++ i = x->num; ++ while (i--) ++ c->split[--c->start[255 & x->hp[i].h]] = x->hp[i]; ++ } ++ ++ for (i = 0;i < 256;++i) { ++ count = c->count[i]; ++ ++ len = count + count; /* no overflow possible */ ++ uint32_pack(c->final + 8 * i,c->pos); ++ uint32_pack(c->final + 8 * i + 4,len); ++ ++ for (u = 0;u < len;++u) ++ c->hash[u].h = c->hash[u].p = 0; ++ ++ hp = c->split + c->start[i]; ++ for (u = 0;u < count;++u) { ++ where = (hp->h >> 8) % len; ++ while (c->hash[where].p) ++ if (++where == len) ++ where = 0; ++ c->hash[where] = *hp++; ++ } ++ ++ for (u = 0;u < len;++u) { ++ uint32_pack(buf,c->hash[u].h); ++ uint32_pack(buf + 4,c->hash[u].p); ++ if (substdio_put(&c->ss,buf,8) == -1) return -1; ++ if (posplus(c,8) == -1) return -1; ++ } ++ } ++ ++ if (substdio_flush(&c->ss) == -1) return -1; ++ if (seek_begin(c->fd) == -1) return -1; ++ return substdio_putflush(&c->ss,c->final,sizeof c->final); ++} +diff -upN qmail-1.03/cdb_make.h qmail-ldap/cdb_make.h +--- qmail-1.03/cdb_make.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/cdb_make.h Fri Apr 16 20:32:45 2004 +@@ -0,0 +1,39 @@ ++/* Public domain. */ ++ ++#ifndef CDB_MAKE_H ++#define CDB_MAKE_H ++ ++#include "substdio.h" ++#include "uint32.h" ++ ++#define CDB_HPLIST 1000 ++ ++struct cdb_hp { uint32 h; uint32 p; } ; ++ ++struct cdb_hplist { ++ struct cdb_hp hp[CDB_HPLIST]; ++ struct cdb_hplist *next; ++ int num; ++} ; ++ ++struct cdb_make { ++ char ssbuf[8192]; ++ char final[2048]; ++ uint32 count[256]; ++ uint32 start[256]; ++ struct cdb_hplist *head; ++ struct cdb_hp *split; /* includes space for hash */ ++ struct cdb_hp *hash; ++ uint32 numentries; ++ substdio ss; ++ uint32 pos; ++ int fd; ++} ; ++ ++extern int cdb_make_start(struct cdb_make *,int); ++extern int cdb_make_addbegin(struct cdb_make *,unsigned int,unsigned int); ++extern int cdb_make_addend(struct cdb_make *,unsigned int,unsigned int,uint32); ++extern int cdb_make_add(struct cdb_make *,const char *,unsigned int,const char *,unsigned int); ++extern int cdb_make_finish(struct cdb_make *); ++ ++#endif +diff -upN qmail-1.03/cdb_seek.c qmail-ldap/cdb_seek.c +--- qmail-1.03/cdb_seek.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdb_seek.c Thu Jan 1 01:00:00 1970 +@@ -1,95 +0,0 @@ +-#include +-#include +-extern int errno; +-#include "cdb.h" +- +-#ifndef SEEK_SET +-#define SEEK_SET 0 +-#endif +- +-int cdb_bread(fd,buf,len) +-int fd; +-char *buf; +-int len; +-{ +- int r; +- while (len > 0) { +- do +- r = read(fd,buf,len); +- while ((r == -1) && (errno == EINTR)); +- if (r == -1) return -1; +- if (r == 0) { errno = EIO; return -1; } +- buf += r; +- len -= r; +- } +- return 0; +-} +- +-static int match(fd,key,len) +-int fd; +-char *key; +-unsigned int len; +-{ +- char buf[32]; +- int n; +- int i; +- +- while (len > 0) { +- n = sizeof(buf); +- if (n > len) n = len; +- if (cdb_bread(fd,buf,n) == -1) return -1; +- for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0; +- key += n; +- len -= n; +- } +- return 1; +-} +- +-int cdb_seek(fd,key,len,dlen) +-int fd; +-char *key; +-unsigned int len; +-uint32 *dlen; +-{ +- char packbuf[8]; +- uint32 pos; +- uint32 h; +- uint32 lenhash; +- uint32 h2; +- uint32 loop; +- uint32 poskd; +- +- h = cdb_hash(key,len); +- +- pos = 8 * (h & 255); +- if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; +- +- if (cdb_bread(fd,packbuf,8) == -1) return -1; +- +- pos = cdb_unpack(packbuf); +- lenhash = cdb_unpack(packbuf + 4); +- +- if (!lenhash) return 0; +- h2 = (h >> 8) % lenhash; +- +- for (loop = 0;loop < lenhash;++loop) { +- if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1; +- if (cdb_bread(fd,packbuf,8) == -1) return -1; +- poskd = cdb_unpack(packbuf + 4); +- if (!poskd) return 0; +- if (cdb_unpack(packbuf) == h) { +- if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1; +- if (cdb_bread(fd,packbuf,8) == -1) return -1; +- if (cdb_unpack(packbuf) == len) +- switch(match(fd,key,len)) { +- case -1: +- return -1; +- case 1: +- *dlen = cdb_unpack(packbuf + 4); +- return 1; +- } +- } +- if (++h2 == lenhash) h2 = 0; +- } +- return 0; +-} +diff -upN qmail-1.03/cdb_unpack.c qmail-ldap/cdb_unpack.c +--- qmail-1.03/cdb_unpack.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdb_unpack.c Thu Jan 1 01:00:00 1970 +@@ -1,12 +0,0 @@ +-#include "cdb.h" +- +-uint32 cdb_unpack(buf) +-unsigned char *buf; +-{ +- uint32 num; +- num = buf[3]; num <<= 8; +- num += buf[2]; num <<= 8; +- num += buf[1]; num <<= 8; +- num += buf[0]; +- return num; +-} +diff -upN qmail-1.03/cdbmake.h qmail-ldap/cdbmake.h +--- qmail-1.03/cdbmake.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmake.h Thu Jan 1 01:00:00 1970 +@@ -1,35 +0,0 @@ +-#ifndef CDBMAKE_H +-#define CDBMAKE_H +- +-#include "uint32.h" +- +-#define CDBMAKE_HPLIST 1000 +- +-struct cdbmake_hp { uint32 h; uint32 p; } ; +- +-struct cdbmake_hplist { +- struct cdbmake_hp hp[CDBMAKE_HPLIST]; +- struct cdbmake_hplist *next; +- int num; +-} ; +- +-struct cdbmake { +- char final[2048]; +- uint32 count[256]; +- uint32 start[256]; +- struct cdbmake_hplist *head; +- struct cdbmake_hp *split; /* includes space for hash */ +- struct cdbmake_hp *hash; +- uint32 numentries; +-} ; +- +-extern void cdbmake_pack(); +-#define CDBMAKE_HASHSTART ((uint32) 5381) +-extern uint32 cdbmake_hashadd(); +- +-extern void cdbmake_init(); +-extern int cdbmake_add(); +-extern int cdbmake_split(); +-extern uint32 cdbmake_throw(); +- +-#endif +diff -upN qmail-1.03/cdbmake_add.c qmail-ldap/cdbmake_add.c +--- qmail-1.03/cdbmake_add.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmake_add.c Thu Jan 1 01:00:00 1970 +@@ -1,117 +0,0 @@ +-#include "cdbmake.h" +- +-void cdbmake_init(cdbm) +-struct cdbmake *cdbm; +-{ +- cdbm->head = 0; +- cdbm->split = 0; +- cdbm->hash = 0; +- cdbm->numentries = 0; +-} +- +-int cdbmake_add(cdbm,h,p,alloc) +-struct cdbmake *cdbm; +-uint32 h; +-uint32 p; +-char *(*alloc)(); +-{ +- struct cdbmake_hplist *head; +- +- head = cdbm->head; +- if (!head || (head->num >= CDBMAKE_HPLIST)) { +- head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist)); +- if (!head) return 0; +- head->num = 0; +- head->next = cdbm->head; +- cdbm->head = head; +- } +- head->hp[head->num].h = h; +- head->hp[head->num].p = p; +- ++head->num; +- ++cdbm->numentries; +- return 1; +-} +- +-int cdbmake_split(cdbm,alloc) +-struct cdbmake *cdbm; +-char *(*alloc)(); +-{ +- int i; +- uint32 u; +- uint32 memsize; +- struct cdbmake_hplist *x; +- +- for (i = 0;i < 256;++i) +- cdbm->count[i] = 0; +- +- for (x = cdbm->head;x;x = x->next) { +- i = x->num; +- while (i--) +- ++cdbm->count[255 & x->hp[i].h]; +- } +- +- memsize = 1; +- for (i = 0;i < 256;++i) { +- u = cdbm->count[i] * 2; +- if (u > memsize) +- memsize = u; +- } +- +- memsize += cdbm->numentries; /* no overflow possible up to now */ +- u = (uint32) 0 - (uint32) 1; +- u /= sizeof(struct cdbmake_hp); +- if (memsize > u) return 0; +- +- cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp)); +- if (!cdbm->split) return 0; +- +- cdbm->hash = cdbm->split + cdbm->numentries; +- +- u = 0; +- for (i = 0;i < 256;++i) { +- u += cdbm->count[i]; /* bounded by numentries, so no overflow */ +- cdbm->start[i] = u; +- } +- +- for (x = cdbm->head;x;x = x->next) { +- i = x->num; +- while (i--) +- cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i]; +- } +- +- return 1; +-} +- +-uint32 cdbmake_throw(cdbm,pos,b) +-struct cdbmake *cdbm; +-uint32 pos; +-int b; +-{ +- uint32 len; +- uint32 j; +- uint32 count; +- struct cdbmake_hp *hp; +- uint32 where; +- +- count = cdbm->count[b]; +- +- len = count + count; /* no overflow possible */ +- cdbmake_pack(cdbm->final + 8 * b,pos); +- cdbmake_pack(cdbm->final + 8 * b + 4,len); +- +- if (len) { +- for (j = 0;j < len;++j) +- cdbm->hash[j].h = cdbm->hash[j].p = 0; +- +- hp = cdbm->split + cdbm->start[b]; +- for (j = 0;j < count;++j) { +- where = (hp->h >> 8) % len; +- while (cdbm->hash[where].p) +- if (++where == len) +- where = 0; +- cdbm->hash[where] = *hp++; +- } +- } +- +- return len; +-} +diff -upN qmail-1.03/cdbmake_hash.c qmail-ldap/cdbmake_hash.c +--- qmail-1.03/cdbmake_hash.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmake_hash.c Thu Jan 1 01:00:00 1970 +@@ -1,10 +0,0 @@ +-#include "cdbmake.h" +- +-uint32 cdbmake_hashadd(h,c) +-uint32 h; +-unsigned int c; +-{ +- h += (h << 5); +- h ^= (uint32) (unsigned char) c; +- return h; +-} +diff -upN qmail-1.03/cdbmake_pack.c qmail-ldap/cdbmake_pack.c +--- qmail-1.03/cdbmake_pack.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmake_pack.c Thu Jan 1 01:00:00 1970 +@@ -1,11 +0,0 @@ +-#include "cdbmake.h" +- +-void cdbmake_pack(buf,num) +-unsigned char *buf; +-uint32 num; +-{ +- *buf++ = num; num >>= 8; +- *buf++ = num; num >>= 8; +- *buf++ = num; num >>= 8; +- *buf = num; +-} +diff -upN qmail-1.03/cdbmss.c qmail-ldap/cdbmss.c +--- qmail-1.03/cdbmss.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmss.c Thu Jan 1 01:00:00 1970 +@@ -1,65 +0,0 @@ +-#include "readwrite.h" +-#include "seek.h" +-#include "alloc.h" +-#include "cdbmss.h" +- +-int cdbmss_start(c,fd) +-struct cdbmss *c; +-int fd; +-{ +- cdbmake_init(&c->cdbm); +- c->fd = fd; +- c->pos = sizeof(c->cdbm.final); +- substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf)); +- return seek_set(fd,(seek_pos) c->pos); +-} +- +-int cdbmss_add(c,key,keylen,data,datalen) +-struct cdbmss *c; +-unsigned char *key; +-unsigned int keylen; +-unsigned char *data; +-unsigned int datalen; +-{ +- uint32 h; +- int i; +- +- cdbmake_pack(c->packbuf,(uint32) keylen); +- cdbmake_pack(c->packbuf + 4,(uint32) datalen); +- if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; +- if (substdio_put(&c->ss,key,keylen) == -1) return -1; +- if (substdio_put(&c->ss,data,datalen) == -1) return -1; +- +- h = CDBMAKE_HASHSTART; +- for (i = 0;i < keylen;++i) +- h = cdbmake_hashadd(h,(unsigned int) key[i]); +- +- if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1; +- +- c->pos += 8 + keylen + datalen; /* XXX: overflow? */ +- return 0; +-} +- +-int cdbmss_finish(c) +-struct cdbmss *c; +-{ +- int i; +- uint32 len; +- uint32 u; +- +- if (!cdbmake_split(&c->cdbm,alloc)) return -1; +- +- for (i = 0;i < 256;++i) { +- len = cdbmake_throw(&c->cdbm,c->pos,i); +- for (u = 0;u < len;++u) { +- cdbmake_pack(c->packbuf,c->cdbm.hash[u].h); +- cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p); +- if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; +- c->pos += 8; /* XXX: overflow? */ +- } +- } +- +- if (substdio_flush(&c->ss) == -1) return -1; +- if (seek_begin(c->fd) == -1) return -1; +- return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final)); +-} +diff -upN qmail-1.03/cdbmss.h qmail-ldap/cdbmss.h +--- qmail-1.03/cdbmss.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/cdbmss.h Thu Jan 1 01:00:00 1970 +@@ -1,16 +0,0 @@ +-#ifndef CDBMSS_H +-#define CDBMSS_H +- +-#include "cdbmake.h" +-#include "substdio.h" +- +-struct cdbmss { +- char ssbuf[1024]; +- struct cdbmake cdbm; +- substdio ss; +- char packbuf[8]; +- uint32 pos; +- int fd; +-} ; +- +-#endif +diff -upN qmail-1.03/check.c qmail-ldap/check.c +--- qmail-1.03/check.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/check.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,282 @@ ++/* ++ * Copyright (c) 1998-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "qmail-ldap.h" ++#include "check.h" ++#include "str.h" ++ ++extern unsigned char testvektor[128]; ++ ++/* XXX this is not a security checker, it just looks that no special chars ++ * XXX are in the string this is because the ldap server could send some ++ * XXX faked datas */ ++int sanitycheckb(char *s, unsigned int len, unsigned char mask) ++{ ++ unsigned char *tv; ++ unsigned int x; ++ ++ tv = testvektor; ++ ++ x = (unsigned int)*s++; if (!len--) return 1; ++ /* is this char allowed as first char (normaly '-' is not) */ ++ if (x > 0x7F || !(tv[x] & mask) || tv[x] & NOT_FIRST) return 0; ++ ++ for (;;) { ++ x = (unsigned int)*s++; if (!len--) return 1; ++ if (x > 0x7F || !(tv[x] & mask)) return 0; ++ x = (unsigned int)*s++; if (!len--) return 1; ++ if (x > 0x7F || !(tv[x] & mask)) return 0; ++ x = (unsigned int)*s++; if (!len--) return 1; ++ if (x > 0x7F || !(tv[x] & mask)) return 0; ++ x = (unsigned int)*s++; if (!len--) return 1; ++ if (x > 0x7F || !(tv[x] & mask)) return 0; ++ } ++ return 0; /* paranoia */ ++} ++ ++/* XXX this is not a security checker, it just looks that no special chars ++ * XXX are in the string this is because the ldap server could send some ++ * XXX faked datas */ ++int sanitypathcheckb(char *s, unsigned int len, unsigned char mask) ++/* works like sanitycheckb but also looks that there is no '..' in the ++ * string. This should be used for maildirpaths */ ++{ ++ unsigned char *tv; ++ unsigned int x; ++ enum { NODOT, FIRST, SLASH, ONEDOT, TWODOT } state = FIRST; ++ ++ tv = testvektor; ++ ++ while (len--) { ++ x = (unsigned int)*s++; ++ if (x > 0x7F || !(tv[x] & mask)) return 0; ++ if (state == FIRST && tv[x] & NOT_FIRST) return 0; ++ switch (x) { ++ case '.': ++ switch (state) { ++ case ONEDOT: ++ state = TWODOT; ++ break; ++ case NODOT: ++ break; ++ default: ++ state = ONEDOT; ++ } ++ break; ++ case '/': ++ if (state == TWODOT) ++ return 0; ++ state = SLASH; ++ break; ++ default: ++ state = NODOT; ++ break; ++ } ++ } ++ return 1; ++} ++ ++int sanitychecks(register char *s, register unsigned char mask) ++{ ++ return sanitycheckb(s, str_len(s), mask); ++} ++ ++int sanitypathchecks(register char *s, register unsigned char mask) ++{ ++ return sanitypathcheckb(s, str_len(s), mask); ++} ++ ++/************************************************************ ++You can allow or deny chars by adding: ++ DENY_ALL: always deny this char ++ ALLOW_ALL: always allow this char ++ ALLOW_USER: allow this char for username checks (chck_user) ++ DENY_USER: deny this char for username checks (chck_user) ++ ALLOW_PATH: allow this char for path checks (chck_path) ++ DENY_PATH: deny this char for path checks (chck_path) ++ ALLOW_PROG: allow this char for program checks (chck_prog) ++ DENY_PROG: deny this char for program checks (chck_prog) ++ NOT_FIRST: deny this char at the beginning of a string ++ SPACE: alias to ALLOW_PROG ++ PARANOIA: deny most shell special chars like '|' or '*' for program checks ++ can be turned on or of in qmail-ldap.h ++ Example: ++ * 7 \007 ^G * DENY_ALL, * deny control chars * ++ * 45 '-' * ALLOW_ALL|NOT_FIRST, * allowed but not first * ++ * 47 '/' * ALLOW_ALL&DENY_USER, * allowed only for path and prog * ++ * 58 ':' * ALLOW_PROG|ALLOW_PATH, * like before * ++ ++ As you can see ALLOWs have to be ORed together whereas DENYs have to be ANDed ++ NOT_FIRST has to be ORed and PARANOIA has to be ANDed. ++ ++************************************************************/ ++ ++unsigned char testvektor[128] = { ++#define SPACE ALLOW_PROG ++#if RESTRICT_PROG == 1 ++# define PARANOIA DENY_PROG ++#else ++# define PARANOIA 0xFF ++#endif ++ /* nr char */ ++ /********************/ ++ /* 0 \000 ^@ */ DENY_ALL, ++ /* 1 \001 ^A */ DENY_ALL, ++ /* 2 \002 ^B */ DENY_ALL, ++ /* 3 \003 ^C */ DENY_ALL, ++ /* 4 \004 ^D */ DENY_ALL, ++ /* 5 \005 ^E */ DENY_ALL, ++ /* 6 \006 ^F */ DENY_ALL, ++ /* 7 \007 ^G */ DENY_ALL, ++ /* 8 \010 ^F */ DENY_ALL, ++ /* 9 \011 \t */ SPACE, ++ /* 10 \012 \n */ SPACE, ++ /* 11 \013 ^K */ DENY_ALL, ++ /* 12 \014 ^L */ DENY_ALL, ++ /* 13 \015 ^M */ DENY_ALL, ++ /* 14 \016 ^N */ DENY_ALL, ++ /* 15 \017 ^O */ DENY_ALL, ++ /* 16 \020 ^P */ DENY_ALL, ++ /* 17 \021 ^Q */ DENY_ALL, ++ /* 18 \022 ^R */ DENY_ALL, ++ /* 19 \023 ^S */ DENY_ALL, ++ /* 20 \024 ^T */ DENY_ALL, ++ /* 21 \025 ^U */ DENY_ALL, ++ /* 22 \026 ^V */ DENY_ALL, ++ /* 23 \027 ^W */ DENY_ALL, ++ /* 24 \030 ^X */ DENY_ALL, ++ /* 25 \031 ^Y */ DENY_ALL, ++ /* 26 \032 ^Z */ DENY_ALL, ++ /* 27 \033 ESC */ DENY_ALL, ++ /* 28 \034 ^\ */ DENY_ALL, ++ /* 29 \035 ^] */ DENY_ALL, ++ /* 30 \036 ^^ */ DENY_ALL, ++ /* 31 \037 ^_ */ DENY_ALL, ++ /* 32 ' ' */ SPACE, ++ /* 33 '!' */ ALLOW_PROG&PARANOIA, ++ /* 34 '"' */ ALLOW_PROG, ++ /* 35 '#' */ ALLOW_ALL, ++ /* 36 '$' */ ALLOW_PROG&PARANOIA, ++ /* 37 '%' */ ALLOW_PROG&PARANOIA, ++ /* 38 '&' */ ALLOW_PROG&PARANOIA, ++ /* 39 ''' */ ALLOW_PROG, ++ /* 40 '(' */ ALLOW_PROG&PARANOIA, ++ /* 41 ')' */ ALLOW_PROG&PARANOIA, ++ /* 42 '*' */ ALLOW_PROG&PARANOIA, ++ /* 43 '+' */ ALLOW_PROG, ++ /* 44 ',' */ ALLOW_PROG, ++ /* 45 '-' */ ALLOW_ALL|NOT_FIRST, /*XXX*/ ++ /* 46 '.' */ ALLOW_ALL, ++ /* 47 '/' */ ALLOW_ALL&DENY_USER, ++ /* 48 '0' */ ALLOW_ALL, ++ /* 49 '1' */ ALLOW_ALL, ++ /* 50 '2' */ ALLOW_ALL, ++ /* 51 '3' */ ALLOW_ALL, ++ /* 52 '4' */ ALLOW_ALL, ++ /* 53 '5' */ ALLOW_ALL, ++ /* 54 '6' */ ALLOW_ALL, ++ /* 55 '7' */ ALLOW_ALL, ++ /* 56 '8' */ ALLOW_ALL, ++ /* 57 '9' */ ALLOW_ALL, ++ /* 58 ':' */ ALLOW_PROG|ALLOW_PATH, ++ /* 59 ';' */ ALLOW_PROG&PARANOIA, ++ /* 60 '<' */ ALLOW_PROG&PARANOIA, ++ /* 61 '=' */ ALLOW_PROG|ALLOW_PATH, ++ /* 62 '>' */ ALLOW_PROG&PARANOIA, ++ /* 63 '?' */ ALLOW_PROG&PARANOIA, ++ /* 64 '@' */ ALLOW_USER|ALLOW_PATH|ALLOW_PROG, /*XXX*/ ++ /* 65 'A' */ ALLOW_ALL, ++ /* 66 'B' */ ALLOW_ALL, ++ /* 67 'C' */ ALLOW_ALL, ++ /* 68 'D' */ ALLOW_ALL, ++ /* 69 'E' */ ALLOW_ALL, ++ /* 70 'F' */ ALLOW_ALL, ++ /* 71 'G' */ ALLOW_ALL, ++ /* 72 'H' */ ALLOW_ALL, ++ /* 73 'I' */ ALLOW_ALL, ++ /* 74 'J' */ ALLOW_ALL, ++ /* 75 'K' */ ALLOW_ALL, ++ /* 76 'L' */ ALLOW_ALL, ++ /* 77 'M' */ ALLOW_ALL, ++ /* 78 'N' */ ALLOW_ALL, ++ /* 79 'O' */ ALLOW_ALL, ++ /* 80 'P' */ ALLOW_ALL, ++ /* 81 'Q' */ ALLOW_ALL, ++ /* 82 'R' */ ALLOW_ALL, ++ /* 83 'S' */ ALLOW_ALL, ++ /* 84 'T' */ ALLOW_ALL, ++ /* 85 'U' */ ALLOW_ALL, ++ /* 86 'V' */ ALLOW_ALL, ++ /* 87 'W' */ ALLOW_ALL, ++ /* 88 'X' */ ALLOW_ALL, ++ /* 89 'Y' */ ALLOW_ALL, ++ /* 90 'Z' */ ALLOW_ALL, ++ /* 91 '[' */ ALLOW_PROG&PARANOIA, ++ /* 92 '\\' */ ALLOW_PROG, ++ /* 93 ']' */ ALLOW_PROG&PARANOIA, ++ /* 94 '^' */ ALLOW_PROG&PARANOIA, ++ /* 95 '_' */ ALLOW_ALL, ++ /* 96 '`' */ ALLOW_PROG&PARANOIA, ++ /* 97 'a' */ ALLOW_ALL, ++ /* 98 'b' */ ALLOW_ALL, ++ /* 99 'c' */ ALLOW_ALL, ++ /* 100 'd' */ ALLOW_ALL, ++ /* 101 'e' */ ALLOW_ALL, ++ /* 102 'f' */ ALLOW_ALL, ++ /* 103 'g' */ ALLOW_ALL, ++ /* 104 'h' */ ALLOW_ALL, ++ /* 105 'i' */ ALLOW_ALL, ++ /* 106 'j' */ ALLOW_ALL, ++ /* 107 'k' */ ALLOW_ALL, ++ /* 108 'l' */ ALLOW_ALL, ++ /* 109 'm' */ ALLOW_ALL, ++ /* 110 'n' */ ALLOW_ALL, ++ /* 111 'o' */ ALLOW_ALL, ++ /* 112 'p' */ ALLOW_ALL, ++ /* 113 'q' */ ALLOW_ALL, ++ /* 114 'r' */ ALLOW_ALL, ++ /* 115 's' */ ALLOW_ALL, ++ /* 116 't' */ ALLOW_ALL, ++ /* 117 'u' */ ALLOW_ALL, ++ /* 118 'v' */ ALLOW_ALL, ++ /* 119 'w' */ ALLOW_ALL, ++ /* 120 'x' */ ALLOW_ALL, ++ /* 121 'y' */ ALLOW_ALL, ++ /* 122 'z' */ ALLOW_ALL, ++ /* 123 '{' */ ALLOW_PROG&PARANOIA, ++ /* 124 '|' */ ALLOW_PROG&PARANOIA, ++ /* 125 '}' */ ALLOW_PROG&PARANOIA, ++ /* 126 '~' */ ALLOW_PROG&PARANOIA, ++ /* 127 ^? */ DENY_ALL ++}; ++ +diff -upN qmail-1.03/check.h qmail-ldap/check.h +--- qmail-1.03/check.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/check.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (c) 1998-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef _CHECK_H_ ++#define _CHECK_H_ ++ ++ ++#define DENY_ALL 0x00 ++#define ALLOW_USER 0x01 ++#define ALLOW_PATH 0x02 ++#define ALLOW_PROG 0x04 ++#define ALLOW_ALL (ALLOW_USER | ALLOW_PATH | ALLOW_PROG) ++#define DENY_USER (unsigned char) ~ALLOW_USER ++#define DENY_PATH (unsigned char) ~ALLOW_PATH ++#define DENY_PROG (unsigned char) ~ALLOW_PROG ++#define NOT_FIRST 0x80 ++ ++ ++extern int sanitycheckb(char *, unsigned int, unsigned char); ++extern int sanitychecks(char *, unsigned char); ++ ++extern int sanitypathcheckb(char *, unsigned int , unsigned char); ++extern int sanitypathchecks(char *, unsigned char); ++ ++#define check_userb(str, len) sanitycheckb((str), (len), ALLOW_USER) ++#define check_users(str) sanitychecks((str), ALLOW_USER) ++ ++#define check_pathb(str, len) sanitypathcheckb((str), (len), ALLOW_PATH) ++#define check_paths(str) sanitypathchecks((str), ALLOW_PATH) ++ ++#define check_progb(str, len) sanitycheckb((str), (len), ALLOW_PROG) ++#define check_progs(str) sanitychecks((str), ALLOW_PROG) ++ ++#endif +diff -upN qmail-1.03/checkpassword.c qmail-ldap/checkpassword.c +--- qmail-1.03/checkpassword.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/checkpassword.c Wed Nov 3 15:53:14 2004 +@@ -0,0 +1,291 @@ ++/* ++ * Copyright (c) 1998-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include "auth_mod.h" ++#include "auto_uids.h" ++#include "byte.h" ++#include "check.h" ++#include "env.h" ++#include "error.h" ++#include "fmt.h" ++#include "passwd.h" ++#include "pbsexec.h" ++#include "prot.h" ++#include "qldap.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "scan.h" ++#include "str.h" ++#include "stralloc.h" ++#ifdef QLDAP_CLUSTER ++#include "qldap-cluster.h" ++#endif ++ ++#include "checkpassword.h" ++ ++int ++check(checkfunc *f, stralloc *login, stralloc *authdata, ++ struct credentials *c, int fast) ++{ ++ int i, r; ++ ++ for (i = 0; f[i] != 0; i++) ++ switch (r = f[i](login, authdata, c, fast)) { ++ case OK: ++ case FORWARD: ++ return r; ++ case NOSUCH: ++ /* lets try an other backend */ ++ break; ++ case BADPASS: ++ /* NOTE: users defined in two dbs are not allowed */ ++ return BADPASS; ++ default: ++ return r; ++ } ++ ++ return NOSUCH; ++} ++ ++char num[FMT_ULONG]; ++ ++int ++check_ldap(stralloc *login, stralloc *authdata, ++ struct credentials *c, int fast) ++{ ++ static stralloc ld = {0}; ++ qldap *q; ++ char *filter; ++ int r, status, pwok, needforward; ++ unsigned long count, size, max; ++ const char *attrs[] = { ++ LDAP_UID, /* the first 10 attrs are default */ ++ LDAP_QMAILUID, ++ LDAP_QMAILGID, ++ LDAP_ISACTIVE, ++ LDAP_MAILHOST, ++ LDAP_MAILSTORE, ++ LDAP_HOMEDIR, ++ LDAP_QUOTA_SIZE, ++ LDAP_QUOTA_COUNT, ++ LDAP_MAXMSIZE, ++ LDAP_PASSWD, 0}; /* passwd is extra */ ++ ++ /* TODO more debug output is needed */ ++ needforward = 0; ++ q = qldap_new(); ++ if (q == 0) ++ return ERRNO; ++ ++ r = qldap_open(q); ++ if (r != OK) goto fail; ++ r = qldap_bind(q, 0, 0); ++ if (r != OK) goto fail; ++ ++ if (fast) { ++ /* just comapre passwords and account status */ ++ attrs[0] = LDAP_ISACTIVE; ++ if (qldap_need_rebind() == 0) { ++ attrs[1] = LDAP_PASSWD; ++ attrs[2] = 0; ++ } else ++ attrs[1] = 0; ++ } else { ++ if (qldap_need_rebind() != 0) ++ attrs[10] = 0; ++ } ++ ++ filter = filter_uid(login->s); ++ if (filter == 0) { r = ERRNO; goto fail; } ++ ++ r = qldap_lookup(q, filter, attrs); ++ if (r != OK) goto fail; ++ ++ r = qldap_get_status(q, &status); ++ if (r != OK) goto fail; ++ if (status == STATUS_BOUNCE || status == STATUS_NOACCESS || ++ status == STATUS_DELETE) { ++ qldap_free(q); ++ return ACC_DISABLED; ++ } ++ ++ if (!fast) { ++#ifdef QLDAP_CLUSTER ++ r = qldap_get_attr(q, LDAP_MAILHOST, &c->forwarder, ++ SINGLE_VALUE); ++ if (r != OK && r != NOSUCH) goto fail; ++ if (r == OK && cluster(c->forwarder.s) == 1) { ++ /* hostname is different, so I reconnect */ ++ logit(8, "check_ldap: forwarding session to %s\n", ++ c->forwarder.s); ++ needforward = 1; ++ } ++#endif ++ ++ r = qldap_get_uid(q, &c->uid); ++ if (r != OK) goto fail; ++ r = qldap_get_gid(q, &c->gid); ++ if (r != OK) goto fail; ++ r = qldap_get_mailstore(q, &c->home, &c->maildir); ++ if (r != OK) goto fail; ++ if (!stralloc_0(&c->home) || ++ !stralloc_0(&c->maildir)) ++ return ERRNO; ++ size = count = max = 0; ++ r = qldap_get_quota(q, &size, &count, &max); ++ if (r != OK) goto fail; ++ if (max != 0) { ++ num[fmt_ulong(num, max)] = 0; ++ if (!env_put2("DATASIZE", num)) ++ auth_error(ERRNO); ++ } ++ if (size != 0 || count != 0) { ++ if (!stralloc_copys(&ld, "")) auth_error(ERRNO); ++ if (size != 0) { ++ if (!stralloc_catb(&ld, num, ++ fmt_ulong(num, size))) ++ auth_error(ERRNO); ++ if (!stralloc_append(&ld, "S")) ++ auth_error(ERRNO); ++ } ++ if (count != 0) { ++ if (size != 0) ++ if (!stralloc_append(&ld, ",")) ++ auth_error(ERRNO); ++ if (!stralloc_catb(&ld, num, ++ fmt_ulong(num, count))) ++ auth_error(ERRNO); ++ if (!stralloc_append(&ld, "C")) ++ auth_error(ERRNO); ++ } ++ if (!stralloc_0(&ld)) auth_error(ERRNO); ++ if (!env_put2(ENV_QUOTA, ld.s )) auth_error(ERRNO); ++ } ++ } ++ ++ if (qldap_need_rebind() == 0) { ++ r = qldap_get_attr(q, LDAP_PASSWD, &ld, SINGLE_VALUE); ++ if (r != OK) goto fail; ++ pwok = cmp_passwd(authdata->s, ld.s); ++ } else { ++ r = qldap_get_dn(q, &ld); ++ if (r != OK) goto fail; ++ r = qldap_rebind(q, ld.s, authdata->s); ++ switch (r) { ++ case OK: ++ pwok = OK; ++ break; ++ case LDAP_BIND_AUTH: ++ pwok = BADPASS; ++ break; ++ default: ++ pwok = r; ++ break; ++ } ++ } ++ logit(32, "check_ldap: password compare was %s\n", ++ pwok == OK?"successful":"not successful"); ++ qldap_free(q); ++ if (pwok == OK && needforward == 1) ++ return FORWARD; ++ return pwok; ++fail: ++ qldap_free(q); ++ return r; ++ ++} ++ ++void ++change_uid(int uid, int gid) ++{ ++ int id; ++ ++ id = geteuid(); ++ if (id != 0 && (id == uid || id == -1)) { ++ /* not running as root so return */ ++ logit(32, "change_uid: already running non root\n"); ++ return; ++ } ++ if (uid == -1 && gid == -1) { ++ /* run as non-privileged user qmaild group nofiles */ ++ uid = auto_uidd; ++ gid = auto_gidn; ++ } ++ /* first set the group id */ ++ if (prot_gid(gid) == -1) ++ auth_error(ERRNO); ++ logit(32, "setgid succeeded (%i)\n", gid); ++ ++ /* ... then the user id */ ++ if (prot_uid(uid) == -1) ++ auth_error(ERRNO); ++ logit(32, "setuid succeeded (%i)\n", uid); ++ ++ /* ... now check that we are realy not running as root */ ++ if (!getuid()) ++ auth_error(FAILED); ++} ++ ++void ++setup_env(char *user, struct credentials *c) ++{ ++ /* set up the environment for the execution of the subprogram */ ++ if (!env_put2("USER", user)) ++ auth_error(ERRNO); ++ ++ /* only courier-imap needs this but we set it anyway */ ++ if (!env_put2("AUTHENTICATED", user)) ++ auth_error(ERRNO); ++ ++ if (c->home.s != 0 && c->home.len > 0) ++ if (!env_put2("HOME", c->home.s)) ++ auth_error(ERRNO); ++ ++ if (c->maildir.s != 0 && c->maildir.len > 0) { ++ if (!env_put2("MAILDIR", c->maildir.s)) ++ auth_error(ERRNO); ++ } else { ++ if (!env_unset("MAILDIR")) ++ auth_error(ERRNO); ++ } ++ logit(32, "environment successfully set: " ++ "USER %s, HOME %s, MAILDIR %s\n", ++ user, c->home.s != 0 && c->home.len > 0? ++ c->home.s:"unset, forwarding", ++ c->maildir.s != 0 && c->maildir.len > 0? ++ c->maildir.s:"unset, using aliasempty"); ++} ++ +diff -upN qmail-1.03/checkpassword.h qmail-ldap/checkpassword.h +--- qmail-1.03/checkpassword.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/checkpassword.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __CHECKPASSWORD_H__ ++#define __CHECKPASSWORD_H__ ++ ++#include "stralloc.h" ++ ++struct credentials { ++ int uid; ++ int gid; ++ stralloc home; ++ stralloc maildir; ++ stralloc forwarder; ++}; ++ ++typedef int (*checkfunc)(stralloc *, stralloc *, struct credentials *, int); ++ ++int check(checkfunc *, stralloc *, stralloc *, struct credentials *, int); ++int check_ldap(stralloc *, stralloc *, struct credentials *, int); ++void check_credentials(struct credentials *); ++void change_uid(int, int); ++void setup_env(char *, struct credentials *); ++ ++#endif +diff -upN qmail-1.03/chkshsgr.c qmail-ldap/chkshsgr.c +--- qmail-1.03/chkshsgr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/chkshsgr.c Thu Jan 29 16:48:14 2004 +@@ -1,9 +1,12 @@ ++#include ++#include + #include "exit.h" +-void main() ++ ++int main(int argc, char ** argv) + { + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/chkspawn.c qmail-ldap/chkspawn.c +--- qmail-1.03/chkspawn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/chkspawn.c Thu Jan 29 16:48:14 2004 +@@ -8,7 +8,7 @@ + char num[FMT_ULONG]; + fd_set fds; + +-void main() ++int main(int argc, char **argv) + { + unsigned long hiddenlimit; + unsigned long maxnumd; +@@ -22,8 +22,8 @@ void main() + _exit(1); + } + +- if (auto_spawn > 255) { +- substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n"); ++ if (auto_spawn > 65000) { ++ substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 65000.\n"); + substdio_flush(subfderr); + _exit(1); + } +@@ -44,5 +44,5 @@ limit in conf-spawn be at most "); + substdio_flush(subfderr); + _exit(1); + } +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/coe.h qmail-ldap/coe.h +--- qmail-1.03/coe.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/coe.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,6 @@ + #ifndef COE_H + #define COE_H + +-extern int coe(); ++extern int coe(int); + + #endif +diff -upN qmail-1.03/commands.c qmail-ldap/commands.c +--- qmail-1.03/commands.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/commands.c Tue Feb 17 15:31:30 2004 +@@ -11,6 +11,7 @@ substdio *ss; + struct commands *c; + { + int i; ++ unsigned int n; + char *arg; + + for (;;) { +@@ -28,13 +29,13 @@ struct commands *c; + + cmd.s[cmd.len] = 0; + +- i = str_chr(cmd.s,' '); +- arg = cmd.s + i; ++ n = str_chr(cmd.s,' '); ++ arg = cmd.s + n; + while (*arg == ' ') ++arg; +- cmd.s[i] = 0; ++ cmd.s[n] = 0; + +- for (i = 0;c[i].text;++i) if (case_equals(c[i].text,cmd.s)) break; +- c[i].fun(arg); +- if (c[i].flush) c[i].flush(); ++ for (n = 0;c[n].text;++n) if (case_equals(c[n].text,cmd.s)) break; ++ c[n].fun(arg); ++ if (c[n].flush) c[n].flush(); + } + } +diff -upN qmail-1.03/commands.h qmail-ldap/commands.h +--- qmail-1.03/commands.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/commands.h Tue Oct 28 18:21:31 2003 +@@ -1,12 +1,14 @@ + #ifndef COMMANDS_H + #define COMMANDS_H + ++#include "substdio.h" ++ + struct commands { +- char *text; ++ const char *text; + void (*fun)(); + void (*flush)(); + } ; + +-extern int commands(); ++extern int commands(substdio *, struct commands *); + + #endif +diff -upN qmail-1.03/condredirect.c qmail-ldap/condredirect.c +--- qmail-1.03/condredirect.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/condredirect.c Tue Oct 28 18:21:31 2003 +@@ -1,3 +1,4 @@ ++#include + #include "sig.h" + #include "readwrite.h" + #include "exit.h" +@@ -23,12 +24,12 @@ int mywrite(fd,buf,len) int fd; char *bu + + char inbuf[SUBSTDIO_INSIZE]; + char outbuf[1]; +-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); ++substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf); + substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf); + + char num[FMT_ULONG]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -36,7 +37,7 @@ char **argv; + char *dtline; + int pid; + int wstat; +- char *qqx; ++ const char *qqx; + + if (!argv[1] || !argv[2]) + strerr_die1x(100,"condredirect: usage: condredirect newaddress program [ arg ... ]"); +@@ -82,4 +83,6 @@ char **argv; + qqx = qmail_close(&qqt); + if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); + strerr_die2x(99,"condredirect: qp ",num); ++ /* NOTREACHED */ ++ return 1; + } +diff -upN qmail-1.03/condwrite.c qmail-ldap/condwrite.c +--- qmail-1.03/condwrite.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/condwrite.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,487 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++/* based on qmail-local.c and condredirect.c by D. J. Bernstein */ ++#include ++#include ++#include ++#include "auto_qmail.h" ++#include "byte.h" ++#include "env.h" ++#include "error.h" ++#include "fmt.h" ++#include "getln.h" ++#include "gfrom.h" ++#include "lock.h" ++#include "maildir++.h" ++#include "now.h" ++#include "open.h" ++#include "qmail-ldap.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "subfd.h" ++#include "substdio.h" ++#include "wait.h" ++#ifdef AUTOMAILDIRMAKE ++#include "mailmaker.h" ++#include "qldap-errno.h" ++#endif ++ ++#define FATAL "condwrite: fatal: " ++ ++void temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)"); ++} ++void temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)"); ++} ++void temp_childcrashed(void) ++{ ++ strerr_die2x(111, FATAL, "Aack, child crashed. (#4.3.0)"); ++} ++void temp_fork(void) ++{ ++ strerr_die4x(111, FATAL, "Unable to fork: ", ++ error_str(errno), ". (#4.3.0)"); ++} ++void ++temp_slowlock(void) ++{ ++ strerr_die2x(111, FATAL, ++ "File has been locked for 30 seconds straight. (#4.3.0)"); ++} ++ ++char *quotastring; ++ ++stralloc dtline = {0}; ++stralloc rpline = {0}; ++stralloc ufline = {0}; ++stralloc messline = {0}; ++ ++char buf[1024]; ++char outbuf[1024]; ++ ++char fntmptph[80 + FMT_ULONG * 2]; ++char fnnewtph[83 + FMT_ULONG * 3]; ++void tryunlinktmp() { unlink(fntmptph); } ++void sigalrm() { tryunlinktmp(); _exit(3); } ++int msfd = -1; /* global filedescriptor to the quota file */ ++ ++void ++maildir_child(char *dir) ++{ ++ unsigned long pid; ++ unsigned long tnow; ++ char host[64]; ++ char *s; ++ int loop; ++ struct stat st; ++ int fd; ++ substdio ss; ++ substdio ssout; ++ ++ sig_alarmcatch(sigalrm); ++ if (chdir(dir) == -1) { ++ if (error_temp(errno)) _exit(1); else _exit(2); ++ } ++ ++ pid = getpid(); ++ host[0] = 0; ++ gethostname(host,sizeof(host)); ++ for (loop = 0;;++loop) ++ { ++ tnow = now(); ++ s = fntmptph; ++ s += fmt_str(s,"tmp/"); ++ s += fmt_ulong(s,tnow); *s++ = '.'; ++ s += fmt_ulong(s,pid); *s++ = '.'; ++ s += fmt_strn(s,host,sizeof(host)); *s++ = 0; ++ if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; ++ /* really should never get to this point */ ++ if (loop == 2) _exit(1); ++ sleep(2); ++ } ++ str_copy(fnnewtph,fntmptph); ++ byte_copy(fnnewtph,3,"new"); ++ ++ alarm(86400); ++ fd = open_excl(fntmptph); ++ if (fd == -1) _exit(1); ++ ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf)); ++ if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; ++ if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; ++ ++ switch(substdio_copy(&ssout,&ss)) { ++ case -2: tryunlinktmp(); _exit(4); ++ case -3: goto fail; ++ } ++ ++ if (substdio_flush(&ssout) == -1) goto fail; ++ if (fsync(fd) == -1) goto fail; ++ if (fstat(fd, &st) == -1) goto fail; ++ if (close(fd) == -1) goto fail; /* NFS dorks */ ++ ++ s = fnnewtph; ++ while( *s ) s++; ++ s += fmt_str(s,",S="); ++ s += fmt_ulong(s,(unsigned long) st.st_size); ++ *s++ = 0; ++ ++ if( quotastring && *quotastring ) { ++ /* finally update the quota file "maildirsize" */ ++ quota_add(msfd, (unsigned long) st.st_size, 1); ++ close(msfd); ++ } ++ ++ if (link(fntmptph,fnnewtph) == -1) goto fail; ++ /* if it was error_exist, almost certainly successful; i hate NFS */ ++ tryunlinktmp(); ++ _exit(0); ++ ++fail: ++ tryunlinktmp(); ++ _exit(1); ++} ++ ++/* end child process */ ++ ++/* quota handling warning and bounce */ ++void ++quota_bounce(const char *type) ++{ ++ strerr_die4x(100, FATAL, "The users ", type, ++ " is over the allowed quota (size). (#5.2.2)"); ++} ++ ++stralloc qwapp = {0}; ++ ++void ++quota_warning(char *fn) ++{ ++ int child; ++ char *(args[3]); ++ int wstat; ++ ++ if (!stralloc_copys(&qwapp, auto_qmail)) temp_nomem(); ++ if (!stralloc_cats(&qwapp, "/bin/qmail-quotawarn")) temp_nomem(); ++ if (!stralloc_0(&qwapp)) temp_nomem(); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ switch(child = fork()) ++ { ++ case -1: ++ temp_fork(); ++ case 0: ++ args[0] = qwapp.s; args[1] = fn; args[2] = 0; ++ sig_pipedefault(); ++ execv(*args,args); ++ _exit(2); ++ } ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) ++ temp_childcrashed(); ++ switch(wait_exitcode(wstat)) ++ { ++ case 2: ++ strerr_die6x(111, FATAL, "Unable to run quotawarn program: ", ++ qwapp.s, ": ",error_str(errno),". (#4.2.2)"); ++ case 111: _exit(111); ++ case 0: break; ++ default: _exit(100); ++ } ++ ++} ++ ++/* end -- quota handling warning and bounce */ ++ ++void ++maildir_write(char *fn) ++{ ++ int child; ++ int wstat; ++ ++ /* quota handling maildir */ ++ struct stat mailst; ++ int perc; ++ quota_t q; ++ unsigned long mailsize; ++ ++#ifdef AUTOMAILDIRMAKE ++ switch (maildir_make(fn)) { ++ case OK: ++ break; ++ case MAILDIR_CORRUPT: ++ strerr_die4x(111, FATAL, "The maildir '", fn, ++ "' seems to be corrupted. (#4.2.1)"); ++ case ERRNO: ++ default: ++ strerr_die4x(111, FATAL, "Unable to create maildir '", ++ fn, "' (#4.3.0)"); ++ } ++#endif ++ ++ if (quotastring && *quotastring) { ++ if (fstat(0, &mailst) != 0) ++ strerr_die4x(111, FATAL, ++ "Can not stat mail for quota: ", ++ error_str(errno), ". (#4.3.0)"); ++ mailsize = mailst.st_size; ++ quota_get(&q, quotastring); ++ if (quota_calc(fn, &msfd, &q) == -1) { ++ /* second chance */ ++ sleep(3); ++ if (quota_calc(fn, &msfd, &q) == -1) { ++ strerr_die2x(111, FATAL, ++ "Temporary race condition while " ++ "calculating quota. (#4.3.0)"); ++ } ++ } ++ /* fd can be -1, quota_add/rm take care of that */ ++ ++ if (quota_check(&q, mailsize, 1, &perc) != 0) { /* 0 if OK */ ++ if (quota_recalc(fn, &msfd, &q) == -1) { ++ /* second chance */ ++ sleep(3); ++ if (quota_recalc(fn, &msfd, &q) == -1) ++ strerr_die2x(111, FATAL, ++ "Temporary race condition while " ++ "recalculating quota. (#4.3.0)"); ++ } ++ if (quota_check(&q, mailsize, 1, &perc) != 0) { ++ /* bounce mail but drop a warning first */ ++ quota_warning(fn); ++ quota_bounce("mailfolder"); ++ } ++ } ++ /* fd can be -1, quota_add/rm take care of that */ ++ ++ if (perc >= QUOTA_WARNING_LEVEL) ++ /* drop a warning when mailbox is around 80% full */ ++ quota_warning(fn); ++ } ++ ++ /* end -- quota handling maildir */ ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ switch(child = fork()) ++ { ++ case -1: ++ temp_fork(); ++ case 0: ++ maildir_child(fn); ++ _exit(111); ++ } ++ ++ if (msfd != -1) close(msfd); ++ /* close the maildirsize fd in the parent */ ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) ++ temp_childcrashed(); ++ switch(wait_exitcode(wstat)) ++ { ++ case 0: ++ /* we exit with 99 so no more deliveries are done */ ++ _exit(99); ++ case 2: ++ strerr_die2x(111, FATAL, ++ "Unable to chdir to maildir. (#4.2.1)"); ++ case 3: ++ strerr_die2x(111, FATAL, ++ "Timeout on maildir delivery. (#4.3.0)"); ++ case 4: ++ strerr_die2x(111, FATAL, "Unable to read message. (#4.3.0)"); ++ default: ++ strerr_die2x(111, FATAL, ++ "Temporary error on maildir delivery. (#4.3.0)"); ++ } ++} ++ ++void ++mailfile(char *fn) ++{ ++ int fd; ++ substdio ss; ++ substdio ssout; ++ int match; ++ seek_pos pos; ++ int flaglocked; ++ ++ /* quota handling mbox */ ++ struct stat filest, mailst; ++ long int totalsize; ++ quota_t q; ++ ++ if(quotastring && *quotastring) { ++ quota_get(&q, quotastring); ++ if (stat(fn, &filest) == -1) { ++ /* size of nonexisting mailfile */ ++ filest.st_size = 0; ++ if ( errno != error_noent) ++ strerr_die6x(111, FATAL, "Unable to quota ", fn, ++ ": ",error_str(errno), ". (#4.3.0)"); ++ } ++ if (fstat(0, &mailst) != 0) ++ strerr_die4x(111, FATAL, "Unable to quota mail: ", ++ error_str(errno), ". (#4.3.0)"); ++ ++ totalsize = (long) filest.st_size + (long) mailst.st_size; ++ if ( totalsize*100/q.quota_size >= QUOTA_WARNING_LEVEL) ++ /* drop a warning when mailbox is around 80% full */ ++ quota_warning(fn); ++ if ( totalsize > q.quota_size ) ++ quota_bounce("mailbox"); ++ } ++ ++ /* end -- quota handling mbox */ ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ fd = open_append(fn); ++ if (fd == -1) ++ strerr_die6x(111, FATAL, "Unable to open ",fn,": ", ++ error_str(errno),". (#4.2.1)"); ++ ++ sig_alarmcatch(temp_slowlock); ++ alarm(30); ++ flaglocked = (lock_ex(fd) != -1); ++ alarm(0); ++ sig_alarmdefault(); ++ ++ seek_end(fd); ++ pos = seek_cur(fd); ++ ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf)); ++ if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; ++ if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; ++ if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; ++ for (;;) { ++ if (getln(&ss,&messline,&match,'\n') != 0) { ++ strerr_warn4(FATAL, "Unable to read message: ", ++ error_str(errno),". (#4.3.0)",0); ++ if (flaglocked) seek_trunc(fd,pos); close(fd); ++ _exit(111); ++ } ++ if (!match && !messline.len) break; ++ if (gfrom(messline.s,messline.len)) ++ if (substdio_bput(&ssout,">",1)) goto writeerrs; ++ if (substdio_bput(&ssout,messline.s,messline.len)) ++ goto writeerrs; ++ if (!match) { ++ if (substdio_bputs(&ssout,"\n")) goto writeerrs; ++ break; ++ } ++ } ++ if (substdio_bputs(&ssout,"\n")) goto writeerrs; ++ if (substdio_flush(&ssout)) goto writeerrs; ++ if (fsync(fd) == -1) goto writeerrs; ++ close(fd); ++ _exit(99); ++ ++writeerrs: ++ strerr_warn6(FATAL, "Unable to write ",fn,": ", ++ error_str(errno),". (#4.3.0)",0); ++ if (flaglocked) seek_trunc(fd,pos); ++ close(fd); ++ _exit(111); ++} ++ ++int main(int argc, char **argv) ++{ ++ char *s; ++ int pid, wstat; ++ ++ if (!env_init()) temp_nomem(); ++ if (!argv[1] || !argv[2]) ++ strerr_die1x(100,"condwrite: usage: " ++ "condwrite {maildir/|mailfile} program [ arg ... ]"); ++ ++ if ((s = env_get("RPLINE"))) { ++ if (!stralloc_copys(&rpline, s)) temp_nomem(); ++ } else ++ strerr_die2x(100, FATAL, "RPLINE not present."); ++ ++ if ((s = env_get("DTLINE"))) { ++ if (!stralloc_copys(&dtline, s)) temp_nomem(); ++ } else ++ strerr_die2x(100, FATAL, "DTLINE not present."); ++ ++ if ((s = env_get("UFLINE"))) { ++ if (!stralloc_copys(&ufline, s)) temp_nomem(); ++ } else ++ strerr_die2x(100, FATAL, "UFLINE not present."); ++ ++ pid = fork(); ++ if (pid == -1) ++ temp_fork(); ++ if (pid == 0) { ++ execvp(argv[2],argv + 2); ++ if (error_temp(errno)) _exit(111); ++ _exit(100); ++ } ++ if (wait_pid(&wstat,pid) == -1) ++ strerr_die2x(111,FATAL,"wait failed"); ++ if (wait_crashed(wstat)) ++ temp_childcrashed(); ++ switch(wait_exitcode(wstat)) { ++ case 0: break; ++ case 111: strerr_die2x(111,FATAL,"temporary child error"); ++ default: _exit(0); ++ } ++ ++ if (seek_begin(0) == -1) ++ temp_rewind(); ++ sig_pipeignore(); ++ ++ /* quota, dotmode and forwarding handling - part 1 */ ++ /* setting the quota */ ++ quotastring = env_get(ENV_QUOTA); ++ ++ if(argv[1][str_len(argv[1]) - 1] == '/') ++ maildir_write(argv[1]); ++ else ++ mailfile(argv[1]); ++ return 100; ++} +diff -upN qmail-1.03/conf-spawn qmail-ldap/conf-spawn +--- qmail-1.03/conf-spawn Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/conf-spawn Sun Jan 16 13:52:14 2000 +@@ -1,4 +1,4 @@ +-120 ++500 + + This is a silent concurrency limit. You can't set it above 255. On some + systems you can't set it above 125. qmail will refuse to compile if the +diff -upN qmail-1.03/constmap.c qmail-ldap/constmap.c +--- qmail-1.03/constmap.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/constmap.c Mon Mar 1 14:29:43 2004 +@@ -4,7 +4,7 @@ + + static constmap_hash hash(s,len) + char *s; +-int len; ++unsigned int len; + { + unsigned char ch; + constmap_hash h; +@@ -18,10 +18,10 @@ int len; + return h; + } + +-char *constmap(cm,s,len) ++const char *constmap(cm,s,len) + struct constmap *cm; +-char *s; +-int len; ++const char *s; ++unsigned int len; + { + constmap_hash h; + int pos; +@@ -39,18 +39,19 @@ int len; + + int constmap_init(cm,s,len,flagcolon) + struct constmap *cm; +-char *s; +-int len; ++const char *s; ++unsigned int len; + int flagcolon; + { +- int i; +- int j; +- int k; ++ unsigned int i; ++ unsigned int j; ++ unsigned int k; + int pos; + constmap_hash h; + + cm->num = 0; + for (j = 0;j < len;++j) if (!s[j]) ++cm->num; ++ if (cm->num < 0) return 0; + + h = 64; + while (h && (h < cm->num)) h += h; +@@ -58,9 +59,9 @@ int flagcolon; + + cm->first = (int *) alloc(sizeof(int) * h); + if (cm->first) { +- cm->input = (char **) alloc(sizeof(char *) * cm->num); ++ cm->input = (const char **) alloc(sizeof(char *) * cm->num); + if (cm->input) { +- cm->inputlen = (int *) alloc(sizeof(int) * cm->num); ++ cm->inputlen = (unsigned int *) alloc(sizeof(unsigned int) * cm->num); + if (cm->inputlen) { + cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); + if (cm->hash) { +@@ -111,4 +112,5 @@ struct constmap *cm; + alloc_free(cm->inputlen); + alloc_free(cm->input); + alloc_free(cm->first); ++ cm->num = 0; + } +diff -upN qmail-1.03/constmap.h qmail-ldap/constmap.h +--- qmail-1.03/constmap.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/constmap.h Tue Feb 17 15:31:30 2004 +@@ -9,12 +9,12 @@ struct constmap { + constmap_hash *hash; + int *first; + int *next; +- char **input; +- int *inputlen; ++ const char **input; ++ unsigned int *inputlen; + } ; + +-extern int constmap_init(); +-extern void constmap_free(); +-extern char *constmap(); ++extern int constmap_init(struct constmap *, const char *, unsigned int, int); ++extern void constmap_free(struct constmap *); ++extern const char *constmap(struct constmap *, const char *, unsigned int); + + #endif +diff -upN qmail-1.03/control.c qmail-ldap/control.c +--- qmail-1.03/control.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/control.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "readwrite.h" + #include "open.h" + #include "getln.h" +@@ -7,6 +8,7 @@ + #include "control.h" + #include "alloc.h" + #include "scan.h" ++#include "limit.h" + + static char inbuf[64]; + static stralloc line = {0}; +@@ -27,7 +29,7 @@ stralloc *sa; + } + } + +-int control_init() ++int control_init(void) + { + int r; + r = control_readline(&me,"control/me"); +@@ -37,9 +39,9 @@ int control_init() + + int control_rldef(sa,fn,flagme,def) + stralloc *sa; +-char *fn; ++const char *fn; + int flagme; +-char *def; ++const char *def; + { + int r; + r = control_readline(sa,fn); +@@ -51,7 +53,7 @@ char *def; + + int control_readline(sa,fn) + stralloc *sa; +-char *fn; ++const char *fn; + { + substdio ss; + int fd; +@@ -60,7 +62,7 @@ char *fn; + fd = open_read(fn); + if (fd == -1) { if (errno == error_noent) return 0; return -1; } + +- substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf)); + + if (getln(&ss,sa,&match,'\n') == -1) { close(fd); return -1; } + +@@ -71,7 +73,7 @@ char *fn; + + int control_readint(i,fn) + int *i; +-char *fn; ++const char *fn; + { + unsigned long u; + switch(control_readline(&line,fn)) +@@ -81,13 +83,33 @@ char *fn; + } + if (!stralloc_0(&line)) return -1; + if (!scan_ulong(line.s,&u)) return 0; ++ if (u > INT_MAX) { ++ errno = error_range; ++ return -1; ++ } + *i = u; + return 1; + } + ++int control_readulong(ul,fn) ++unsigned long *ul; ++const char *fn; ++{ ++ unsigned long u; ++ switch(control_readline(&line,fn)) ++ { ++ case 0: return 0; ++ case -1: return -1; ++ } ++ if (!stralloc_0(&line)) return -1; ++ if (!scan_ulong(line.s,&u)) return 0; ++ *ul = u; ++ return 1; ++} ++ + int control_readfile(sa,fn,flagme) + stralloc *sa; +-char *fn; ++const char *fn; + int flagme; + { + substdio ss; +@@ -112,7 +134,7 @@ int flagme; + return -1; + } + +- substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf)); + + for (;;) + { +@@ -123,6 +145,36 @@ int flagme; + if (line.s[0]) + if (line.s[0] != '#') + if (!stralloc_cat(sa,&line)) break; ++ if (!match) { close(fd); return 1; } ++ } ++ close(fd); ++ return -1; ++} ++ ++int control_readrawfile(sa,fn) ++stralloc *sa; ++const char *fn; ++{ ++ substdio ss; ++ int fd; ++ int match; ++ ++ if (!stralloc_copys(sa,"")) return -1; ++ ++ fd = open_read(fn); ++ if (fd == -1) ++ { ++ if (errno == error_noent) return 0; ++ return -1; ++ } ++ ++ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf)); ++ ++ for (;;) ++ { ++ if (getln(&ss,&line,&match,'\n') == -1) break; ++ if (!match && !line.len) { close(fd); return 1; } ++ if (!stralloc_cat(sa,&line)) break; + if (!match) { close(fd); return 1; } + } + close(fd); +diff -upN qmail-1.03/control.h qmail-ldap/control.h +--- qmail-1.03/control.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/control.h Tue Oct 28 18:21:31 2003 +@@ -1,10 +1,14 @@ + #ifndef CONTROL_H + #define CONTROL_H + +-extern int control_init(); +-extern int control_readline(); +-extern int control_rldef(); +-extern int control_readint(); +-extern int control_readfile(); ++#include "stralloc.h" ++ ++extern int control_init(void); ++extern int control_readline(stralloc *, const char *); ++extern int control_rldef(stralloc *, const char *, int, const char *); ++extern int control_readint(int *, const char *); ++extern int control_readulong(unsigned long *, const char *); ++extern int control_readfile(stralloc *, const char *, int); ++extern int control_readrawfile(stralloc *, const char *); + + #endif +diff -upN qmail-1.03/date822fmt.c qmail-ldap/date822fmt.c +--- qmail-1.03/date822fmt.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/date822fmt.c Tue Oct 28 18:21:31 2003 +@@ -2,7 +2,7 @@ + #include "fmt.h" + #include "date822fmt.h" + +-static char *montab[12] = { ++static const char *montab[12] = { + "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" + }; + +diff -upN qmail-1.03/date822fmt.h qmail-ldap/date822fmt.h +--- qmail-1.03/date822fmt.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/date822fmt.h Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,9 @@ + #ifndef DATE822FMT_H + #define DATE822FMT_H + +-extern unsigned int date822fmt(); ++#include "datetime.h" ++ ++extern unsigned int date822fmt(char *, struct datetime *); + #define DATE822FMT 60 + + #endif +diff -upN qmail-1.03/datetime.h qmail-ldap/datetime.h +--- qmail-1.03/datetime.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/datetime.h Tue Oct 28 18:21:31 2003 +@@ -14,7 +14,7 @@ struct datetime { + + typedef long datetime_sec; + +-extern void datetime_tai(); +-extern datetime_sec datetime_untai(); ++extern void datetime_tai(struct datetime *, datetime_sec); ++extern datetime_sec datetime_untai(struct datetime *); + + #endif +diff -upN qmail-1.03/digest.c qmail-ldap/digest.c +--- qmail-1.03/digest.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest.c Thu Jul 1 16:28:30 2004 +@@ -0,0 +1,196 @@ ++/* ++ * Copyright (c) 1998-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "base64.h" ++#include "error.h" ++#include "passwd.h" ++#include "qldap-errno.h" ++#include "readwrite.h" ++#include "sgetopt.h" ++#include "stralloc.h" ++ ++ ++#define RANDDEV "/dev/urandom" ++ ++const char *mode[] = { ++ "{CRYPT}", ++ "{MD4}", ++ "{MD5}", ++ "{NS-MTA-MD5}", ++ "{SMD5}", ++ "{SHA}", ++ "{SSHA}", ++ "{RMD160}", ++ 0 }; ++ ++stralloc pw = {0}; ++stralloc salt = {0}; ++ ++void ++usage(void) ++{ ++ fprintf(stderr, ++ "usage:\tdigest [ -c ] [ -b | -5 | -C | -f cryptformat ] [ -s base64Salt ]\n\t[ -S hexSalt ] passwd\n" ++ "\tdigest -v password hashedPassword\n"); ++ exit(1); ++} ++ ++void ++getsalt(stralloc *b, int blen) ++{ ++ char buf[64]; ++ int l, fd; ++ ++ fd = open(RANDDEV, O_RDONLY); ++ if (fd == -1) { ++ fprintf(stderr, "digest: open %s failed: %s.\n", ++ RANDDEV, error_str(errno)); ++ exit(1); ++ } ++ l = read(fd, buf, sizeof(buf)); ++ if (l == -1) { ++ fprintf(stderr, "digest: read failed: %s.\n", ++ error_str(errno)); ++ exit(1); ++ } ++ if (l < blen) { ++ fprintf(stderr, "digest: not enough random data read.\n"); ++ exit(1); ++ } ++ if (!stralloc_copyb(b, buf, blen)) { ++ fprintf(stderr, "digest: stralloc_copyb failed: %s.\n", ++ error_str(errno)); ++ exit(1); ++ } ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ int i, opt, m; ++ char *clear, *encrypted; ++ const char *cformat; ++ ++ clear = (char *)0; ++ encrypted = (char *)0; ++ m = 0; ++ cformat = "XX"; ++ while ((opt = getopt(argc, argv, "5bcf:s:S:v")) != opteof) ++ switch (opt) { ++ case '5': ++ /* md5 format */ ++ cformat = "$1$XXXXXXXX$"; ++ break; ++ case 'b': ++ /* blowfish format */ ++ cformat = "$2a$07$XXXXXXXXXXXXXXXXXXXXXXXX"; ++ break; ++ case 'C': ++ /* good (acctually bad) old crypt */ ++ cformat = "XX"; ++ break; ++ case 'c': ++ m = 0; ++ break; ++ case 'f': ++ cformat = optarg; ++ break; ++ case 's': ++ if (b64_ptons(optarg, &salt) == -1) { ++ fprintf(stderr, "digest: bad base64 string.\n"); ++ usage(); ++ } ++ break; ++ case 'S': ++ if (hex_ptons(optarg, &salt) == -1) { ++ fprintf(stderr, "digest: bad hex string.\n"); ++ usage(); ++ } ++ break; ++ case 'v': ++ m = 1; ++ break; ++ default: ++ ++ usage(); ++ } ++ ++ argc -= optind; ++ argv += optind; ++ if (m == 0) { ++ if (argc != 1) usage(); ++ clear = argv[0]; ++ if (salt.s == 0) ++ getsalt(&salt, 16); ++ feed_salt(salt.s, salt.len); ++ feed_crypt(cformat); ++ for (i = 0; mode[i] != 0; i++) { ++ if (make_passwd(mode[i], clear, &pw) == OK) { ++ stralloc_0(&pw); ++ printf("%s%s\n", mode[i], pw.s); ++ } else ++ printf("%s failed.\n", mode[i]); ++ } ++ } else { ++ if (argc != 2) usage(); ++ clear = argv[0]; ++ encrypted = argv[1]; ++ switch(cmp_passwd(clear, encrypted)) { ++ case OK: ++ printf("passwords are equal.\n"); ++ break; ++ case BADPASS: ++ printf("passwords are NOT equal.\n"); ++ break; ++ case ERRNO: ++ printf("digest: cmp_passwd: %s.\n", error_str(errno)); ++ exit(1); ++ case ILLVAL: ++ printf("digest: cmp_password: " ++ "illegal hashed password.\n"); ++ exit(1); ++ default: ++ printf("digest: cmp_password: failed."); ++ exit(1); ++ } ++ } ++ ++ exit(0); ++} ++ +diff -upN qmail-1.03/digest_md4.c qmail-ldap/digest_md4.c +--- qmail-1.03/digest_md4.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_md4.c Tue Feb 17 15:31:30 2004 +@@ -0,0 +1,290 @@ ++/* digest_md4.c for QLDAP modified to use djb stuff */ ++/* contains MD4 algorithm stolen directly from OpenBSD */ ++ ++/* */ ++/* MD4 */ ++/* */ ++ ++/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. ++ ++ License to copy and use this software is granted provided that it ++ is identified as the "RSA Data Security, Inc. MD4 Message-Digest ++ Algorithm" in all material mentioning or referencing this software ++ or this function. ++ ++ License is also granted to make and use derivative works provided ++ that such works are identified as "derived from the RSA Data ++ Security, Inc. MD4 Message-Digest Algorithm" in all material ++ mentioning or referencing the derived work. ++ ++ RSA Data Security, Inc. makes no representations concerning either ++ the merchantability of this software or the suitability of this ++ software for any particular purpose. It is provided "as is" ++ without express or implied warranty of any kind. ++ ++ These notices must be retained in any copies of any part of this ++ documentation and/or software. ++ */ ++ ++#include ++#include "uint32.h" ++#include "byte.h" ++#include "digest_md4.h" ++ ++/* POINTER defines a generic pointer type */ ++typedef unsigned char *POINTER; ++ ++/* Constants for MD4Transform routine. ++ */ ++#define S11 3 ++#define S12 7 ++#define S13 11 ++#define S14 19 ++#define S21 3 ++#define S22 5 ++#define S23 9 ++#define S24 13 ++#define S31 3 ++#define S32 9 ++#define S33 11 ++#define S34 15 ++ ++static void MD4Transform(uint32 [4], const unsigned char [64]); ++ ++#ifdef __LITTLE_ENDIAN__ ++#define Encode byte_copy ++#define Decode byte_copy ++#else /* __BIG_ENDIAN__ */ ++static void Encode(void *, size_t, const void *); ++static void Decode(void *, size_t, const void *); ++#endif /* __LITTLE_ENDIAN__ */ ++ ++static unsigned char PADDING[64] = { ++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++}; ++ ++/* F, G and H are basic MD4 functions. ++ */ ++#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) ++#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) ++#define H(x, y, z) ((x) ^ (y) ^ (z)) ++ ++/* ROTATE_LEFT rotates x left n bits. ++ */ ++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ ++/* Rotation is separate from addition to prevent recomputation */ ++#define FF(a, b, c, d, x, s) { \ ++ (a) += F ((b), (c), (d)) + (x); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ } ++#define GG(a, b, c, d, x, s) { \ ++ (a) += G ((b), (c), (d)) + (x) + (uint32)0x5a827999; \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ } ++#define HH(a, b, c, d, x, s) { \ ++ (a) += H ((b), (c), (d)) + (x) + (uint32)0x6ed9eba1; \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ } ++ ++#ifdef __BIG_ENDIAN__ ++/* Encodes input (uint32) into output (unsigned char). Assumes len is ++ a multiple of 4. ++ */ ++static void ++Encode(void *out, size_t len, const void *in) ++{ ++ const uint32 *input = in; ++ unsigned char *output = out; ++ size_t i, j; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) { ++ output[j] = (unsigned char)(input[i] & 0xff); ++ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); ++ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); ++ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); ++ } ++} ++ ++/* Decodes input (unsigned char) into output (uint32). Assumes len is ++ a multiple of 4. ++ */ ++static void ++Decode(void *out, size_t len, const void *in) ++{ ++ uint32 *output = out; ++ const unsigned char *input = in; ++ size_t i, j; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) ++ output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) | ++ (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24); ++} ++#endif /* __BIG_ENDIAN__ */ ++ ++/* MD4 initialization. Begins an MD4 operation, writing a new context. ++ */ ++void ++MD4Init(MD4_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ ++ /* Load magic initialization constants. ++ */ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xefcdab89; ++ context->state[2] = 0x98badcfe; ++ context->state[3] = 0x10325476; ++} ++ ++/* MD4 block update operation. Continues an MD4 message-digest ++ operation, processing another message block, and updating the ++ context. ++ */ ++void ++MD4Update(MD4_CTX *context, const unsigned char *input, size_t inputLen) ++{ ++ unsigned int i, idx, partLen; ++ ++ /* Compute number of bytes mod 64 */ ++ idx = (unsigned int)((context->count[0] >> 3) & 0x3F); ++ ++ /* Update number of bits */ ++ if ( (context->count[0] += ((uint32)inputLen << 3)) /* lower part of count */ ++ < ((uint32)inputLen << 3) ) ++ context->count[1]++; /* low part of count overflowed */ ++ ++ context->count[1] += ((uint32)inputLen >> 29); /* update high part of count */ ++ ++ partLen = 64 - idx; ++ /* Transform as many times as possible. */ ++ if (inputLen >= partLen) { ++ byte_copy ++ ((POINTER)&context->buffer[idx], partLen, input); ++ MD4Transform(context->state, context->buffer); ++ ++ for (i = partLen; i + 63 < inputLen; i += 64) ++ MD4Transform(context->state, &input[i]); ++ ++ idx = 0; ++ } ++ else ++ i = 0; ++ ++ /* Buffer remaining input */ ++ byte_copy ++ ((POINTER)&context->buffer[idx], inputLen-i, &input[i]); ++} ++ ++/* MD4 finalization. Ends an MD4 message-digest operation, writing the ++ the message digest and zeroizing the context. ++ */ ++void ++MD4Final(unsigned char digest[MD4_LEN], MD4_CTX *context) ++{ ++ unsigned char bits[8]; ++ unsigned int idx, padLen; ++ uint32 hi, lo; ++ ++ /* Save number of bits */ ++ hi = context->count[1]; ++ lo = context->count[0]; ++ Encode (bits, 4, &lo); ++ Encode (bits + 4, 4, &hi); ++ ++ /* Pad out to 56 mod 64. ++ */ ++ idx = (unsigned int)((context->count[0] >> 3) & 0x3f); ++ padLen = (idx < 56) ? (56 - idx) : (120 - idx); ++ MD4Update (context, PADDING, padLen); ++ ++ /* Append length (before padding) */ ++ MD4Update (context, bits, 8); ++ ++ if (digest != (unsigned char *)0) { ++ /* Store state in digest */ ++ Encode (digest, 16, context->state); ++ ++ /* Zeroize sensitive information. ++ */ ++ byte_zero((POINTER) context, sizeof (*context)); ++ } ++} ++ ++/* MD4 basic transformation. Transforms state based on block. ++ */ ++static void ++MD4Transform(uint32 state[4], const unsigned char block[64]) ++{ ++ uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; ++ ++ Decode (x, 64, block); ++ ++ /* Round 1 */ ++ FF (a, b, c, d, x[ 0], S11); /* 1 */ ++ FF (d, a, b, c, x[ 1], S12); /* 2 */ ++ FF (c, d, a, b, x[ 2], S13); /* 3 */ ++ FF (b, c, d, a, x[ 3], S14); /* 4 */ ++ FF (a, b, c, d, x[ 4], S11); /* 5 */ ++ FF (d, a, b, c, x[ 5], S12); /* 6 */ ++ FF (c, d, a, b, x[ 6], S13); /* 7 */ ++ FF (b, c, d, a, x[ 7], S14); /* 8 */ ++ FF (a, b, c, d, x[ 8], S11); /* 9 */ ++ FF (d, a, b, c, x[ 9], S12); /* 10 */ ++ FF (c, d, a, b, x[10], S13); /* 11 */ ++ FF (b, c, d, a, x[11], S14); /* 12 */ ++ FF (a, b, c, d, x[12], S11); /* 13 */ ++ FF (d, a, b, c, x[13], S12); /* 14 */ ++ FF (c, d, a, b, x[14], S13); /* 15 */ ++ FF (b, c, d, a, x[15], S14); /* 16 */ ++ ++ /* Round 2 */ ++ GG (a, b, c, d, x[ 0], S21); /* 17 */ ++ GG (d, a, b, c, x[ 4], S22); /* 18 */ ++ GG (c, d, a, b, x[ 8], S23); /* 19 */ ++ GG (b, c, d, a, x[12], S24); /* 20 */ ++ GG (a, b, c, d, x[ 1], S21); /* 21 */ ++ GG (d, a, b, c, x[ 5], S22); /* 22 */ ++ GG (c, d, a, b, x[ 9], S23); /* 23 */ ++ GG (b, c, d, a, x[13], S24); /* 24 */ ++ GG (a, b, c, d, x[ 2], S21); /* 25 */ ++ GG (d, a, b, c, x[ 6], S22); /* 26 */ ++ GG (c, d, a, b, x[10], S23); /* 27 */ ++ GG (b, c, d, a, x[14], S24); /* 28 */ ++ GG (a, b, c, d, x[ 3], S21); /* 29 */ ++ GG (d, a, b, c, x[ 7], S22); /* 30 */ ++ GG (c, d, a, b, x[11], S23); /* 31 */ ++ GG (b, c, d, a, x[15], S24); /* 32 */ ++ ++ /* Round 3 */ ++ HH (a, b, c, d, x[ 0], S31); /* 33 */ ++ HH (d, a, b, c, x[ 8], S32); /* 34 */ ++ HH (c, d, a, b, x[ 4], S33); /* 35 */ ++ HH (b, c, d, a, x[12], S34); /* 36 */ ++ HH (a, b, c, d, x[ 2], S31); /* 37 */ ++ HH (d, a, b, c, x[10], S32); /* 38 */ ++ HH (c, d, a, b, x[ 6], S33); /* 39 */ ++ HH (b, c, d, a, x[14], S34); /* 40 */ ++ HH (a, b, c, d, x[ 1], S31); /* 41 */ ++ HH (d, a, b, c, x[ 9], S32); /* 42 */ ++ HH (c, d, a, b, x[ 5], S33); /* 43 */ ++ HH (b, c, d, a, x[13], S34); /* 44 */ ++ HH (a, b, c, d, x[ 3], S31); /* 45 */ ++ HH (d, a, b, c, x[11], S32); /* 46 */ ++ HH (c, d, a, b, x[ 7], S33); /* 47 */ ++ HH (b, c, d, a, x[15], S34); /* 48 */ ++ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ ++ /* Zeroize sensitive information. ++ */ ++ byte_zero((POINTER) x, sizeof (x)); ++} ++ +diff -upN qmail-1.03/digest_md4.h qmail-ldap/digest_md4.h +--- qmail-1.03/digest_md4.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_md4.h Thu Aug 21 11:36:41 2003 +@@ -0,0 +1,45 @@ ++/* digest_md4.h for QLDAP modified to use djb's stuff */ ++ ++/* */ ++/* MD4 */ ++/* */ ++ ++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All ++ rights reserved. ++ ++ License to copy and use this software is granted provided that it ++ is identified as the "RSA Data Security, Inc. MD4 Message-Digest ++ Algorithm" in all material mentioning or referencing this software ++ or this function. ++ License is also granted to make and use derivative works provided ++ that such works are identified as "derived from the RSA Data ++ Security, Inc. MD4 Message-Digest Algorithm" in all material ++ mentioning or referencing the derived work. ++ ++ RSA Data Security, Inc. makes no representations concerning either ++ the merchantability of this software or the suitability of this ++ software for any particular purpose. It is provided "as is" ++ without express or implied warranty of any kind. ++ ++ These notices must be retained in any copies of any part of this ++ documentation and/or software. */ ++ ++#ifndef _MD4_H_ ++#define _MD4_H_ ++ ++#include "uint32.h" ++ ++/* MD4 context. */ ++typedef struct MD4Context { ++ uint32 state[4]; /* state (ABCD) */ ++ uint32 count[2]; /* number of bits, modulo 2^64 */ ++ unsigned char buffer[64]; /* input buffer */ ++} MD4_CTX; ++ ++#define MD4_LEN 16 ++ ++void MD4Init(MD4_CTX *); ++void MD4Update(MD4_CTX *, const unsigned char *, size_t); ++void MD4Final(unsigned char [MD4_LEN], MD4_CTX *); ++ ++#endif /* _MD4_H_ */ +diff -upN qmail-1.03/digest_md5.c qmail-ldap/digest_md5.c +--- qmail-1.03/digest_md5.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_md5.c Tue Feb 17 15:31:30 2004 +@@ -0,0 +1,319 @@ ++/* digest_md5.c for QLDAP modified to use djb's stuff */ ++/* contains MD5 algorithm stolen directly from OpenBSD */ ++ ++/* */ ++/* MD5 */ ++/* */ ++ ++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All ++rights reserved. ++ ++License to copy and use this software is granted provided that it ++is identified as the "RSA Data Security, Inc. MD5 Message-Digest ++Algorithm" in all material mentioning or referencing this software ++or this function. ++ ++License is also granted to make and use derivative works provided ++that such works are identified as "derived from the RSA Data ++Security, Inc. MD5 Message-Digest Algorithm" in all material ++mentioning or referencing the derived work. ++ ++RSA Data Security, Inc. makes no representations concerning either ++the merchantability of this software or the suitability of this ++software for any particular purpose. It is provided "as is" ++without express or implied warranty of any kind. ++ ++These notices must be retained in any copies of any part of this ++documentation and/or software. ++ */ ++ ++#include ++#include "uint32.h" ++#include "byte.h" ++#include "digest_md5.h" ++ ++/* POINTER defines a generic pointer type */ ++typedef unsigned char *POINTER; ++ ++/* Constants for MD5Transform routine. ++ */ ++#define S11 7 ++#define S12 12 ++#define S13 17 ++#define S14 22 ++#define S21 5 ++#define S22 9 ++#define S23 14 ++#define S24 20 ++#define S31 4 ++#define S32 11 ++#define S33 16 ++#define S34 23 ++#define S41 6 ++#define S42 10 ++#define S43 15 ++#define S44 21 ++ ++static void MD5Transform (uint32 [4], const unsigned char [64]); ++ ++#ifdef __LITTLE_ENDIAN__ ++#define Encode byte_copy ++#define Decode byte_copy ++#else /* __BIG_ENDIAN__ */ ++static void Encode(void *, size_t, const void *); ++static void Decode(void *, size_t, const void *); ++#endif /* __LITTLE_ENDIAN__ */ ++ ++static unsigned char PADDING[64] = { ++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++}; ++ ++/* F, G, H and I are basic MD5 functions. ++ */ ++#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) ++#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) ++#define H(x, y, z) ((x) ^ (y) ^ (z)) ++#define I(x, y, z) ((y) ^ ((x) | (~z))) ++ ++/* ROTATE_LEFT rotates x left n bits. ++ */ ++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. ++Rotation is separate from addition to prevent recomputation. ++ */ ++#define FF(a, b, c, d, x, s, ac) { \ ++ (a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define GG(a, b, c, d, x, s, ac) { \ ++ (a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define HH(a, b, c, d, x, s, ac) { \ ++ (a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++#define II(a, b, c, d, x, s, ac) { \ ++ (a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \ ++ (a) = ROTATE_LEFT ((a), (s)); \ ++ (a) += (b); \ ++ } ++ ++#ifdef __BIG_ENDIAN__ ++/* Encodes input (uint32) into output (unsigned char). Assumes len is ++ a multiple of 4. ++ */ ++static void ++Encode(void *out, size_t len, const void *in) ++{ ++ unsigned char *output = out; ++ size_t i, j; ++ const uint32 *input = in; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) { ++ output[j] = (unsigned char)(input[i] & 0xff); ++ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); ++ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); ++ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); ++ } ++} ++ ++/* Decodes input (unsigned char) into output (uint32). Assumes len is ++ a multiple of 4. ++ */ ++static void ++Decode(void *out, size_t len, const void *in) ++{ ++ uint32 *output = out; ++ const unsigned char *input = in; ++ size_t i, j; ++ ++ for (i = 0, j = 0; j < len; i++, j += 4) ++ output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) | ++ (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24); ++} ++#endif /* __BIG_ENDIAN__ */ ++ ++/* MD5 initialization. Begins an MD5 operation, writing a new context. ++ */ ++void ++MD5Init(MD5_CTX *context) ++{ ++ context->count[0] = 0; ++ context->count[1] = 0; ++ ++ /* Load magic initialization constants. */ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xefcdab89; ++ context->state[2] = 0x98badcfe; ++ context->state[3] = 0x10325476; ++} ++ ++/* MD5 block update operation. Continues an MD5 message-digest ++ operation, processing another message block, and updating the ++ context. ++ */ ++void ++MD5Update(MD5_CTX *context, const unsigned char *input, size_t inputLen) ++{ ++ unsigned int i, idx, partLen; ++ ++ /* Compute number of bytes mod 64 */ ++ idx = (unsigned int)((context->count[0] >> 3) & 0x3F); ++ ++ /* Update number of bits */ ++ if ( (context->count[0] += ((uint32)inputLen << 3)) /* lower part of count */ ++ < ((uint32)inputLen << 3) ) ++ context->count[1]++; /* low part of count overflowed */ ++ ++ context->count[1] += ((uint32)inputLen >> 29); /* update high part of count */ ++ ++ partLen = 64 - idx; ++ ++ /* Transform as many times as possible. */ ++ if (inputLen >= partLen) { ++ byte_copy ((POINTER)&context->buffer[idx], partLen, input); ++ MD5Transform (context->state, context->buffer); ++ ++ for (i = partLen; i + 63 < inputLen; i += 64) ++ MD5Transform (context->state, &input[i]); ++ ++ idx = 0; ++ } ++ else ++ i = 0; ++ ++ /* Buffer remaining input */ ++ byte_copy ((POINTER)&context->buffer[idx], inputLen-i, &input[i]); ++} ++ ++/* MD5 finalization. Ends an MD5 message-digest operation, writing the ++ the message digest and zeroizing the context. ++ */ ++void ++MD5Final(unsigned char digest[MD5_LEN], MD5_CTX *context) ++{ ++ unsigned char bits[8]; ++ unsigned int idx; ++ size_t padLen; ++ uint32 hi, lo; ++ ++ /* Save number of bits */ ++ hi = context->count[1]; ++ lo = context->count[0]; ++ Encode (bits, 4, &lo); ++ Encode (bits + 4, 4, &hi); ++ ++ /* Pad out to 56 mod 64. */ ++ idx = (unsigned int)((context->count[0] >> 3) & 0x3f); ++ padLen = (idx < 56) ? (56 - idx) : (120 - idx); ++ MD5Update (context, PADDING, padLen); ++ ++ /* Append length (before padding) */ ++ MD5Update (context, bits, 8); ++ ++ if (digest != (unsigned char *)0) { ++ /* Store state in digest */ ++ Encode (digest, 16, context->state); ++ ++ /* Zeroize sensitive information. */ ++ byte_zero ((POINTER)context, sizeof (*context)); ++ } ++} ++ ++/* MD5 basic transformation. Transforms state based on block. ++ */ ++static void ++MD5Transform(uint32 state[4], const unsigned char block[64]) ++{ ++ uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; ++ ++ Decode (x, 64, block); ++ ++ /* Round 1 */ ++ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ ++ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ ++ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ ++ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ ++ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ ++ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ ++ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ ++ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ ++ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ ++ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ ++ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ ++ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ ++ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ ++ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ ++ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ ++ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ ++ ++ /* Round 2 */ ++ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ ++ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ ++ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ ++ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ ++ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ ++ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ ++ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ ++ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ ++ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ ++ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ ++ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ ++ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ ++ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ ++ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ ++ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ ++ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ ++ ++ /* Round 3 */ ++ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ ++ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ ++ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ ++ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ ++ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ ++ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ ++ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ ++ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ ++ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ ++ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ ++ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ ++ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ ++ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ ++ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ ++ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ ++ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ ++ ++ /* Round 4 */ ++ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ ++ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ ++ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ ++ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ ++ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ ++ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ ++ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ ++ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ ++ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ ++ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ ++ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ ++ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ ++ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ ++ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ ++ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ ++ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ ++ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ ++ /* Zeroize sensitive information. */ ++ byte_zero ((POINTER)x, sizeof (x)); ++} ++ +diff -upN qmail-1.03/digest_md5.h qmail-ldap/digest_md5.h +--- qmail-1.03/digest_md5.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_md5.h Thu Aug 21 11:36:41 2003 +@@ -0,0 +1,47 @@ ++/* digest_md5.h for QLDAP modified to use djb's stuff */ ++ ++/* */ ++/* MD5 */ ++/* */ ++ ++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All ++rights reserved. ++ ++License to copy and use this software is granted provided that it ++is identified as the "RSA Data Security, Inc. MD5 Message-Digest ++Algorithm" in all material mentioning or referencing this software ++or this function. ++ ++License is also granted to make and use derivative works provided ++that such works are identified as "derived from the RSA Data ++Security, Inc. MD5 Message-Digest Algorithm" in all material ++mentioning or referencing the derived work. ++ ++RSA Data Security, Inc. makes no representations concerning either ++the merchantability of this software or the suitability of this ++software for any particular purpose. It is provided "as is" ++without express or implied warranty of any kind. ++ ++These notices must be retained in any copies of any part of this ++documentation and/or software. ++ */ ++ ++#ifndef _MD5_H_ ++#define _MD5_H_ ++ ++#include "uint32.h" ++ ++/* MD5 context. */ ++typedef struct MD5Context { ++ uint32 state[4]; /* state (ABCD) */ ++ uint32 count[2]; /* number of bits, modulo 2^64 */ ++ unsigned char buffer[64]; /* input buffer */ ++} MD5_CTX; ++ ++#define MD5_LEN 16 ++ ++void MD5Init(MD5_CTX *); ++void MD5Update(MD5_CTX *, const unsigned char *, size_t); ++void MD5Final(unsigned char [MD5_LEN], MD5_CTX *); ++ ++#endif /* _MD5_H_ */ +diff -upN qmail-1.03/digest_rmd160.c qmail-ldap/digest_rmd160.c +--- qmail-1.03/digest_rmd160.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_rmd160.c Thu Sep 4 21:46:19 2003 +@@ -0,0 +1,412 @@ ++/* digest_rmd160.c for QLDAP checkpassword.c */ ++/* contains RMD160 algorithm stolen directly from OpenBSD */ ++ ++/* */ ++/* RMD160 */ ++/* */ ++ ++/********************************************************************\ ++ * ++ * FILE: rmd160.c ++ * ++ * CONTENTS: A sample C-implementation of the RIPEMD-160 ++ * hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * (Arranged for libc by Todd C. Miller) ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++\********************************************************************/ ++ ++/* header files */ ++#include ++#include "uint32.h" ++#include "byte.h" ++#include "digest_rmd160.h" ++ ++/* macro definitions */ ++ ++/* collect four bytes into one word: */ ++#define BYTES_TO_DWORD(strptr) \ ++ (((uint32) *((strptr)+3) << 24) | \ ++ ((uint32) *((strptr)+2) << 16) | \ ++ ((uint32) *((strptr)+1) << 8) | \ ++ ((uint32) *(strptr))) ++ ++/* ROL(x, n) cyclically rotates x over n bits to the left */ ++/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ ++#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* the three basic functions F(), G() and H() */ ++#define F(x, y, z) ((x) ^ (y) ^ (z)) ++#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) ++#define H(x, y, z) (((x) | ~(y)) ^ (z)) ++#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) ++#define J(x, y, z) ((x) ^ ((y) | ~(z))) ++ ++/* the eight basic operations FF() through III() */ ++#define FF(a, b, c, d, e, x, s) { \ ++ (a) += F((b), (c), (d)) + (x); \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define GG(a, b, c, d, e, x, s) { \ ++ (a) += G((b), (c), (d)) + (x) + 0x5a827999U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define HH(a, b, c, d, e, x, s) { \ ++ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define II(a, b, c, d, e, x, s) { \ ++ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define JJ(a, b, c, d, e, x, s) { \ ++ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define FFF(a, b, c, d, e, x, s) { \ ++ (a) += F((b), (c), (d)) + (x); \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define GGG(a, b, c, d, e, x, s) { \ ++ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define HHH(a, b, c, d, e, x, s) { \ ++ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define III(a, b, c, d, e, x, s) { \ ++ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++#define JJJ(a, b, c, d, e, x, s) { \ ++ (a) += J((b), (c), (d)) + (x) + 0x50a28be6U; \ ++ (a) = ROL((a), (s)) + (e); \ ++ (c) = ROL((c), 10); \ ++} ++ ++void ++RMD160Init(RMD160_CTX *context) ++{ ++ ++ /* ripemd-160 initialization constants */ ++ context->state[0] = 0x67452301U; ++ context->state[1] = 0xefcdab89U; ++ context->state[2] = 0x98badcfeU; ++ context->state[3] = 0x10325476U; ++ context->state[4] = 0xc3d2e1f0U; ++ context->length[0] = context->length[1] = 0; ++ context->buflen = 0; ++} ++ ++static void ++RMD160Transform(uint32 state[5], const uint32 block[16]) ++{ ++ uint32 aa = state[0], bb = state[1], cc = state[2], ++ dd = state[3], ee = state[4]; ++ uint32 aaa = state[0], bbb = state[1], ccc = state[2], ++ ddd = state[3], eee = state[4]; ++ ++ /* round 1 */ ++ FF(aa, bb, cc, dd, ee, block[ 0], 11); ++ FF(ee, aa, bb, cc, dd, block[ 1], 14); ++ FF(dd, ee, aa, bb, cc, block[ 2], 15); ++ FF(cc, dd, ee, aa, bb, block[ 3], 12); ++ FF(bb, cc, dd, ee, aa, block[ 4], 5); ++ FF(aa, bb, cc, dd, ee, block[ 5], 8); ++ FF(ee, aa, bb, cc, dd, block[ 6], 7); ++ FF(dd, ee, aa, bb, cc, block[ 7], 9); ++ FF(cc, dd, ee, aa, bb, block[ 8], 11); ++ FF(bb, cc, dd, ee, aa, block[ 9], 13); ++ FF(aa, bb, cc, dd, ee, block[10], 14); ++ FF(ee, aa, bb, cc, dd, block[11], 15); ++ FF(dd, ee, aa, bb, cc, block[12], 6); ++ FF(cc, dd, ee, aa, bb, block[13], 7); ++ FF(bb, cc, dd, ee, aa, block[14], 9); ++ FF(aa, bb, cc, dd, ee, block[15], 8); ++ ++ /* round 2 */ ++ GG(ee, aa, bb, cc, dd, block[ 7], 7); ++ GG(dd, ee, aa, bb, cc, block[ 4], 6); ++ GG(cc, dd, ee, aa, bb, block[13], 8); ++ GG(bb, cc, dd, ee, aa, block[ 1], 13); ++ GG(aa, bb, cc, dd, ee, block[10], 11); ++ GG(ee, aa, bb, cc, dd, block[ 6], 9); ++ GG(dd, ee, aa, bb, cc, block[15], 7); ++ GG(cc, dd, ee, aa, bb, block[ 3], 15); ++ GG(bb, cc, dd, ee, aa, block[12], 7); ++ GG(aa, bb, cc, dd, ee, block[ 0], 12); ++ GG(ee, aa, bb, cc, dd, block[ 9], 15); ++ GG(dd, ee, aa, bb, cc, block[ 5], 9); ++ GG(cc, dd, ee, aa, bb, block[ 2], 11); ++ GG(bb, cc, dd, ee, aa, block[14], 7); ++ GG(aa, bb, cc, dd, ee, block[11], 13); ++ GG(ee, aa, bb, cc, dd, block[ 8], 12); ++ ++ /* round 3 */ ++ HH(dd, ee, aa, bb, cc, block[ 3], 11); ++ HH(cc, dd, ee, aa, bb, block[10], 13); ++ HH(bb, cc, dd, ee, aa, block[14], 6); ++ HH(aa, bb, cc, dd, ee, block[ 4], 7); ++ HH(ee, aa, bb, cc, dd, block[ 9], 14); ++ HH(dd, ee, aa, bb, cc, block[15], 9); ++ HH(cc, dd, ee, aa, bb, block[ 8], 13); ++ HH(bb, cc, dd, ee, aa, block[ 1], 15); ++ HH(aa, bb, cc, dd, ee, block[ 2], 14); ++ HH(ee, aa, bb, cc, dd, block[ 7], 8); ++ HH(dd, ee, aa, bb, cc, block[ 0], 13); ++ HH(cc, dd, ee, aa, bb, block[ 6], 6); ++ HH(bb, cc, dd, ee, aa, block[13], 5); ++ HH(aa, bb, cc, dd, ee, block[11], 12); ++ HH(ee, aa, bb, cc, dd, block[ 5], 7); ++ HH(dd, ee, aa, bb, cc, block[12], 5); ++ ++ /* round 4 */ ++ II(cc, dd, ee, aa, bb, block[ 1], 11); ++ II(bb, cc, dd, ee, aa, block[ 9], 12); ++ II(aa, bb, cc, dd, ee, block[11], 14); ++ II(ee, aa, bb, cc, dd, block[10], 15); ++ II(dd, ee, aa, bb, cc, block[ 0], 14); ++ II(cc, dd, ee, aa, bb, block[ 8], 15); ++ II(bb, cc, dd, ee, aa, block[12], 9); ++ II(aa, bb, cc, dd, ee, block[ 4], 8); ++ II(ee, aa, bb, cc, dd, block[13], 9); ++ II(dd, ee, aa, bb, cc, block[ 3], 14); ++ II(cc, dd, ee, aa, bb, block[ 7], 5); ++ II(bb, cc, dd, ee, aa, block[15], 6); ++ II(aa, bb, cc, dd, ee, block[14], 8); ++ II(ee, aa, bb, cc, dd, block[ 5], 6); ++ II(dd, ee, aa, bb, cc, block[ 6], 5); ++ II(cc, dd, ee, aa, bb, block[ 2], 12); ++ ++ /* round 5 */ ++ JJ(bb, cc, dd, ee, aa, block[ 4], 9); ++ JJ(aa, bb, cc, dd, ee, block[ 0], 15); ++ JJ(ee, aa, bb, cc, dd, block[ 5], 5); ++ JJ(dd, ee, aa, bb, cc, block[ 9], 11); ++ JJ(cc, dd, ee, aa, bb, block[ 7], 6); ++ JJ(bb, cc, dd, ee, aa, block[12], 8); ++ JJ(aa, bb, cc, dd, ee, block[ 2], 13); ++ JJ(ee, aa, bb, cc, dd, block[10], 12); ++ JJ(dd, ee, aa, bb, cc, block[14], 5); ++ JJ(cc, dd, ee, aa, bb, block[ 1], 12); ++ JJ(bb, cc, dd, ee, aa, block[ 3], 13); ++ JJ(aa, bb, cc, dd, ee, block[ 8], 14); ++ JJ(ee, aa, bb, cc, dd, block[11], 11); ++ JJ(dd, ee, aa, bb, cc, block[ 6], 8); ++ JJ(cc, dd, ee, aa, bb, block[15], 5); ++ JJ(bb, cc, dd, ee, aa, block[13], 6); ++ ++ /* parallel round 1 */ ++ JJJ(aaa, bbb, ccc, ddd, eee, block[ 5], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, block[14], 9); ++ JJJ(ddd, eee, aaa, bbb, ccc, block[ 7], 9); ++ JJJ(ccc, ddd, eee, aaa, bbb, block[ 0], 11); ++ JJJ(bbb, ccc, ddd, eee, aaa, block[ 9], 13); ++ JJJ(aaa, bbb, ccc, ddd, eee, block[ 2], 15); ++ JJJ(eee, aaa, bbb, ccc, ddd, block[11], 15); ++ JJJ(ddd, eee, aaa, bbb, ccc, block[ 4], 5); ++ JJJ(ccc, ddd, eee, aaa, bbb, block[13], 7); ++ JJJ(bbb, ccc, ddd, eee, aaa, block[ 6], 7); ++ JJJ(aaa, bbb, ccc, ddd, eee, block[15], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, block[ 8], 11); ++ JJJ(ddd, eee, aaa, bbb, ccc, block[ 1], 14); ++ JJJ(ccc, ddd, eee, aaa, bbb, block[10], 14); ++ JJJ(bbb, ccc, ddd, eee, aaa, block[ 3], 12); ++ JJJ(aaa, bbb, ccc, ddd, eee, block[12], 6); ++ ++ /* parallel round 2 */ ++ III(eee, aaa, bbb, ccc, ddd, block[ 6], 9); ++ III(ddd, eee, aaa, bbb, ccc, block[11], 13); ++ III(ccc, ddd, eee, aaa, bbb, block[ 3], 15); ++ III(bbb, ccc, ddd, eee, aaa, block[ 7], 7); ++ III(aaa, bbb, ccc, ddd, eee, block[ 0], 12); ++ III(eee, aaa, bbb, ccc, ddd, block[13], 8); ++ III(ddd, eee, aaa, bbb, ccc, block[ 5], 9); ++ III(ccc, ddd, eee, aaa, bbb, block[10], 11); ++ III(bbb, ccc, ddd, eee, aaa, block[14], 7); ++ III(aaa, bbb, ccc, ddd, eee, block[15], 7); ++ III(eee, aaa, bbb, ccc, ddd, block[ 8], 12); ++ III(ddd, eee, aaa, bbb, ccc, block[12], 7); ++ III(ccc, ddd, eee, aaa, bbb, block[ 4], 6); ++ III(bbb, ccc, ddd, eee, aaa, block[ 9], 15); ++ III(aaa, bbb, ccc, ddd, eee, block[ 1], 13); ++ III(eee, aaa, bbb, ccc, ddd, block[ 2], 11); ++ ++ /* parallel round 3 */ ++ HHH(ddd, eee, aaa, bbb, ccc, block[15], 9); ++ HHH(ccc, ddd, eee, aaa, bbb, block[ 5], 7); ++ HHH(bbb, ccc, ddd, eee, aaa, block[ 1], 15); ++ HHH(aaa, bbb, ccc, ddd, eee, block[ 3], 11); ++ HHH(eee, aaa, bbb, ccc, ddd, block[ 7], 8); ++ HHH(ddd, eee, aaa, bbb, ccc, block[14], 6); ++ HHH(ccc, ddd, eee, aaa, bbb, block[ 6], 6); ++ HHH(bbb, ccc, ddd, eee, aaa, block[ 9], 14); ++ HHH(aaa, bbb, ccc, ddd, eee, block[11], 12); ++ HHH(eee, aaa, bbb, ccc, ddd, block[ 8], 13); ++ HHH(ddd, eee, aaa, bbb, ccc, block[12], 5); ++ HHH(ccc, ddd, eee, aaa, bbb, block[ 2], 14); ++ HHH(bbb, ccc, ddd, eee, aaa, block[10], 13); ++ HHH(aaa, bbb, ccc, ddd, eee, block[ 0], 13); ++ HHH(eee, aaa, bbb, ccc, ddd, block[ 4], 7); ++ HHH(ddd, eee, aaa, bbb, ccc, block[13], 5); ++ ++ /* parallel round 4 */ ++ GGG(ccc, ddd, eee, aaa, bbb, block[ 8], 15); ++ GGG(bbb, ccc, ddd, eee, aaa, block[ 6], 5); ++ GGG(aaa, bbb, ccc, ddd, eee, block[ 4], 8); ++ GGG(eee, aaa, bbb, ccc, ddd, block[ 1], 11); ++ GGG(ddd, eee, aaa, bbb, ccc, block[ 3], 14); ++ GGG(ccc, ddd, eee, aaa, bbb, block[11], 14); ++ GGG(bbb, ccc, ddd, eee, aaa, block[15], 6); ++ GGG(aaa, bbb, ccc, ddd, eee, block[ 0], 14); ++ GGG(eee, aaa, bbb, ccc, ddd, block[ 5], 6); ++ GGG(ddd, eee, aaa, bbb, ccc, block[12], 9); ++ GGG(ccc, ddd, eee, aaa, bbb, block[ 2], 12); ++ GGG(bbb, ccc, ddd, eee, aaa, block[13], 9); ++ GGG(aaa, bbb, ccc, ddd, eee, block[ 9], 12); ++ GGG(eee, aaa, bbb, ccc, ddd, block[ 7], 5); ++ GGG(ddd, eee, aaa, bbb, ccc, block[10], 15); ++ GGG(ccc, ddd, eee, aaa, bbb, block[14], 8); ++ ++ /* parallel round 5 */ ++ FFF(bbb, ccc, ddd, eee, aaa, block[12] , 8); ++ FFF(aaa, bbb, ccc, ddd, eee, block[15] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, block[10] , 12); ++ FFF(ddd, eee, aaa, bbb, ccc, block[ 4] , 9); ++ FFF(ccc, ddd, eee, aaa, bbb, block[ 1] , 12); ++ FFF(bbb, ccc, ddd, eee, aaa, block[ 5] , 5); ++ FFF(aaa, bbb, ccc, ddd, eee, block[ 8] , 14); ++ FFF(eee, aaa, bbb, ccc, ddd, block[ 7] , 6); ++ FFF(ddd, eee, aaa, bbb, ccc, block[ 6] , 8); ++ FFF(ccc, ddd, eee, aaa, bbb, block[ 2] , 13); ++ FFF(bbb, ccc, ddd, eee, aaa, block[13] , 6); ++ FFF(aaa, bbb, ccc, ddd, eee, block[14] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, block[ 0] , 15); ++ FFF(ddd, eee, aaa, bbb, ccc, block[ 3] , 13); ++ FFF(ccc, ddd, eee, aaa, bbb, block[ 9] , 11); ++ FFF(bbb, ccc, ddd, eee, aaa, block[11] , 11); ++ ++ /* combine results */ ++ ddd += cc + state[1]; /* final result for state[0] */ ++ state[1] = state[2] + dd + eee; ++ state[2] = state[3] + ee + aaa; ++ state[3] = state[4] + aa + bbb; ++ state[4] = state[0] + bb + ccc; ++ state[0] = ddd; ++} ++ ++void ++RMD160Update(RMD160_CTX *context, const unsigned char *data, size_t nbytes) ++{ ++ uint32 X[16]; ++ uint32 ofs = 0; ++ uint32 i; ++#ifdef __BIG_ENDIAN__ ++ uint32 j; ++#endif /* __BIG_ENDIAN__ */ ++ ++ /* update length[] */ ++ if (context->length[0] + nbytes < context->length[0]) ++ context->length[1]++; /* overflow to msb of length */ ++ context->length[0] += nbytes; ++ ++ byte_zero(X, sizeof(X)); ++ ++ if ( context->buflen + nbytes < 64 ) ++ { ++ byte_copy(context->bbuffer + context->buflen, nbytes, data); ++ context->buflen += nbytes; ++ } ++ else ++ { ++ /* process first block */ ++ ofs = 64 - context->buflen; ++ byte_copy(context->bbuffer + context->buflen, ofs, data); ++#ifdef __LITTLE_ENDIAN__ ++ byte_copy(X, sizeof(X), context->bbuffer); ++#else /* __BIG_ENDIAN__ */ ++ for (j=0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); ++#endif /* __LITTLE_ENDIAN__ */ ++ RMD160Transform(context->state, X); ++ nbytes -= ofs; ++ ++ /* process remaining complete blocks */ ++ for (i = 0; i < (nbytes >> 6); i++) { ++#ifdef __LITTLE_ENDIAN__ ++ byte_copy(X, sizeof(X), data + (64 * i) + ofs); ++#else /* __BIG_ENDIAN__ */ ++ for (j=0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(data + (64 * i) + (4 * j) + ofs); ++#endif /* __LITTLE_ENDIAN__ */ ++ RMD160Transform(context->state, X); ++ } ++ ++ /* ++ * Put last bytes from data into context's buffer ++ */ ++ context->buflen = nbytes & 63; ++ byte_copy(context->bbuffer, context->buflen, data + (64 * i) + ofs); ++ } ++} ++ ++void ++RMD160Final(unsigned char digest[RMD160_LEN], RMD160_CTX *context) ++{ ++ uint32 i; ++ uint32 X[16]; ++#ifdef __BIG_ENDIAN__ ++ uint32 j; ++#endif /* __BIG_ENDIAN__ */ ++ ++ /* append the bit m_n == 1 */ ++ context->bbuffer[context->buflen] = '\200'; ++ ++ byte_zero(context->bbuffer + context->buflen + 1, ++ 63 - context->buflen); ++#ifdef __LITTLE_ENDIAN__ ++ byte_copy(X, sizeof(X), context->bbuffer); ++#else /* __BIG_ENDIAN__ */ ++ for (j=0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); ++#endif /* __LITTLE_ENDIAN__ */ ++ if ((context->buflen) > 55) { ++ /* length goes to next block */ ++ RMD160Transform(context->state, X); ++ byte_zero(X, sizeof(X)); ++ } ++ ++ /* append length in bits */ ++ X[14] = context->length[0] << 3; ++ X[15] = (context->length[0] >> 29) | ++ (context->length[1] << 3); ++ RMD160Transform(context->state, X); ++ ++ if (digest != (unsigned char*)0) { ++ for (i = 0; i < 20; i += 4) { ++ /* extracts the 8 least significant bits. */ ++ digest[i] = context->state[i>>2]; ++ digest[i + 1] = (context->state[i>>2] >> 8); ++ digest[i + 2] = (context->state[i>>2] >> 16); ++ digest[i + 3] = (context->state[i>>2] >> 24); ++ } ++ } ++} ++ +diff -upN qmail-1.03/digest_rmd160.h qmail-ldap/digest_rmd160.h +--- qmail-1.03/digest_rmd160.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_rmd160.h Thu Aug 21 11:36:41 2003 +@@ -0,0 +1,49 @@ ++/* digest_rmd160.h for QLDAP modified to use djb's stuff */ ++ ++/* */ ++/* RMD160 */ ++/* */ ++ ++/********************************************************************\ ++ * ++ * FILE: rmd160.h ++ * ++ * CONTENTS: Header file for a sample C-implementation of the ++ * RIPEMD-160 hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++\********************************************************************/ ++ ++#ifndef _RMD160_H /* make sure this file is read only once */ ++#define _RMD160_H ++ ++/********************************************************************/ ++#include "uint32.h" ++ ++/* structure definitions */ ++ ++typedef struct { ++ uint32 state[5]; /* state (ABCDE) */ ++ uint32 length[2]; /* number of bits */ ++ unsigned char bbuffer[64]; /* overflow buffer */ ++ uint32 buflen; /* number of chars in bbuffer */ ++} RMD160_CTX; ++ ++/********************************************************************/ ++ ++#define RMD160_LEN 20 ++ ++/* function prototypes */ ++ ++void RMD160Init(RMD160_CTX *); ++void RMD160Update(RMD160_CTX *, const unsigned char *, size_t); ++void RMD160Final(unsigned char [RMD160_LEN], RMD160_CTX *); ++ ++#endif /* _RMD160_H */ +diff -upN qmail-1.03/digest_sha1.c qmail-ldap/digest_sha1.c +--- qmail-1.03/digest_sha1.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_sha1.c Thu Sep 4 21:46:19 2003 +@@ -0,0 +1,247 @@ ++/* digest_sha1.c for QLDAP modified to use djb stuff */ ++/* contains SHA1 algorithm stolen directly from OpenBSD */ ++/* $OpenBSD: sha1.c,v 1.11 2003/01/08 19:53:59 millert Exp $ */ ++ ++/* */ ++/* SHA1 */ ++/* */ ++ ++/* ++ * SHA-1 in C ++ * By Steve Reid ++ * 100% Public Domain ++ * ++ * Test Vectors (from FIPS PUB 180-1) ++ * "abc" ++ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D ++ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" ++ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 ++ * A million repetitions of "a" ++ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F ++ */ ++ ++#define SHA1HANDSOFF /* Copies data before messing with it. */ ++ ++#include ++#include "uint32.h" ++#include "byte.h" ++#include "digest_sha1.h" ++ ++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) ++ ++/* ++ * blk0() and blk() perform the initial expand. ++ * I got the idea of expanding during the round function from SSLeay ++ */ ++#ifdef __LITTLE_ENDIAN__ ++# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ ++ |(rol(block->l[i],8)&0x00FF00FF)) ++#else /* __BIG_ENDIAN__ */ ++# define blk0(i) block->l[i] ++#endif /* __LITTLE_ENDIAN__ */ ++ ++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ++ ^block->l[(i+2)&15]^block->l[i&15],1)) ++ ++/* ++ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 ++ */ ++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); ++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); ++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); ++ ++typedef union { ++ unsigned char c[64]; ++ uint32 l[16]; ++} CHAR64LONG16; ++ ++#ifdef __sparc_v9__ ++static void do_R01(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *); ++static void do_R2(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *); ++static void do_R3(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *); ++static void do_R4(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *); ++ ++#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) ++#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) ++#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) ++#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) ++#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) ++ ++static void ++do_R01(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block) ++{ ++ nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3); ++ nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); ++ nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); ++ nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15); ++ nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); ++} ++ ++static void ++do_R2(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block) ++{ ++ nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23); ++ nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); ++ nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); ++ nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35); ++ nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); ++} ++ ++static void ++do_R3(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block) ++{ ++ nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43); ++ nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); ++ nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); ++ nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55); ++ nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); ++} ++ ++static void ++do_R4(uint32 *a, uint32 *b, uint32 *c, uint32 *d, uint32 *e, CHAR64LONG16 *block) ++{ ++ nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63); ++ nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); ++ nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); ++ nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75); ++ nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); ++} ++#endif ++ ++/* ++ * Hash a single 512-bit block. This is the core of the algorithm. ++ */ ++static void ++SHA1Transform(uint32 state[5], const unsigned char buffer[64]) ++{ ++ uint32 a, b, c, d, e; ++ CHAR64LONG16 *block; ++ ++#ifdef SHA1HANDSOFF ++ static CHAR64LONG16 workspace; ++ block = &workspace; ++ byte_copy(block, 64, buffer); ++#else ++ block = (CHAR64LONG16 *)buffer; ++#endif ++ ++ /* Copy context->state[] to working vars */ ++ a = state[0]; ++ b = state[1]; ++ c = state[2]; ++ d = state[3]; ++ e = state[4]; ++ ++#ifdef __sparc_v9__ ++ do_R01(&a, &b, &c, &d, &e, block); ++ do_R2(&a, &b, &c, &d, &e, block); ++ do_R3(&a, &b, &c, &d, &e, block); ++ do_R4(&a, &b, &c, &d, &e, block); ++#else ++ /* 4 rounds of 20 operations each. Loop unrolled. */ ++ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); ++ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); ++ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); ++ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); ++ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); ++ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); ++ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); ++ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); ++ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); ++ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); ++ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); ++ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); ++ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); ++ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); ++ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); ++ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); ++ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); ++ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); ++ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); ++ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); ++#endif ++ ++ /* Add the working vars back into context.state[] */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ state[4] += e; ++ ++ /* Wipe variables */ ++ a = b = c = d = e = 0; ++} ++ ++/* ++ * SHA1Init - Initialize new context ++ */ ++void ++SHA1Init(SHA1_CTX *context) ++{ ++ ++ /* SHA1 initialization constants */ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++ context->state[4] = 0xC3D2E1F0; ++ context->count[0] = context->count[1] = 0; ++} ++ ++ ++/* ++ * Run your data through this. ++ */ ++void ++SHA1Update(SHA1_CTX *context, const unsigned char *data, size_t len) ++{ ++ unsigned int i, j; ++ ++ j = context->count[0]; ++ if ((context->count[0] += len << 3) < j) ++ context->count[1] += (len>>29)+1; ++ j = (j >> 3) & 63; ++ if ((j + len) > 63) { ++ byte_copy(&context->buffer[j], (i = 64-j), data); ++ SHA1Transform(context->state, context->buffer); ++ for ( ; i + 63 < len; i += 64) ++ SHA1Transform(context->state, &data[i]); ++ j = 0; ++ } else { ++ i = 0; ++ } ++ byte_copy(&context->buffer[j], len - i, &data[i]); ++} ++ ++ ++/* ++ * Add padding and return the message digest. ++ */ ++void ++SHA1Final(unsigned char digest[SHA1_LEN], SHA1_CTX *context) ++{ ++ unsigned int i; ++ unsigned char finalcount[8]; ++ ++ for (i = 0; i < 8; i++) { ++ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] ++ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ ++ } ++ SHA1Update(context, (const unsigned char *)"\200", 1); ++ while ((context->count[0] & 504) != 448) ++ SHA1Update(context, (const unsigned char *)"\0", 1); ++ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ ++ ++ if (digest) { ++ for (i = 0; i < 20; i++) ++ digest[i] = (unsigned char) ++ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); ++ /* Zeroize sensitive information. ++ */ ++ byte_zero(context, sizeof (*context)); ++ } ++ ++} ++ +diff -upN qmail-1.03/digest_sha1.h qmail-ldap/digest_sha1.h +--- qmail-1.03/digest_sha1.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/digest_sha1.h Thu Aug 21 11:36:41 2003 +@@ -0,0 +1,30 @@ ++/* digest_sha1.h for QLDAP modified to use djb stuff */ ++ ++/* */ ++/* SHA1 */ ++/* */ ++ ++/* ++ * SHA-1 in C ++ * By Steve Reid ++ * 100% Public Domain ++ */ ++ ++#ifndef _SHA1_H ++#define _SHA1_H ++ ++#include "uint32.h" ++ ++typedef struct { ++ uint32 state[5]; ++ uint32 count[2]; ++ unsigned char buffer[64]; ++} SHA1_CTX; ++ ++#define SHA1_LEN 20 ++ ++void SHA1Init(SHA1_CTX *); ++void SHA1Update(SHA1_CTX *, const unsigned char *, size_t); ++void SHA1Final(unsigned char [SHA1_LEN], SHA1_CTX *); ++ ++#endif /* _SHA1_H */ +diff -upN qmail-1.03/dirmaker qmail-ldap/dirmaker +--- qmail-1.03/dirmaker Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/dirmaker Wed May 5 17:42:11 2004 +@@ -0,0 +1,5 @@ ++#!/bin/sh ++# public domain ++# ++/bin/mkdir -m 700 -p $1 ++#EOF +diff -upN qmail-1.03/dirmaker.c qmail-ldap/dirmaker.c +--- qmail-1.03/dirmaker.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/dirmaker.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifdef AUTOHOMEDIRMAKE ++#include ++#include ++ ++#include "error.h" ++#include "control.h" ++#include "open.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qlx.h" ++#include "stralloc.h" ++#include "wait.h" ++ ++#include "dirmaker.h" ++ ++ ++static stralloc dirmaker = {0}; ++ ++int ++dirmaker_init(void) ++/* ~control/dirmaker SHOULD to be only writeable for root */ ++{ ++ if (control_rldef(&dirmaker, "control/dirmaker", 0, "") == -1) ++ return -1; ++ if (!stralloc_0(&dirmaker)) ++ return -1; ++ logit(64, "init: control/dirmaker: %s\n", dirmaker.s); ++ return 0; ++} ++ ++int ++dirmaker_make(const char *home, const char *maildir) ++{ ++ char *(dirargs[3]); ++ int child, wstat; ++ ++ if (dirmaker.s == 0 || dirmaker.len < 2) ++ return MAILDIR_UNCONF; ++ ++ switch(child = fork()) { ++ case -1: ++ if (error_temp(errno)) return MAILDIR_FAILED; ++ return MAILDIR_HARD; ++ case 0: ++ dirargs[0] = dirmaker.s; dirargs[1] = (char *)home; ++ dirargs[2] = (char *)maildir; dirargs[3] = 0; ++ execvp(*dirargs,dirargs); ++ if (error_temp(errno)) _exit(QLX_EXECSOFT); ++ _exit(QLX_EXECHARD); ++ } ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) { ++ return MAILDIR_CRASHED; ++ } ++ switch(wait_exitcode(wstat)) { ++ case 0: ++ return OK; ++ case 100: case QLX_EXECHARD: ++ return MAILDIR_HARD; ++ default: ++ return MAILDIR_FAILED; ++ } ++} ++#endif ++ +diff -upN qmail-1.03/dirmaker.h qmail-ldap/dirmaker.h +--- qmail-1.03/dirmaker.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/dirmaker.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __DIRMAKER_H__ ++#define __DIRMAKER_H__ ++ ++/* init handler */ ++int dirmaker_init(void); ++ ++/* executes the dirmaker returns OK on success */ ++int dirmaker_make(const char *, const char *); ++ ++#endif +diff -upN qmail-1.03/dns.c qmail-ldap/dns.c +--- qmail-1.03/dns.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dns.c Tue Oct 28 18:21:31 2003 +@@ -7,8 +7,8 @@ + #include + extern int res_query(); + extern int res_search(); +-extern int errno; + extern int h_errno; ++#include "errno.h" + #include "ip.h" + #include "ipalloc.h" + #include "fmt.h" +@@ -17,14 +17,20 @@ extern int h_errno; + #include "stralloc.h" + #include "dns.h" + #include "case.h" ++#ifdef IGNOREVERISIGN ++#include "byte.h" ++#define FUCKVERISIGN ++#endif + + 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 u_long saveresoptions; + + static int numanswers; + static char name[MAXDNAME]; +@@ -45,18 +51,35 @@ int type; + 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((char **)&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 +89,7 @@ int type; + if (i < QFIXEDSZ) return DNS_SOFT; + responsepos += QFIXEDSZ; + } +- numanswers = ntohs(response.hdr.ancount); ++ numanswers = ntohs(((HEADER *)response.buf)->ancount); + return 0; + } + +@@ -219,32 +242,32 @@ stralloc *sa; + + #define FMT_IAA 40 + +-static int iaafmt(s,ip) ++static int iaafmt(s,tip) + char *s; +-struct ip_address *ip; ++struct ip_address *tip; + { + unsigned int i; + unsigned int len; + len = 0; +- i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; ++ i = fmt_ulong(s,(unsigned long) tip->d[3]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; +- i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; ++ i = fmt_ulong(s,(unsigned long) tip->d[2]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; +- i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; ++ i = fmt_ulong(s,(unsigned long) tip->d[1]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; +- i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; ++ i = fmt_ulong(s,(unsigned long) tip->d[0]); len += i; if (s) s += i; + i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i; + return len; + } + +-int dns_ptr(sa,ip) ++int dns_ptr(sa,tip) + stralloc *sa; +-struct ip_address *ip; ++struct ip_address *tip; + { + int r; + +- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM; +- sa->len = iaafmt(sa->s,ip); ++ if (!stralloc_ready(sa,iaafmt((char *) 0,tip))) return DNS_MEM; ++ sa->len = iaafmt(sa->s,tip); + switch(resolve(sa,T_PTR)) + { + case DNS_MEM: return DNS_MEM; +@@ -263,13 +286,22 @@ struct ip_address *ip; + return DNS_HARD; + } + +-static int dns_ipplus(ia,sa,pref) ++#ifdef FUCKVERISIGN ++static stralloc tld = {0}; ++static ipalloc tldia = {0}; ++#endif ++ ++static int dns_ipplus(ia,sa,spref) + ipalloc *ia; + stralloc *sa; +-int pref; ++int spref; + { + int r; + struct ip_mx ix; ++#ifdef FUCKVERISIGN ++ int j; ++ struct ip_mx tldix; ++#endif + + if (!stralloc_copy(&glue,sa)) return DNS_MEM; + if (!stralloc_0(&glue)) return DNS_MEM; +@@ -280,8 +312,35 @@ int pref; + if (!ipalloc_append(ia,&ix)) return DNS_MEM; + return 0; + } ++ + } + ++#ifdef FUCKVERISIGN ++ j = byte_rchr(sa->s,sa->len,'.'); ++ if (j+2 < sa->len) { ++ if(!stralloc_copys(&tld, "*")) return DNS_MEM; ++ if(!stralloc_catb(&tld, sa->s+j, sa->len-j)) return DNS_MEM; ++ switch(resolve(&tld,T_A)) ++ { ++ case DNS_HARD: tldia.len = 0; break; ++ case DNS_MEM: return DNS_MEM; ++ case DNS_SOFT: return DNS_SOFT; ++ default: ++ if (!ipalloc_readyplus(&tldia,0)) return DNS_MEM; ++ tldia.len = 0; ++ tldix.pref = 0; ++ while ((r = findip(T_A)) != 2) ++ { ++ if (r == DNS_SOFT) return DNS_SOFT; ++ if (r == 1) { ++ tldix.ip = ip; ++ if (!ipalloc_append(&tldia,&tldix)) return DNS_MEM; ++ } ++ } ++ } ++ } ++#endif ++ + switch(resolve(sa,T_A)) + { + case DNS_MEM: return DNS_MEM; +@@ -291,10 +350,17 @@ int pref; + while ((r = findip(T_A)) != 2) + { + ix.ip = ip; +- ix.pref = pref; ++ ix.pref = spref; + if (r == DNS_SOFT) return DNS_SOFT; +- if (r == 1) ++ if (r == 1) { ++#ifdef FUCKVERISIGN ++ for (j = 0; j < tldia.len; j++) ++ if (byte_diff(&tldia.ix[j].ip, sizeof(struct ip_address), &ip) == 0) ++ break; ++ if (j < tldia.len) continue; ++#endif + if (!ipalloc_append(ia,&ix)) return DNS_MEM; ++ } + } + return 0; + } +diff -upN qmail-1.03/dns.h qmail-ldap/dns.h +--- qmail-1.03/dns.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dns.h Tue Oct 28 18:21:31 2003 +@@ -1,14 +1,18 @@ + #ifndef DNS_H + #define DNS_H + ++#include "ip.h" ++#include "ipalloc.h" ++#include "stralloc.h" ++ + #define DNS_SOFT -1 + #define DNS_HARD -2 + #define DNS_MEM -3 + +-void dns_init(); +-int dns_cname(); +-int dns_mxip(); +-int dns_ip(); +-int dns_ptr(); ++void dns_init(int); ++int dns_cname(stralloc *); ++int dns_mxip(ipalloc *, stralloc *, unsigned long); ++int dns_ip(ipalloc *, stralloc *); ++int dns_ptr(stralloc *, struct ip_address *); + + #endif +diff -upN qmail-1.03/dnscname.c qmail-ldap/dnscname.c +--- qmail-1.03/dnscname.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnscname.c Thu Jan 29 16:48:14 2004 +@@ -8,7 +8,7 @@ + + stralloc sa = {0}; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -21,5 +21,5 @@ char **argv; + dnsdoe(dns_cname(&sa)); + substdio_putflush(subfdout,sa.s,sa.len); + substdio_putsflush(subfdout,"\n"); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/dnsdoe.h qmail-ldap/dnsdoe.h +--- qmail-1.03/dnsdoe.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnsdoe.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,6 @@ + #ifndef DNSDOE_H + #define DNSDOE_H + +-extern void dnsdoe(); ++extern void dnsdoe(int); + + #endif +diff -upN qmail-1.03/dnsfq.c qmail-ldap/dnsfq.c +--- qmail-1.03/dnsfq.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnsfq.c Thu Jan 29 16:48:14 2004 +@@ -10,7 +10,7 @@ + stralloc sa = {0}; + ipalloc ia = {0}; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -28,5 +28,5 @@ char **argv; + dnsdoe(dns_ptr(&sa,&ia.ix[0].ip)); + substdio_putflush(subfdout,sa.s,sa.len); + substdio_putsflush(subfdout,"\n"); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/dnsip.c qmail-ldap/dnsip.c +--- qmail-1.03/dnsip.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnsip.c Thu Jan 29 16:48:14 2004 +@@ -12,7 +12,7 @@ char temp[IPFMT]; + stralloc sa = {0}; + ipalloc ia = {0}; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -30,5 +30,5 @@ char **argv; + substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip)); + substdio_putsflush(subfdout,"\n"); + } +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/dnsmxip.c qmail-ldap/dnsmxip.c +--- qmail-1.03/dnsmxip.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnsmxip.c Mon Feb 2 15:02:25 2004 +@@ -1,3 +1,5 @@ ++#include ++#include + #include "substdio.h" + #include "subfd.h" + #include "stralloc.h" +@@ -14,7 +16,7 @@ char temp[IPFMT + FMT_ULONG]; + stralloc sa = {0}; + ipalloc ia = {0}; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -33,8 +35,8 @@ char **argv; + { + substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip)); + substdio_puts(subfdout," "); +- substdio_put(subfdout,temp,fmt_ulong(temp,(unsigned long) ia.ix[j].pref)); ++ substdio_put(subfdout,temp,fmt_uint(temp,ia.ix[j].pref)); + substdio_putsflush(subfdout,"\n"); + } +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/dnsptr.c qmail-ldap/dnsptr.c +--- qmail-1.03/dnsptr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/dnsptr.c Thu Jan 29 16:48:14 2004 +@@ -11,7 +11,7 @@ + stralloc sa = {0}; + struct ip_address ip; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -23,5 +23,5 @@ char **argv; + dnsdoe(dns_ptr(&sa,&ip)); + substdio_putflush(subfdout,sa.s,sa.len); + substdio_putsflush(subfdout,"\n"); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/endian.c qmail-ldap/endian.c +--- qmail-1.03/endian.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/endian.c Thu Jan 29 16:48:14 2004 +@@ -0,0 +1,34 @@ ++/* endian.c ++ * ---------------------------------------------------------------------------- ++ * "THE BEER-WARE LICENSE" (Revision 42): ++ * wrote this file. As long as you retain this notice you ++ * can do whatever you want with this stuff. If we meet some day, and you think ++ * this stuff is worth it, you can buy me a beer in return. Claudio Jeker ++ * ---------------------------------------------------------------------------- ++ * ++ * This is a lowest-common-denominator (endian) program which should compile ++ * under the default cc on any system, no matter how primitite ... ++ * (even the SunOS one ;-) ) ++ */ ++ ++#include ++ ++ ++union endian_t { ++ unsigned char c[8]; ++ long l; ++} endian; ++ ++int main() ++{ ++ ++ endian.c[0]=0x80; endian.c[1]=0; endian.c[2]=0; endian.c[3]=0; ++ endian.c[4]=0; endian.c[5]=0; endian.c[6]=0; endian.c[7]=0; ++ ++ if( endian.l < 0 ) ++ printf( "-D__BIG_ENDIAN__" ); ++ else ++ printf( "-D__LITTLE_ENDIAN__" ); ++ ++ return(0); ++} +diff -upN qmail-1.03/env.c qmail-ldap/env.c +--- qmail-1.03/env.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/env.c Tue Feb 17 15:31:30 2004 +@@ -11,8 +11,8 @@ No known patent problems. + #include "env.h" + + int env_isinit = 0; /* if env_isinit: */ +-static int ea; /* environ is a pointer to ea+1 char*'s. */ +-static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ ++static unsigned int ea; /* environ is a pointer to ea+1 char*'s. */ ++static unsigned int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ + + static void env_goodbye(i) int i; + { +@@ -23,22 +23,26 @@ static void env_goodbye(i) int i; + + static char *null = 0; + +-void env_clear() ++void env_clear(void) + { + if (env_isinit) while (en) env_goodbye(0); + else environ = &null; + } + +-static void env_unsetlen(s,len) char *s; int len; ++static void env_unsetlen(s,len) const char *s; unsigned int len; + { +- int i; +- for (i = en - 1;i >= 0;--i) ++ unsigned int i; ++ ++ i = en; ++ do { ++ --i; + if (!str_diffn(s,environ[i],len)) + if (environ[i][len] == '=') + env_goodbye(i); ++ } while (i > 0); + } + +-int env_unset(s) char *s; ++int env_unset(s) const char *s; + { + if (!env_isinit) if (!env_init()) return 0; + env_unsetlen(s,str_len(s)); +@@ -47,13 +51,13 @@ int env_unset(s) char *s; + + static int env_add(s) char *s; + { +- char *t; ++ const char *t; + t = env_findeq(s); + if (t) env_unsetlen(s,t - s); + if (en == ea) + { + ea += 30; +- if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) ++ if (!alloc_re((char **)&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) + { ea = en; return 0; } + } + environ[en++] = s; +@@ -61,7 +65,7 @@ static int env_add(s) char *s; + return 1; + } + +-int env_put(s) char *s; ++int env_put(s) const char *s; + { + char *u; + if (!env_isinit) if (!env_init()) return 0; +@@ -72,10 +76,10 @@ int env_put(s) char *s; + return 1; + } + +-int env_put2(s,t) char *s; char *t; ++int env_put2(s,t) const char *s; const char *t; + { + char *u; +- int slen; ++ unsigned int slen; + if (!env_isinit) if (!env_init()) return 0; + slen = str_len(s); + u = alloc(slen + str_len(t) + 2); +@@ -87,10 +91,10 @@ int env_put2(s,t) char *s; char *t; + return 1; + } + +-int env_init() ++int env_init(void) + { + char **newenviron; +- int i; ++ unsigned int i; + for (en = 0;environ[en];++en) ; + ea = en + 10; + newenviron = (char **) alloc((ea + 1) * sizeof(char *)); +diff -upN qmail-1.03/env.h qmail-ldap/env.h +--- qmail-1.03/env.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/env.h Tue Oct 28 18:21:31 2003 +@@ -3,14 +3,14 @@ + + extern int env_isinit; + +-extern int env_init(); +-extern int env_put(); +-extern int env_put2(); +-extern int env_unset(); +-extern /*@null@*/char *env_get(); +-extern char *env_pick(); +-extern void env_clear(); +-extern char *env_findeq(); ++extern int env_init(void); ++extern int env_put(const char *); ++extern int env_put2(const char *, const char *); ++extern int env_unset(const char *); ++extern /*@null@*/char *env_get(const char *); ++extern char *env_pick(void); ++extern void env_clear(void); ++extern const char *env_findeq(const char *); + + extern char **environ; + +diff -upN qmail-1.03/envread.c qmail-ldap/envread.c +--- qmail-1.03/envread.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/envread.c Thu Jan 29 16:48:14 2004 +@@ -2,26 +2,26 @@ + #include "str.h" + + extern /*@null@*/char *env_get(s) +-char *s; ++const char *s; + { +- int i; ++ unsigned int i; + unsigned int slen; + char *envi; + + slen = str_len(s); +- for (i = 0;envi = environ[i];++i) ++ for (i = 0;(envi = environ[i]);++i) + if ((!str_diffn(s,envi,slen)) && (envi[slen] == '=')) + return envi + slen + 1; + return 0; + } + +-extern char *env_pick() ++extern char *env_pick(void) + { + return environ[0]; + } + +-extern char *env_findeq(s) +-char *s; ++extern const char *env_findeq(s) ++const char *s; + { + for (;*s;++s) + if (*s == '=') +diff -upN qmail-1.03/error.3 qmail-ldap/error.3 +--- qmail-1.03/error.3 Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/error.3 Tue Oct 28 18:21:31 2003 +@@ -4,8 +4,6 @@ error \- syscall error codes + .SH SYNTAX + .B #include + +-extern int \fBerrno\fP; +- + extern int \fBerror_intr\fP; + .br + extern int \fBerror_nomem\fP; +diff -upN qmail-1.03/error.c qmail-ldap/error.c +--- qmail-1.03/error.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/error.c Wed May 5 17:42:11 2004 +@@ -1,4 +1,3 @@ +-#include + #include "error.h" + + /* warning: as coverage improves here, should update error_{str,temp} */ +@@ -93,3 +92,18 @@ EACCES; + #else + -13; + #endif ++ ++int error_range = ++#ifdef ERANGE ++ERANGE; ++#else ++-14; ++#endif ++ ++int error_proto = ++#ifdef EPROTO ++EPROTO; ++#else ++-15; ++#endif ++ +diff -upN qmail-1.03/error.h qmail-ldap/error.h +--- qmail-1.03/error.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/error.h Wed May 5 17:42:11 2004 +@@ -1,7 +1,7 @@ + #ifndef ERROR_H + #define ERROR_H + +-extern int errno; ++#include + + extern int error_intr; + extern int error_nomem; +@@ -16,8 +16,10 @@ extern int error_again; + extern int error_pipe; + extern int error_perm; + extern int error_acces; ++extern int error_range; ++extern int error_proto; + +-extern char *error_str(); +-extern int error_temp(); ++extern const char *error_str(int); ++extern int error_temp(int); + + #endif +diff -upN qmail-1.03/error_str.c qmail-ldap/error_str.c +--- qmail-1.03/error_str.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/error_str.c Wed May 5 17:42:11 2004 +@@ -3,7 +3,7 @@ + + #define X(e,s) if (i == e) return s; + +-char *error_str(i) ++const char *error_str(i) + int i; + { + X(0,"no error") +@@ -20,6 +20,8 @@ int i; + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") ++ X(error_range,"numerical result out of range") ++ X(error_proto,"protocol error") + #ifdef ESRCH + X(ESRCH,"no such process") + #endif +@@ -92,9 +94,6 @@ int i; + #ifdef EDOM + X(EDOM,"input out of range") + #endif +-#ifdef ERANGE +- X(ERANGE,"output out of range") +-#endif + #ifdef EALREADY + X(EALREADY,"operation already in progress") + #endif +@@ -262,9 +261,6 @@ int i; + #endif + #ifdef ECOMM + X(ECOMM,"communication error") +-#endif +-#ifdef EPROTO +- X(EPROTO,"protocol error") + #endif + #ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +diff -upN qmail-1.03/except.c qmail-ldap/except.c +--- qmail-1.03/except.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/except.c Tue Oct 28 18:21:31 2003 +@@ -1,3 +1,4 @@ ++#include + #include "fork.h" + #include "strerr.h" + #include "wait.h" +@@ -6,7 +7,7 @@ + + #define FATAL "except: fatal: " + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -32,6 +33,7 @@ char **argv; + switch(wait_exitcode(wstat)) { + case 0: _exit(100); + case 111: strerr_die2x(111,FATAL,"temporary child error"); +- default: _exit(0); ++ default: break; + } ++ return 0; + } +diff -upN qmail-1.03/execcheck.c qmail-ldap/execcheck.c +--- qmail-1.03/execcheck.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/execcheck.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++/* ++ * Code and idea is based on a patch by Russel Nelson. ++ */ ++ ++#ifdef SMTPEXECCHECK ++#include "byte.h" ++#include "case.h" ++#include "control.h" ++#include "env.h" ++#include "qmail.h" ++#include "str.h" ++#include "stralloc.h" ++ ++#include "execcheck.h" ++ ++extern void die_nomem(); /* needed error function from qmail-smtpd,c */ ++extern void die_control(); ++ ++static int checkexecutable = 0; ++static int flagexecutable; ++static stralloc signatures = {0}; ++ ++void ++execcheck_setup(void) ++{ ++ if (env_get("REJECTEXEC")) checkexecutable = 1; ++ switch (control_readfile(&signatures,"control/signatures",0)) { ++ case 0: ++ checkexecutable = 0; ++ break; ++ case 1: ++ break; ++ default: ++ die_control(); ++ } ++} ++ ++int ++execcheck_on(void) ++{ ++ return checkexecutable; ++} ++ ++int ++execcheck_flag(void) ++{ ++ return flagexecutable; ++} ++ ++static int ++signatures_match(stralloc *line, char *sig) ++{ ++ unsigned int k; ++ ++ for (k = 0; k < line->len && *sig; k++, sig++) ++ if (*sig != '*') ++ if (*sig != line->s[k]) return 0; ++ if (*sig) return 0; ++ return 1; ++} ++ ++static int ++signatures_check(stralloc *line) ++{ ++ unsigned int i, j; ++ ++ for (i = j = 0; i < signatures.len; i++) ++ if (!signatures.s[i]) { ++ if (signatures_match(line, signatures.s + j)) ++ return 1; ++ j = i+1; ++ } ++ return 0; ++} ++ ++static int linespastheader; /* = 0 if in header (mime or mail) ++ * = 1 line after blank line ++ * = 2 somewhere in body ++ */ ++static unsigned int boundary_start; ++static unsigned int boundary_len; ++static int flagrfc822; ++static char linetype; ++ ++static stralloc line = {0}; ++static stralloc content = {0}; ++static stralloc boundary = {0}; ++static stralloc token = {0}; ++ ++static void ++parse_token(void) ++{ ++ if (token.len == 0 || *token.s == '\0') ++ return; ++ ++ if (case_startb(token.s, token.len, "boundary=")) { ++ /* ++ * push the current boundary. ++ * Append a null and remember start. ++ */ ++ boundary_start = boundary.len; ++ if (!stralloc_cats(&boundary, "--")) ++ die_nomem(); ++ if (!stralloc_cats(&boundary, token.s + 9)) ++ die_nomem(); ++ boundary_len = boundary.len - boundary_start; ++ if (!stralloc_0(&boundary)) ++ die_nomem(); ++ return; ++ } ++ if (!case_diffb(token.s, token.len, "message/rfc822")) { ++ flagrfc822 = 1; ++ return; ++ } ++} ++ ++static void ++parse_contenttype(void) ++{ ++ char *c; ++ int flagquoted = 0; ++ int flagcomment = 0; ++ ++ if (content.len == 0) /* NO MIME header */ ++ return; ++ ++ if (!stralloc_0(&content)) die_nomem(); ++ ++ for (c = content.s; *c != '\0'; ) { ++ for (; *c != '\0'; c++) ++ if (*c != ' ' && *c != '\t' && *c != ';') ++ break; ++ ++ if (!stralloc_copys(&token, "")) die_nomem(); ++ for (; *c != '\0'; c++) ++ switch (*c) { ++ case ' ': ++ case '\t': ++ case ';': ++ if (flagquoted) ++ break; ++ goto token_done; ++ case '"': ++ if (flagquoted) ++ flagquoted = 0; ++ else ++ flagquoted = 1; ++ break; ++ case '(': ++ if (flagquoted) { ++ if (!stralloc_append(&token, c)) ++ die_nomem(); ++ break; ++ } ++ flagcomment = 1; ++ break; ++ case ')': ++ if (flagquoted) { ++ if (!stralloc_append(&token, c)) ++ die_nomem(); ++ break; ++ } ++ flagcomment = 0; ++ break; ++ default: ++ if (flagcomment) ++ break; ++ if (!stralloc_append(&token, c)) die_nomem(); ++ break; ++ } ++token_done: ++ if (!stralloc_0(&token)) die_nomem(); ++ parse_token(); ++ } ++} ++ ++void ++execcheck_start(void) ++{ ++ boundary.len = 0; ++ content.len = 0; ++ linespastheader = 0; ++ boundary_start = 0; ++ boundary_len = 0; ++ flagexecutable = 0; ++ flagrfc822 = 0; ++ linetype = ' '; ++} ++ ++void ++execcheck_put(struct qmail *qq, const char *ch) ++{ ++ if (!checkexecutable) ++ return; ++ ++ /* already bad so leave it */ ++ if (flagexecutable) ++ return; ++ ++ if (line.len < 1024) ++ if (!stralloc_catb(&line,ch,1)) die_nomem(); ++ ++ if (*ch != '\n') ++ /* wait until we have a entire line together */ ++ return; ++ ++ if (linespastheader == 0) { ++ /* ++ * in mail or mime header, search for content-type ++ * and possible boundary ++ */ ++ if (line.len == 1) { /* end of header */ ++ linespastheader = 1; ++ if (content.len) /* MIME header */ ++ parse_contenttype(); ++ if (flagrfc822) { ++ /* now the forwarded rfc822 header is comming */ ++ linespastheader = 0; ++ flagrfc822 = 0; ++ } ++ } else { /* header lines */ ++ if (*line.s == ' ' || *line.s == '\t') { ++ switch(linetype) { ++ case 'C': ++ if (!stralloc_catb(&content, ++ line.s, line.len-1)) ++ die_nomem(); ++ break; ++ default: ++ break; ++ } ++ } else { ++ if (case_startb(line.s, line.len, ++ "content-type:")) { ++ if (!stralloc_copyb(&content, ++ line.s+13, line.len-14)) ++ die_nomem(); ++ linetype = 'C'; ++ } else { ++ linetype = ' '; ++ } ++ } ++ } ++ } else { /* non-header lines */ ++ if (boundary_len && *line.s == '-' && ++ stralloc_starts(&line,boundary.s + boundary_start)) { ++ /* mime boundary matched */ ++ if (line.len > boundary_len + 2 && ++ !str_diffn(line.s + boundary_len, "--", 2)) { ++ /* end marker - pop last boundary */ ++ linespastheader = 2; ++ if (boundary_start) { ++ boundary.len = boundary_start; ++ boundary_start = byte_rchr(boundary.s, ++ boundary.len - 1, '\0'); ++ if (boundary_start + 1 >= boundary.len) ++ boundary_start = 0; ++ boundary_len = boundary.len - 1 - ++ boundary_start; ++ } else ++ boundary_len = 0; ++ } else ++ linespastheader = 0; ++ } else if (linespastheader == 1) { ++ if (signatures_check(&line)) { ++ flagexecutable = 1; ++ qmail_fail(qq); ++ } ++ linespastheader = 2; ++ } ++ } ++ line.len = 0; ++} ++ ++#endif ++ +diff -upN qmail-1.03/execcheck.h qmail-ldap/execcheck.h +--- qmail-1.03/execcheck.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/execcheck.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __EXECCHECK_H__ ++#define __EXECCHECK_H__ ++ ++struct qmail; ++ ++void execcheck_setup(void); ++void execcheck_start(void); ++int execcheck_on(void); ++int execcheck_flag(void); ++void execcheck_put(struct qmail *, const char *); ++ ++#endif +diff -upN qmail-1.03/exit.h qmail-ldap/exit.h +--- qmail-1.03/exit.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/exit.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,7 @@ + #ifndef EXIT_H + #define EXIT_H + +-extern void _exit(); ++/* XXX unistd.h */ ++extern void _exit(int); + + #endif +diff -upN qmail-1.03/fd.h qmail-ldap/fd.h +--- qmail-1.03/fd.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fd.h Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,7 @@ + #ifndef FD_H + #define FD_H + +-extern int fd_copy(); +-extern int fd_move(); ++extern int fd_copy(int, int); ++extern int fd_move(int, int); + + #endif +diff -upN qmail-1.03/fd_copy.c qmail-ldap/fd_copy.c +--- qmail-1.03/fd_copy.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fd_copy.c Tue Oct 28 18:21:31 2003 +@@ -1,4 +1,5 @@ + #include ++#include + #include "fd.h" + + int fd_copy(to,from) +diff -upN qmail-1.03/fd_move.c qmail-ldap/fd_move.c +--- qmail-1.03/fd_move.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fd_move.c Tue Oct 28 18:21:31 2003 +@@ -1,3 +1,4 @@ ++#include + #include "fd.h" + + int fd_move(to,from) +diff -upN qmail-1.03/fifo.c qmail-ldap/fifo.c +--- qmail-1.03/fifo.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fifo.c Tue Oct 28 18:21:31 2003 +@@ -4,7 +4,7 @@ + #include "fifo.h" + + #ifdef HASMKFIFO +-int fifo_make(fn,mode) char *fn; int mode; { return mkfifo(fn,mode); } ++int fifo_make(fn,mode) const char *fn; int mode; { return mkfifo(fn,mode); } + #else +-int fifo_make(fn,mode) char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); } ++int fifo_make(fn,mode) const char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); } + #endif +diff -upN qmail-1.03/fifo.h qmail-ldap/fifo.h +--- qmail-1.03/fifo.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fifo.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,6 @@ + #ifndef FIFO_H + #define FIFO_H + +-extern int fifo_make(); ++extern int fifo_make(const char *, int); + + #endif +diff -upN qmail-1.03/fmt.h qmail-ldap/fmt.h +--- qmail-1.03/fmt.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fmt.h Tue Oct 28 18:21:31 2003 +@@ -4,22 +4,26 @@ + #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ + #define FMT_LEN ((char *) 0) /* convenient abbreviation */ + +-extern unsigned int fmt_uint(); +-extern unsigned int fmt_uint0(); ++extern unsigned int fmt_uint(char *, unsigned int); ++extern unsigned int fmt_uint0(char *, unsigned int, unsigned int); ++/* XXX not available in qmail-1.03 + extern unsigned int fmt_xint(); + extern unsigned int fmt_nbbint(); + extern unsigned int fmt_ushort(); + extern unsigned int fmt_xshort(); + extern unsigned int fmt_nbbshort(); +-extern unsigned int fmt_ulong(); ++*/ ++extern unsigned int fmt_ulong(char *, unsigned long); ++/* XXX not available in qmail-1.03 + extern unsigned int fmt_xlong(); + extern unsigned int fmt_nbblong(); + + extern unsigned int fmt_plusminus(); + extern unsigned int fmt_minus(); + extern unsigned int fmt_0x(); ++*/ + +-extern unsigned int fmt_str(); +-extern unsigned int fmt_strn(); ++extern unsigned int fmt_str(char *, const char *); ++extern unsigned int fmt_strn(char *, const char *, unsigned int); + + #endif +diff -upN qmail-1.03/fmt_str.c qmail-ldap/fmt_str.c +--- qmail-1.03/fmt_str.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fmt_str.c Tue Oct 28 18:21:31 2003 +@@ -1,12 +1,12 @@ + #include "fmt.h" + + unsigned int fmt_str(s,t) +-register char *s; register char *t; ++register char *s; register const char *t; + { + register unsigned int len; + char ch; + len = 0; +- if (s) { while (ch = t[len]) s[len++] = ch; } ++ if (s) { while ((ch = t[len])) s[len++] = ch; } + else while (t[len]) len++; + return len; + } +diff -upN qmail-1.03/fmt_strn.c qmail-ldap/fmt_strn.c +--- qmail-1.03/fmt_strn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fmt_strn.c Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,7 @@ + #include "fmt.h" + + unsigned int fmt_strn(s,t,n) +-register char *s; register char *t; register unsigned int n; ++register char *s; register const char *t; register unsigned int n; + { + register unsigned int len; + char ch; +diff -upN qmail-1.03/fmtqfn.c qmail-ldap/fmtqfn.c +--- qmail-1.03/fmtqfn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fmtqfn.c Tue Oct 28 18:21:31 2003 +@@ -4,7 +4,7 @@ + + unsigned int fmtqfn(s,dirslash,id,flagsplit) + char *s; +-char *dirslash; ++const char *dirslash; + unsigned long id; + int flagsplit; + { +diff -upN qmail-1.03/fmtqfn.h qmail-ldap/fmtqfn.h +--- qmail-1.03/fmtqfn.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fmtqfn.h Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,7 @@ + #ifndef FMTQFN_H + #define FMTQFN_H + +-extern unsigned int fmtqfn(); ++extern unsigned int fmtqfn(char *, const char *, unsigned long, int); + + #define FMTQFN 40 /* maximum space needed, if len(dirslash) <= 10 */ + +diff -upN qmail-1.03/fork.h1 qmail-ldap/fork.h1 +--- qmail-1.03/fork.h1 Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fork.h1 Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,8 @@ + #ifndef FORK_H + #define FORK_H + +-extern int fork(); ++#include ++ + #define vfork fork + + #endif +diff -upN qmail-1.03/fork.h2 qmail-ldap/fork.h2 +--- qmail-1.03/fork.h2 Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/fork.h2 Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,6 @@ + #ifndef FORK_H + #define FORK_H + +-extern int fork(); +-extern int vfork(); ++#include + + #endif +diff -upN qmail-1.03/forward.c qmail-ldap/forward.c +--- qmail-1.03/forward.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/forward.c Thu Jan 29 16:48:14 2004 +@@ -13,7 +13,7 @@ void die_nomem() { strerr_die2x(111,FATA + + struct qmail qqt; + +-int mywrite(fd,buf,len) int fd; char *buf; int len; ++int mywrite(int fd, void *buf, int len) + { + qmail_put(&qqt,buf,len); + return len; +@@ -21,18 +21,18 @@ int mywrite(fd,buf,len) int fd; char *bu + + char inbuf[SUBSTDIO_INSIZE]; + char outbuf[1]; +-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); ++substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf); + substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf); + + char num[FMT_ULONG]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { + char *sender; + char *dtline; +- char *qqx; ++ const char *qqx; + + sig_pipeignore(); + +@@ -57,4 +57,5 @@ char **argv; + qqx = qmail_close(&qqt); + if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); + strerr_die2x(0,"forward: qp ",num); ++ return 0; + } +diff -upN qmail-1.03/gen_allocdefs.h qmail-ldap/gen_allocdefs.h +--- qmail-1.03/gen_allocdefs.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/gen_allocdefs.h Tue Oct 28 18:21:31 2003 +@@ -8,7 +8,7 @@ int ta_ready(x,n) register ta *x; regist + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ +- if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ ++ if (alloc_re((char **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ +@@ -21,7 +21,7 @@ int ta_rplus(x,n) register ta *x; regist + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ +- if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ ++ if (alloc_re((char **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ +diff -upN qmail-1.03/getln.h qmail-ldap/getln.h +--- qmail-1.03/getln.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/getln.h Tue Oct 28 18:21:31 2003 +@@ -1,7 +1,10 @@ + #ifndef GETLN_H + #define GETLN_H + +-extern int getln(); +-extern int getln2(); ++#include "stralloc.h" ++#include "substdio.h" ++ ++extern int getln(substdio *, stralloc *, int *, int); ++extern int getln2(substdio *, stralloc *, char **, unsigned int *, int); + + #endif +diff -upN qmail-1.03/gettimeofday.c qmail-ldap/gettimeofday.c +--- qmail-1.03/gettimeofday.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/gettimeofday.c Tue Oct 28 18:21:31 2003 +@@ -0,0 +1,13 @@ ++#include ++#include ++ ++struct timeval sincepoch = {0,0}; ++struct timezone notimezone = {0,0}; ++ ++int main() ++{ ++ gettimeofday(&sincepoch, ¬imezone); ++ printf("%d\n", sincepoch.tv_sec); ++ return 0; ++} ++ +diff -upN qmail-1.03/gfrom.h qmail-ldap/gfrom.h +--- qmail-1.03/gfrom.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/gfrom.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,6 @@ + #ifndef GFROM_H + #define GFROM_H + +-extern int gfrom(); ++extern int gfrom(char *, int); + + #endif +diff -upN qmail-1.03/headerbody.h qmail-ldap/headerbody.h +--- qmail-1.03/headerbody.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/headerbody.h Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,10 @@ + #ifndef HEADERBODY_H + #define HEADERBODY_H + +-extern int headerbody(); ++#include "stralloc.h" ++#include "substdio.h" ++ ++extern int headerbody(substdio *, ++ void (*)(stralloc *), void (*)(void), void (*)(stralloc *)); + + #endif +diff -upN qmail-1.03/hfield.c qmail-ldap/hfield.c +--- qmail-1.03/hfield.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/hfield.c Thu Jan 29 16:48:14 2004 +@@ -1,6 +1,6 @@ + #include "hfield.h" + +-static char *(hname[]) = { ++static const char *(hname[]) = { + "unknown-header" + , "sender" + , "from" +@@ -35,13 +35,13 @@ static char *(hname[]) = { + + static int hmatch(s,len,t) + char *s; +-int len; +-char *t; ++unsigned int len; ++const char *t; + { +- int i; ++ unsigned int i; + char ch; + +- for (i = 0;ch = t[i];++i) ++ for (i = 0;(ch = t[i]);++i) + { + if (i >= len) return 0; + if (ch != s[i]) +@@ -62,12 +62,12 @@ char *t; + + int hfield_known(s,len) + char *s; +-int len; ++unsigned int len; + { +- int i; +- char *t; ++ unsigned int i; ++ const char *t; + +- for (i = 1;t = hname[i];++i) ++ for (i = 1;(t = hname[i]);++i) + if (hmatch(s,len,t)) + return i; + return 0; +@@ -75,10 +75,10 @@ int len; + + int hfield_valid(s,len) + char *s; +-int len; ++unsigned int len; + { +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + char ch; + + for (j = 0;j < len;++j) +@@ -105,9 +105,9 @@ int len; + + unsigned int hfield_skipname(s,len) + char *s; +-int len; ++unsigned int len; + { +- int i; ++ unsigned int i; + char ch; + + for (i = 0;i < len;++i) +diff -upN qmail-1.03/hfield.h qmail-ldap/hfield.h +--- qmail-1.03/hfield.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/hfield.h Thu Jan 29 16:48:14 2004 +@@ -1,9 +1,9 @@ + #ifndef HFIELD_H + #define HFIELD_H + +-extern unsigned int hfield_skipname(); +-extern int hfield_known(); +-extern int hfield_valid(); ++extern unsigned int hfield_skipname(char *, unsigned int); ++extern int hfield_known(char *, unsigned int); ++extern int hfield_valid(char *, unsigned int); + + #define H_SENDER 1 + #define H_FROM 2 +diff -upN qmail-1.03/hier.c qmail-ldap/hier.c +--- qmail-1.03/hier.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/hier.c Thu Jul 1 16:28:30 2004 +@@ -1,9 +1,21 @@ + #include "auto_qmail.h" + #include "auto_split.h" + #include "auto_uids.h" ++#include "auto_userl.h" + #include "fmt.h" + #include "fifo.h" + ++extern void c(const char *, const char *, const char *, int, int, int); ++extern void C(const char *, const char *, const char *, const char *, ++ int, int, int); ++extern void d(const char *, const char *, int, int, int); ++extern void h(const char *, int, int, int); ++extern void l(const char *, const char *, const char *, const char *, ++ int, int, int); ++extern void p(const char *, const char *, int, int, int); ++extern void z(const char *, const char *, int, int, int, int); ++ ++ + char buf[100 + FMT_ULONG]; + + void dsplit(base,uid,mode) +@@ -34,8 +46,46 @@ void hier() + d(auto_qmail,"control",auto_uido,auto_gidq,0755); + d(auto_qmail,"users",auto_uido,auto_gidq,0755); + d(auto_qmail,"bin",auto_uido,auto_gidq,0755); +- d(auto_qmail,"boot",auto_uido,auto_gidq,0755); + d(auto_qmail,"doc",auto_uido,auto_gidq,0755); ++ ++ /* boot restructured for daemontools */ ++ d(auto_qmail,"boot",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd/log",auto_uido,auto_gidq,0755); ++ ++ /* logging restructured for daemontools */ ++ d(auto_qmail,"log",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-smtpd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-qmqpd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pop3d",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-imapd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pop3d-ssl",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-imapd-ssl",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pbsdbd",auto_uidl,auto_gidq,0755); ++ + d(auto_qmail,"man",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755); +@@ -50,30 +100,57 @@ void hier() + + d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); ++#ifndef BIGTODO + d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); ++#endif + d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); + + dsplit("queue/mess",auto_uidq,0750); + dsplit("queue/info",auto_uids,0700); + dsplit("queue/local",auto_uids,0700); + dsplit("queue/remote",auto_uids,0700); ++#ifdef BIGTODO ++ dsplit("queue/intd",auto_uidq,0700); ++ dsplit("queue/todo",auto_uidq,0750); ++#endif + + d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); + z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); + z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); + p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); + +- c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); ++ /* rules file for tcpserver */ ++ C(auto_qmail,"control","qmail-smtpd.rules","qmail-smtpd.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-qmqpd.rules","qmail-qmqpd.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-pop3d.rules","qmail-pop3d.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-imapd.rules","qmail-imapd.rules",auto_uido,auto_gidq,0644); ++ ++ /* Makefile for cdb creation */ ++ C(auto_qmail,"control","Makefile","Makefile.cdb-p",auto_uido,auto_gidq,0644); ++ ++ /* signature file for qmail-smtpd ecexcheck freature */ ++ C(auto_qmail,"control","signatures","signatures",auto_uido,auto_gidq,0644); ++ ++ /* run files for boot/supervise scripts */ ++ C(auto_qmail,"boot/qmail", "run", "qmail.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-smtpd", "run", "qmail-smtpd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-qmqpd", "run", "qmail-qmqpd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pop3d", "run", "qmail-pop3d.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-imapd", "run", "qmail-imapd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pop3d-ssl", "run", "qmail-pop3d-ssl.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-imapd-ssl", "run", "qmail-imapd-ssl.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pbsdbd", "run", "qmail-pbsdbd.run",auto_uido,auto_gidq,0755); ++ ++ /* run files for logging process */ ++ l(auto_qmail,"boot/qmail/log","log/qmail",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-smtpd/log","log/qmail-smtpd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-qmqpd/log","log/qmail-qmqpd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pop3d/log","log/qmail-pop3d",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-imapd/log","log/qmail-imapd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pop3d-ssl/log","log/qmail-pop3d-ssl",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-imapd-ssl/log","log/qmail-imapd-ssl",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pbsdbd/log","log/qmail-pbsdbd",auto_userl,auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); +@@ -98,6 +175,13 @@ void hier() + c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPGROUP",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPINSTALL",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPNEWS",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPTODO",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPPICTURE",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","EXTTODO",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","POPBEFORESMTP",auto_uido,auto_gidq,0644); + + c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); + c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); +@@ -108,6 +192,9 @@ void hier() + c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); ++#ifdef EXTERNAL_TODO ++ c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711); ++#endif + c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); +@@ -135,6 +222,7 @@ void hier() + c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","condwrite",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); +@@ -143,6 +231,21 @@ void hier() + c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-reply",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-quotawarn",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","auth_pop",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","auth_imap",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","auth_smtp",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-verify",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-ldaplookup",auto_uido,0,0750); ++ c(auto_qmail,"bin","qmail-cdb",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","digest",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbsadd",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbscheck",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbsdbd",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-forward",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-secretary",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-group",auto_uido,auto_gidq,0755); + + c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); +diff -upN qmail-1.03/hostname.c qmail-ldap/hostname.c +--- qmail-1.03/hostname.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/hostname.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "substdio.h" + #include "subfd.h" + #include "readwrite.h" +@@ -5,7 +6,7 @@ + + char host[256]; + +-void main() ++int main() + { + host[0] = 0; /* sigh */ + gethostname(host,sizeof(host)); +@@ -13,5 +14,5 @@ void main() + substdio_puts(subfdoutsmall,host); + substdio_puts(subfdoutsmall,"\n"); + substdio_flush(subfdoutsmall); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/idedit.c qmail-ldap/idedit.c +--- qmail-1.03/idedit.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/idedit.c Tue Oct 28 18:21:31 2003 +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + #include "readwrite.h" + #include "exit.h" + #include "scan.h" +@@ -9,6 +10,7 @@ + #include "open.h" + #include "seek.h" + #include "fork.h" ++#include "wait.h" + + #define FATAL "idedit: fatal: " + #define WARNING "idedit: warning: " +@@ -67,7 +69,7 @@ char *pos3; + pw = getpwnam(account); + + if (!pw && group) { +- args[0] = "add-account"; ++ args[0] = (char *)"add-account"; + args[1] = account; + args[2] = group; + args[3] = home; +@@ -101,7 +103,7 @@ char *pos3; + gr = getgrnam(group); + + if (!gr) { +- args[0] = "add-group"; ++ args[0] = (char *)"add-group"; + args[1] = group; + args[2] = 0; + run(); +@@ -120,7 +122,7 @@ char *pos3; + strerr_die3x(111,FATAL,"excessively large gid for ",group); + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -143,5 +145,5 @@ char **argv; + u("qmailr","qmail","/var/qmail",argv[26],argv[27],argv[28],argv[29]); + u("qmails","qmail","/var/qmail",argv[30],argv[31],argv[32],argv[33]); + +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/install-big.c qmail-ldap/install-big.c +--- qmail-1.03/install-big.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/install-big.c Thu Jul 1 16:28:30 2004 +@@ -1,11 +1,22 @@ + #include "auto_qmail.h" + #include "auto_split.h" + #include "auto_uids.h" ++#include "auto_userl.h" + #include "fmt.h" + #include "fifo.h" + + char buf[100 + FMT_ULONG]; + ++extern void c(const char *, const char *, const char *, int, int, int); ++extern void C(const char *, const char *, const char *, const char *, ++ int, int, int); ++extern void d(const char *, const char *, int, int, int); ++extern void h(const char *, int, int, int); ++extern void l(const char *, const char *, const char *, const char *, ++ int, int, int); ++extern void p(const char *, const char *, int, int, int); ++extern void z(const char *, const char *, int, int, int, int); ++ + void dsplit(base,uid,mode) + char *base; /* must be under 100 bytes */ + int uid; +@@ -35,6 +46,45 @@ void hier() + d(auto_qmail,"users",auto_uido,auto_gidq,0755); + d(auto_qmail,"bin",auto_uido,auto_gidq,0755); + d(auto_qmail,"boot",auto_uido,auto_gidq,0755); ++ ++ /* boot restructured for daemontools */ ++ d(auto_qmail,"boot",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-smtpd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-qmqpd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pop3d-ssl/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-imapd-ssl/log",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd/env",auto_uido,auto_gidq,0755); ++ d(auto_qmail,"boot/qmail-pbsdbd/log",auto_uido,auto_gidq,0755); ++ ++ /* logging restructured for daemontools */ ++ d(auto_qmail,"log",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-smtpd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-qmqpd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pop3d",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-imapd",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pop3d-ssl",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-imapd-ssl",auto_uidl,auto_gidq,0755); ++ d(auto_qmail,"log/qmail-pbsdbd",auto_uidl,auto_gidq,0755); ++ + d(auto_qmail,"doc",auto_uido,auto_gidq,0755); + d(auto_qmail,"man",auto_uido,auto_gidq,0755); + d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); +@@ -50,30 +100,57 @@ void hier() + + d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); + d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); ++#ifndef BIGTODO + d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); + d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); ++#endif + d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); + + dsplit("queue/mess",auto_uidq,0750); + dsplit("queue/info",auto_uids,0700); + dsplit("queue/local",auto_uids,0700); + dsplit("queue/remote",auto_uids,0700); ++#ifdef BIGTODO ++ dsplit("queue/intd",auto_uidq,0700); ++ dsplit("queue/todo",auto_uidq,0750); ++#endif + + d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); + z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); + z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); + p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); + +- c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); +- c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); ++ /* rules file for tcpserver */ ++ C(auto_qmail,"control","qmail-smtpd.rules","qmail-smtpd.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-qmqpd.rules","qmail-qmqpd.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-pop3d.rules","qmail-pop3d.rules",auto_uido,auto_gidq,0644); ++ C(auto_qmail,"control","qmail-imapd.rules","qmail-imapd.rules",auto_uido,auto_gidq,0644); ++ ++ /* Makefile for cdb creation */ ++ C(auto_qmail,"control","Makefile","Makefile.cdb-p",auto_uido,auto_gidq,0644); ++ ++ /* signature file for qmail-smtpd ecexcheck freature */ ++ C(auto_qmail,"control","signatures","signatures",auto_uido,auto_gidq,0644); ++ ++ /* run files for boot/supervise scripts */ ++ C(auto_qmail,"boot/qmail", "run", "qmail.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-smtpd", "run", "qmail-smtpd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-qmqpd", "run", "qmail-qmqpd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pop3d", "run", "qmail-pop3d.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-imapd", "run", "qmail-imapd.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pop3d-ssl", "run", "qmail-pop3d-ssl.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-imapd-ssl", "run", "qmail-imapd-ssl.run",auto_uido,auto_gidq,0755); ++ C(auto_qmail,"boot/qmail-pbsdbd", "run", "qmail-pbsdbd.run",auto_uido,auto_gidq,0755); ++ ++ /* run files for logging process */ ++ l(auto_qmail,"boot/qmail/log","log/qmail",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-smtpd/log","log/qmail-smtpd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-qmqpd/log","log/qmail-qmqpd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pop3d/log","log/qmail-pop3d",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-imapd-ssl/log","log/qmail-imapd-ssl",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pop3d-ssl/log","log/qmail-pop3d-ssl",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-imapd/log","log/qmail-imapd",auto_userl,auto_uido,auto_gidq,0755); ++ l(auto_qmail,"boot/qmail-pbsdbd/log","log/qmail-pbsdbd",auto_userl,auto_uido,auto_gidq,0755); + + c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); +@@ -98,6 +175,13 @@ void hier() + c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPGROUP",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPINSTALL",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPNEWS",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPTODO",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","QLDAPPICTURE",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","EXTTODO",auto_uido,auto_gidq,0644); ++ c(auto_qmail,"doc","POPBEFORESMTP",auto_uido,auto_gidq,0644); + + c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); + c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); +@@ -108,6 +192,9 @@ void hier() + c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); ++#ifdef EXTERNAL_TODO ++ c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711); ++#endif + c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); + c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); + c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); +@@ -135,6 +222,7 @@ void hier() + c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","condwrite",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); +@@ -143,7 +231,22 @@ void hier() + c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); + c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); +- ++ c(auto_qmail,"bin","qmail-reply",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-quotawarn",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","auth_pop",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","auth_imap",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","auth_smtp",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-verify",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-ldaplookup",auto_uido,0,0750); ++ c(auto_qmail,"bin","qmail-cdb",auto_uido,auto_gidq,0700); ++ c(auto_qmail,"bin","digest",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbsadd",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbscheck",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","pbsdbd",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-forward",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-secretary",auto_uido,auto_gidq,0755); ++ c(auto_qmail,"bin","qmail-group",auto_uido,auto_gidq,0755); ++ + c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); + c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644); +diff -upN qmail-1.03/install.c qmail-ldap/install.c +--- qmail-1.03/install.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/install.c Thu Oct 30 11:11:13 2003 +@@ -1,9 +1,13 @@ ++#include ++#include ++#include + #include "substdio.h" + #include "strerr.h" + #include "error.h" + #include "open.h" + #include "readwrite.h" + #include "exit.h" ++#include "fifo.h" + + extern void hier(); + +@@ -12,7 +16,7 @@ extern void hier(); + int fdsourcedir = -1; + + void h(home,uid,gid,mode) +-char *home; ++const char *home; + int uid; + int gid; + int mode; +@@ -27,8 +31,8 @@ int mode; + } + + void d(home,subdir,uid,gid,mode) +-char *home; +-char *subdir; ++const char *home; ++const char *subdir; + int uid; + int gid; + int mode; +@@ -45,8 +49,8 @@ int mode; + } + + void p(home,fifo,uid,gid,mode) +-char *home; +-char *fifo; ++const char *home; ++const char *fifo; + int uid; + int gid; + int mode; +@@ -68,9 +72,9 @@ substdio ssin; + substdio ssout; + + void c(home,subdir,file,uid,gid,mode) +-char *home; +-char *subdir; +-char *file; ++const char *home; ++const char *subdir; ++const char *file; + int uid; + int gid; + int mode; +@@ -84,7 +88,7 @@ int mode; + fdin = open_read(file); + if (fdin == -1) + strerr_die4sys(111,FATAL,"unable to read ",file,": "); +- substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof inbuf); ++ substdio_fdbuf(&ssin,subread,fdin,inbuf,sizeof inbuf); + + if (chdir(home) == -1) + strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); +@@ -94,7 +98,7 @@ int mode; + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); +- substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); ++ substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf); + + switch(substdio_copy(&ssout,&ssin)) { + case -2: +@@ -117,9 +121,123 @@ int mode; + strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); + } + ++void C(home,subdir,file,source,uid,gid,mode) ++const char *home; ++const char *subdir; ++const char *file; ++const char *source; ++int uid; ++int gid; ++int mode; ++{ ++ struct stat st; ++ int fdin; ++ int fdout; ++ ++ if (fchdir(fdsourcedir) == -1) ++ strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); ++ ++ fdin = open_read(source); ++ if (fdin == -1) ++ strerr_die4sys(111,FATAL,"unable to read ",source,": "); ++ substdio_fdbuf(&ssin,subread,fdin,inbuf,sizeof inbuf); ++ ++ if (chdir(home) == -1) ++ strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); ++ if (chdir(subdir) == -1) ++ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); ++ ++ /* if file seems to exist don't overwrite */ ++ if (stat(file, &st) == 0) { ++ close(fdin); ++ return; ++ } ++ ++ fdout = open_trunc(file); ++ if (fdout == -1) ++ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); ++ substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf); ++ ++ switch(substdio_copy(&ssout,&ssin)) { ++ case -2: ++ strerr_die4sys(111,FATAL,"unable to read ",source,": "); ++ case -3: ++ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); ++ } ++ ++ close(fdin); ++ if (substdio_flush(&ssout) == -1) ++ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); ++ if (fsync(fdout) == -1) ++ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); ++ if (close(fdout) == -1) /* NFS silliness */ ++ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); ++ ++ if (chown(file,uid,gid) == -1) ++ strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); ++ if (chmod(file,mode) == -1) ++ strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); ++} ++ ++void l(home,subdir,logdir,loguser,uid,gid,mode) ++const char *home; ++const char *subdir; ++const char *logdir; ++const char *loguser; ++int uid; ++int gid; ++int mode; ++{ ++ int fdout; ++ struct stat st; ++ ++ if (chdir(home) == -1) ++ strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); ++ if (chdir(subdir) == -1) ++ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); ++ ++ /* if file seems to exist don't overwrite */ ++ if (stat("run", &st) == 0) return; ++ ++ fdout = open_trunc("run"); ++ if (fdout == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf); ++ ++ /* write log script */ ++ if (substdio_puts(&ssout, ++ "#!/bin/sh\n\nexec setuidgid ") == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, loguser) == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, " multilog t ") == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, home) == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, "/") == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, logdir) == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (substdio_puts(&ssout, "\n\n") == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ ++ if (substdio_flush(&ssout) == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (fsync(fdout) == -1) ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ if (close(fdout) == -1) /* NFS silliness */ ++ strerr_die4sys(111,FATAL,"unable to write .../",subdir,"/run: "); ++ ++ if (chown("run",uid,gid) == -1) ++ strerr_die4sys(111,FATAL,"unable to chown .../",subdir,"/run: "); ++ if (chmod("run",mode) == -1) ++ strerr_die4sys(111,FATAL,"unable to chmod .../",subdir,"/run: "); ++} ++ ++ + void z(home,file,len,uid,gid,mode) +-char *home; +-char *file; ++const char *home; ++const char *file; + int len; + int uid; + int gid; +@@ -133,7 +251,7 @@ int mode; + fdout = open_trunc(file); + if (fdout == -1) + strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); +- substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); ++ substdio_fdbuf(&ssout,subwrite,fdout,outbuf,sizeof outbuf); + + while (len-- > 0) + if (substdio_put(&ssout,"",1) == -1) +@@ -152,7 +270,7 @@ int mode; + strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",file,": "); + } + +-void main() ++int main() + { + fdsourcedir = open_read("."); + if (fdsourcedir == -1) +@@ -160,5 +278,5 @@ void main() + + umask(077); + hier(); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/instcheck.c qmail-ldap/instcheck.c +--- qmail-1.03/instcheck.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/instcheck.c Thu Oct 30 11:11:13 2003 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "strerr.h" + #include "error.h" + #include "readwrite.h" +@@ -50,8 +51,8 @@ int mode; + } + + void d(home,subdir,uid,gid,mode) +-char *home; +-char *subdir; ++const char *home; ++const char *subdir; + int uid; + int gid; + int mode; +@@ -62,8 +63,8 @@ int mode; + } + + void p(home,fifo,uid,gid,mode) +-char *home; +-char *fifo; ++const char *home; ++const char *fifo; + int uid; + int gid; + int mode; +@@ -74,9 +75,25 @@ int mode; + } + + void c(home,subdir,file,uid,gid,mode) +-char *home; +-char *subdir; +-char *file; ++const char *home; ++const char *subdir; ++const char *file; ++int uid; ++int gid; ++int mode; ++{ ++ if (chdir(home) == -1) ++ strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); ++ if (chdir(subdir) == -1) ++ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); ++ perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode); ++} ++ ++void C(home,subdir,file,source,uid,gid,mode) ++const char *home; ++const char *subdir; ++const char *file; ++const char *source; + int uid; + int gid; + int mode; +@@ -89,8 +106,8 @@ int mode; + } + + void z(home,file,len,uid,gid,mode) +-char *home; +-char *file; ++const char *home; ++const char *file; + int len; + int uid; + int gid; +@@ -101,8 +118,24 @@ int mode; + perm("",home,"/",file,S_IFREG,uid,gid,mode); + } + +-void main() ++void l(home,subdir,logdir,loguser,uid,gid,mode) ++const char *home; ++const char *subdir; ++const char *logdir; ++const char *loguser; ++int uid; ++int gid; ++int mode; ++{ ++ if (chdir(home) == -1) ++ strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); ++ if (chdir(subdir) == -1) ++ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); ++ perm(".../",subdir,"/","run",S_IFREG,uid,gid,mode); ++} ++ ++int main() + { + hier(); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/ip.c qmail-ldap/ip.c +--- qmail-1.03/ip.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ip.c Tue Feb 17 15:31:30 2004 +@@ -21,26 +21,42 @@ struct ip_address *ip; + } + + unsigned int ip_scan(s,ip) +-char *s; ++const char *s; + struct ip_address *ip; + { + unsigned int i; + unsigned int len; + unsigned long u; +- ++ ++ /* ++ * Don't play games. everything over 255 is invalid and we need a full ++ * IP address. No magic expands like 127.1 or similar bullshit. ++ */ + len = 0; +- i = scan_ulong(s,&u); if (!i) return 0; ip->d[0] = u; s += i; len += i; ++ i = scan_ulong(s,&u); ++ if (!i || u > 255) return 0; ++ ip->d[0] = u; s += i; len += i; ++ + if (*s != '.') return 0; ++s; ++len; +- i = scan_ulong(s,&u); if (!i) return 0; ip->d[1] = u; s += i; len += i; ++ i = scan_ulong(s,&u); ++ if (!i || u > 255) return 0; ++ ip->d[1] = u; s += i; len += i; ++ + if (*s != '.') return 0; ++s; ++len; +- i = scan_ulong(s,&u); if (!i) return 0; ip->d[2] = u; s += i; len += i; ++ i = scan_ulong(s,&u); ++ if (!i || u > 255) return 0; ++ ip->d[2] = u; s += i; len += i; ++ + if (*s != '.') return 0; ++s; ++len; +- i = scan_ulong(s,&u); if (!i) return 0; ip->d[3] = u; s += i; len += i; ++ i = scan_ulong(s,&u); ++ if (!i || u > 255) return 0; ++ ip->d[3] = u; s += i; len += i; ++ + return len; + } + + unsigned int ip_scanbracket(s,ip) +-char *s; ++const char *s; + struct ip_address *ip; + { + unsigned int len; +diff -upN qmail-1.03/ip.h qmail-ldap/ip.h +--- qmail-1.03/ip.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ip.h Tue Oct 28 18:21:32 2003 +@@ -3,9 +3,9 @@ + + struct ip_address { unsigned char d[4]; } ; + +-extern unsigned int ip_fmt(); ++extern unsigned int ip_fmt(char *, struct ip_address *); + #define IPFMT 19 +-extern unsigned int ip_scan(); +-extern unsigned int ip_scanbracket(); ++extern unsigned int ip_scan(const char *, struct ip_address *); ++extern unsigned int ip_scanbracket(const char *, struct ip_address *); + + #endif +diff -upN qmail-1.03/ipalloc.h qmail-ldap/ipalloc.h +--- qmail-1.03/ipalloc.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ipalloc.h Tue Oct 28 18:21:32 2003 +@@ -8,7 +8,7 @@ struct ip_mx { struct ip_address ip; int + #include "gen_alloc.h" + + GEN_ALLOC_typedef(ipalloc,struct ip_mx,ix,len,a) +-extern int ipalloc_readyplus(); +-extern int ipalloc_append(); ++extern int ipalloc_readyplus(ipalloc *, unsigned int); ++extern int ipalloc_append(ipalloc *, struct ip_mx *); + + #endif +diff -upN qmail-1.03/ipme.c qmail-ldap/ipme.c +--- qmail-1.03/ipme.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ipme.c Thu Jan 29 16:48:14 2004 +@@ -8,6 +8,7 @@ + #ifndef SIOCGIFCONF /* whatever works */ + #include + #endif ++#include + #include "hassalen.h" + #include "byte.h" + #include "ip.h" +@@ -36,7 +37,7 @@ int ipme_init() + struct ifconf ifc; + char *x; + struct ifreq *ifr; +- struct sockaddr_in *sin; ++ struct sockaddr_in *s_in; + int len; + int s; + struct ip_mx ix; +@@ -45,6 +46,12 @@ int ipme_init() + 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; } + + if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; + +@@ -70,8 +77,8 @@ int ipme_init() + if (len < sizeof(*ifr)) + len = sizeof(*ifr); + if (ifr->ifr_addr.sa_family == AF_INET) { +- sin = (struct sockaddr_in *) &ifr->ifr_addr; +- byte_copy(&ix.ip,4,&sin->sin_addr); ++ s_in = (struct sockaddr_in *) &ifr->ifr_addr; ++ byte_copy(&ix.ip,4,&s_in->sin_addr); + if (ioctl(s,SIOCGIFFLAGS,x) == 0) + if (ifr->ifr_flags & IFF_UP) + if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } +@@ -82,8 +89,8 @@ int ipme_init() + if (ifr->ifr_flags & IFF_UP) + if (ioctl(s,SIOCGIFADDR,x) == 0) + if (ifr->ifr_addr.sa_family == AF_INET) { +- sin = (struct sockaddr_in *) &ifr->ifr_addr; +- byte_copy(&ix.ip,4,&sin->sin_addr); ++ s_in = (struct sockaddr_in *) &ifr->ifr_addr; ++ byte_copy(&ix.ip,4,&s_in->sin_addr); + if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } + } + #endif +diff -upN qmail-1.03/ipme.h qmail-ldap/ipme.h +--- qmail-1.03/ipme.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ipme.h Tue Oct 28 18:21:32 2003 +@@ -6,7 +6,7 @@ + + extern ipalloc ipme; + +-extern int ipme_init(); +-extern int ipme_is(); ++extern int ipme_init(void); ++extern int ipme_is(struct ip_address *); + + #endif +diff -upN qmail-1.03/ipmeprint.c qmail-ldap/ipmeprint.c +--- qmail-1.03/ipmeprint.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ipmeprint.c Thu Jan 29 16:48:14 2004 +@@ -6,9 +6,9 @@ + + char temp[IPFMT]; + +-void main() ++int main(int argc, char **argv) + { +- int j; ++ unsigned int j; + switch(ipme_init()) + { + case 0: substdio_putsflush(subfderr,"out of memory\n"); _exit(111); +@@ -20,5 +20,5 @@ void main() + substdio_puts(subfdout,"\n"); + } + substdio_flush(subfdout); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/limit.h qmail-ldap/limit.h +--- qmail-1.03/limit.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/limit.h Thu Jan 29 16:03:13 2004 +@@ -0,0 +1,22 @@ ++#ifndef __LIMIT_H__ ++#define __LIMIT_H__ ++ ++#include ++ ++/* ++ * we only need the max value for 32bit integers so make sure that we have ++ * those available. ++ * So we assume ILP32 or I32LP64 based systems which should be the default ++ * for unix systems. AFAIK only Cray is ILP64... ++ */ ++#ifndef UINT_MAX ++#define UINT_MAX 0xffffffffU /* max value for an unsigned int */ ++#endif ++#ifndef INT_MAX ++#define INT_MAX 0x7fffffff /* max value for an int */ ++#endif ++#ifndef INT_MIN ++#define INT_MIN (-0x7fffffff-1) /* min value for an int */ ++#endif ++ ++#endif +diff -upN qmail-1.03/localdelivery.c qmail-ldap/localdelivery.c +--- qmail-1.03/localdelivery.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/localdelivery.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "control.h" ++#include "qldap-debug.h" ++ ++#include "localdelivery.h" ++ ++static int flaglocaldelivery; ++ ++int ++localdelivery_init(void) ++{ ++ flaglocaldelivery = 1; /* localdelivery is on (DEFAULT) */ ++ ++ if (control_readint(&flaglocaldelivery, ++ "control/ldaplocaldelivery") == -1) ++ return -1; ++ logit(64, "init: control/ldaplocaldelivery: %i\n", flaglocaldelivery); ++ return 0; ++} ++ ++int ++localdelivery(void) ++{ ++ return flaglocaldelivery; ++} ++ +diff -upN qmail-1.03/localdelivery.h qmail-ldap/localdelivery.h +--- qmail-1.03/localdelivery.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/localdelivery.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __LOCALDELIVERY_H__ ++#define __LOCALDELIVERY_H__ ++ ++int localdelivery_init(void); ++ ++/* returns true if localdelivery is on */ ++int localdelivery(void); ++ ++#endif ++ +diff -upN qmail-1.03/locallookup.c qmail-ldap/locallookup.c +--- qmail-1.03/locallookup.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/locallookup.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++/* ++ * Based on D. J. Bernsteins checkpassword program. ++ */ ++ ++#include ++#include ++#include "error.h" ++#include "getln.h" ++#include "localdelivery.h" ++#include "open.h" ++#include "passwd.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "readwrite.h" ++#include "substdio.h" ++ ++#include "checkpassword.h" ++#include "locallookup.h" ++ ++/* Edit the first lines in the Makefile to enable local passwd lookups ++ * and debug options. ++ * To use shadow passwords under Solaris, uncomment the 'SHADOWOPTS' line ++ * in the Makefile. ++ * To use shadow passwords under Linux, uncomment the 'SHADOWOPTS' line and ++ * the 'SHADOWLIBS=-lshadow' line in the Makefile. ++ */ ++#include ++#ifdef PW_SHADOW ++#include ++#endif ++#ifdef AIX ++#include ++#endif ++ ++int ++check_passwd(stralloc *login, stralloc *authdata, ++ struct credentials *c, int fast) ++{ ++ int ret; ++ struct passwd *pw; ++#ifdef PW_SHADOW ++ struct spwd *spw; ++#endif ++#ifdef AIX ++ struct userpw *spw; ++#endif ++ ++ if (localdelivery() == 0) return NOSUCH; ++ ++ pw = getpwnam(login->s); ++ if (!pw) { ++ /* XXX: unfortunately getpwnam() hides temporary errors */ ++ logit(32, "check_passwd: user %s not found in passwd db\n", ++ login->s); ++ return NOSUCH; ++ } ++ logit(32, "check_passwd: user %s found in passwd db\n", ++ login->s); ++ if (!fast) { ++ c->gid = pw->pw_gid; ++ c->uid = pw->pw_uid; ++ /* ++ * Here we don't check the home and maildir path, if a user ++ * has a faked passwd entry, then you have a bigger problem ++ * on your system than just a guy how can read the mail of ++ * other users/customers. ++ */ ++ if (!stralloc_copys(&c->home, pw->pw_dir)) ++ return ERRNO; ++ if (!stralloc_0(&c->home)) ++ return ERRNO; ++ ++ ret = get_local_maildir(&c->home, &c->maildir); ++ if (ret != 0) ++ return ret; ++ logit(32, "get_local_maildir: maildir=%s\n", c->maildir.s); ++ } ++ ++#ifdef PW_SHADOW ++ spw = getspnam(login->s); ++ if (!spw) ++ /* XXX: again, temp hidden */ ++ return FAILED; ++ ret = cmp_passwd((unsigned char*) authdata->s, spw->sp_pwdp); ++#else /* no PW_SHADOW */ ++#ifdef AIX ++ spw = getuserpw(login->s); ++ if (!spw) ++ /* XXX: and again */ ++ return FAILED; ++ ret = cmp_passwd((unsigned char*) authdata->s, spw->upw_passwd); ++#else /* no AIX */ ++ ret = cmp_passwd((unsigned char*) authdata->s, pw->pw_passwd); ++#endif /* END AIX */ ++#endif /* END PW_SHADOW */ ++ logit(32, "check_pw: password compare was %s\n", ++ ret==OK?"successful":"not successful"); ++ return ret; ++} ++ ++ ++int ++get_local_maildir(stralloc *home, stralloc *maildir) ++{ ++ substdio ss; ++ char buf[512]; ++ int dirfd, fd, match, save; ++ ++ dirfd = open_read("."); ++ if (dirfd == -1) ++ return ERRNO; ++ if (chdir(home->s) == -1) ++ return ERRNO; ++ ++ if ((fd = open_read(".qmail")) == -1) { ++ if (errno == error_noent) return 0; ++ return ERRNO; ++ } ++ ++ substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf)); ++ while (1) { ++ if (getln(&ss, maildir, &match, '\n') != 0) goto tryclose; ++ if (!match && !maildir->len) { ++ if (!stralloc_copyb(maildir, "", 1)) goto tryclose; ++ break; ++ } ++ if ((maildir->s[0] == '.' || maildir->s[0] == '/') && ++ maildir->s[maildir->len-2] == '/') { ++ maildir->s[maildir->len-1] = '\0'; ++ break; ++ } ++ } ++ if (fchdir(dirfd) == -1) ++ return ERRNO; ++ close(dirfd); ++ close(fd); ++ return 0; ++ ++tryclose: ++ save = errno; /* preserve errno */ ++ if (fchdir(dirfd) == -1) ++ return ERRNO; ++ close(dirfd); ++ close(fd); ++ errno = save; ++ return ERRNO; ++} ++ +diff -upN qmail-1.03/locallookup.h qmail-ldap/locallookup.h +--- qmail-1.03/locallookup.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/locallookup.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __LOCALLOOKUP_H__ ++#define __LOCALLOOKUP_H__ ++ ++#include "stralloc.h" ++ ++struct credentials; ++ ++int check_passwd(stralloc *, stralloc *, struct credentials *, int); ++int get_local_maildir(stralloc *, stralloc *); ++ ++#endif ++ +diff -upN qmail-1.03/lock.h qmail-ldap/lock.h +--- qmail-1.03/lock.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/lock.h Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,8 @@ + #ifndef LOCK_H + #define LOCK_H + +-extern int lock_ex(); +-extern int lock_un(); +-extern int lock_exnb(); ++extern int lock_ex(int); ++extern int lock_un(int); ++extern int lock_exnb(int); + + #endif +diff -upN qmail-1.03/maildir++.c qmail-ldap/maildir++.c +--- qmail-1.03/maildir++.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/maildir++.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,736 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++ ++#include "alloc.h" ++#include "byte.h" ++#include "direntry.h" ++#include "error.h" ++#include "fmt.h" ++#include "getln.h" ++#include "now.h" ++#include "open.h" ++#include "readwrite.h" ++#include "scan.h" ++#include "seek.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++ ++#include "maildir++.h" ++ ++static void temp_nomem() { strerr_die1x(111,"Out of memory. (QUOTA #1.0.1)"); } ++ ++static int mailfolder(void); ++int quota_parsesize(quota_t *, int *, char *, int); ++static int quota_calcsize(quota_t *, int *, char *, int); ++static int quota_writesize(quota_t *, int *, time_t); ++static int check_maxtime(time_t); ++static int get_file_size(char *, struct stat *); ++static void calc_curnew(quota_t *, time_t *); ++static int read5120(const char *, char *, int *); ++ ++ ++static stralloc path = {0}; ++static char writebuf[3*FMT_ULONG]; /* enough big to hold all needed data */ ++static char buf5120[5120]; /* buffer for maildirsize */ ++ ++/* alarm handler */ ++static void ++sigalrm() ++{ ++ unlink(path.s); ++ strerr_die1x(111,"Timeout while writing maildirsize. (QUOTA #1.0.2)"); ++} ++ ++void ++quota_add(int fd, unsigned long size, unsigned long count) ++/* add size and count to the quota (maildirsize) */ ++{ ++ char num[FMT_ULONG]; ++ seek_pos pos; ++ substdio ss; ++ ++ if (fd == -1) return; ++ ++ seek_end(fd); ++ pos = seek_cur(fd); /* again savety */ ++ ++ substdio_fdbuf(&ss,subwrite,fd,writebuf,sizeof(writebuf)); ++ ++ /* create string of the form '1234 12\n' and add it to the quota */ ++ if (substdio_bput(&ss, num, fmt_ulong(num, size) ) == -1) ++ goto addfail; ++ if (substdio_bput(&ss, " ", 1) == -1) ++ goto addfail; ++ if (substdio_bput(&ss, num, fmt_ulong(num, count) ) == -1) ++ goto addfail; ++ if (substdio_bput(&ss, "\n", 1) == -1) ++ goto addfail; ++ if (substdio_flush(&ss) == -1) ++ goto addfail; ++ if (fsync(fd) == -1) ++ goto addfail; ++ ++ return; ++ ++addfail: ++ strerr_warn3("Unable to add file to quota: ", error_str(errno), ++ ". (QUOTA #1.2.1)",0); ++ seek_trunc(fd,pos); /* recover form error */ ++ return; /* ignore errors, perhaps the file was removed */ ++} ++ ++void ++quota_rm(int fd, unsigned long size, unsigned long count) ++/* remove size and count from the quota (maildirsize) * ++ * both size and count are POSITVE integers */ ++{ ++ char num[FMT_ULONG]; ++ seek_pos pos; ++ substdio ss; ++ ++ if (fd == -1) return; ++ ++ seek_end(fd); ++ pos = seek_cur(fd); /* again savety */ ++ ++ substdio_fdbuf(&ss,subwrite,fd,writebuf,sizeof(writebuf)); ++ ++ /* create string of the form '-1232 -12\n' and add it to the quota */ ++ if (substdio_bput(&ss, "-", 1) == -1) ++ goto rmfail; ++ if (substdio_bput(&ss, num, fmt_ulong(num, size)) == -1) ++ goto rmfail; ++ if (substdio_bput(&ss, " -", 2) == -1) ++ goto rmfail; ++ if (substdio_bput(&ss, num, fmt_ulong(num, count)) == -1) ++ goto rmfail; ++ if (substdio_bput(&ss, "\n", 1) == -1) ++ goto rmfail; ++ if (substdio_flush(&ss) == -1) ++ goto rmfail; ++ if (fsync(fd) == -1) ++ goto rmfail; ++ return; ++ ++rmfail: ++ strerr_warn3("Unable to remove file from quota: ", error_str(errno), ++ ". (QUOTA #1.3.1)",0); ++ seek_trunc(fd,pos); /* recover form error */ ++ return; /* ignore errors, perhaps the file was removed */ ++} ++ ++int ++quota_calc(const char *dir, int *fd, quota_t *q) ++{ ++ int i = 0; ++ int ret; ++ ++ if (! stralloc_copys(&path, dir)) temp_nomem(); ++ if (path.s[path.len-1] != '/') ++ if (! stralloc_cats(&path, "/")) temp_nomem(); ++ ++ while (mailfolder()) { ++ if (! stralloc_cats(&path, "../")) temp_nomem(); ++ if (i++ > 1 ) strerr_die1x(111, ++ "Unable to calc quota: recursive " ++ "maildir++ (QUOTA #1.1.1)"); ++ } ++ ++ if (! stralloc_cats(&path, "maildirsize")) temp_nomem(); ++ if (! stralloc_0(&path)) temp_nomem(); ++ ++ *fd = read5120(path.s, buf5120, &i); ++ ++ if (*fd != -1) { ++ ret = quota_parsesize(q, fd, buf5120, i); ++ } else { ++ ret = quota_calcsize(q, fd, buf5120, i); ++ } ++ return ret; ++} ++ ++int ++quota_recalc(const char *dir, int *fd, quota_t *q) ++{ ++ int i = 0; ++ int j; ++ int lines = 0; ++ time_t tm; ++ struct stat st; ++ ++ if (!stralloc_copys(&path, dir)) temp_nomem(); ++ if (path.s[path.len-1] != '/') ++ if (!stralloc_cats(&path, "/")) temp_nomem(); ++ ++ while (mailfolder()) { ++ if (!stralloc_cats(&path, "../")) temp_nomem(); ++ if (i++ > 1 ) strerr_die1x(111, ++ "Unable to calc quota: recursive " ++ "maildir++ (QUOTA #1.1.1)"); ++ } ++ ++ if (!stralloc_cats(&path, "maildirsize")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ ++ *fd = read5120(path.s, buf5120, &i); ++ ++ if (*fd != -1) { ++ for (j = 0; j < i && lines <= 2 ; j++) { ++ if (buf5120[j] == '\n') lines++; ++ } ++ if (lines <= 2) { ++ if (fstat(*fd, &st) == -1) ++ strerr_die3x(111, ++ "Unable to fstat maildirsize: ", ++ error_str(errno), " (QUOTA #1.5.1)"); ++ tm = now(); ++ if (tm < st.st_mtime + 900) { ++ /* ++ parsed quota of quota_calc() is still valid. ++ It is important that the caller does not ++ clear the quota struct. ++ */ ++ /* ++ If this can not be granted quota_parsesize() ++ needs to be called here. ++ */ ++ return 0; ++ } ++ } ++ /* need to recalculate the quota */ ++ close(*fd); ++ *fd = -1; ++ unlink(path.s); ++ } ++ ++ return quota_calcsize(q, fd, buf5120, i); ++} ++ ++int ++quota_check(quota_t *q, unsigned long size, unsigned long count, int *perc) ++{ ++ int sp , cp; ++ ++ if (q->quota_size == 0 && q->quota_count == 0) { ++ /* no quota defined */ ++ if (perc) *perc = 0; ++ return 0; ++ } ++ ++ if (perc != (int *)0) { ++ sp = q->quota_size != 0 ? ++ (int)((q->size + size)*100.0/q->quota_size) : ++ 0; ++ cp = q->quota_count != 0 ? ++ (int)((q->count + count)*100.0/q->quota_count) : ++ 0; ++ if (sp > cp) ++ *perc = sp; ++ else ++ *perc = cp; ++ } ++ ++ if (q->size + size > q->quota_size && q->quota_size != 0) { ++ return -1; ++ } ++ ++ if (q->count + count > q->quota_count && q->quota_count != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void ++quota_get(quota_t *q, const char *quota) ++{ ++ unsigned long i; ++ ++ q->quota_size = 0; ++ q->quota_count = 0; ++ q->size = 0; ++ q->count = 0; ++ ++ if (quota == (char *)0) return; ++ ++ while (*quota) { ++ if (*quota < '0' || *quota > '9') { ++ quota++; ++ continue; ++ } ++ ++ /* parse found number */ ++ quota += scan_ulong(quota, &i); ++ ++ switch (*quota) { ++ case 'S': ++ q->quota_size = i; ++ break; ++ case 'C': ++ q->quota_count = i; ++ break; ++ default: ++ /* ignore */ ++ break; ++ } ++ } ++} ++ ++static int ++mailfolder(void) ++{ ++ unsigned int len; ++ struct stat st; ++ ++ /* ++ * check if we are in a maildir subfolder, normaly this is impossible ++ */ ++ ++ len = path.len; ++ if (!stralloc_cats(&path, "maildirfolder")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ path.len = len; /* cut away what this function has added */ ++ ++ if (stat(path.s, &st) == -1) { /* are we in a subdir ? */ ++ if (errno != error_noent) { ++ strerr_die3x(111, "Unable to stat maildirfolder: ", ++ error_str(errno), " (QUOTA #1.4.1)"); ++ } ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++int ++quota_parsesize(quota_t *q, int *fd, char *buf, int len) ++{ ++ char *s; ++ quota_t dummy; ++ long fig, pn; ++ int i; ++ char c; ++ ++ for (i = 0; i < len; i++) { ++ if (buf[i] == '\n') buf[i] = '\0'; ++ } ++ ++ quota_get(&dummy, buf); ++ if (q->quota_size == 0 && q->quota_count == 0) { ++ /* no quota defined */ ++ q->quota_size = dummy.quota_size; ++ q->quota_count = dummy.quota_count; ++ } ++ ++ if (q->quota_size != dummy.quota_size || ++ q->quota_count != dummy.quota_count) { ++ /* quota definition has changed, remove old maildirsize file ++ * and recalculate the quota */ ++ close(*fd); *fd = -1; ++ unlink(path.s); ++ return quota_calcsize(q, fd, buf, len); ++ } ++ ++ q->size = 0; q->count = 0; /* just to be sure */ ++ s = buf; ++ ++ while (s - buf < len) { ++ while (*s++) ; /* hop over the last line */ ++ ++ pn = 1; ++ while ((c = *s) < '0' || c > '9') { ++ if (c == '\0') break; ++ if (c == '-') pn = -1; ++ s++; /* hop over spaces */ ++ } ++ if (c == '\0') continue; ++ ++ /* first comes the size ... */ ++ if ((i = scan_ulong(s, &fig)) == 0) continue; ++ s += i; ++ q->size += (fig * pn); ++ ++ pn = 1; ++ while ((c = *s) < '0' || c > '9') { ++ if (c == '-') pn = -1; ++ s++; /* hop over spaces */ ++ } ++ ++ /* ... then the file count */ ++ if ((i = scan_ulong(s, &fig)) == 0) continue; ++ s += i; ++ q->count += (fig * pn); ++ } ++ ++ return 0; ++} ++ ++static int ++quota_calcsize(quota_t *q, int *fd, char *buf, int len) ++{ ++ unsigned int plen; ++ time_t tm; ++ time_t maxtime; ++ direntry *dp; ++ DIR *dirp; ++ ++ if (q->quota_size == 0 && q->quota_count == 0) { ++ /* no quota defined */ ++ return 0; ++ } ++ ++ q->size = 0; q->count = 0; /* just to be sure */ ++ ++ tm = now(); ++ maxtime = 0; ++ ++ /* first pop away 'maildirsize' in path */ ++ path.len -= 12; /* including the '\0' char */ ++ plen = path.len; ++ ++ if (!stralloc_0(&path)) temp_nomem(); ++ ++ dirp = opendir(path.s); ++ while (dirp && (dp = readdir(dirp)) != 0) { ++ if (dp->d_name[0] == '.' && ++ dp->d_name[1] != '\0' && ++ dp->d_name[1] != '.' ++#ifndef QUOTATRASH ++ && str_diff(".Trash", dp->d_name) ++#endif ++ ) { ++ ++ path.len = plen; ++ if (!stralloc_cats(&path, dp->d_name)) temp_nomem(); ++ calc_curnew(q, &maxtime); ++ path.len = plen; ++ } ++ } ++ if (dirp) closedir(dirp); ++ ++ path.len = plen; ++ calc_curnew(q, &maxtime); ++ path.len = plen; ++ ++ /* quota is calculated, now create the new maildirsize file */ ++ return quota_writesize(q, fd, maxtime); ++} ++ ++static int ++quota_writesize(quota_t *q, int *fd, time_t maxtime) ++{ ++ int pid; ++ int i; ++ char *buf; ++ char *s; ++ char num[FMT_ULONG]; ++ time_t tm; ++ struct stat st; ++ substdio ss; ++ ++ /* write maildirsize in standart Maildir manner */ ++ sig_alarmcatch(sigalrm); ++ ++ for (i = 0; ; ++i) { ++ tm = now(); ++ pid = getpid(); ++ buf = (char *)alloc(path.len + 17 + (2 * FMT_ULONG) + 2); ++ if (buf == (char *)0) ++ temp_nomem(); ++ s = buf; ++ byte_copy(s, path.len, path.s); s += path.len; ++ byte_copy(s, 17, "/tmp/maildirsize."); s += 17; ++ s += fmt_ulong(s,maxtime); *s++ = '.'; ++ s += fmt_ulong(s,pid); *s++ = 0; ++ if (stat(buf, &st) == -1) if (errno == error_noent) break; ++ /* really should never get to this point */ ++ if (i == 2) _exit(1); ++ sleep(2); ++ } ++ ++ alarm(86400); ++ ++ if ((*fd = open(buf, O_RDWR|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1) { ++ if (errno == error_noent) return 0; ++ goto fail; ++ } ++ ++ substdio_fdbuf(&ss,subwrite,*fd,writebuf,sizeof(writebuf)); ++ ++ if (q->quota_size != 0) { ++ if (substdio_bput(&ss, num, fmt_ulong(num, q->quota_size)) ++ == -1 ) ++ goto fail; ++ if (substdio_bput(&ss,"S", 1) == -1) ++ goto fail; ++ if (q->quota_count != 0) ++ if (substdio_bput(&ss,",", 1) == -1) ++ goto fail; ++ } ++ if (q->quota_count != 0) { ++ if (substdio_bput(&ss, num, fmt_ulong(num, q->quota_count)) ++ == -1) ++ goto fail; ++ if (substdio_bput(&ss,"C", 1) == -1 ) ++ goto fail; ++ } ++ if (substdio_bput(&ss,"\n", 1) == -1) ++ goto fail; ++ if (substdio_bput(&ss, num, fmt_ulong(num, q->size)) == -1) ++ goto fail; ++ if (substdio_bput(&ss, " ", 1) == -1) ++ goto fail; ++ if (substdio_bput(&ss, num, fmt_ulong(num, q->count)) == -1) ++ goto fail; ++ if (substdio_bput(&ss, "\n", 1) == -1) ++ goto fail; ++ if (substdio_flush(&ss) == -1) ++ goto fail; ++ if (fsync(*fd) == -1) ++ goto fail; ++ ++ i = check_maxtime(maxtime); ++ if (!stralloc_cats(&path, "maildirsize")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ if (unlink(path.s) == -1 && errno != error_noent) goto fail; ++ ++ if (i) { ++ /* race condition, don't write maildir size */ ++ unlink(buf); ++ alloc_free(buf); ++ *fd = -1; ++ return -1; ++ } ++ if (link(buf,path.s) == -1) goto fail; ++ unlink(buf); ++ ++ /* unset the alarm, else %*#! may happen */ ++ alarm(0); ++ sig_alarmdefault(); ++ ++ return 0; ++ ++fail: ++ strerr_warn3("Problems while trying to get maildirsize: ", ++ error_str(errno), ". (QUOTA #1.1.1)", 0); ++ unlink(buf); ++ *fd = -1; ++ return -1; ++} ++ ++static int ++check_maxtime(time_t t) ++/* check if a directory has changed, to avoid race conditions */ ++{ ++ direntry *dp; ++ DIR *dirp; ++ struct stat filest; ++ unsigned int slen; ++ int i; ++ ++ slen = path.len; ++ if (!stralloc_0(&path)) temp_nomem(); ++ dirp = opendir(path.s); ++ path.len = slen; ++ ++ i = 0; ++ while (dirp && (dp = readdir(dirp)) != 0) { ++ if (dp->d_name[0] == '.' && ++ dp->d_name[1] != '\0' && ++ dp->d_name[1] != '.' ++#ifndef QUOTATRASH ++ && str_diff(".Trash", dp->d_name) ++#endif ++ ) { ++ ++ path.len = slen; ++ if (!stralloc_cats(&path, dp->d_name)) temp_nomem(); ++ if (!stralloc_cats(&path, "/cur")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ if (stat(path.s, &filest) == 0 ++ && filest.st_mtime > t) { ++ i = 1; ++ break; ++ } ++ path.len = slen; ++ if (!stralloc_cats(&path, dp->d_name)) temp_nomem(); ++ if (!stralloc_cats(&path, "/new")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ if (stat(path.s, &filest) == 0 ++ && filest.st_mtime > t) { ++ i = 1; ++ break; ++ } ++ } ++ if (!str_diff("new", dp->d_name)) { ++ path.len = slen; ++ if (!stralloc_cats(&path, "/new")) temp_nomem(); ++ if (stat(path.s, &filest) == 0 ++ && filest.st_mtime > t) { ++ i = 1; ++ break; ++ } ++ } ++ if (!str_diff("cur", dp->d_name)) { ++ path.len = slen; ++ if (!stralloc_cats(&path, "/cur")) temp_nomem(); ++ if (stat(path.s, &filest) == 0 ++ && filest.st_mtime > t) { ++ i = 1; ++ break; ++ } ++ } ++ } ++ if (dirp) closedir(dirp); ++ ++ path.len = slen; ++ return i; ++} ++ ++static int ++get_file_size(char *name, struct stat *st) ++/* get the filesize of the file name in dir, via the name or a stat */ ++{ ++ char *s = name; ++ unsigned int slen; ++ ++ while (*s) { ++ if (*s != ',' || s[1] != 'S' || s[2] != '=') { ++ s++; ++ } else { ++ s += 3; ++ st->st_size = 0; ++ while (*s >= '0' && *s <= '9') ++ st->st_size = st->st_size*10 + (*s++ - '0'); ++ return 0; ++ } ++ } ++ /* stat the file */ ++ slen = --path.len; /* path was zero terminated */ ++ if (!stralloc_cats(&path, name)) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ path.len = slen; ++ ++ if (stat(path.s, st) == 0) { ++ if (!stralloc_0(&path)) temp_nomem(); ++ return 0; ++ } else { ++ if (!stralloc_0(&path)) temp_nomem(); ++ return -1; ++ } ++} ++ ++static void ++calc_curnew(quota_t *q, time_t *maxtime) ++/* calculate the size of the two dirs new and cur of a maildir ++ * (uses get_file_size) */ ++{ ++ struct stat filest; ++ direntry *dp; ++ DIR *dirp; ++ char *f; ++ int i; ++ ++ if (!stralloc_cats(&path, "/new/")) temp_nomem(); ++ if (!stralloc_0(&path)) temp_nomem(); ++ ++ for (i = 0; i < 2; i++) { ++ /* update the latest modified time to avoid race conditions */ ++ if (stat(path.s, &filest) == 0 && filest.st_mtime > *maxtime) ++ *maxtime = filest.st_mtime; ++ ++ dirp = opendir(path.s); ++ /* start with new */ ++ while (dirp && (dp = readdir(dirp)) != 0) { ++ f = dp->d_name; ++ if ( *f == '.' ) continue; /* ignore all dot-files */ ++ while(*f) { ++ if (*f != ':' || f[1] != '2' || f[2] != ',') { ++ f++; ++ } else { ++ f += 3; ++ while ( *f >= 'A' ++ && *f <= 'Z' ++ && *f != 'T') f++; ++ break; ++ } ++ } ++ if (*f == 'T') continue; ++ /* get the file size */ ++ if(get_file_size(dp->d_name, &filest) == 0) { ++ q->count++; ++ q->size += (long)filest.st_size; ++ } ++ } ++ if (dirp) closedir(dirp); ++ ++ /* the same thing with cur */ ++ fmt_str(path.s + path.len - 5, "cur"); ++ } ++} ++ ++static int ++read5120(const char *fn, char* buf, int *len) ++{ ++ int fd; ++ int r; ++ ++ if ((fd = open(fn, O_RDWR|O_NDELAY|O_APPEND, 0600)) == -1) { ++ if (errno == error_noent) return -1; ++ strerr_die3x(111, "Unable to open maildirsize: ", ++ error_str(errno), " (QUOTA #1.5.1)"); ++ } ++ ++ *len = 0; ++ for (;;) { ++ r = read(fd, buf, 5120 - *len); ++ if (r == -1) if (errno == error_intr) continue; ++ if (*len >= 5120) { /* file to big */ ++ close(fd); ++ unlink(path.s); ++ return -1; ++ } ++ if (r == 0) return fd; /* no more data */ ++ *len += r; ++ buf += r; ++ } ++} ++ +diff -upN qmail-1.03/maildir++.h qmail-ldap/maildir++.h +--- qmail-1.03/maildir++.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/maildir++.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __MAILDIRPP_H__ ++#define __MAILDIRPP_H__ ++ ++typedef struct { ++ unsigned long quota_size; ++ unsigned long quota_count; ++ long size; ++ long count; ++} quota_t; ++ ++void quota_add(int , unsigned long , unsigned long); ++void quota_rm(int , unsigned long , unsigned long); ++int quota_calc(const char *, int *fd, quota_t *); ++int quota_recalc(const char *, int *fd, quota_t *); ++int quota_check(quota_t *, unsigned long , unsigned long , int *); ++void quota_get(quota_t *, const char *); ++ ++#endif +diff -upN qmail-1.03/maildir.c qmail-ldap/maildir.c +--- qmail-1.03/maildir.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/maildir.c Tue Oct 28 18:21:32 2003 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "prioq.h" + #include "env.h" + #include "stralloc.h" +@@ -12,7 +13,7 @@ + struct strerr maildir_chdir_err; + struct strerr maildir_scan_err; + +-int maildir_chdir() ++int maildir_chdir(void) + { + char *maildir; + maildir = env_get("MAILDIR"); +@@ -28,32 +29,32 @@ stralloc *tmpname; + { + DIR *dir; + direntry *d; +- datetime_sec time; ++ datetime_sec tnow; + struct stat st; + +- time = now(); ++ tnow = now(); + + dir = opendir("tmp"); + if (!dir) return; + +- while (d = readdir(dir)) ++ while ((d = readdir(dir))) + { + if (d->d_name[0] == '.') continue; + if (!stralloc_copys(tmpname,"tmp/")) break; + if (!stralloc_cats(tmpname,d->d_name)) break; + if (!stralloc_0(tmpname)) break; + if (stat(tmpname->s,&st) == 0) +- if (time > st.st_atime + 129600) ++ if (tnow > st.st_atime + 129600) + unlink(tmpname->s); + } + closedir(dir); + } + +-static int append(pq,filenames,subdir,time) ++static int append(pq,filenames,subdir,tnow) + prioq *pq; + stralloc *filenames; + char *subdir; +-datetime_sec time; ++datetime_sec tnow; + { + DIR *dir; + direntry *d; +@@ -65,7 +66,7 @@ datetime_sec time; + if (!dir) + STRERR_SYS3(-1,maildir_scan_err,"unable to scan $MAILDIR/",subdir,": ") + +- while (d = readdir(dir)) ++ while ((d = readdir(dir))) + { + if (d->d_name[0] == '.') continue; + pos = filenames->len; +@@ -74,7 +75,7 @@ datetime_sec time; + if (!stralloc_cats(filenames,d->d_name)) break; + if (!stralloc_0(filenames)) break; + if (stat(filenames->s + pos,&st) == 0) +- if (st.st_mtime < time) /* don't want to mix up the order */ ++ if (st.st_mtime < tnow) /* don't want to mix up the order */ + { + pe.dt = st.st_mtime; + pe.id = pos; +@@ -94,15 +95,14 @@ int flagnew; + int flagcur; + { + struct prioq_elt pe; +- datetime_sec time; +- int r; ++ datetime_sec tnow; + + if (!stralloc_copys(filenames,"")) return 0; + while (prioq_min(pq,&pe)) prioq_delmin(pq); + +- time = now(); ++ tnow = now(); + +- if (flagnew) if (append(pq,filenames,"new",time) == -1) return -1; +- if (flagcur) if (append(pq,filenames,"cur",time) == -1) return -1; ++ if (flagnew) if (append(pq,filenames,"new",tnow) == -1) return -1; ++ if (flagcur) if (append(pq,filenames,"cur",tnow) == -1) return -1; + return 0; + } +diff -upN qmail-1.03/maildir.h qmail-ldap/maildir.h +--- qmail-1.03/maildir.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/maildir.h Tue Oct 28 18:21:32 2003 +@@ -1,12 +1,15 @@ + #ifndef MAILDIR_H + #define MAILDIR_H + ++#include "prioq.h" ++#include "stralloc.h" + #include "strerr.h" ++ + extern struct strerr maildir_chdir_err; + extern struct strerr maildir_scan_err; + +-extern int maildir_chdir(); +-extern void maildir_clean(); +-extern int maildir_scan(); ++extern int maildir_chdir(void); ++extern void maildir_clean(stralloc *); ++extern int maildir_scan(prioq *, stralloc *, int, int); + + #endif +diff -upN qmail-1.03/maildir2mbox.c qmail-ldap/maildir2mbox.c +--- qmail-1.03/maildir2mbox.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/maildir2mbox.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,7 @@ ++#include ++#include ++#include ++#include + #include "readwrite.h" + #include "prioq.h" + #include "env.h" +@@ -33,7 +37,7 @@ char outbuf[SUBSTDIO_OUTSIZE]; + + void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); } + +-void main() ++int main() + { + substdio ssin; + substdio ssout; +@@ -73,8 +77,8 @@ void main() + if (fdnewmbox == -1) + strerr_die4sys(111,FATAL,"unable to create ",mboxtmp,": "); + +- substdio_fdbuf(&ssin,read,fdoldmbox,inbuf,sizeof(inbuf)); +- substdio_fdbuf(&ssout,write,fdnewmbox,outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ssin,subread,fdoldmbox,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssout,subwrite,fdnewmbox,outbuf,sizeof(outbuf)); + + switch(substdio_copy(&ssout,&ssin)) + { +@@ -90,7 +94,7 @@ void main() + fd = open_read(filenames.s + pe.id); + if (fd == -1) + strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": "); +- substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf)); + + if (getln(&ssin,&line,&match,'\n') != 0) + strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": "); +@@ -158,5 +162,5 @@ void main() + strerr_warn4(WARNING,"$MAILDIR/",filenames.s + pe.id," will be delivered twice; unable to unlink: ",&strerr_sys); + } + +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/maildirmake.c qmail-ldap/maildirmake.c +--- qmail-1.03/maildirmake.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/maildirmake.c Tue Oct 28 18:21:32 2003 +@@ -1,9 +1,12 @@ ++#include ++#include ++#include + #include "strerr.h" + #include "exit.h" + + #define FATAL "maildirmake: fatal: " + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -20,5 +23,5 @@ char **argv; + strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/new: "); + if (mkdir("cur",0700) == -1) + strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/cur: "); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/maildirwatch.c qmail-ldap/maildirwatch.c +--- qmail-1.03/maildirwatch.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/maildirwatch.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "getln.h" + #include "substdio.h" + #include "subfd.h" +@@ -28,7 +29,7 @@ void addtext(s,n) char *s; int n; + void dobody(h) stralloc *h; { addtext(h->s,h->len); } + void doheader(h) stralloc *h; + { +- int i; ++ unsigned int i; + switch(hfield_known(h->s,h->len)) + { + case H_SUBJECT: +@@ -58,11 +59,11 @@ prioq pq = {0}; + char inbuf[SUBSTDIO_INSIZE]; + substdio ssin; + +-void main() ++int main() + { + struct prioq_elt pe; + int fd; +- int i; ++ unsigned int i; + + if (maildir_chdir() == -1) + strerr_die1(111,FATAL,&maildir_chdir_err); +@@ -81,7 +82,7 @@ void main() + + fd = open_read(filenames.s + pe.id); + if (fd == -1) continue; +- substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf)); + + if (!stralloc_copys(&sender,"?")) die_nomem(); + if (!stralloc_copys(&recipient,"?")) die_nomem(); +@@ -122,4 +123,6 @@ void main() + substdio_flush(subfdout); + sleep(30); + } ++ /* NOTREACHED */ ++ return 1; + } +diff -upN qmail-1.03/mailmagic.c qmail-ldap/mailmagic.c +--- qmail-1.03/mailmagic.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/mailmagic.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,205 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "byte.h" ++#include "case.h" ++#include "error.h" ++#include "getln.h" ++#include "now.h" ++#include "stralloc.h" ++#include "substdio.h" ++ ++#include "qmail-ldap.h" ++#include "mailmagic.h" ++ ++static unsigned int mypos; ++static stralloc *mysa; ++ ++static void ++sa_init(stralloc *header) ++{ ++ mypos = 0; ++ mysa = header; ++} ++ ++static int ++sa_read(int fd, void *buf, int len) ++{ ++ int t; ++ ++ t = mysa->len - mypos; ++ if (t == 0) return 0; ++ if (t < 0) { ++ errno = error_io; ++ return -1; ++ } ++ if (t > len) t = len; ++ byte_copy(buf, t, mysa->s + mypos); ++ mypos += t; ++ return t; ++} ++ ++static char buf[256]; ++static stralloc line = {0}; ++ ++#ifndef REPLY_SUBJ ++#define REPLY_SUBJ "Your Mail" ++#endif ++ ++static unsigned int ++magicsubject(stralloc *l, stralloc *h, stralloc *s) ++{ ++ unsigned int i, j; ++ ++ j = l->len; ++ for (i = 0; i < j; i++) { ++ if (l->s[i] != '%') { ++ if (!stralloc_append(h, &l->s[i])) return -1; ++ continue; ++ } ++ if (case_startb(l->s + i, j - i, "%SUBJECT%") == 0) { ++ if (!stralloc_append(h, &l->s[i])) return -1; ++ continue; ++ } ++ i += 8; /* strlen("%SUBJECT%") - 1 */ ++ if (s == 0 || s->s == 0 || s->len == 0) { ++ if (!stralloc_cats(h, REPLY_SUBJ)) return -1; ++ } else { ++ if (!stralloc_cat(h, s)) return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++headermagic(stralloc *mess, stralloc *header, stralloc *subj, ++ struct mheader *h) ++{ ++ substdio ss; ++ unsigned int pos, i; ++ int match, w; ++ ++ if (!stralloc_copys(header, "")) return -1; ++ for (i = 0; h[i].f != 0; i++) h[i].seen = 0; ++ pos = 0; w = 0; ++ ++ sa_init(mess); ++ substdio_fdbuf(&ss, sa_read, -1, buf, sizeof(buf)); ++ if (getln(&ss, &line, &match, '\n') != 0) return -1; ++ if (match && case_diffb(line.s, line.len, "%HEADER%\n") == 0) { ++ pos += line.len; ++ for (;;) { ++ if (getln(&ss, &line, &match, '\n') != 0) return -1; ++ if (!match) break; ++ pos += line.len; ++ if (line.len <= 1) break; ++ if (*line.s == '\t' || *line.s == ' ') ++ if (w) { ++ if (!stralloc_cat(header, &line)) ++ return -1; ++ continue; ++ } ++ w = 0; ++ for (i = 0; h[i].f != 0; i++) { ++ if (case_startb(line.s, line.len, h[i].f) == 0) ++ continue; ++ if (h[i].type == DENY) break; ++ if (h[i].type == FORCE) break; ++ w = 1; ++ h[i].seen = 1; ++ if (h[i].type == SUBJECT) { ++ if (magicsubject(&line, ++ header, subj) == -1) ++ return -1; ++ break; ++ } ++ if (!stralloc_cat(header, &line)) return -1; ++ } ++ } ++ } ++ ++ for (i = 0; h[i].f != 0; i++) ++ if (h[i].seen == 0 && h[i].v != 0) ++ if (h[i].type != DENY ) { ++ if (h[i].type == SUBJECT) { ++ if (!stralloc_copys(&line, h[i].f)) ++ return -1; ++ if (!stralloc_append(&line, " ")) ++ return -1; ++ if (!stralloc_cats(&line, h[i].v)) ++ return -1; ++ if (line.s[line.len-1] != '\n') ++ if (!stralloc_append(&line, ++ "\n")) return -1; ++ if (magicsubject(&line, ++ header, subj) == -1) ++ return -1; ++ continue; ++ } ++ if (!stralloc_cats(header, h[i].f)) return -1; ++ if (!stralloc_append(header, " ")) return -1; ++ if (!stralloc_cats(header, h[i].v)) return -1; ++ if (header->s[header->len-1] != '\n') ++ if (!stralloc_append(header, "\n")) ++ return -1; ++ } ++ return pos; ++} ++ ++static stralloc mimebound = {0}; ++ ++int ++mimemagichead(stralloc *h, stralloc *salt) ++{ ++ if (!stralloc_copys(&mimebound, "--")) return -1; ++ if (!stralloc_cat(&mimebound, salt)) return -1; ++ ++ if (!stralloc_cats(h, "Content-Type: multipart/mixed; boundary=\"")) ++ return -1; ++ if (!stralloc_catb(h, mimebound.s + 2, mimebound.len - 2)) return -1; ++ if (!stralloc_cats(h, "\"\n\n" ++ "This is a multi-part message in MIME format.\n" ++ "If you can read this your mail user agent does" ++ "not support MIME messages\n")) return -1; ++ ++ if (!stralloc_0(&mimebound)) return -1; ++ return 0; ++} ++ ++char * ++mimemagic(void) ++{ ++ return mimebound.s; ++} ++ +diff -upN qmail-1.03/mailmagic.h qmail-ldap/mailmagic.h +--- qmail-1.03/mailmagic.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/mailmagic.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __HEADERMAGIC_H__ ++#define __HEADERMAGIC_H__ ++ ++#include "stralloc.h" ++ ++#define DENY 1 ++#define ALLOW 2 ++#define FORCE 3 ++#define SUBJECT 4 ++#define DEFAULT "" ++ ++struct mheader { ++ const char *f; /* field */ ++ const char *v; /* default value */ ++ int type; /* one of DENY, ALLOW, FORCE, SUBJECT */ ++ int seen; /* used internally */ ++}; ++ ++int headermagic(stralloc *, stralloc *, stralloc *, struct mheader *); ++int mimemagichead(stralloc *, stralloc *); ++char *mimemagic(void); ++ ++#endif ++ +diff -upN qmail-1.03/mailmaker.c qmail-ldap/mailmaker.c +--- qmail-1.03/mailmaker.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/mailmaker.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,112 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifdef AUTOMAILDIRMAKE ++#include ++#include ++#include ++#include ++ ++#include "error.h" ++#include "open.h" ++#include "qldap-errno.h" ++ ++#include "mailmaker.h" ++ ++/* ++ * XXX the maildirmake stuff is directly in qmail-local.c and qmail-pop3d.c ++ * XXX this is simpler and better (Perhaps I'll find a better way sometimes) ;-) ++ * XXX BULLSHIT! Simpler and better, was I on drugs? This needs definitifly a ++ * XXX rewrite and while doing that I can also fix the problem with courier. ++ */ ++static int makedir(const char *); ++ ++static int ++makedir(const char *dir) ++{ ++ struct stat st; ++ ++ if (stat(dir, &st) == -1) { ++ if (errno == error_noent) { ++ if (mkdir(dir,0700) == -1) return ERRNO; ++ } else ++ return ERRNO; ++ } else if (!S_ISDIR(st.st_mode)) ++ return MAILDIR_CORRUPT; ++ ++ return OK; ++} ++ ++int ++maildir_make(char *maildir) ++{ ++ int dirfd, oldmask, r, se; ++ ++ oldmask = umask(077); ++ dirfd = open_read("."); ++ if (dirfd == -1) ++ return ERRNO; ++ if (chdir(maildir) == -1) { ++ if ((r = makedir(maildir)) != OK) goto fail; ++ if (chdir(maildir) == -1) { ++ if (errno == ENOTDIR) { ++ r = MAILDIR_CORRUPT; ++ goto fail; ++ } else { ++ r = ERRNO; ++ goto fail; ++ } ++ } ++ } ++ if ((r = makedir("tmp")) != OK) goto fail; ++ if ((r = makedir("cur")) != OK) goto fail; ++ if ((r = makedir("new")) != OK) goto fail; ++ ++ umask(oldmask); ++ if (fchdir(dirfd) == -1) { ++ r = ERRNO; ++ goto fail; ++ } ++ close(dirfd); ++ return OK; ++ ++fail: ++ se = errno; ++ umask(oldmask); ++ fchdir(dirfd); ++ close(dirfd); ++ errno = se; ++ return r; ++} ++#endif ++ +diff -upN qmail-1.03/mailmaker.h qmail-ldap/mailmaker.h +--- qmail-1.03/mailmaker.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/mailmaker.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __MAILMAKER_H__ ++#define __MAILMAKER_H__ ++ ++/* checks and creates maildirs as needed */ ++int maildir_make(char *); ++ ++#endif +diff -upN qmail-1.03/myctime.c qmail-ldap/myctime.c +--- qmail-1.03/myctime.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/myctime.c Tue Oct 28 18:21:32 2003 +@@ -2,10 +2,10 @@ + #include "fmt.h" + #include "myctime.h" + +-static char *daytab[7] = { ++static const char *daytab[7] = { + "Sun","Mon","Tue","Wed","Thu","Fri","Sat" + }; +-static char *montab[12] = { ++static const char *montab[12] = { + "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" + }; + +diff -upN qmail-1.03/myctime.h qmail-ldap/myctime.h +--- qmail-1.03/myctime.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/myctime.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,8 @@ + #ifndef MYCTIME_H + #define MYCTIME_H + +-extern char *myctime(); ++#include "datetime.h" ++ ++extern char *myctime(datetime_sec); + + #endif +diff -upN qmail-1.03/ndelay.h qmail-ldap/ndelay.h +--- qmail-1.03/ndelay.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/ndelay.h Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #ifndef NDELAY_H + #define NDELAY_H + +-extern int ndelay_on(); +-extern int ndelay_off(); ++extern int ndelay_on(int fd); ++extern int ndelay_off(int fd); + + #endif +diff -upN qmail-1.03/newfield.c qmail-ldap/newfield.c +--- qmail-1.03/newfield.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/newfield.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,5 @@ ++#include ++#include + #include "fmt.h" + #include "datetime.h" + #include "stralloc.h" +@@ -25,7 +27,7 @@ datetime_sec when; + + static unsigned int msgidfmt(s,idhost,idhostlen,when) + char *s; +-char *idhost; ++const char *idhost; + int idhostlen; + datetime_sec when; + { +@@ -58,7 +60,7 @@ datetime_sec when; + } + + int newfield_msgidmake(idhost,idhostlen,when) +-char *idhost; ++const char *idhost; + int idhostlen; + datetime_sec when; + { +diff -upN qmail-1.03/newfield.h qmail-ldap/newfield.h +--- qmail-1.03/newfield.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/newfield.h Tue Oct 28 18:21:32 2003 +@@ -1,12 +1,13 @@ + #ifndef NEWFIELD_H + #define NEWFIELD_H + ++#include "datetime.h" + #include "stralloc.h" + + extern stralloc newfield_date; +-extern int newfield_datemake(); ++extern int newfield_datemake(datetime_sec); + + extern stralloc newfield_msgid; +-extern int newfield_msgidmake(); ++extern int newfield_msgidmake(const char *, int, datetime_sec); + + #endif +diff -upN qmail-1.03/now.c qmail-ldap/now.c +--- qmail-1.03/now.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/now.c Tue Oct 28 18:21:32 2003 +@@ -2,7 +2,7 @@ + #include "datetime.h" + #include "now.h" + +-datetime_sec now() ++datetime_sec now(void) + { +- return time((long *) 0); ++ return time((void *)0); + } +diff -upN qmail-1.03/now.h qmail-ldap/now.h +--- qmail-1.03/now.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/now.h Tue Oct 28 18:21:32 2003 +@@ -3,6 +3,6 @@ + + #include "datetime.h" + +-extern datetime_sec now(); ++extern datetime_sec now(void); + + #endif +diff -upN qmail-1.03/open.h qmail-ldap/open.h +--- qmail-1.03/open.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open.h Tue Oct 28 18:21:32 2003 +@@ -1,10 +1,10 @@ + #ifndef OPEN_H + #define OPEN_H + +-extern int open_read(); +-extern int open_excl(); +-extern int open_append(); +-extern int open_trunc(); +-extern int open_write(); ++extern int open_read(const char *); ++extern int open_excl(const char *); ++extern int open_append(const char *); ++extern int open_trunc(const char *); ++extern int open_write(const char *); + + #endif +diff -upN qmail-1.03/open_append.c qmail-ldap/open_append.c +--- qmail-1.03/open_append.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open_append.c Tue Oct 28 18:21:32 2003 +@@ -2,5 +2,5 @@ + #include + #include "open.h" + +-int open_append(fn) char *fn; ++int open_append(fn) const char *fn; + { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } +diff -upN qmail-1.03/open_excl.c qmail-ldap/open_excl.c +--- qmail-1.03/open_excl.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open_excl.c Tue Oct 28 18:21:32 2003 +@@ -2,5 +2,5 @@ + #include + #include "open.h" + +-int open_excl(fn) char *fn; ++int open_excl(fn) const char *fn; + { return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); } +diff -upN qmail-1.03/open_read.c qmail-ldap/open_read.c +--- qmail-1.03/open_read.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open_read.c Tue Oct 28 18:21:32 2003 +@@ -2,5 +2,5 @@ + #include + #include "open.h" + +-int open_read(fn) char *fn; ++int open_read(fn) const char *fn; + { return open(fn,O_RDONLY | O_NDELAY); } +diff -upN qmail-1.03/open_trunc.c qmail-ldap/open_trunc.c +--- qmail-1.03/open_trunc.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open_trunc.c Tue Oct 28 18:21:32 2003 +@@ -2,5 +2,5 @@ + #include + #include "open.h" + +-int open_trunc(fn) char *fn; ++int open_trunc(fn) const char *fn; + { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } +diff -upN qmail-1.03/open_write.c qmail-ldap/open_write.c +--- qmail-1.03/open_write.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/open_write.c Tue Oct 28 18:21:32 2003 +@@ -2,5 +2,5 @@ + #include + #include "open.h" + +-int open_write(fn) char *fn; ++int open_write(fn) const char *fn; + { return open(fn,O_WRONLY | O_NDELAY); } +diff -upN qmail-1.03/output.c qmail-ldap/output.c +--- qmail-1.03/output.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/output.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,181 @@ ++/* ++ * Copyright (c) 2001-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "stralloc.h" ++#include "substdio.h" ++#include "fmt.h" ++#include "str.h" ++#include "scan.h" ++#include "output.h" ++ ++#include ++ ++char num[FMT_ULONG]; ++ ++static const char nullString[] = "(null pointer)"; ++static const char ioHexArray[] = "0123456789abcdef"; ++ ++static int fmt_hexulong(char *s, unsigned long x) ++ /* s has to be allready allocated, use at least FMT_ULONG chars ++ * 40 chars should be enough for a 20 byte unsigned long (2^160) ++ * so djb's fmt_ulong would first fail ;-) */ ++{ ++ unsigned int i; ++ ++ for (i = 0; i < sizeof(unsigned long) * 2; i++) { ++ *s++ = (ioHexArray[(x >> (sizeof(unsigned long)*8 - 4)) & 0xf]); ++ x = x << 4; ++ } ++ return sizeof(unsigned long) * 2; ++} ++ ++void va_output(substdio *ss, char const *fmt, va_list args) ++/* ++ * works like vprintf has the format options %i, ... ++ * all flags (#, 0, -, ' ', +, ' ... ) are not supported if not special noted ++ * Also not supported are all options for foating-point numbers ++ * (not needed in qmail) ++ * Supported conversion specifiers: diouxcsSp% ++ * diux are for integer (long) conversions ++ * c is a single unsigned char ++ * s is a zero terminated string ++ * S is a stralloc object (should not be zero terminated (else the zero ++ * will be printed)) ++ * p is the hex address of a generic pointer (void *) ++ * % is the % sign ++ */ ++{ ++ unsigned long ul; ++ long l; ++ char *s; ++ char const *start; ++ char const *cur; ++ void *p; ++ unsigned char c; ++ stralloc *sa; ++ ++ start = fmt; ++ cur = fmt; ++ if (!cur) return; ++ while (*cur) { ++ if (*cur == '%') { ++ if ( substdio_put(ss, start, cur-start) == -1 ) return; ++ /* ++ * no need to care if the output is save qmail-send ++ * looks if the output is save ++ */ ++ cur++; ++ switch (*cur) { ++ case 'd': ++ case 'i': ++ l = va_arg(args, long); ++ if (l < 0) { ++ /* negativ number, d and i are signed */ ++ l *= -1; ++ if (substdio_put(ss, "-", 1) == -1) ++ return; ++ } ++ ul = (unsigned long)l; ++ if (substdio_put(ss, num, fmt_ulong(num, ul))) ++ return; ++ break; ++ case 'u': ++ ul = va_arg(args, unsigned long); ++ if (substdio_put(ss, num, fmt_ulong(num, ul))) ++ return; ++ break; ++ case 's': ++ s = va_arg(args, char *); ++ if (!s) { ++ if (substdio_put(ss, nullString, ++ str_len(nullString))) ++ return; ++ break; ++ } ++ if (substdio_put(ss, s, str_len(s))) return; ++ break; ++ case 'S': ++ sa = va_arg(args, stralloc *); ++ if (!sa) { ++ if (substdio_put(ss, nullString, ++ str_len(nullString))) ++ return; ++ break; ++ } ++ if (substdio_put(ss, sa->s, sa->len)) ++ return; ++ break; ++ case '%': ++ if (substdio_put(ss, "%", 1) == -1) ++ return; ++ break; ++ case 'p': ++ p = va_arg(args, void *); ++ ul = (unsigned long)p; ++ if (substdio_put(ss, "0x", 2)) return; ++ if (substdio_put(ss, num, ++ fmt_hexulong(num, ul))) ++ return; ++ break; ++ case 'x': ++ ul = va_arg(args, unsigned long); ++ if (substdio_put(ss, "0x", 2)) return; ++ if (substdio_put(ss, num, ++ fmt_hexulong(num, ul))) ++ return; ++ break; ++ case 'c': ++ c = (unsigned char) ++ va_arg(args, unsigned int); ++ substdio_BPUTC(ss, c); ++ break; ++ } ++ start = ++cur; ++ } else { ++ ++cur; ++ } ++ } ++ if (substdio_put(ss, start, cur-start) == -1) return; ++} ++ ++void output(substdio *ss, char const *fmt, ...) ++ /* see va_output */ ++{ ++ va_list args; ++ ++ va_start(args,fmt); ++ va_output(ss, fmt, args); ++ va_end(args); ++ if (substdio_flush(ss) == -1) return; ++} ++ +diff -upN qmail-1.03/output.h qmail-ldap/output.h +--- qmail-1.03/output.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/output.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (c) 2001-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __OUTPUT_H__ ++#define __OUTPUT_H__ ++ ++#include ++#include "substdio.h" ++ ++#define STDERR 2 ++#define STDOUT 1 ++#define STDIN 0 ++ ++void va_output(substdio *ss, char const *fmt, va_list args); ++/* ++ * works like printf has the format options %i, ... ++ * all flags (#, 0, -, ' ', +, ' ... ) are not supported ++ * Also not supported are all options for foating-point numbers ++ * (not needed in qmail) ++ * Supported conversion specifiers: diuxcsSp% ++ * diux are for integer (long) conversions (di are signed all other unsigned) ++ * c is a single unsigned char ++ * s is a zero terminated string ++ * S is a stralloc object (should not be zero terminated (else the zero ++ * will be printed)) ++ * p is the hex address of a generic pointer (void *) ++ * % is the % sign ++ */ ++ ++void output(substdio *ss, char const *fmt, ...); ++ ++#endif +diff -upN qmail-1.03/passwd.c qmail-ldap/passwd.c +--- qmail-1.03/passwd.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/passwd.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,360 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifdef linux ++#define _XOPEN_SOURCE ++#endif ++#include ++#include "base64.h" ++#include "byte.h" ++#include "case.h" ++#include "digest_md4.h" ++#include "digest_md5.h" ++#include "digest_rmd160.h" ++#include "digest_sha1.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "str.h" ++#include "stralloc.h" ++ ++#include "passwd.h" ++ ++static stralloc hashed = {0}; ++static stralloc salt = {0}; ++static stralloc intermediate = {0}; ++static stralloc cryptformat = {0}; ++ ++static int do_crypt(char *, char *); ++static int do_md4(char *, char *); ++static int do_md5(char *, char *); ++static int do_nsmta_md5(char *, char *); ++static int do_smd5(char *, char *); ++static int do_sha1(char *, char *); ++static int do_ssha1(char *, char *); ++static int do_rmd160(char *, char *); ++ ++static struct func { ++ const char *scheme; ++ unsigned int slen; ++ int (*func)(char *, char *); ++} algo[] = { ++ { "{crypt}", 7, do_crypt }, ++ { "{md4}", 5, do_md4 }, ++ { "{md5}", 5, do_md5 }, ++ { "{ns-mta-md5}", 12, do_nsmta_md5 }, ++ { "{smd5}", 6, do_smd5 }, ++ { "{sha}", 5, do_sha1 }, ++ { "{ssha}", 6, do_ssha1 }, ++ { "{rmd160}", 8, do_rmd160 }, ++ { 0, 0, 0 } ++}; ++ ++/* return zero on success else the error number */ ++int ++cmp_passwd(char *clear, char *encrypted) ++{ ++ int i, r; ++ ++ for (i = 0; algo[i].scheme != 0; i++) { ++ if (case_diffb(encrypted, algo[i].slen, algo[i].scheme) == 0) { ++ encrypted += algo[i].slen; ++ r = algo[i].func(clear, encrypted); ++ if (r != OK) return r; ++ logit(256, "cpm_passwd: comparing hashed %s" ++ "passwd (%S == %s)\n", ++ algo[i].scheme, hashed, encrypted); ++ if (str_diffn(hashed.s, encrypted, hashed.len) == 0 && ++ encrypted[hashed.len] == 0) ++ return OK; ++ /* hashed passwds are equal */ ++ return BADPASS; ++ } ++ } ++ logit(256, "cpm_passwd: comparing crypt(3) passwd (%s == %s)\n", ++ crypt(clear,encrypted), encrypted); ++ if (str_diff(encrypted, crypt(clear,encrypted)) == 0) ++ return OK; ++#ifdef CLEARTEXTPASSWD ++#warning ___CLEARTEXT_PASSWORD_SUPPORT_IS_ON___ ++ /* CLEARTEXTPASSWD ARE NOT GOOD */ ++ /* so they are disabled by default */ ++ if (str_diff(encrypted, clear) == 0) ++ return OK; ++#endif ++ return BADPASS; ++} ++ ++int ++make_passwd(const char *want, char *clear, stralloc *result) ++{ ++ int i, r; ++ ++ for (i = 0; algo[i].scheme != 0; i++) { ++ if (case_diffb(want, algo[i].slen, algo[i].scheme) == 0) { ++ r = algo[i].func(clear, (char *) 0); ++ if (r != OK) return r; ++ if (!stralloc_copy(result, &hashed)) return ERRNO; ++ return OK; ++ } ++ } ++ return NOSUCH; ++} ++ ++int ++feed_salt(char *b, int l) ++{ ++ if (!stralloc_copyb(&salt, b, l)) return ERRNO; ++ return OK; ++} ++ ++void ++feed_crypt(const char *format) ++{ ++ unsigned int len, slen; ++ ++ len = str_chr(format, 'X'); ++ if (format[len] != 'X') goto fail; ++ if (!stralloc_copyb(&cryptformat, format, len)) goto fail; ++ for (slen = len; format[slen] == 'X'; slen++) ; ++ slen -= len; ++ if (slen > salt.len * 4 / 3) goto fail; /* slen is in base64 but salt ++ is not. The conversion isn't ++ 100% correct but close ++ enough. */ ++ if (b64_ntops(salt.s, slen, &intermediate) == -1) goto fail; ++ if (!stralloc_catb(&cryptformat, intermediate.s, slen)) goto fail; ++ if (!stralloc_0(&cryptformat)) goto fail; ++ return; ++ ++fail: ++ /* crypt will fail later */ ++ if (!stralloc_copys(&cryptformat, "")) return; ++ if (!stralloc_copys(&intermediate, "")) return; ++} ++ ++static int ++do_crypt(char *clear, char *encrypted) ++{ ++ if (encrypted) { ++ if (!stralloc_copys(&hashed, crypt(clear, encrypted))) ++ return ERRNO; ++ } else { ++ /* salt and prefix */ ++ if (cryptformat.s == 0 || cryptformat.len == 0) ++ return ILLVAL; ++ if (!stralloc_copys(&hashed, crypt(clear, cryptformat.s))) ++ return ERRNO; ++ } ++ return OK; ++} ++ ++static int ++do_md4(char *clear, char *encrypted) ++{ ++ MD4_CTX ctx; ++ unsigned char buffer[MD4_LEN]; ++ ++ /* not slated */ ++ MD4Init(&ctx); ++ MD4Update(&ctx, clear, str_len(clear)); ++ MD4Final(buffer,&ctx); ++ if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO; ++ ++ return OK; ++} ++ ++static int ++do_md5(char *clear, char *encrypted) ++{ ++ MD5_CTX ctx; ++ unsigned char buffer[MD5_LEN]; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, clear, str_len(clear)); ++ MD5Final(buffer,&ctx); ++ if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO; ++ ++ return OK; ++} ++ ++static int ++do_nsmta_md5(char *clear, char *encrypted) ++{ ++/* ++ * Netscape MTA MD5 as found in Netscape MailServer < 2.02 and ++ * Software.com's Post.Office ++ */ ++ MD5_CTX ctx; ++ unsigned char buffer[MD5_LEN]; ++ unsigned char c; ++ ++ /* NS-MTA-MD5 */ ++ if (encrypted) { ++ if (str_len(encrypted) != 64) ++ return BADVAL; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, &encrypted[32], 32); ++ c = 89; ++ MD5Update(&ctx, &c, 1); ++ MD5Update(&ctx, clear, str_len(clear)); ++ c = 247; ++ MD5Update(&ctx, &c, 1); ++ MD5Update(&ctx, &encrypted[32], 32); ++ MD5Final(buffer, &ctx); ++ ++ if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1) ++ return ERRNO; ++ if (!stralloc_catb(&hashed, &encrypted[32], 32)) return ERRNO; ++ ++ return OK; ++ } else { ++ if (salt.s == 0 || salt.len < 16) ++ return FAILED; ++ if (hex_ntops(salt.s, 16, &intermediate) == -1) return ERRNO; ++ if (intermediate.len != 32) return FAILED; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, intermediate.s, 32); ++ c = 89; ++ MD5Update(&ctx, &c, 1); ++ MD5Update(&ctx, clear, str_len(clear)); ++ c = 247; ++ MD5Update(&ctx, &c, 1); ++ MD5Update(&ctx, intermediate.s, 32); ++ MD5Final(buffer, &ctx); ++ ++ if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1) ++ return ERRNO; ++ if (!stralloc_cat(&hashed, &intermediate)) return ERRNO; ++ ++ return OK; ++ } ++} ++ ++static int ++do_smd5(char *clear, char *encrypted) ++{ ++ MD5_CTX ctx; ++ ++ if (encrypted) { ++ if (b64_ptons(encrypted, &salt) == -1) ++ return BADVAL; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, clear, str_len(clear)); ++ MD5Update(&ctx, salt.s + MD5_LEN, salt.len - MD5_LEN); ++ MD5Final(salt.s,&ctx); ++ if (b64_ntops(salt.s, salt.len, &hashed) == -1) ++ return ERRNO; ++ return OK; ++ } else { ++ if (salt.s == 0 || salt.len < 4) ++ return FAILED; ++ if (!stralloc_ready(&intermediate, MD5_LEN)) return ERRNO; ++ intermediate.len = MD5_LEN; ++ MD5Init(&ctx); ++ MD5Update(&ctx, clear, str_len(clear)); ++ MD5Update(&ctx, salt.s, salt.len); ++ MD5Final(intermediate.s,&ctx); ++ ++ if (!stralloc_cat(&intermediate, &salt)) return ERRNO; ++ if (b64_ntops(intermediate.s, intermediate.len, &hashed) == -1) ++ return ERRNO; ++ ++ return OK; ++ } ++} ++ ++static int ++do_sha1(char *clear, char *encrypted) ++{ ++ SHA1_CTX ctx; ++ unsigned char buffer[SHA1_LEN]; ++ ++ SHA1Init(&ctx); ++ SHA1Update(&ctx, clear, str_len(clear)); ++ SHA1Final(buffer,&ctx); ++ if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO; ++ ++ return OK; ++} ++ ++static int ++do_ssha1(char *clear, char *encrypted) ++{ ++ SHA1_CTX ctx; ++ ++ if (encrypted) { ++ if (b64_ptons(encrypted, &salt) == -1) ++ return BADVAL; ++ ++ SHA1Init(&ctx); ++ SHA1Update(&ctx, clear, str_len(clear)); ++ SHA1Update(&ctx, salt.s + SHA1_LEN, salt.len - SHA1_LEN); ++ SHA1Final(salt.s,&ctx); ++ if (b64_ntops(salt.s, salt.len, &hashed) == -1) ++ return ERRNO; ++ return OK; ++ } else { ++ if (salt.s == 0 || salt.len < 4) ++ return FAILED; ++ if (!stralloc_ready(&intermediate, SHA1_LEN)) return ERRNO; ++ intermediate.len = SHA1_LEN; ++ SHA1Init(&ctx); ++ SHA1Update(&ctx, clear, str_len(clear)); ++ SHA1Update(&ctx, salt.s, salt.len); ++ SHA1Final(intermediate.s,&ctx); ++ ++ if (!stralloc_cat(&intermediate, &salt)) return ERRNO; ++ if (b64_ntops(intermediate.s, intermediate.len, &hashed) == -1) ++ return ERRNO; ++ ++ return OK; ++ } ++} ++ ++static int ++do_rmd160(char *clear, char *encrypted) ++{ ++ RMD160_CTX ctx; ++ unsigned char buffer[RMD160_LEN]; ++ ++ RMD160Init(&ctx); ++ RMD160Update(&ctx, clear, str_len(clear)); ++ RMD160Final(buffer,&ctx); ++ if (b64_ntops(buffer, sizeof(buffer), &hashed) == -1) return ERRNO; ++ ++ return OK; ++} ++ +diff -upN qmail-1.03/passwd.h qmail-ldap/passwd.h +--- qmail-1.03/passwd.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/passwd.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __PASSWD_H__ ++#define __PASSWD_H__ ++ ++#include "stralloc.h" ++ ++/* returns 0 on success else a errro number is returned (see qldap-errno.h) */ ++int cmp_passwd(char *, char *); ++ ++/* make a password */ ++int make_passwd(const char *, char *, stralloc *); ++ ++/* feed salt pool for passwd generation */ ++int feed_salt(char *, int); ++ ++/* feed crypt(3) format to the passwd function */ ++void feed_crypt(const char *); ++ ++#endif +diff -upN qmail-1.03/pbsadd.c qmail-ldap/pbsadd.c +--- qmail-1.03/pbsadd.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/pbsadd.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,362 @@ ++/* ++ * Copyright (c) 2002-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "alloc.h" ++#include "auto_qmail.h" ++#include "byte.h" ++#include "control.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "ip.h" ++#include "open.h" ++#include "readwrite.h" ++#include "str.h" ++#include "stralloc.h" ++#include "substdio.h" ++ ++static void die(void); ++static void logit(const char* ); ++static void logits(const char *); ++static void die_badenv(void); ++static void die_control(void); ++static void die_dir(void); ++static void die_exec(void); ++static void die_secret(void); ++static void log_socket(void); ++static void die_dirback(void); ++static void die_envs(void); ++static void log_nomem(void); ++static void log_envsize(void); ++static void log_envvar(char *); ++ ++void setup(void); ++static void uint16_pack_big(char [], unsigned int); ++int sendrequest(int, char *, unsigned int, struct ip_address *); ++unsigned int addenv(char *, unsigned int); ++ ++char sserrbuf[128]; ++substdio sserr = SUBSTDIO_FDBUF(subwrite,2,sserrbuf,sizeof sserrbuf); ++ ++char **childargs; ++ ++#define MAX_PACKET_SIZE 1024 ++char packet[MAX_PACKET_SIZE]; ++ ++stralloc addresses = {0}; ++stralloc envs = {0}; ++stralloc secret = {0}; ++struct ip_address *servers; ++unsigned int numservers = 0; ++unsigned int numenvs = 0; ++unsigned int serverport = 2821; ++ ++void ++setup(void) ++{ ++ char* s; ++ unsigned int i, len; ++ int fdsourcedir; ++ ++ fdsourcedir = open_read("."); ++ if (fdsourcedir == -1) ++ die_dir(); ++ ++ if (chdir(auto_qmail) == -1) die_control(); ++ ++ if (control_readfile(&addresses,"control/pbsservers",0) != 1) ++ die_control(); ++ ++ if (control_readint(&serverport,"control/pbsport") == -1) ++ die_control(); ++ if (serverport > 65000) ++ die_control(); ++ if (control_rldef(&secret,"control/pbssecret",0,"") != 1) ++ die_control(); ++ if (secret.len > 255) ++ die_secret(); ++ if (control_readfile(&envs,"control/pbsenv",0) == -1) ++ die_control(); ++ ++ if (fchdir(fdsourcedir) == -1) ++ die_dirback(); ++ close(fdsourcedir); ++ ++ for (i = 0; i < addresses.len; i++) ++ if(addresses.s[i] == '\0') numservers++; ++ if (numservers == 0) die_control(); ++ ++ for (i = 0; i < envs.len; i++) ++ if(envs.s[i] == '\0') numenvs++; ++ if (numenvs > 255) die_envs(); ++ ++ servers = (struct ip_address*) ++ alloc(numservers * sizeof(struct ip_address)); ++ if (!servers) log_nomem(); ++ ++ s = addresses.s; ++ for (i = 0; i < numservers; i++) { ++ len = ip_scan(s, &servers[i]); ++ if (len == 0 || len > 15) die_control(); ++ while (*s++); ++ } ++ ++} ++ ++ ++static void ++uint16_pack_big(char s[2], unsigned int u) ++{ ++ s[1] = u & 255; ++ s[0] = (u >> 8) & 255; ++} ++ ++int ++sendrequest(int fd, char *buf, unsigned int len, struct ip_address *ip) ++{ ++ struct sockaddr_in s; ++ ++ byte_zero(&s,sizeof(s)); ++ byte_copy(&s.sin_addr,4,ip); ++ uint16_pack_big((char *)&s.sin_port, serverport); ++ s.sin_family = AF_INET; ++ ++ return sendto(fd, buf, len, 0, (struct sockaddr*)&s, sizeof(s)); ++} ++ ++ ++unsigned int ++addenv(char *buf, unsigned int len) ++{ ++ unsigned int i; ++ unsigned int vlen; /* length of the envvar */ ++ unsigned int elen; /* length of the envname */ ++ unsigned int telen; /* length of the envline envname=rewritename */ ++ unsigned int olen; /* old length of the packet buffer */ ++ char *e; ++ char *v; ++ ++ olen = len; ++ buf += len; ++ *buf++ = numenvs; len++; ++ ++ e = envs.s; ++ for (i=0; i < numenvs; i++) { ++ telen = str_len(e); ++ /* we are not interested in the rewrite name */ ++ elen = str_chr(e, '='); ++ e[elen] = '\0'; ++ ++ /* get the requested envvar */ ++ v = env_get(e); ++ vlen = v != (char *)0?str_len(v):0; ++ ++ /* write the result */ ++ if (elen + vlen + 1 > 255) { ++ /* Check that length indicator does not overflow */ ++ log_envvar(e); ++ return olen; ++ } ++ if (len + elen + vlen + 2 > MAX_PACKET_SIZE) { ++ /* ++ * Packet may not overflow. ++ * The environment is written like this: ++ * [length]envname"="envvar ++ */ ++ log_envsize(); ++ return olen; ++ } ++ *buf++ = elen + vlen + 1; len++; /* length */ ++ byte_copy(buf, elen, e); buf+=elen, len+=elen; /* envname */ ++ *buf++ = '='; len++; /* "=" */ ++ if (vlen != 0) { ++ byte_copy(buf, vlen, v); ++ buf+=vlen; ++ len+=vlen; ++ } ++ if (len > MAX_PACKET_SIZE) { ++ /* call me paranoid ... */ ++ log_envsize(); ++ return olen; ++ } ++ e += telen + 1; ++ } ++ return len; ++} ++ ++int ++main(int argc, char** argv) ++{ ++ struct ip_address ip; ++ char *ipstr; ++ char *s; ++ int sfd; ++ unsigned int i, len; ++ ++ childargs = argv + 1; ++ ++ if (env_get("NOPBS")) goto done; ++ ++ setup(); ++ ++ ipstr = env_get("TCPREMOTEIP"); ++ if (!ipstr) die_badenv(); ++ len = ip_scan(ipstr, &ip); ++ if (len == 0 || len > 15) die_badenv(); ++ ++ sfd = socket(AF_INET,SOCK_DGRAM,0); ++ if (sfd == -1) { ++ log_socket(); ++ goto done; ++ } ++ ++ /* create request */ ++ s = packet; len = 0; ++ *s++ = 'A'; len++; /* ADD */ ++ *s++ = 4; len++; /* Size of address in bytes (4 IPv4|16 IPv6) */ ++ byte_copy(s, 4, &ip); s+=4; len+=4; ++ *s++ = secret.len; len++; /* secret length */ ++ byte_copy(s, secret.len, secret.s); s+=secret.len; len+=secret.len; ++ len = addenv(packet, len); ++ ++ /* send update notification to all servers */ ++ for (i = 0; i < numservers; i++) { ++ sendrequest(sfd, packet, len, &servers[i]); ++ } ++ close(sfd); /* try to close socket */ ++done: ++ if (!*childargs) _exit(0); ++ else execvp(*childargs,childargs); ++ /* should never reach this point */ ++ die_exec(); ++ /* NOTREACHED */ ++ return 1; ++} ++ ++static void ++die(void) ++{ ++ _exit(1); ++} ++ ++static void ++logit(const char* s) ++{ ++ substdio_puts(&sserr,s); ++ substdio_puts(&sserr,"\n"); ++ substdio_flush(&sserr); ++} ++ ++static void ++logits(const char *s) ++{ ++ substdio_puts(&sserr,s); ++} ++ ++static void ++die_badenv(void) ++{ ++ logit("pbsadd unable to read $TCPREMOTEIP"); die(); ++} ++ ++static void ++die_control(void) ++{ ++ logit("pbsadd unable to read controls"); die(); ++} ++ ++static void ++die_dir(void) ++{ ++ logit("pbsadd unable to open current directory"); die(); ++} ++ ++static void ++die_exec(void) ++{ ++ logit("pbsadd unable to start pop3 daemon"); die(); ++} ++ ++static void ++die_secret(void) ++{ ++ logit("pbsadd control/pbssecret is to long"); die(); ++} ++ ++static void ++log_socket(void) ++{ ++ logit("pbsadd socket syscall failed"); ++} ++ ++static void ++die_dirback(void) ++{ ++ logit("pbsadd unable to switch back to source directory"); ++ die(); ++} ++ ++static void ++die_envs(void) ++{ ++ logit("pbsadd control/pbsenvs has to many entries"); ++ die(); ++} ++ ++static void ++log_nomem(void) ++{ ++ logit("pbsadd out of memory"); ++ if (*childargs) _exit(111); ++ else execvp(*childargs,childargs); ++ /* should never reach this point */ ++ die_exec(); ++} ++ ++static void ++log_envsize(void) ++{ ++ logit("pbsadd to many environment entries (pkg to small)"); ++} ++ ++static void ++log_envvar(char *s) ++{ ++ logits("pbsadd environment "); logits(s); logit(" is to big"); ++} ++ +diff -upN qmail-1.03/pbscheck.c qmail-ldap/pbscheck.c +--- qmail-1.03/pbscheck.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/pbscheck.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,421 @@ ++/* ++ * Copyright (c) 2002-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "alloc.h" ++#include "auto_qmail.h" ++#include "byte.h" ++#include "control.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "ip.h" ++#include "now.h" ++#include "open.h" ++#include "str.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "timeoutread.h" ++#include "timeoutwrite.h" ++ ++static void die(void); ++static int safewrite(int, void *, int); ++static void putstr(const char *); ++static void flush(void); ++static void errstr(const char *); ++static void logit(const char *); ++static void die_usage(void); ++static void die_exec(void); ++static void die_badenv(void); ++static void die_control(void); ++static void die_nomem(void); ++static void die_envs(void); ++static void die_dir(void); ++static void die_dirback(void); ++void setup(void); ++static void uint16_pack_big(char [], unsigned int); ++int sendrequest(int, char *, unsigned int, struct ip_address *); ++int env_snap(void); ++void env_rewrite(char**, char**); ++void setenv(char *, unsigned int); ++ ++char ssoutbuf[128]; ++substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); ++ ++char sserrbuf[128]; ++substdio sserr = SUBSTDIO_FDBUF(safewrite,2,sserrbuf,sizeof sserrbuf); ++ ++#define MAX_PACKET_SIZE 1024 ++char packet[MAX_PACKET_SIZE]; ++ ++stralloc addresses = {0}; ++stralloc envs = {0}; ++struct ip_address *servers; ++unsigned int numservers = 0; ++unsigned int numenvs = 0; ++unsigned int serverport = 2821; ++ ++ ++void ++setup(void) ++{ ++ char* s; ++ unsigned int i, len; ++ int fdsourcedir; ++ ++ fdsourcedir = open_read("."); ++ if (fdsourcedir == -1) ++ die_dir(); ++ ++ if (chdir(auto_qmail) == -1) die_control(); ++ ++ if (control_readfile(&addresses,"control/pbsservers",0) != 1) ++ die_control(); ++ ++ if (control_readint(&serverport,"control/pbsport") == -1) ++ die_control(); ++ if (serverport > 65000) ++ die_control(); ++ if (control_readfile(&envs,"control/pbsenv",0) == -1) ++ die_control(); ++ ++ if (fchdir(fdsourcedir) == -1) ++ die_dirback(); ++ close(fdsourcedir); ++ ++ for (i = 0; i < addresses.len; i++) ++ if( addresses.s[i] == '\0') numservers++; ++ if (numservers == 0) die_control(); ++ ++ for (i = 0; i < envs.len; i++) ++ if( envs.s[i] == '\0') numenvs++; ++ if (numenvs > 255) die_envs(); ++ ++ servers = (struct ip_address*) ++ alloc(numservers * sizeof(struct ip_address)); ++ if (!servers) die_nomem(); ++ ++ s = addresses.s; ++ for (i = 0; i < numservers; i++) { ++ len = ip_scan(s, &servers[i]); ++ if (len == 0 || len > 15) die_control(); ++ while (*s++); ++ } ++} ++ ++ ++static void ++uint16_pack_big(char s[2], unsigned int u) ++{ ++ s[1] = u & 255; ++ s[0] = (u >> 8) & 255; ++} ++ ++int ++sendrequest(int fd, char *buf, unsigned int len, struct ip_address *ip) ++{ ++ struct sockaddr_in s; ++ ++ byte_zero(&s,sizeof(s)); ++ byte_copy(&s.sin_addr,4,ip); ++ uint16_pack_big((char *)&s.sin_port, serverport); ++ s.sin_family = AF_INET; ++ ++ return sendto(fd, buf, len, 0, (struct sockaddr*)&s, sizeof(s)); ++} ++ ++char **envsnap; ++ ++int ++env_snap(void) ++{ ++ unsigned int en, i; ++ ++ for (en = 0;environ[en];++en) ; ++ envsnap = (char **) alloc((en + 1) * sizeof(char *)); ++ if (!envsnap) return 0; ++ for (en = 0;environ[en];++en) { ++ envsnap[en] = alloc(str_len(environ[en]) + 1); ++ if (!envsnap[en]) { ++ for (i = 0; i < en; ++i) alloc_free(envsnap[i]); ++ alloc_free(envsnap); ++ return 0; ++ } ++ str_copy(envsnap[en],environ[en]); ++ } ++ envsnap[en] = 0; ++ return 1; ++} ++ ++stralloc vbuf = {0}; ++ ++void ++env_rewrite(char** name, char** value) ++{ ++ char *e; ++ unsigned int i; ++ unsigned int llen; ++ unsigned int nlen; ++ unsigned int elen; ++ ++ e = envs.s; ++ nlen = str_len(*name); ++ ++ for (i=0; i < numenvs; i++) { ++ llen = str_len(e); ++ if (byte_equal(*name, nlen, e)) ++ if (*(e + nlen) == '=') { ++ elen = str_chr(e + nlen + 1, '='); ++ if (*(e + nlen + elen + 1) == '=') { ++ *(e + nlen + elen + 1) = '\0'; ++ if (!stralloc_copys(&vbuf, ++ e + nlen + elen + 2)) ++ die_nomem(); ++ if (!stralloc_cats(&vbuf, *value)) ++ die_nomem(); ++ if (!stralloc_0(&vbuf)) die_nomem(); ++ *value = vbuf.s; ++ } ++ *name = e + nlen + 1; ++ return; ++ } ++ e += llen + 1; ++ } ++} ++ ++void setenv(char *env, unsigned int envlen) ++{ ++ char *v; ++ char *e; ++ unsigned int numenv; ++ unsigned int elen; ++ unsigned int nlen; ++ unsigned int tlen; ++ unsigned int i; ++ ++ if (!env_snap()) die_nomem(); ++ ++ numenv=(unsigned char)*env++; envlen--; ++ ++ nlen=(unsigned char)*env++; envlen--; ++ for (i=0; i < numenv; i++) { ++ elen=nlen; ++ if (envlen <= 0) { ++ environ = envsnap; ++ return; ++ } ++ nlen=(unsigned char)*(env+elen); ++ *(env+elen)=0; ++ tlen = str_chr(env, '='); ++ env[tlen] = '\0'; ++ e = env; ++ v = env + tlen + 1; ++ env_rewrite(&e, &v); ++ if (!env_put2(e, v)) die_nomem(); ++ env+=elen+1; envlen-=(elen+1); ++ } ++} ++ ++int main (int argc, char** argv) ++{ ++ struct ip_address ip; ++ char **childargs; ++ char *ipstr; ++ char *s; ++ unsigned long t; ++ int sfd = -1; ++ unsigned int len; ++ int i; ++ ++ childargs = argv + 1; ++ if (!*childargs) die_usage(); ++ ++ if (env_get("NOPBS")) goto start_daemon; ++ ++ setup(); ++ ++ t = now() ^ getpid(); /* at least on OpenBSD this is mostly random */ ++ t %= numservers; ++ ++ ipstr = env_get("TCPREMOTEIP"); ++ if (!ipstr) die_badenv(); ++ len = ip_scan(ipstr, &ip); ++ if (len == 0 || len > 15) die_badenv(); ++ ++ sfd = socket(AF_INET,SOCK_DGRAM,0); ++ if (sfd == -1) goto start_daemon; ++ ++ /* create request */ ++ s = packet; len = 0; ++ *s++ = 'Q'; len++; /* Query */ ++ *s++ = 4; len++; /* Size of address in bytes (4 IPv4|16 IPv6) */ ++ byte_copy(s, 4, &ip); s+=4; len+=4; ++ *s++ = 0; len++; /* status */ ++ ++ i = sendrequest(sfd, packet, len, &servers[t]); ++ if (i <= 0) goto start_daemon; ++ t = 0; ++ do { ++ /* wait a seconds for answer */ ++ i = timeoutread(1, sfd, packet, sizeof(packet)); ++ if (i != -1) break; ++ if (i == -1 && errno != error_timeout) goto start_daemon; ++ ++ if (t >= numservers) { ++ logit("pbscheck: no response from server"); ++ goto start_daemon; /* no response */ ++ } ++ ++ i = sendrequest(sfd, packet, len, &servers[t]); ++ if (i <= 0) goto start_daemon; ++ t++; ++ ++ } while(1); ++ ++ if (packet[0] != 'R') goto start_daemon; /* R = Reply */ ++ if (packet[1] != 4) goto start_daemon; ++ /* check address */ ++ if (byte_diff(packet + 2, 4, &ip)) goto start_daemon; ++ if (*(packet + 2 + packet[1]) == 'R') { ++ if (!env_put("RELAYCLIENT=")) die_nomem(); ++ } ++ setenv(packet + 3 + packet[1], i - packet[1] - 3); ++ ++start_daemon: ++ if (sfd == -1) close(sfd); /* try to close socket */ ++ ++ /* start smtpd */ ++ execvp(*childargs,childargs); ++ /* should never reach this point */ ++ die_exec(); ++ /* NOTREACHED */ ++ return 1; ++} ++ ++static void die(void) ++{ ++ _exit(1); ++} ++ ++static int safewrite(int fd, void *buf, int len) ++{ ++ int r; ++ r = timeoutwrite(1200,fd,buf,len); ++ if (r <= 0) die(); ++ return r; ++} ++ ++static void putstr(const char *s) ++{ ++ substdio_puts(&ssout,s); ++} ++ ++static void flush(void) ++{ ++ substdio_flush(&ssout); ++} ++ ++static void errstr(const char *s) ++{ ++ putstr(s); ++ putstr("\r\n"); ++ flush(); ++} ++ ++static void logit(const char *s) ++{ ++ substdio_puts(&sserr,s); ++ substdio_puts(&sserr,"\n"); ++ substdio_flush(&sserr); ++} ++ ++static void die_usage(void) ++{ ++ errstr("554 pop before smtp subprogram uncorrectly installed (#5.3.5)"); ++ logit("usage: pbscheck subprogram ..."); ++ die(); ++} ++ ++static void die_exec(void) ++{ ++ errstr("554 unable to start smtp daemon (#5.3.5)"); ++ logit("pbscheck: unable to start smtp daemon"); ++ die(); ++} ++ ++static void die_badenv(void) ++{ ++ errstr("554 unable to read $TCPREMOTEIP (#5.3.5)"); ++ logit("pbscheck: unable to read $TCPREMOTEIP"); ++ die(); ++} ++ ++static void die_control(void) ++{ ++ errstr("554 unable to read controls (#5.3.5)"); ++ logit("pbscheck unable to read controls"); ++ die(); ++} ++ ++static void die_nomem(void) ++{ ++ errstr("421 out of memory (#4.3.0)"); ++ logit("pbscheck out of memory"); ++ die(); ++} ++ ++static void die_envs(void) ++{ ++ errstr("554 to many additional environments defined (#5.3.5)"); ++ logit("pbscheck control/pbsenvs has to many entries"); ++ die(); ++} ++ ++static void die_dir(void) ++{ ++ errstr("421 chdir failed (#4.3.0)"); ++ logit("pbscheck unable to open current directory"); ++ die(); ++} ++ ++static void die_dirback(void) ++{ ++ errstr("421 chdir failed (#4.3.0)"); ++ logit("pbscheck unable to switch back to source directory"); ++ die(); ++} ++ +diff -upN qmail-1.03/pbsdbd.c qmail-ldap/pbsdbd.c +--- qmail-1.03/pbsdbd.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/pbsdbd.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,486 @@ ++/* ++ * Copyright (c) 2002-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "alloc.h" ++#include "auto_qmail.h" ++#include "byte.h" ++#include "control.h" ++#include "ip.h" ++#include "ndelay.h" ++#include "now.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++#include "uint32.h" ++ ++static void die_control(void); ++static void die_nomem(void); ++static void init(void); ++static int socket_bind(int); ++static void cache_impossible(void); ++static void set4(unsigned long, uint32); ++static uint32 get4(unsigned long); ++unsigned long hash(const unsigned char *,unsigned int); ++void unlinkaddr(const unsigned char *, unsigned int); ++void setaddr(const unsigned char *, unsigned int, ++ unsigned long, char *, unsigned int); ++int checkaddr(const unsigned char *, unsigned int, ++ unsigned long, char **, unsigned int *); ++static int doit(void); ++ ++struct ip_address ip; ++unsigned int port = 2821; ++stralloc addr = {0}; ++stralloc secret = {0}; ++unsigned int timeout = 600; /* 10 Min */ ++ ++unsigned long cachesize = 1048576; /* 1 MB */ ++unsigned char *cache; ++unsigned long hashsize; ++unsigned int hashbits; ++unsigned long writer; ++unsigned long oldest; ++unsigned long unused; ++ ++static unsigned char buf[1024]; ++static unsigned int len; ++ ++#define fatal "pbsdbd: fatal: " ++#define warning "pbsdbd: warning: " ++#define info "pbsdbd: info: " ++ ++static void ++die_control(void) ++{ ++ strerr_die2x(111, fatal, "unable to read controls"); ++} ++ ++static void ++die_nomem(void) ++{ ++ strerr_die2x(111, fatal, "out of memory"); ++} ++ ++static void ++init(void) ++{ ++ unsigned int l; ++ ++ if (chdir(auto_qmail) == -1) die_control(); ++ ++ if (control_rldef(&addr,"control/pbsip",0, "0.0.0.0") == -1) ++ die_control(); ++ if (!stralloc_0(&addr)) die_nomem(); ++ ++ l = ip_scan(addr.s, &ip); ++ if (l == 0 && l > 15) die_control(); ++ ++ if (control_rldef(&secret,"control/pbssecret",0,"") != 1) ++ die_control(); ++ ++ if (control_readint(&port,"control/pbsport") == -1) die_control(); ++ if (port > 65000) die_control(); ++ ++ /* if a luser sets bad values it's his fault */ ++ if (control_readulong(&cachesize,"control/pbscachesize") == -1) ++ die_control(); ++ if (control_readint(&timeout,"control/pbstimeout") == -1) ++ die_control(); ++ ++ cache = alloc(cachesize); ++ if (!cache) die_nomem(); ++ ++ hashsize = 4; ++ while (hashsize <= (cachesize >> 5)) hashsize <<= 1; ++ ++ writer = hashsize; ++ oldest = cachesize; ++ unused = cachesize; ++ ++} ++ ++static int ++socket_bind(int s) ++{ ++ int opt = 1; ++ struct sockaddr_in soin; ++ char *x; ++ ++ setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); ++ ++ byte_zero(&soin,sizeof(soin)); ++ byte_copy(&soin.sin_addr,4,&ip); ++ x = (char *) &soin.sin_port; ++ x[1] = port; port >>= 8; x[0] = port; ++ soin.sin_family = AF_INET; ++ ++ return bind(s,(struct sockaddr *) &soin,sizeof soin); ++} ++ ++static void ++cache_impossible(void) ++{ ++ strerr_die2x(111, fatal, "cache corrupted"); ++} ++ ++static void ++set4(unsigned long pos, uint32 u) ++{ ++ unsigned char *s; ++ ++ if (pos > cachesize - 4) cache_impossible(); ++ ++ s = cache + pos; ++ s[3] = u & 255; ++ u >>= 8; ++ s[2] = u & 255; ++ u >>= 8; ++ s[1] = u & 255; ++ s[0] = u >> 8; ++} ++ ++static uint32 ++get4(unsigned long pos) ++{ ++ unsigned char *s; ++ uint32 result; ++ ++ if (pos > cachesize - 4) cache_impossible(); ++ s = cache + pos; ++ result = s[0]; ++ result <<= 8; ++ result += s[1]; ++ result <<= 8; ++ result += s[2]; ++ result <<= 8; ++ result += s[3]; ++ ++ return result; ++} ++ ++unsigned long ++hash(const unsigned char *key,unsigned int keylen) ++{ ++ unsigned long result = 5381; ++ ++ while (keylen) { ++ result = (result << 5) + result; ++ result ^= *key; ++ ++key; ++ --keylen; ++ } ++ result <<= 2; ++ result &= hashsize - 4; ++ return result; ++} ++ ++void ++unlinkaddr(const unsigned char *key, unsigned int keylen) ++{ ++ unsigned long pos; ++ unsigned long prevpos; ++ unsigned long nextpos; ++ unsigned int loop; ++ ++ if (!cache) return; ++ ++ prevpos = hash(key,keylen); ++ pos = get4(prevpos); ++ loop = 0; ++ ++ while (pos) { ++ if (pos + 13 > cachesize) cache_impossible(); ++ nextpos = prevpos ^ get4(pos); ++ if (nextpos == prevpos) cache_impossible(); ++ if (*(cache + pos + 12) == keylen) { ++ if (pos + 13 + keylen > cachesize) cache_impossible(); ++ if (byte_equal(key,keylen,cache + pos + 13)) { ++ set4(prevpos, get4(prevpos) ^ pos ^ nextpos); ++ if (nextpos != 0) ++ set4(nextpos, ++ get4(nextpos) ^ pos ^ prevpos); ++ set4(pos, 0); ++ //strerr_warn2(info, "clearing entry.", 0); ++ return; ++ } ++ } ++ prevpos = pos; ++ pos = nextpos; ++ if (++loop > 100) { ++ strerr_warn2(warning, "hash flooding", 0); ++ return; /* to protect against hash flooding */ ++ } ++ } ++} ++ ++/* to be stored: 4-byte link, 4-byte timestamp, 4-byte envsize, 1-byte size, ++ size-byte Address and envsize-byte Environment */ ++/* see also dnscache */ ++void ++setaddr(const unsigned char *key, unsigned int keylen, ++ unsigned long timenow, char *env, unsigned int envlen) ++{ ++ unsigned int entrylen; ++ unsigned int tmplen; ++ unsigned int keyhash; ++ unsigned long pos; ++ ++ if (!cache) return; ++ if (keylen > 255) return; ++ ++ entrylen = 13 + keylen + envlen; ++ ++ unlinkaddr(key, keylen); ++ ++ while (writer + entrylen > oldest) { ++ if (oldest == unused) { ++ if (writer <= hashsize) cache_impossible(); ++ unused = writer; ++ oldest = hashsize; ++ writer = hashsize; ++ strerr_warn2(info, "reached end of cache, wrapping...", 0); ++ } ++ ++ pos = get4(oldest); ++ if (!pos) ++ strerr_warn2(info, "skipping cleared entry", 0); ++ if (pos) ++ set4(pos,get4(pos) ^ oldest); ++ ++ if (oldest + 13 > cachesize) cache_impossible(); ++ tmplen = get4(oldest + 8); ++ oldest += 13 + tmplen + *(cache + oldest + 12); ++ if (oldest > unused) cache_impossible(); ++ if (oldest == unused) { ++ unused = cachesize; ++ oldest = cachesize; ++ } ++ } ++ ++ keyhash = hash(key,keylen); ++ ++ pos = get4(keyhash); ++ if (pos) ++ set4(pos,get4(pos) ^ keyhash ^ writer); ++ set4(writer,pos ^ keyhash); ++ set4(writer + 4,timenow + timeout); ++ set4(writer + 8,envlen); ++ if (writer + 13 > cachesize) cache_impossible(); ++ *(cache + writer + 12) = keylen; ++ byte_copy(cache + writer + 13,keylen,key); ++ byte_copy(cache + writer + 13 + keylen,envlen,env); ++ ++ set4(keyhash,writer); ++ ++ writer += entrylen; ++} ++ ++int ++checkaddr(const unsigned char *key, unsigned int keylen, ++ unsigned long timenow, char **env, unsigned int *envlen) ++{ ++ unsigned long pos; ++ unsigned long prevpos; ++ unsigned long nextpos; ++ unsigned long u; ++ unsigned int loop; ++ ++ if (!cache) return 0; ++ ++ prevpos = hash(key,keylen); ++ pos = get4(prevpos); ++ loop = 0; ++ *env = 0; ++ *envlen = 0; ++ ++ while (pos) { ++ if (pos + 13 > cachesize) cache_impossible(); ++ if (*(cache + pos + 12) == keylen) { ++ if (pos + 13 + keylen > cachesize) cache_impossible(); ++ if (byte_equal(key,keylen,cache + pos + 13)) { ++ u = get4(pos + 4); ++ if (u < timenow) { ++ //strerr_warn2(info, ++ // "cache hit but timed out", 0); ++ return 0; ++ } ++ *envlen = get4(pos + 8); ++ if (pos + 13 + keylen + *envlen > cachesize) ++ cache_impossible(); ++ *env = cache + pos + 13 + keylen; ++ return 1; ++ } ++ } ++ nextpos = prevpos ^ get4(pos); ++ if (nextpos == prevpos) cache_impossible(); ++ prevpos = pos; ++ pos = nextpos; ++ if (++loop > 100) { ++ strerr_warn2(warning, "hash flooding", 0); ++ return 0; /* to protect against hash flooding */ ++ } ++ } ++ ++ //strerr_warn2(info, "not in cache", 0); ++ return 0; ++} ++ ++ ++/* ++ * pbs packets have following format: ++ * header: ++ * 1-byte type, 1-byte address-size, address-size-byte ++ * ++ * secret used in type add packets: ++ * 1-byte secret-size, secret-size-bytes secret ++ * ++ * may-relay byte used in respnse packets: ++ * 1-byte may-relay ('R' for may-relay and 'N' for may-not-relay) ++ * ++ * optional environment vars for type add and result: ++ * 1-byte #-of-entries ++ * environment vars entries ++ * 1-byte size, n-byte env-name, 1-byte '"', m-byte env-var ++ * where n + m + 1 = size. ++ * ++ * Allowed types are 'A' for add, 'Q' for query, 'R' response. ++ * Type 'A' uses the header and secret plus optional environment vars. ++ * Type 'Q' does only need the header. ++ * Type 'R' needs the header and the may-relay byte and ++ * optional environment vars. ++ */ ++ ++static int doit(void) ++{ ++ unsigned char *sec; ++ unsigned int sec_len; ++ unsigned char *env; ++ unsigned long timenow; ++ unsigned int envlen; ++ unsigned int i; ++ ++ if (buf[1] + 2 >= len) { ++ strerr_warn2(warning, "bad packet", 0); ++ return 0; ++ } ++ ++ timenow = now(); ++ ++ switch(buf[0]) { ++ case 'Q': ++ //strerr_warn2(info, "query packet", 0); ++ if (checkaddr(&buf[2], buf[1], timenow, ++ (char**)&env, &envlen)) { ++ *(buf + 2 + buf[1]) = 'R'; ++ if (envlen + buf[1] + 3 > 1024) { ++ strerr_warn2(warning, "environment would " ++ "exceed package size, dropped", 0); ++ return 0; ++ } ++ byte_copy(buf+3+buf[1], envlen, env); ++ len += envlen; ++ } else { ++ *(buf + 2 + buf[1]) = 'N'; ++ } ++ buf[0] = 'R'; ++ return 1; ++ case 'A': ++ //strerr_warn2(info, "add packet", 0); ++ sec_len = *(buf + 2 + buf[1]); ++ sec = buf + 2 + buf[1] + 1; ++ if (buf + len < sec + sec_len) { ++ strerr_warn2(warning, "bad packet", 0); ++ return 0; ++ } ++ if (secret.len != sec_len || ++ byte_diff(secret.s, sec_len, sec)) { ++ strerr_warn2(warning, "no authorized add packet", 0); ++ return 0; ++ } ++ env = buf + 3 + buf[1] + *(buf + 2 + buf[1]); ++ envlen = 1; ++ for (i=0; i < *env; i++) { ++ envlen += env[envlen] + 1; ++ if (buf + len < env + envlen) { ++ strerr_warn2(warning, "environment would " ++ "exceed package size, dropped", 0); ++ return 0; ++ } ++ } ++ if (buf + len != env + envlen) { ++ strerr_warn2(warning, "trailing garbadge at end " ++ "of packet, dropped", 0); ++ return 0; ++ } ++ setaddr(&buf[2], buf[1], timenow, env, envlen); ++ return 0; ++ case 'R': ++ strerr_warn2(warning, "response recived", 0); ++ return 0; ++ default: ++ strerr_warn2(warning, "bad packet", 0); ++ return 0; ++ } ++} ++ ++int main(int argc, char** argv) ++{ ++ struct sockaddr_in sa; ++ unsigned int dummy; ++ int udp; ++ ++ init(); ++ ++ udp = socket(AF_INET, SOCK_DGRAM, 0); ++ if (udp == -1) ++ strerr_die2sys(111,fatal,"unable to create UDP socket: "); ++ if (socket_bind(udp) == -1) ++ strerr_die2sys(111,fatal,"unable to bind UDP socket: "); ++ ++ ndelay_off(udp); ++ ++ for (;;) { ++ dummy = sizeof(sa); ++ len = recvfrom(udp, buf, sizeof(buf), 0, ++ (struct sockaddr*) &sa, &dummy); ++ if (len < 0) continue; ++ if (!doit()) continue; ++ sendto(udp, buf, len, 0, (struct sockaddr*) &sa, sizeof(sa)); ++ /* may block for buffer space; if it fails, too bad */ ++ } ++} ++ +diff -upN qmail-1.03/pbsexec.c qmail-ldap/pbsexec.c +--- qmail-1.03/pbsexec.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/pbsexec.c Wed May 5 17:42:11 2004 +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include "env.h" ++#include "open.h" ++#include "qldap-debug.h" ++#include "wait.h" ++ ++#include "pbsexec.h" ++ ++char *pbstool = 0; ++ ++void ++pbsexec(void) ++{ ++ char *(args[3]); ++ int child, wstat; ++ ++ if (pbstool == 0 || *pbstool == 0) return; ++ ++ if (env_get("NOPBS")) return; ++ ++ switch (child = fork()) { ++ case -1: ++ return; ++ case 0: ++ /* the pbstool may not read or write to the connection */ ++ close(0); open_read("/dev/null"); ++ close(1); open_write("/dev/null"); ++ close(3); ++ ++ args[0] = pbstool; ++ args[1] = 0; ++ execvp(*args, args); ++ _exit(111); ++ } ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) ++ logit(2, "pbsexec: %s crashed\n", pbstool); ++ else if (wait_exitcode(wstat)) ++ logit(2, "pbsexec: %s failed, exit code %d\n", ++ pbstool, wait_exitcode(wstat)); ++ else ++ logit(64, "pbsexec: %s OK\n", pbstool); ++ ++ return; ++} ++ +diff -upN qmail-1.03/pbsexec.h qmail-ldap/pbsexec.h +--- qmail-1.03/pbsexec.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/pbsexec.h Wed May 5 17:42:11 2004 +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __PBSEXEC_H__ ++#define __PBSEXEC_H__ ++ ++extern char *pbstool; ++ ++void pbsexec(void); ++ ++#endif +diff -upN qmail-1.03/popfetch.pl qmail-ldap/popfetch.pl +--- qmail-1.03/popfetch.pl Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/popfetch.pl Wed May 5 17:42:12 2004 +@@ -0,0 +1,94 @@ ++#!/usr/bin/perl ++# ++# Copyright (c) 1999-2004 Andre Oppermann, ++# Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# 1. Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# 2. Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# 3. All advertising materials mentioning features or use of this software ++# must display the following acknowledgement: ++# This product includes software developed by Internet Business ++# Solutions AG and its contributors. ++# 4. Neither the name of the author nor the names of its contributors ++# may be used to endorse or promote products derived from this software ++# without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++# SUCH DAMAGE. ++# ++ ++# $localhost and $server need to changed ++# If a file by the name "done" exists in the maildir we don't try to ++# fetch the mails again. ++# by Ingo Oppermann ++ ++use Mail::POP3Client; ++ ++# Variables ++ ++$path = $ARGV[3]; ++$mailpath = "./".$path; ++$username = $ARGV[0]; ++$pw = $ARGV[1]; ++$server = 'mail.pipeline.ch'; ++$localhost = "mail.schweizerinserate.ch"; ++@filenames; ++ ++# Main ++ ++if(-e $mailpath."/done") ++{ ++ ; ++} ++else ++{ ++ $pop = new Mail::POP3Client($username,$pw,$server); ++ $numofmails = $pop->Count; ++ print $numofmails; ++ for($i = 1; $i <= $numofmails; $i++) ++ { ++ $curtime = time(); ++ $random = rand(); ++ $filename = $curtime.".".$$.".".$random.$localhost; ++ push(@filenames, $filename); ++ open(OUT, ">".$mailpath."/tmp/".$filename); ++ foreach($pop->Retrieve($i)) ++ { ++ print OUT $_, "\n"; ++ } ++# Uncomment the next line if the retrieved mail should be deleted from ++# the old pop server ++ # $pop->Delete($i); ++ close(OUT); ++ } ++ $pop->Close; ++ ++ foreach(@filenames) ++ { ++ $filename = $_; ++ $program = "mv $mailpath/tmp/$filename $mailpath/new/$filename"; ++ open(PROG, "|$program"); ++ close(PROG); ++ } ++ open(CHECK, ">$mailpath/done"); ++ print CHECK 1; ++ close(CHECK); ++} ++ ++exec "$ARGV[2] $ARGV[3]"; ++ +diff -upN qmail-1.03/predate.c qmail-ldap/predate.c +--- qmail-1.03/predate.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/predate.c Thu Jan 29 16:48:14 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "datetime.h" + #include "fork.h" + #include "wait.h" +@@ -10,17 +11,18 @@ + #include "subfd.h" + #include "readwrite.h" + #include "exit.h" ++#include "sig.h" + + #define FATAL "predate: fatal: " + +-static char *montab[12] = { ++static const char *montab[12] = { + "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" + }; + + char num[FMT_ULONG]; + char outbuf[1024]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -29,7 +31,7 @@ char **argv; + struct datetime dt; + datetime_sec utc; + datetime_sec local; +- int minutes; ++ unsigned int minutes; + int pi[2]; + substdio ss; + int wstat; +@@ -55,7 +57,7 @@ char **argv; + strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); + } + close(pi[0]); +- substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ss,subwrite,pi[1],outbuf,sizeof(outbuf)); + + time(&now); + +@@ -112,5 +114,5 @@ char **argv; + strerr_die2sys(111,FATAL,"wait failed: "); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); +- _exit(wait_exitcode(wstat)); ++ return wait_exitcode(wstat); + } +diff -upN qmail-1.03/preline.c qmail-ldap/preline.c +--- qmail-1.03/preline.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/preline.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "fd.h" + #include "sgetopt.h" + #include "readwrite.h" +@@ -23,10 +24,10 @@ int flagdtline = 1; char *dtline; + + char outbuf[SUBSTDIO_OUTSIZE]; + char inbuf[SUBSTDIO_INSIZE]; +-substdio ssout = SUBSTDIO_FDBUF(write,1,outbuf,sizeof outbuf); +-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); ++substdio ssout = SUBSTDIO_FDBUF(subwrite,1,outbuf,sizeof outbuf); ++substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf); + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -86,5 +87,5 @@ char **argv; + strerr_die2sys(111,FATAL,"wait failed: "); + if (wait_crashed(wstat)) + strerr_die2x(111,FATAL,"child crashed"); +- _exit(wait_exitcode(wstat)); ++ return wait_exitcode(wstat); + } +diff -upN qmail-1.03/prioq.c qmail-ldap/prioq.c +--- qmail-1.03/prioq.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/prioq.c Thu Jan 29 16:48:14 2004 +@@ -36,9 +36,9 @@ struct prioq_elt *pe; + void prioq_delmin(pq) + prioq *pq; + { +- int i; +- int j; +- int n; ++ unsigned int i; ++ unsigned int j; ++ unsigned int n; + if (!pq->p) return; + n = pq->len; + if (!n) return; +diff -upN qmail-1.03/prioq.h qmail-ldap/prioq.h +--- qmail-1.03/prioq.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/prioq.h Tue Oct 28 18:21:32 2003 +@@ -8,8 +8,8 @@ struct prioq_elt { datetime_sec dt; unsi + + GEN_ALLOC_typedef(prioq,struct prioq_elt,p,len,a) + +-extern int prioq_insert(); +-extern int prioq_min(); +-extern void prioq_delmin(); ++extern int prioq_insert(prioq *, struct prioq_elt *); ++extern int prioq_min(prioq *, struct prioq_elt *); ++extern void prioq_delmin(prioq *); + + #endif +diff -upN qmail-1.03/profile.patch qmail-ldap/profile.patch +--- qmail-1.03/profile.patch Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/profile.patch Fri Jul 26 14:12:11 2002 +@@ -0,0 +1,62 @@ ++diff -BbuN qmail-ldap/Makefile qmail-test/Makefile ++--- qmail-ldap/Makefile Thu Jul 20 22:07:09 2000 +++++ qmail-test/Makefile Thu Jul 20 22:55:52 2000 ++@@ -1402,12 +1402,13 @@ ++ sig.a strerr.a getln.a wait.a case.a cdb.a fd.a open.a stralloc.a \ ++ alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \ ++ auto_spawn.o auto_usera.o env.a qldap-ldaplib.o qldap-debug.o \ ++-qldap-errno.o +++qldap-errno.o qldap-profile.o ++ ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o control.o \ ++- check.o qldap-ldaplib.o qldap-debug.o sig.a strerr.a getln.a \ +++ check.o qldap-ldaplib.o qldap-profile.o \ +++ qldap-debug.o sig.a strerr.a getln.a \ ++ wait.a case.a cdb.a fd.a open.a env.a stralloc.a alloc.a \ ++ substdio.a str.a qldap-errno.o error.a fs.a auto_qmail.o \ ++- auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS) +++ auto_uids.o auto_usera.o auto_spawn.o $(LDAPLIBS) $(LIBTAI) ++ ++ qmail-lspawn.0: \ ++ qmail-lspawn.8 ++@@ -1419,7 +1420,8 @@ ++ slurpclose.h auto_qmail.h auto_uids.h qlx.h qmail-ldap.h check.h \ ++ qldap-ldaplib.h qldap-errno.h qldap-debug.h env.h auto_usera.h \ ++ auto_uids.h fmt.h sig.h ++- ./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) qmail-lspawn.c +++ ./compile $(LDAPFLAGS) $(HDIRMAKE) $(LDAPINCLUDES) $(INCTAI) +++ qmail-lspawn.c ++ ++ qmail-newmrh: \ ++ load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \ ++diff -BbuN qmail-ldap/qmail-lspawn.c qmail-test/qmail-lspawn.c ++--- qmail-ldap/qmail-lspawn.c Mon Jul 3 13:22:01 2000 +++++ qmail-test/qmail-lspawn.c Thu Jul 20 22:55:53 2000 ++@@ -31,6 +31,7 @@ ++ #include "str.h" ++ #include ++ #include +++#include "qldap-profile.h" ++ ++ char *aliasempty; ++ ++@@ -369,7 +370,9 @@ ++ extra[6].what = 0; ++ ++ /* do the search for the email address */ +++ start_timing(0, "first ldap_lookup"); ++ ret = ldap_lookup(&search, attrs, &info, extra); +++ stop_timing(0); ++ if (!stralloc_copys(&filter, "")) _exit(QLX_NOMEM); ++ /* XXX doesn't free mem */ ++ if ( ret != 0 && qldap_errno == LDAP_NOSUCH ) { ++@@ -391,8 +394,10 @@ ++ ++ debug(16, "retry with filter '%s'\n", filter.s); ++ /* do the search for the email address */ +++ start_timing(0, "first ldap_lookup"); ++ ret = ldap_lookup(&search, attrs, &info, extra); ++ /* count the results, we must have exactly one */ +++ stop_timing(0); ++ } ++ alloc_free(filter.s); filter.s = 0; ++ if ( ret != 0 ) { +diff -upN qmail-1.03/prot.c qmail-ldap/prot.c +--- qmail-1.03/prot.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/prot.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "hasshsgr.h" + #include "prot.h" + +diff -upN qmail-1.03/prot.h qmail-ldap/prot.h +--- qmail-1.03/prot.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/prot.h Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #ifndef PROT_H + #define PROT_H + +-extern int prot_gid(); +-extern int prot_uid(); ++extern int prot_gid(int); ++extern int prot_uid(int); + + #endif +diff -upN qmail-1.03/qbiff.c qmail-ldap/qbiff.c +--- qmail-1.03/qbiff.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qbiff.c Thu Jan 29 16:48:14 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include + #ifndef UTMP_FILE + #ifdef _PATH_UTMP +@@ -33,7 +34,7 @@ stralloc woof = {0}; + stralloc tofrom = {0}; + stralloc text = {0}; + +-void doit(s,n) char *s; int n; ++void doit(s,n) char *s; unsigned int n; + { + if (!stralloc_catb(&text,s,n)) _exit(0); + if (text.len > 78) text.len = 78; +@@ -41,7 +42,7 @@ void doit(s,n) char *s; int n; + void dobody(h) stralloc *h; { doit(h->s,h->len); } + void doheader(h) stralloc *h; + { +- int i; ++ unsigned int i; + if (hfield_known(h->s,h->len) == H_SUBJECT) + { + i = hfield_skipname(h->s,h->len); +@@ -50,13 +51,13 @@ void doheader(h) stralloc *h; + } + void finishheader() { ; } + +-void main() ++int main() + { + char *user; + char *sender; + char *userext; + struct stat st; +- int i; ++ unsigned int i; + + if (chdir("/dev") == -1) _exit(0); + +@@ -90,9 +91,9 @@ void main() + + fdutmp = open_read(UTMP_FILE); + if (fdutmp == -1) _exit(0); +- substdio_fdbuf(&ssutmp,read,fdutmp,bufutmp,sizeof(bufutmp)); ++ substdio_fdbuf(&ssutmp,subread,fdutmp,bufutmp,sizeof(bufutmp)); + +- while (substdio_get(&ssutmp,&ut,sizeof(ut)) == sizeof(ut)) ++ while (substdio_get(&ssutmp,(char *)&ut,sizeof(ut)) == sizeof(ut)) + if (!str_diffn(ut.ut_name,user,sizeof(ut.ut_name))) + { + byte_copy(line,sizeof(ut.ut_line),ut.ut_line); +@@ -105,9 +106,9 @@ void main() + if (fstat(fdtty,&st) == -1) { close(fdtty); continue; } + if (!(st.st_mode & 0100)) { close(fdtty); continue; } + if (st.st_uid != getuid()) { close(fdtty); continue; } +- substdio_fdbuf(&sstty,write,fdtty,buftty,sizeof(buftty)); ++ substdio_fdbuf(&sstty,subwrite,fdtty,buftty,sizeof(buftty)); + substdio_putflush(&sstty,woof.s,woof.len); + close(fdtty); + } +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qldap-cluster.c qmail-ldap/qldap-cluster.c +--- qmail-1.03/qldap-cluster.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-cluster.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,92 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifdef QLDAP_CLUSTER ++#include "constmap.h" ++#include "control.h" ++#include "qldap-debug.h" ++#include "str.h" ++#include "stralloc.h" ++ ++#include "qldap-cluster.h" ++ ++static int clusteron; ++static stralloc me = {0}; ++static stralloc mh = {0}; /* buffer for constmap */ ++static struct constmap mailhosts_map; ++ ++ ++int ++cluster_init(void) ++{ ++ clusteron = 0; /* default is off */ ++ ++ if (control_readline(&me, "control/me") != 1) ++ return -1; ++ if (control_readint(&clusteron, "control/ldapcluster") == -1) ++ return -1; ++ logit(64, "init: control/ldapcluster: %i\n", clusteron); ++ ++ if (clusteron == 0) ++ return 0; ++ ++ if (control_readfile(&mh,"control/ldapclusterhosts",0) == -1) ++ return -1; ++ logit(64, "init_ldap: control/ldapclusterhosts: read\n"); ++ if (!stralloc_cat(&mh, &me) || !stralloc_0(&mh)) ++ return -1; ++ if (mailhosts_map.num != 0) constmap_free(&mailhosts_map); ++ if (!constmap_init(&mailhosts_map, mh.s, mh.len,0)) ++ return -1; ++ return 0; ++} ++ ++int ++cluster(char *mailhost) ++/* returns 1 if mail/connection needs to be forwarded else 0 */ ++{ ++ if (clusteron == 0 || mailhost == (char *)0) ++ return 0; ++ if (constmap(&mailhosts_map, mailhost, str_len(mailhost)) == 0) ++ return 1; ++ else ++ return 0; ++} ++ ++stralloc * ++cluster_me(void) ++{ ++ return &me; ++} ++ ++#endif +diff -upN qmail-1.03/qldap-cluster.h qmail-ldap/qldap-cluster.h +--- qmail-1.03/qldap-cluster.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-cluster.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __QLDAP_CLUSTER_H__ ++#define __QLDAP_CLUSTER_H__ ++ ++int cluster_init(void); ++int cluster(char *mailhost); ++stralloc *cluster_me(void); ++ ++#endif +diff -upN qmail-1.03/qldap-debug.c qmail-ldap/qldap-debug.c +--- qmail-1.03/qldap-debug.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-debug.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "output.h" ++#include "qldap-debug.h" ++#include "env.h" ++#include "scan.h" ++#include "readwrite.h" ++ ++#include ++ ++#ifdef ENABLE_PROFILE ++#include ++#endif ++ ++#ifdef DEBUG ++ ++/* ++ * Known LOGLEVELs: ++ * 1 = Error, only errors are reported (not verbose) ++ * 2 = Warning, errors and warnings are reported (normaly not verbose) ++ * 4 = Info, print some information (login name and success or fail) ++ * 8 = Info^2 (more info), session forwarding and maildirmake ... ++ * 16 = Debug, more information about authentication etc. ++ * 32 = Debug^2 (more debug info), even more ... ++ * 64 = LDAP-Debug, show everything in the ldap-module ++ *128 = some more LDAP-Debug stuff (good for ldap test tool) ++ *256 = PASSWD-Debug, this shows the encrypted and clear text passwords ++ * so use it with care ++ *1024= profiling output (if compiled with profile support) ++ */ ++ ++#define LOGLEN 256 ++static int addLOG; ++static unsigned long loglevel; ++substdio sslog; ++char logbuffer[LOGLEN]; ++ ++void ++log_init(int fd, unsigned long mask, int via_spawn) ++/* ++ * Known LOGLEVELs: ++ */ ++{ ++ char *a = env_get("LOGLEVEL"); ++ ++ loglevel = 0; ++ addLOG = via_spawn; ++ if ( a && *a ) { ++ scan_ulong(a, &loglevel); ++ } else if ((a = env_get("DEBUGLEVEL")) && *a ) { ++ scan_ulong(a, &loglevel); ++ } ++ loglevel &= mask; ++ ++ substdio_fdbuf(&sslog, subwrite, fd, logbuffer, sizeof(logbuffer) ); ++/* logit(4, "LOGLEVEL set to %i\n", loglevel); ++ */ ++} ++ ++void ++logit(unsigned long level, const char *fmt, ...) ++/* see va_output (output.c) */ ++{ ++ va_list ap; ++ char ch; ++ ++ va_start(ap, fmt); ++ if ( ! ( loglevel & level ) ) return; ++ ch = 15; ++ if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return; ++ va_output(&sslog, fmt, ap); ++ va_end(ap); ++ ch = 16; ++ if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return; ++ if ( substdio_flush(&sslog) == -1 ) return; ++} ++ ++/* use logstart, logadd and logend with care, if there is no corresponding ++ start or end starnge messages will be loged or some important messages ++ will be lost */ ++void ++logstart(unsigned long level, const char *fmt, ...) ++{ ++ va_list ap; ++ char ch; ++ ++ va_start(ap, fmt); ++ if ( ! ( loglevel & level ) ) return; ++ ch = 15; ++ if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return; ++ va_output(&sslog, fmt, ap); ++ va_end(ap); ++} ++ ++void ++logadd(unsigned long level, const char *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ if ( ! ( loglevel & level ) ) return; ++ va_output(&sslog, fmt, ap); ++ va_end(ap); ++} ++ ++void ++logend(unsigned long level, const char *fmt, ...) ++{ ++ va_list ap; ++ char ch; ++ ++ va_start(ap, fmt); ++ if ( ! ( loglevel & level ) ) return; ++ va_output(&sslog, fmt, ap); ++ va_end(ap); ++ ch = 16; ++ if ( addLOG ) if ( substdio_put(&sslog, &ch, 1) ) return; ++ if ( substdio_flush(&sslog) == -1 ) return; ++} ++ ++void ++profile(const char *s) ++{ ++#ifdef ENABLE_PROFILE ++ char buf[TAIA_PACK]; ++ struct taia t; ++ ++ taia_now(&t); ++ taia_pack(buf,&t); ++ logit(LOG_PROFILE, "PROFILE: %s @%s\n", s, buf); ++#endif ++} ++#else /* DEBUG */ ++void log_init(int fd, unsigned long mask, int via_spawn) {} ++void logit(unsigned long level, const char *fmt, ...) {} ++void logstart(unsigned long level, const char *fmt, ...) {} ++void logadd(unsigned long level, const char *fmt, ...) {} ++void logend(unsigned long level, const char *fmt, ...) {} ++void profile(const char *s) {} ++#endif +diff -upN qmail-1.03/qldap-debug.h qmail-ldap/qldap-debug.h +--- qmail-1.03/qldap-debug.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-debug.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __QLDAP_DEBUG_H__ ++#define __QLDAP_DEBUG_H__ ++ ++extern void log_init(int fd, unsigned long mask, int via_spawn); ++extern void logit(unsigned long level, const char *fmt, ...); ++extern void logstart(unsigned long level, const char *fmt, ...); ++extern void logadd(unsigned long level, const char *fmt, ...); ++extern void logend(unsigned long level, const char *fmt, ...); ++extern void profile(const char *s); ++ ++#define PROFILE(s) profile(s) ++ ++#endif +diff -upN qmail-1.03/qldap-errno.c qmail-ldap/qldap-errno.c +--- qmail-1.03/qldap-errno.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-errno.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "qldap-errno.h" ++#include "error.h" ++ ++/* XXX TODO needs to be removed */ ++int qldap_errno; ++ ++const char *qldap_err_str(int enbr) ++/* returns a string that corresponds to the qldap_errno */ ++{ ++ switch (enbr) { ++ case OK: ++ return "successful"; ++ case ERRNO: ++ return error_str(errno); ++ case FAILED: ++ return "unspecified error"; ++ case PANIC: ++ return "PANIC! Fatal error"; ++ ++ case NOSUCH: ++ return "no such object"; ++ case TOOMANY: ++ return "too many objects"; ++ case TIMEOUT: ++ return "operation timed out"; ++ ++ case BADVAL: ++ return "bad value"; ++ case ILLVAL: ++ return "illegal value"; ++ case NEEDED: ++ return "needed value is missing"; ++ ++ case BADPASS: ++ return "authorization failed, wrong password"; ++ case FORWARD: ++ return "session needs to be forwarded"; ++ ++ case BADCLUSTER: ++ return "misconfigured cluster"; ++ case ACC_DISABLED: ++ return "account disabled"; ++ case AUTH_EXEC: ++ return "unable to start subprogram"; ++ case AUTH_CONF: ++ return "configuration error"; ++ case AUTH_TYPE: ++ return "unsupported authentication mode"; ++ ++ case MAILDIR_NONEXIST: ++ return "maildir/homedir does not exist"; ++ case MAILDIR_UNCONF: ++ return "no dirmaker script configured"; ++ case MAILDIR_CORRUPT: ++ return "maildir seems to be corrupted"; ++ case MAILDIR_CRASHED: ++ return "dirmaker script crashed"; ++ case MAILDIR_FAILED: ++ return "automatic maildir/homedir creation failed"; ++ case MAILDIR_HARD: ++ return "hard error in maildir/homedir creation"; ++ ++ case LDAP_BIND_UNREACH: ++ return "ldap server down or unreachable"; ++ case LDAP_BIND_AUTH: ++ return "wrong bind password for ldap server"; ++ default: ++ return "unknown error occured"; ++ } ++} ++ +diff -upN qmail-1.03/qldap-errno.h qmail-ldap/qldap-errno.h +--- qmail-1.03/qldap-errno.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-errno.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __QLDAP_ERRNO_H__ ++#define __QLDAP_ERRNO_H__ ++ ++/* XXX TODO cleanup */ ++ ++extern int qldap_errno; ++ ++/* generic errors */ ++#define OK 0 /* all OK */ ++#define ERRNO 1 /* check errno for more info */ ++#define FAILED 2 /* generic failed message */ ++#define PANIC 3 /* fatal error happend */ ++ ++#define NOSUCH 4 /* no such object */ ++#define TOOMANY 5 /* too many objects */ ++#define TIMEOUT 6 /* operation timed out */ ++ ++#define BADVAL 7 /* bad value */ ++#define ILLVAL 8 /* illegal value (check failed) */ ++#define NEEDED 9 /* needed value is missing */ ++ ++#define BADPASS 10 /* auth failed wrong password */ ++#define FORWARD 11 /* session needs to be forwarded */ ++ ++/* auth_mod and checkpassword specific errors */ ++#define BADCLUSTER 20 /* bad settings for clustering */ ++#define ACC_DISABLED 21 /* account disabled */ ++#define AUTH_EXEC 22 /* unable to start subprogram */ ++#define AUTH_CONF 23 /* configuration error */ ++#define AUTH_TYPE 24 /* unsuportet auth type */ ++ ++/* maildirmake specific errors */ ++#define MAILDIR_NONEXIST 25 /* maildir/homedir does not exist */ ++#define MAILDIR_UNCONF 26 /* no dirmaker script configured */ ++#define MAILDIR_CORRUPT 27 /* maildir seems to be corrupted */ ++#define MAILDIR_CRASHED 28 /* dirmaker script crashed */ ++#define MAILDIR_FAILED 29 /* automatic maildir creation failed */ ++#define MAILDIR_HARD 30 /* hard error in maildir creation */ ++ ++/* LDAP specific errnos */ ++#define LDAP_BIND_UNREACH 31 /* ldap server down or unreachable */ ++#define LDAP_BIND_AUTH 32 /* wrong bind password */ ++ ++const char *qldap_err_str(int enbr); ++/* returns a string that corresponds to the qldap_errno */ ++ ++#endif +diff -upN qmail-1.03/qldap-filter.c qmail-ldap/qldap-filter.c +--- qmail-1.03/qldap-filter.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-filter.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "auto_break.h" ++#include "qldap.h" ++#include "qmail-ldap.h" ++#include "str.h" ++#include "stralloc.h" ++ ++static stralloc escapedstr = {0}; ++/* ++ * For LDAP, '(', ')', '\', '*' and '\0' have to be escaped with '\'. ++ * We ignore the '\0' case because it is not possible to have a '\0' in s. ++ */ ++char * ++filter_escape(char *s) ++{ ++ char x; ++ ++ /* pre reserve some space */ ++ if (!stralloc_ready(&escapedstr, str_len(s))) return 0; ++ if (!stralloc_copys(&escapedstr, "")) return 0; ++ do { ++ x = *s; ++ if (x == '*' || x == '(' || x == ')' || x == '\\') ++ if (!stralloc_append(&escapedstr, "\\")) return 0; ++ if (!stralloc_append(&escapedstr, s)) return 0; ++ } while (*s++); ++ return escapedstr.s; ++} ++ ++static stralloc ocfilter = {0}; ++extern stralloc objectclass; ++ ++char * ++filter_objectclass(char *searchfilter) ++{ ++ ++ if (searchfilter == (char *)0) return 0; ++ if (objectclass.s == (char *)0 || objectclass.len == 0) ++ return searchfilter; ++ /* (&(objectclass=...)%searchfilter%) */ ++ if (!stralloc_copys(&ocfilter, "(&(") || ++ !stralloc_cats(&ocfilter, LDAP_OBJECTCLASS) || ++ !stralloc_cats(&ocfilter, "=") || ++ !stralloc_cat(&ocfilter, &objectclass) || ++ !stralloc_cats(&ocfilter, ")") || ++ !stralloc_cats(&ocfilter, searchfilter) || ++ !stralloc_cats(&ocfilter, ")") || ++ !stralloc_0(&ocfilter)) ++ return 0; ++ return ocfilter.s; ++} ++ ++static stralloc filter = {0}; ++ ++char * ++filter_uid(char *uid) ++{ ++ char *escaped; ++ ++ if (uid == (char *)0) return 0; ++ ++ escaped = filter_escape(uid); ++ if (escaped == (char *)0) return 0; ++ ++ if (!stralloc_copys(&filter,"(") || ++ !stralloc_cats(&filter, LDAP_UID) || ++ !stralloc_cats(&filter, "=") || ++ !stralloc_cats(&filter, escaped) || ++ !stralloc_cats(&filter, ")") || ++ !stralloc_0(&filter)) ++ return (char *)0; ++ return filter_objectclass(filter.s); ++} ++ ++static int extcnt; ++ ++ ++char * ++filter_mail(char *mail, int *done) ++{ ++ static char *escaped; ++ static unsigned int at, ext, len = 0; ++#ifdef DASH_EXT ++ unsigned int i; ++#endif ++ ++ if (mail == (char *)0) { ++ len = 0; ++ return 0; ++ } ++ ++ if (len == 0) { ++ escaped = filter_escape(mail); ++ if (escaped == (char *)0) return 0; ++ len = str_len(escaped); ++ at = str_rchr(escaped, '@'); ++ if (escaped[at] != '@') { ++ len = 0; ++ return 0; ++ } ++ ext = at; ++ extcnt = -1; ++ *done = 0; ++ } else { ++ if (extcnt == 0) { ++ *done = 1; ++ return 0; ++ } ++#ifdef DASH_EXT ++ /* ++ * limit ext to the first DASH_EXT_LEVELS extensions. ++ * We will only check for (DASH_EXT_LEVELS = 4): ++ * a-b-c-d-e-f-g-...@foobar.com ++ * a-b-c-d-catchall@foobar.com ++ * a-b-c-catchall@foobar.com ++ * a-b-catchall@foobar.com ++ * a-catchall@foobar.com ++ * catchall@foobar.com ++ */ ++ if (ext == at) ++ for (i = 0, ext = 0, extcnt = 1; ++ ext < at && extcnt <= DASH_EXT_LEVELS; ext++) ++ if (escaped[ext] == *auto_break) extcnt++; ++ while (ext != 0 && --ext > 0) { ++ if (escaped[ext] == *auto_break) break; ++ } ++ extcnt--; ++#else ++ /* basic qmail-ldap behavior test for username@domain.com and ++ catchall@domain.com */ ++ ext = 0; ++ extcnt = 0; ++#endif ++ } ++ ++ /* build the search string for the email address */ ++ if (!stralloc_copys(&filter, "(|(" )) return 0; ++ /* mail address */ ++ if (!stralloc_cats(&filter, LDAP_MAIL)) return 0; ++ if (!stralloc_cats(&filter, "=")) return 0; ++ /* username till current '-' */ ++ if (!stralloc_catb(&filter, escaped, ext)) return 0; ++ if (ext != at) { /* do not append catchall in the first round */ ++ /* catchall or default */ ++ if (extcnt > 0) /* add '-' */ ++ if (!stralloc_cats(&filter, auto_break)) ++ return 0; ++ if (!stralloc_cats(&filter, LDAP_CATCH_ALL)) return 0; ++ } ++ /* @damin.com */ ++ if (!stralloc_catb(&filter, escaped+at, len-at)) return 0; ++ ++ /* mailalternate address */ ++ if (!stralloc_cats(&filter, ")(")) return 0; ++ if (!stralloc_cats(&filter, LDAP_MAILALTERNATE)) return 0; ++ if (!stralloc_cats(&filter, "=")) return 0; ++ /* username till current '-' */ ++ if (!stralloc_catb(&filter, escaped, ext)) return 0; ++ if (ext != at) { /* do not append catchall in the first round */ ++ /* catchall or default */ ++ if (extcnt > 0) /* add '-' */ ++ if (!stralloc_cats(&filter, auto_break)) return 0; ++ if (!stralloc_cats(&filter, LDAP_CATCH_ALL)) return 0; ++ } ++ /* @domain.com */ ++ if (!stralloc_catb(&filter, escaped+at, len-at)) return 0; ++ if (!stralloc_cats(&filter, "))")) return 0; ++ if (!stralloc_0(&filter)) return 0; ++ ++ if (extcnt == 0) *done = 1; ++ return filter_objectclass(filter.s); ++} ++ ++int ++filter_mail_ext(void) ++{ ++ return extcnt; ++} +diff -upN qmail-1.03/qldap-profile.c qmail-ldap/qldap-profile.c +--- qmail-1.03/qldap-profile.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-profile.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "taia.h" ++#include "qldap-profile.h" ++#include "qldap-debug.h" ++ ++struct profile_t { ++ struct taia start; ++ char *function; ++}; ++ ++static struct profile_t profile_list[PROFILES_MAX]; ++ ++void start_timing(unsigned int profile, char *function) ++{ ++ if (profile >= PROFILES_MAX) { ++ debug(0x400, "Max Number of profiles exceeded\n"); ++ return; ++ } ++ ++ taia_now(&(profile_list[profile].start)); ++ ++} ++ ++void stop_timing(unsigned int profile) ++{ ++ struct taia stop; ++ struct taia diff; ++ char nano[TAIA_FMTFRAC]; ++ unsigned long sec; ++ ++ if (profile >= PROFILES_MAX) { ++ debug(0x400, "Max Number of profiles exceeded\n"); ++ return; ++ } ++ ++ taia_now(&stop); ++ ++ taia_sub(&diff, &stop, &profile_list[profile].start); ++ nano[taia_fmtfrac(nano, &diff)] = 0; /* terminate to be sure */ ++ nano[7] = 0; /* only the first 6-7 figures are != 0, (nano seconds) */ ++ sec=(unsigned long) ((unsigned long long) diff.sec.x); ++ debug(0x400, "%s took %u.%s Sec\n", profile_list[profile].function, sec, nano); ++ ++} ++ +diff -upN qmail-1.03/qldap-profile.h qmail-ldap/qldap-profile.h +--- qmail-1.03/qldap-profile.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap-profile.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2000-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __QLDAP_PROFILE_H__ ++#define __QLDAP_PROFILE_H__ ++ ++#define PROFILES_MAX 4 /* 4 concurrent profiles */ ++ ++void start_timing(int profile, char *function); ++/* start the timing of a function */ ++ ++void stop_timing(int profile); ++/* stop the timing of a function and print the difference */ ++ ++#endif +diff -upN qmail-1.03/qldap.c qmail-ldap/qldap.c +--- qmail-1.03/qldap.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,1055 @@ ++/* ++ * Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include /* for ldap search timeout */ ++ ++#include ++#include ++ ++#include "alloc.h" ++#include "byte.h" ++#include "case.h" ++#include "check.h" ++#include "control.h" ++#include "error.h" ++#include "fmt.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "scan.h" ++#include "str.h" ++#include "stralloc.h" ++ ++#include "qldap.h" ++ ++struct qldap { ++ int state; ++#define NEW 0 ++#define OPEN 1 ++#define BIND 2 ++#define SEARCH 3 ++#define EXTRACT 4 ++#define REBIND 5 ++#define CLOSE 6 ++#define ERROR -1 ++ LDAP *ld; ++ LDAPMessage *res; /* valid after a search */ ++ LDAPMessage *msg; /* valid after call to ldap_first_entry() */ ++ /* should we store server, binddn, basedn, password, ... */ ++}; ++ ++stralloc ldap_server = {0}; ++stralloc basedn = {0}; ++stralloc objectclass = {0}; ++stralloc ldap_login = {0}; ++stralloc ldap_password = {0}; ++stralloc default_messagestore = {0}; ++stralloc dotmode = {0}; ++unsigned int ldap_timeout = QLDAP_TIMEOUT; /* default timeout is 30 secs */ ++int rebind = 0; /* default off */ ++int default_uid = 0; ++int default_gid = 0; ++unsigned long quotasize = 0; ++unsigned long quotacount = 0; ++ ++ ++static int qldap_close(qldap *); ++ ++static int qldap_set_option(qldap *, int); ++static int check_next_state(qldap *, int); ++ ++#define STATEIN(x, y) ((x)->state == (y)) ++#define CHECK(x, y) \ ++ do { \ ++ if (check_next_state((x), (y)) == 0) { \ ++ logit(128, "qldap: bad state transition %i -> %i",\ ++ (x)->state, y); \ ++ (x)->state = ERROR; \ ++ return FAILED; \ ++ } \ ++ } while (0) ++ ++ ++int ++qldap_ctrl_login(void) ++{ ++ if (control_rldef(&ldap_login, "control/ldaplogin", 0, "") == -1) ++ return -1; ++ if (!stralloc_0(&ldap_login)) return -1; ++ logit(64, "init_ldap: control/ldaplogin: %s\n", ldap_login.s); ++ ++ if (control_rldef(&ldap_password, "control/ldappassword", 0, "") == -1) ++ return -1; ++ if (!stralloc_0(&ldap_password)) return -1; ++ logit(64, "init_ldap: control/ldappassword: %s\n", ldap_password.s); ++ ++ return 0; ++} ++ ++int ++qldap_ctrl_trylogin(void) ++{ ++ if (control_rldef(&ldap_password, "control/ldappassword", 0, "") == ++ -1) { ++ if (!stralloc_catb(&ldap_password, "", 1)) return -1; ++ if (!stralloc_catb(&ldap_login, "", 1)) return -1; ++ return 0; ++ } ++ if (!stralloc_0(&ldap_password)) return -1; ++ ++ if (control_rldef(&ldap_login, "control/ldaplogin", 0, "") == -1) { ++ if (!stralloc_catb(&ldap_password, "", 1)) return -1; ++ if (!stralloc_catb(&ldap_login, "", 1)) return -1; ++ return 0; ++ } ++ if (!stralloc_0(&ldap_login)) return -1; ++ ++ logit(64, "init_ldap: control/ldaplogin: %s\n", ldap_login.s); ++ logit(64, "init_ldap: control/ldappassword: %s\n", ldap_password.s); ++ ++ return 0; ++} ++ ++int ++qldap_ctrl_generic(void) ++{ ++ /* set defaults, so that a reread works */ ++ ldap_timeout = QLDAP_TIMEOUT; /* default timeout is 30 secs */ ++ rebind = 0; /* default off */ ++ default_uid = 0; ++ default_gid = 0; ++ quotasize = 0; ++ quotacount = 0; ++ ++ if (control_readfile(&ldap_server, "control/ldapserver", 0) != 1) ++ return -1; /* ... the errno should be set by control_* */ ++ byte_repl(ldap_server.s, ldap_server.len, '\0', ' '); ++ if (!stralloc_0(&ldap_server)) return -1; ++ logit(64, "init_ldap: control/ldapserver: %s\n", ldap_server.s); ++ ++ if (control_rldef(&basedn, "control/ldapbasedn", 0, "") == -1) ++ return -1; ++ if (!stralloc_0(&basedn)) return -1; ++ logit(64, "init_ldap: control/ldapbasedn: %s\n", basedn.s); ++ ++ if (control_rldef(&objectclass, "control/ldapobjectclass", 0, "") == -1) ++ return -1; ++ logit(64, "init_ldap: control/ldapobjectclass: %S\n", &objectclass); ++ ++ if (control_readint(&ldap_timeout, "control/ldaptimeout") == -1) ++ return -1; ++ logit(64, "init_ldap: control/ldaptimeout: %i\n", ldap_timeout); ++ ++ if (control_readint(&rebind, "control/ldaprebind") == -1) return -1; ++ logit(64, "init_ldap: control/ldaprebind: %i\n", rebind); ++ ++ ++ /* defaults */ ++ if (control_readint(&default_uid, "control/ldapuid") == -1) ++ return -1; ++ if (default_uid != 0) ++ logit(64, "init_ldap: control/ldapuid: %i\n", default_uid); ++ ++ if (control_readint(&default_gid, "control/ldapgid") == -1) ++ return -1; ++ if (default_gid != 0) ++ logit(64, "init_ldap: control/ldapgid: %i\n", default_gid); ++ ++ if (control_rldef(&default_messagestore, ++ "control/ldapmessagestore", 0, "") == -1) ++ return -1; ++ if (default_messagestore.len > 1) { ++ if (default_messagestore.s[default_messagestore.len-1] != '/') ++ if (!stralloc_append(&default_messagestore, "/")) ++ return -1; ++ logit(64, "init_ldap: control/ldapmessagestore: %S\n", ++ &default_messagestore); ++ } else ++ if (!stralloc_copys(&default_messagestore, "")) return -1; ++ ++ if (control_rldef(&dotmode, "control/ldapdefaultdotmode", ++ 0, "ldaponly") == -1) return -1; ++ if (!stralloc_0(&dotmode)) return -1; ++ logit(64, "init_ldap: control/ldapdefaultdotmode: %s\n", dotmode.s); ++ ++ if (control_readulong("asize, "control/defaultquotasize") == -1) ++ return -1; ++ if (control_readulong("acount, "control/defaultquotacount") == -1) ++ return -1; ++ logit(64, "init_ldap: control/defaultquotasize: %u\n", quotasize); ++ logit(64, "init_ldap: control/defaultquotacount: %u\n", quotacount); ++ ++ return 0; ++} ++ ++int ++qldap_need_rebind(void) ++{ ++ return rebind; ++} ++ ++char * ++qldap_basedn(void) ++{ ++ return basedn.s; ++} ++ ++qldap * ++qldap_new(void) ++{ ++ qldap *q; ++ ++ q = (qldap *)alloc(sizeof(qldap)); ++ if (q == 0) return (qldap *)0; ++ byte_zero(q, sizeof(qldap)); ++ return q; ++} ++ ++/****** LDAP OPEN, BIND & CLOSE *********************************************/ ++ ++int ++qldap_open(qldap *q) ++{ ++ int rc; ++ ++ CHECK(q, OPEN); ++ ++ /* allocate the connection */ ++ if ((q->ld = ldap_init(ldap_server.s,LDAP_PORT)) == 0) { ++ logit(128, "qldap_open: init failed\n"); ++ return ERRNO; ++ } ++ logit(128, "qldap_open: init successful\n"); ++ ++ rc = qldap_set_option(q, 0); ++ if (rc != OK) ++ logit(128, "qldap_open: qldap_set_option failed\n"); ++ q->state = rc==OK?OPEN:ERROR; ++ return rc; ++} ++ ++int ++qldap_bind(qldap *q, const char *binddn, const char *passwd) ++{ ++ int rc, try = 0; ++ ++ CHECK(q, BIND); ++ ++ /* bind or rebind to the server with credentials */ ++ if (binddn == (char *)0) { ++ /* use default credentials */ ++ binddn = ldap_login.s; ++ passwd = ldap_password.s; ++ } ++ ++retry: ++ /* connect to the LDAP server */ ++ rc = ldap_simple_bind_s(q->ld, binddn, passwd); ++ try++; ++ /* probably more detailed information should be returned, eg.: ++ LDAP_STRONG_AUTH_NOT_SUPPORTED, ++ LDAP_STRONG_AUTH_REQUIRED, ++ *LDAP_INAPPROPRIATE_AUTH*, ++ LDAP_AUTH_UNKNOWN ++ */ ++ switch (rc) { ++ case LDAP_SUCCESS: ++ logit(128, "qldap_bind: successful\n"); ++ q->state = BIND; ++ return OK; ++ case LDAP_TIMELIMIT_EXCEEDED: ++ case LDAP_SERVER_DOWN: ++ logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc)); ++ q->state = ERROR; ++ return LDAP_BIND_UNREACH; ++ case LDAP_INVALID_CREDENTIALS: ++ logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc)); ++ q->state = ERROR; ++ return LDAP_BIND_AUTH; ++ case LDAP_PROTOCOL_ERROR: ++ logit(128, "qldap_bind: failed wrong protocol (%s)\n", ++ ldap_err2string(rc)); ++ /* bind failed try Version 2 */ ++ if (try > 1) break; ++ logit(128, "qldap_bind: retrying bind with Version 1\n"); ++ qldap_close(q); ++ rc = qldap_open(q); ++ logit(128, "qldap_bind: opened conection for Version 1\n"); ++ qldap_set_option(q, 1); ++ logit(128, "qldap_bind: set options for Version 1\n"); ++ if (rc != OK) break; ++ goto retry; ++ default: ++ logit(128, "qldap_bind: failed (%s)\n", ldap_err2string(rc)); ++ break; ++ } ++ q->state = ERROR; ++ return FAILED; ++} ++ ++int ++qldap_rebind(qldap *q, const char *binddn, const char *passwd) ++{ ++ int rc; ++ ++ CHECK(q, REBIND); ++ ++ if (!STATEIN(q, OPEN)) { ++ qldap_close(q); ++ rc = qldap_open(q); ++ if (rc != OK) return rc; ++ } ++ return qldap_bind(q, binddn, passwd); ++} ++ ++static int ++qldap_close(qldap *q) ++{ ++ CHECK(q, CLOSE); ++ ++ qldap_free_results(q); /* free results */ ++ /* close and free ldap connection */ ++ ldap_unbind_s(q->ld); ++ q->state = CLOSE; ++ return OK; ++} ++ ++int ++qldap_free_results(qldap *q) ++{ ++ if (STATEIN(q, SEARCH) || STATEIN(q, EXTRACT)) { ++ ldap_msgfree(q->res); ++ q->res = (LDAPMessage *)0; ++ q->msg = (LDAPMessage *)0; ++ } ++ return OK; ++} ++ ++int ++qldap_free(qldap *q) ++{ ++ qldap_free_results(q); ++ if (!STATEIN(q, NEW) && !STATEIN(q, CLOSE)) ++ qldap_close(q); ++ byte_zero(q, sizeof(qldap)); ++ alloc_free(q); ++ return OK; ++} ++ ++/****** LDAP SEARCH & FILTER ************************************************/ ++ ++int ++qldap_lookup(qldap *q, const char *filter, const char *attrs[]) ++{ ++ /* search a unique entry */ ++ struct timeval tv; ++ int rc; ++ unsigned int num_entries; ++ ++ CHECK(q, SEARCH); ++ ++ tv.tv_sec = ldap_timeout; ++ tv.tv_usec = 0; ++ ++ rc = ldap_search_st(q->ld, basedn.s, LDAP_SCOPE_SUBTREE, ++ filter, (char **)attrs, 0, &tv, &q->res); ++ ++ switch (rc) { ++ /* probably more detailed information should be returned, eg.: ++ LDAP_TIMELIMIT_EXCEEDED, ++ LDAP_SIZELIMIT_EXCEEDED, ++ LDAP_PARTIAL_RESULTS, ++ LDAP_INSUFFICIENT_ACCESS, ++ LDAP_BUSY, ++ LDAP_UNAVAILABLE, ++ LDAP_UNWILLING_TO_PERFORM, ++ LDAP_TIMEOUT ++ */ ++ ++ case LDAP_SUCCESS: ++ logit(128, "qldap_lookup: search for %s succeeded\n", ++ filter); ++ break; ++ case LDAP_TIMEOUT: ++ case LDAP_TIMELIMIT_EXCEEDED: ++ case LDAP_BUSY: ++ logit(64, "qldap_lookup: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return TIMEOUT; ++ case LDAP_NO_SUCH_OBJECT: ++ logit(64, "qldap_filter: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return NOSUCH; ++ default: ++ logit(64, "qldap_lookup: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return FAILED; ++ } ++ ++ /* count the results, we must have exactly one */ ++ num_entries = ldap_count_entries(q->ld, q->res); ++ if (num_entries != 1) { ++ if (num_entries > 1) { ++ logit(64, "qldap_lookup: Too many entries found (%i)\n", ++ num_entries); ++ return TOOMANY; ++ } else { ++ logit(64, "qldap_lookup: Nothing found\n"); ++ return NOSUCH; ++ } ++ } ++ /* go to the first entry */ ++ q->msg = ldap_first_entry(q->ld, q->res); ++ ++ /* ++ * We already selected the first and only entry so ++ * skip SEARCH state and move directly to EXTRACT state. ++ */ ++ q->state = EXTRACT; ++ return OK; ++} ++ ++int ++qldap_filter(qldap *q, const char *filter, const char *attrs[], ++ char *bdn, int scope) ++{ ++ ++ /* search a unique entry */ ++ struct timeval tv; ++ int rc; ++ ++ /* search multiple entries */ ++ CHECK(q, SEARCH); ++ ++ switch (scope) { ++ case SCOPE_BASE: ++ scope = LDAP_SCOPE_BASE; ++ break; ++ case SCOPE_ONELEVEL: ++ scope = LDAP_SCOPE_ONELEVEL; ++ break; ++ case SCOPE_SUBTREE: ++ scope = LDAP_SCOPE_SUBTREE; ++ break; ++ default: ++ return FAILED; ++ } ++ ++ tv.tv_sec = ldap_timeout; ++ tv.tv_usec = 0; ++ ++ rc = ldap_search_st(q->ld, bdn, scope, filter, ++ (char **)attrs, 0, &tv, &q->res); ++ ++ switch (rc) { ++ /* probably more detailed information should be returned, eg.: ++ LDAP_TIMELIMIT_EXCEEDED, ++ LDAP_SIZELIMIT_EXCEEDED, ++ LDAP_PARTIAL_RESULTS, ++ LDAP_INSUFFICIENT_ACCESS, ++ LDAP_BUSY, ++ LDAP_UNAVAILABLE, ++ LDAP_UNWILLING_TO_PERFORM, ++ LDAP_TIMEOUT ++ */ ++ ++ case LDAP_SUCCESS: ++ logit(128, "qldap_filter: search for %s succeeded\n", ++ filter); ++ break; ++ case LDAP_TIMEOUT: ++ case LDAP_TIMELIMIT_EXCEEDED: ++ case LDAP_BUSY: ++ logit(64, "qldap_filter: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return TIMEOUT; ++ case LDAP_NO_SUCH_OBJECT: ++ logit(64, "qldap_filter: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return NOSUCH; ++ default: ++ logit(64, "qldap_filter: search for %s failed (%s)\n", ++ filter, ldap_err2string(rc) ); ++ return FAILED; ++ } ++ ++ q->state = SEARCH; ++ return OK; ++} ++ ++int ++qldap_count(qldap *q) ++{ ++ CHECK(q, EXTRACT); ++ return ldap_count_entries(q->ld, q->res); ++} ++ ++int ++qldap_first(qldap *q) ++{ ++ CHECK(q, EXTRACT); ++ /* get first match of a qldap_filter search */ ++ ++ q->msg = ldap_first_entry(q->ld, q->res); ++ if (q->msg == (LDAPMessage *)0) { ++ if (ldap_count_entries(q->ld, q->res) == 0) ++ return NOSUCH; ++ else ++ return FAILED; ++ } ++ q->state = EXTRACT; ++ return OK; ++} ++ ++int ++qldap_next(qldap *q) ++{ ++ CHECK(q, EXTRACT); ++ /* get next match of a qldap_filter search */ ++ if (q->msg == 0) return FAILED; ++ ++ q->msg = ldap_next_entry(q->ld, q->msg); ++ if (q->msg == (LDAPMessage*)0) ++ return NOSUCH; ++ q->state = EXTRACT; ++ return OK; ++} ++ ++/****** ATTRIBUTE EXTRACTION *************************************************/ ++ ++static stralloc ldap_attr = {0}; ++ ++int ++qldap_get_uid(qldap *q, int *uid) ++{ ++ unsigned long ul; ++ int r; ++ ++ /* get and check the uid */ ++ r = qldap_get_attr(q, LDAP_QMAILUID, &ldap_attr, SINGLE_VALUE); ++ if (r == OK) { ++ if (ldap_attr.s[scan_ulong(ldap_attr.s, &ul)] != '\0') ++ r = BADVAL; ++ else if (UID_MIN <= ul && ul <= UID_MAX) ++ *uid = ul; ++ else ++ r = ILLVAL; ++ } else if (r == NOSUCH && default_uid != 0) { ++ *uid = default_uid; ++ return OK; ++ } else if (r == NOSUCH) ++ return NEEDED; ++ return r; ++} ++ ++int ++qldap_get_gid(qldap *q, int *gid) ++{ ++ unsigned long ul; ++ int r; ++ ++ /* get and check the gid */ ++ r = qldap_get_attr(q, LDAP_QMAILGID, &ldap_attr, SINGLE_VALUE); ++ if (r == OK) { ++ if (ldap_attr.s[scan_ulong(ldap_attr.s, &ul)] != '\0') ++ r = BADVAL; ++ else if (GID_MIN <= ul && ul <= GID_MAX) ++ *gid = ul; ++ else ++ r = ILLVAL; ++ } else if (r == NOSUCH && default_gid != 0) { ++ *gid = default_gid; ++ return OK; ++ } else if (r == NOSUCH) ++ return NEEDED; ++ return r; ++} ++ ++int ++qldap_get_mailstore(qldap *q, stralloc *hd, stralloc *ms) ++{ ++ int r; ++ /* ++ * get and check the mailstores. ++ * Both homedir and maildir are set from the three ++ * values ~control/ldapmessagestore, homedirectory ++ * and mailmessagestore. ++ * ms is only filled with a value if both homedir ++ * and maildir is used. ++ */ ++ r = qldap_get_attr(q, LDAP_HOMEDIR, hd, SINGLE_VALUE); ++ if (r == NOSUCH) { ++ if (!stralloc_copys(hd, "")) return ERRNO; ++ } else if (r != OK) ++ return r; ++ if (0 < hd->len) { ++ if (hd->s[0] != '/' || check_paths(hd->s) == 0) { ++ /* probably some log warning would be good */ ++ return ILLVAL; ++ } ++ } ++ ++ r = qldap_get_attr(q, LDAP_MAILSTORE, ms, SINGLE_VALUE); ++ if (r == NOSUCH) { ++ if (!stralloc_copys(ms, "")) return ERRNO; ++ } else if (r != OK) ++ return r; ++ if (ms->len > 0) ++ if (check_paths(ms->s) == 0) { ++ /* probably some log warning would be good */ ++ return ILLVAL; ++ } ++ ++ if (hd->len > 0 && ms->len > 0) return OK; ++ if (hd->len > 0) return OK; ++ if (ms->len > 0) { ++ if (ms->s[0] != '/') { ++ if (default_messagestore.s == 0 || ++ default_messagestore.len == 0) ++ return ILLVAL; ++ if (!stralloc_cat(hd, &default_messagestore)) ++ return ERRNO; ++ } ++ if (!stralloc_cat(hd, ms)) ++ return ERRNO; ++ if (!stralloc_copys(ms, "")) return ERRNO; ++ return OK; ++ } ++ return NEEDED; ++} ++ ++int ++qldap_get_user(qldap *q, stralloc *user) ++{ ++ int r; ++ ++ /* get the user name */ ++ r = qldap_get_attr(q, LDAP_UID, user, SINGLE_VALUE); ++ if (r != OK) return r; ++ if (check_users(user->s) == 0) { ++ /* probably some log warning would be good */ ++ return ILLVAL; ++ } ++ return r; ++} ++ ++int ++qldap_get_status(qldap *q, int *status) ++{ ++ int r; ++ ++ /* default value */ ++ *status = STATUS_UNDEF; ++ /* get and check the status of the account */ ++ r = qldap_get_attr(q, LDAP_ISACTIVE, &ldap_attr, SINGLE_VALUE); ++ if (r == NOSUCH) { ++ return OK; ++ } else if (r == OK) { ++ if (!case_diffs(ldap_attr.s, ISACTIVE_BOUNCE)) ++ *status = STATUS_BOUNCE; ++ else if (!case_diffs(ldap_attr.s, ISACTIVE_DELETE)) ++ *status = STATUS_DELETE; ++ else if (!case_diffs(ldap_attr.s, ISACTIVE_NOACCESS)) ++ *status = STATUS_NOACCESS; ++ else *status = STATUS_OK; /* default to OK */ ++ /* perhaps we should spill out a warning for unknown settings */ ++ return OK; ++ } ++ return r; ++} ++ ++int ++qldap_get_dotmode(qldap *q, stralloc *dm) ++{ ++ int r; ++ ++ /* get and check the status of the account */ ++ r = qldap_get_attr(q, LDAP_DOTMODE, &ldap_attr, SINGLE_VALUE); ++ if (r == NOSUCH) { ++ if (!stralloc_copy(dm, &dotmode)) return ERRNO; ++ return OK; ++ } ++ if (r != OK) ++ return r; ++ ++ if (!case_diffs(DOTMODE_LDAPONLY, ldap_attr.s)) { ++ if (!stralloc_copys(dm, DOTMODE_LDAPONLY)) return ERRNO; ++ } else if (!str_diff(DOTMODE_LDAPWITHPROG, ldap_attr.s)) { ++ if (!stralloc_copys(dm, DOTMODE_LDAPWITHPROG)) return ERRNO; ++ } else if (!str_diff(DOTMODE_DOTONLY, ldap_attr.s)) { ++ if (!stralloc_copys(dm, DOTMODE_DOTONLY)) return ERRNO; ++ } else if (!str_diff(DOTMODE_BOTH, ldap_attr.s)) { ++ if (!stralloc_copys(dm, DOTMODE_BOTH)) return ERRNO; ++ } else if (!str_diff(DOTMODE_NONE, ldap_attr.s)) { ++ if (!stralloc_copys(dm, DOTMODE_NONE)) return ERRNO; ++ } else { ++ return ILLVAL; ++ } ++ if (!stralloc_0(dm)) return ERRNO; ++ return OK; ++} ++ ++int ++qldap_get_quota(qldap *q, unsigned long *size, unsigned long *count, ++ unsigned long *max) ++/* XXX move to a quota file? Currently I don't think so. */ ++{ ++ int r; ++ ++ *size = quotasize; ++ *count = quotacount; ++ *max = 0; ++ ++ /* First get the maximum mail size. */ ++ r = qldap_get_ulong(q, LDAP_MAXMSIZE, max); ++ if (r != OK && r != NOSUCH) ++ return r; ++ ++ r = qldap_get_ulong(q, LDAP_QUOTA_SIZE, size); ++ if (r != OK && r != NOSUCH) ++ return r; ++ r = qldap_get_ulong(q, LDAP_QUOTA_COUNT, count); ++ if (r != OK && r != NOSUCH) ++ return r; ++ ++ return OK; ++} ++ ++int ++qldap_get_dn(qldap *q, stralloc *dn) ++{ ++ char *d; ++ ++ CHECK(q, EXTRACT); ++ ++ d = ldap_get_dn(q->ld, q->msg); ++ if (d == (char *)0) ++ return NOSUCH; ++ if (!stralloc_copys(dn, d) || !stralloc_0(dn)) ++ return ERRNO; ++#ifdef LDAP_OPT_PROTOCOL_VERSION ++ /* ++ * OpenLDAP 1.x does not have ldap_memfree() use free() instead. ++ */ ++ ldap_memfree(d); ++#else ++ free(d); ++#endif ++ return OK; ++} ++ ++int ++qldap_get_ulong(qldap *q, const char *attr, unsigned long *ul) ++{ ++ unsigned long ulval; ++ int r; ++ ++ r = qldap_get_attr(q, attr, &ldap_attr, SINGLE_VALUE); ++ if (r == OK) { ++ if (ldap_attr.s[scan_ulong(ldap_attr.s, &ulval)] != '\0') ++ return BADVAL; ++ *ul = ulval; ++ } ++ return r; ++} ++ ++int ++qldap_get_bool(qldap *q, const char *attr, int *bool) ++{ ++ int r; ++ ++ r = qldap_get_attr(q, attr, &ldap_attr, SINGLE_VALUE); ++ if (r == OK) { ++ if (!case_diffs("TRUE", ldap_attr.s)) ++ *bool = 1; ++ else if (!case_diffs("1", ldap_attr.s)) ++ *bool = 1; ++ else if (!case_diffs("FALSE", ldap_attr.s)) ++ *bool = 0; ++ else if (!case_diffs("0", ldap_attr.s)) ++ *bool = 0; ++ else ++ return BADVAL; ++ } ++ return r; ++} ++ ++int ++qldap_get_attr(qldap *q, const char *attr, stralloc *val, int multi) ++{ ++ char **vals; ++ int nvals, i, j, l, r; ++ char sc = ':'; ++ /* ++ * extract value of attr if multivalue use ':' as ++ * separator and escape the sep value with '\\'. ++ */ ++ CHECK(q, EXTRACT); ++ ++ vals = ldap_get_values(q->ld, q->msg, attr); ++ if (vals == (char **)0) { ++#if 0 ++ /* ++ * XXX this does not work. ldap_result2error returns ++ * the result of the bind action in other words success ++ */ ++ /* error occured maybe LDAP_NO_SUCH_ATTRIBUTE */ ++ r = ldap_result2error(q->ld, q->msg, 0); ++ switch (r) { ++ case LDAP_NO_SUCH_ATTRIBUTE: ++ logit(128, "qldap_get_attr: %s\n", ++ ldap_err2string(r)); ++ return NOSUCH; ++ default: ++ logit(128, "qldap_get_attr: %s\n", ++ ldap_err2string(r)); ++ return FAILED; ++ } ++#endif ++ logit(128, "qldap_get_attr(%s): no such attribute\n", attr); ++ return NOSUCH; ++ } ++ nvals = ldap_count_values(vals); ++ ++ r = FAILED; ++ switch (multi) { ++ case SINGLE_VALUE: ++ if (nvals > 1) { ++ r = TOOMANY; ++ break; ++ } ++ if (!stralloc_copys(val, vals[0])) goto fail; ++ if (!stralloc_0(val)) goto fail; ++ r = OK; ++ break; ++ case MULTI_VALUE: ++ if (!stralloc_copys(val, "")) goto fail; ++ for (i = 0; i < nvals; i++) { ++ if (i != 0) ++ if (!stralloc_append(val, &sc)) ++ goto fail; ++ l = str_len(vals[i]); ++ for (j = 0; j < l; j++) { ++ if (vals[i][j] == sc) ++ if (!stralloc_append(val, "\\")) ++ goto fail; ++ if (!stralloc_append(val, &vals[i][j])) ++ goto fail; ++ } ++ } ++ if (!stralloc_0(val)) goto fail; ++ r = OK; ++ break; ++ case OLDCS_VALUE: ++ if (!stralloc_copys(val, "")) goto fail; ++ for (i = 0; i < nvals; i++) { ++ if (i != 0) if (!stralloc_append(val, &sc)) goto fail; ++ byte_repl(vals[i], str_len(vals[i]), ',', sc); ++ if (!stralloc_cats(val, vals[i])) goto fail; ++ } ++ if (!stralloc_0(val)) goto fail; ++ r = OK; ++ break; ++ } ++ ldap_value_free(vals); ++ ++ logit(128, "qldap_get_attr(%s): %s\n", attr, val->s); ++ return r; ++ ++fail: ++ r = errno; ++ ldap_value_free(vals); ++ stralloc_copys(val, ""); ++ errno = r; ++ return ERRNO; ++} ++ ++/****** INTERNAL LDAP FUNCTIONS *********************************************/ ++ ++/* ++ * The rebind procedure - this gets called when the application must ++ * perform a bind operation to follow a referral. Works only with OpenLDAP. ++ */ ++#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) ++#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */ ++static int dorebind(LDAP *, LDAP_CONST char *, ber_tag_t , ber_int_t, void *); ++#else ++static int dorebind(LDAP *, LDAP_CONST char *, int, ber_int_t); ++#endif ++ ++#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */ ++static int ++dorebind(LDAP *ld, LDAP_CONST char *url, ++ ber_tag_t request, ber_int_t msgid, void *dummy) ++#else ++static int ++dorebind(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid) ++#endif ++{ ++ int r; ++ LDAPURLDesc *srv; ++ ++ /* the url parse is just for debugging */ ++ if( (r = ldap_url_parse(url, &srv)) != LDAP_SUCCESS) { ++ logit(64, "dorebind: parse url failed: %s\n", ++ ldap_err2string(r)); ++ return r; ++ } ++ /* Not request is defined in ldap.h - one of LDAP_REQ_XXXXX */ ++ logit(64, "dorebind: referral - host %s:%d, dn \"%s\", " ++ "request %d, msgid %d\n", ++ srv->lud_host, srv->lud_port, srv->lud_dn, request, msgid); ++ ldap_free_urldesc(srv); ++ ++ r = ldap_simple_bind_s(ld, ldap_login.s, ldap_password.s); ++ if (r != LDAP_SUCCESS) { ++ logit(64, "dorebind: ldap_simple_bind_s: %s\n", ++ ldap_err2string(r)); ++ } ++ return r; ++} ++#endif ++ ++static int ++qldap_set_option(qldap *q, int forceV2) ++{ ++#ifdef LDAP_OPT_PROTOCOL_VERSION ++ /* ++ * OpenLDAP 1.x does not have ldap_set_option() so compile only if ++ * available. ++ */ ++ int rc, version; ++ ++ CHECK(q, OPEN); ++ ++ if (forceV2 == 1) { ++ version = LDAP_VERSION2; ++ rc = ldap_set_option(q->ld, ++ LDAP_OPT_PROTOCOL_VERSION, &version); ++ if (rc == LDAP_OPT_SUCCESS) { ++ logit(128, "qldap_set_option: LDAPv2 successful\n"); ++ return OK; ++ } else { ++ logit(128, "qldap_set_option: LDAPv2 failed (%s)\n", ++ ldap_err2string(rc)); ++ return FAILED; ++ } ++ } else { ++ version = LDAP_VERSION3; ++ rc = ldap_set_option(q->ld, ++ LDAP_OPT_PROTOCOL_VERSION, &version); ++ if (rc != LDAP_OPT_SUCCESS) { ++ logit(128, "qldap_set_option: failed (%s)\n", ++ ldap_err2string(rc)); ++ return qldap_set_option(q, 1); ++ } ++ ++#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) ++ /* ++ * currently we support referrals only with OpenLDAP >= 2.x ++ * 1.x does not support it and the other SDKs have other ++ * rebind functions. ++ */ ++#if LDAP_VENDOR_VERSION >= 20100 /* Oh no! They changed again the api, honey. */ ++ rc = ldap_set_rebind_proc(q->ld, dorebind, (void *)0); ++#else ++ rc = ldap_set_rebind_proc(q->ld, dorebind); ++#endif ++ if (rc == LDAP_OPT_SUCCESS) { ++ rc = ldap_set_option(q->ld, LDAP_OPT_REFERRALS, ++ LDAP_OPT_ON); ++ } ++ if (rc != LDAP_OPT_SUCCESS) ++ logit(128, "qldap_set_option: " ++ "enabling referrals failed (%s)\n", ++ ldap_err2string(rc)); ++ else ++ logit(128, "qldap_set_option: " ++ "set referrals successful\n"); ++ /* referral errors are ignored */ ++#endif ++ } ++#endif ++ return OK; ++} ++ ++static int ++check_next_state(qldap *q, int next) ++{ ++ switch (next) { ++ case NEW: ++ /* NEW is a invalid next state */ ++ return 0; ++ case OPEN: ++ /* current state is either NEW, OPEN or CLOSE */ ++ if (STATEIN(q, NEW) || STATEIN(q, OPEN) || STATEIN(q, CLOSE)) ++ return 1; ++ else ++ return 0; ++ case BIND: ++ /* current state is OPEN */ ++ if (STATEIN(q, OPEN)) ++ return 1; ++ else ++ return 0; ++ case SEARCH: ++ /* current state is one of BIND, SEARCH and EXTRACT */ ++ if (STATEIN(q, BIND) || STATEIN(q, SEARCH) || ++ STATEIN(q, EXTRACT)) ++ return 1; ++ else ++ return 0; ++ case EXTRACT: ++ /* current state is EXTRACT */ ++ if (STATEIN(q, EXTRACT) || STATEIN(q, SEARCH)) ++ return 1; ++ else ++ return 0; ++ case REBIND: ++ /* current state is either EXTRACT or OPEN */ ++ if (STATEIN(q, EXTRACT) || STATEIN(q, OPEN)) ++ return 1; ++ else ++ return 0; ++ case CLOSE: ++ /* all states allowed */ ++ return 1; ++ case ERROR: ++ /* ERROR is a invalid next state */ ++ return 0; ++ default: ++ /* bad state */ ++ return 0; ++ } ++} ++ +diff -upN qmail-1.03/qldap.h qmail-ldap/qldap.h +--- qmail-1.03/qldap.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qldap.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,114 @@ ++/* ++ * Copyright (c) 2003-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __QLDAP_H__ ++#define __QLDAP_H__ ++ ++#include "stralloc.h" ++ ++#define SINGLE_VALUE 1 ++#define MULTI_VALUE 2 ++#define OLDCS_VALUE 3 ++ ++#define SCOPE_BASE 0x10 ++#define SCOPE_ONELEVEL 0x20 ++#define SCOPE_SUBTREE 0x30 ++ ++typedef struct qldap qldap; ++ ++int qldap_ctrl_login(void); ++int qldap_ctrl_trylogin(void); ++int qldap_ctrl_generic(void); ++int qldap_need_rebind(void); ++char *qldap_basedn(void); ++qldap *qldap_new(void); ++ ++/* possible errors: ++ * init: FAILED, ERRNO ++ * bind: FAILED, LDAP_BIND_UNREACH, LDAP_BIND_AUTH ++ * rebind: FAILED, ERRNO, LDAP_BIND_UNREACH, LDAP_BIND_AUTH ++ */ ++int qldap_open(qldap *); ++int qldap_bind(qldap *, const char *, const char *); ++int qldap_rebind(qldap *, const char *, const char *); ++ ++/* possible errors: ++ * all free functions return always OK ++ */ ++int qldap_free_results(qldap *); ++int qldap_free(qldap *); ++ ++/* possible errors: ++ * FAILED TIMEOUT TOOMANY NOSUCH ++ */ ++int qldap_lookup(qldap *, const char *, const char *[]); ++ ++/* possible errors: ++ * FAILED TIMEOUT NOSUCH ++ */ ++int qldap_filter(qldap *, const char *, const char *[], char *, int); ++ ++/* ++ * returns -1 on error ++ */ ++int qldap_count(qldap *); ++ ++/* possible errors: ++ * FAILED NOSUCH (no more results) ++ */ ++int qldap_first(qldap *); ++int qldap_next(qldap *); ++ ++/* possible errors of all get functions: ++ * FAILED ERRNO BADVAL ILLVAL NEEDED NOSUCH TOOMANY ++ */ ++int qldap_get_uid(qldap *, int *); ++int qldap_get_gid(qldap *, int *); ++int qldap_get_mailstore(qldap *, stralloc *, stralloc *); ++int qldap_get_user(qldap *, stralloc *); ++int qldap_get_status(qldap *, int *); ++int qldap_get_dotmode(qldap *, stralloc *); ++int qldap_get_quota(qldap *, unsigned long *, unsigned long *, unsigned long *); ++ ++int qldap_get_dn(qldap *, stralloc *); ++int qldap_get_ulong(qldap *, const char *, unsigned long *); ++int qldap_get_bool(qldap *, const char *, int *); ++int qldap_get_attr(qldap *, const char *, stralloc *, int); ++ ++/* qldap-filter.c */ ++char *filter_escape(char *); ++char *filter_objectclass(char *); ++char *filter_uid(char *); ++char *filter_mail(char *, int *); ++int filter_mail_ext(void); ++#endif +diff -upN qmail-1.03/qlx.h qmail-ldap/qlx.h +--- qmail-1.03/qlx.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qlx.h Tue Sep 16 18:57:06 2003 +@@ -15,4 +15,28 @@ + #define QLX_EXECPW 121 + #define QLX_EXECHARD 126 + ++/* qmail-ldap specific exit codes */ ++ ++/* ldap specific errors */ ++#define QLX_MAXSIZE 150 ++#define QLX_LDAPFAIL 152 /* generic fail of ldap functions */ ++#define QLX_LDAPAUTH 153 /* LDAP_BIND_AUTH */ ++#define QLX_SEARCHTIMEOUT 154 /* TIMEOUT */ ++#define QLX_BINDTIMEOUT 155 /* LDAP_BIND_UNREACH */ ++#define QLX_TOOMANY 156 ++#define QLX_NEEDED 157 ++#define QLX_ILLVAL 158 ++#define QLX_DISABLED 159 ++#define QLX_DELETED 160 ++ ++/* cluster errors */ ++#define QLX_CLUSTERSOFT 162 ++#define QLX_CLUSTERHARD 163 ++#define QLX_CLUSTERCRASHED 164 ++#define QLX_CLUSTERLOOP 165 ++/* dirmaker errors */ ++#define QLX_DIRMAKESOFT 167 ++#define QLX_DIRMAKEHARD 168 ++#define QLX_DIRMAKECRASH 169 ++ + #endif +diff -upN qmail-1.03/qmail-cdb.c qmail-ldap/qmail-cdb.c +--- qmail-1.03/qmail-cdb.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-cdb.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++/* ++ * Based on similar code by D. J. Bernstein ++ */ ++ ++#include ++#include ++#include ++#include ++#include "auto_qmail.h" ++#include "case.h" ++#include "cdb_make.h" ++#include "exit.h" ++#include "getln.h" ++#include "open.h" ++#include "readwrite.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++ ++#define FATAL "qmail-cdb: fatal: " ++ ++void die_read(void) ++{ ++ strerr_die2sys(111,FATAL,"unable to read from stdin: "); ++} ++void die_write(const char *f) ++{ ++ strerr_die4sys(111,FATAL,"unable to write to ", f, ": "); ++} ++ ++char inbuf[1024]; ++substdio ssin; ++ ++int fd; ++int fdtemp; ++ ++struct cdb_make cdbm; ++stralloc line = {0}; ++int match; ++ ++int main(int argc, char **argv) ++{ ++ umask(033); ++ ++ if (argc != 3) ++ strerr_die1sys(111,"qmail-cdb: usage: qmail-cdb rules.cdb rules.tmp"); ++ ++ substdio_fdbuf(&ssin,subread,0,inbuf,sizeof inbuf); ++ ++ fdtemp = open_trunc(argv[2]); ++ if (fdtemp == -1) die_write(argv[2]); ++ ++ if (cdb_make_start(&cdbm,fdtemp) == -1) die_write(argv[2]); ++ ++ for (;;) { ++ if (getln(&ssin,&line,&match,'\n') != 0) die_read(); ++ case_lowerb(line.s,line.len); ++ while (line.len) { ++ if (line.s[line.len - 1] == ' ') { --line.len; continue; } ++ if (line.s[line.len - 1] == '\n') { --line.len; continue; } ++ if (line.s[line.len - 1] == '\t') { --line.len; continue; } ++ if (line.s[0] != '#') ++ if (cdb_make_add(&cdbm,line.s,line.len,"",0) == -1) ++ die_write(argv[2]); ++ break; ++ } ++ if (!match) break; ++ } ++ ++ if (cdb_make_finish(&cdbm) == -1) die_write(argv[2]); ++ if (fsync(fdtemp) == -1) die_write(argv[2]); ++ if (close(fdtemp) == -1) die_write(argv[2]); /* NFS stupidity */ ++ if (rename(argv[2],argv[1]) == -1) ++ strerr_die5sys(111, FATAL, "unable to move ", argv[2], " to ", argv[1]); ++ ++ return 0; ++} +diff -upN qmail-1.03/qmail-clean.c qmail-ldap/qmail-clean.c +--- qmail-1.03/qmail-clean.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-clean.c Tue Feb 17 15:31:30 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "readwrite.h" + #include "sig.h" + #include "now.h" +@@ -26,12 +27,12 @@ void cleanuppid() + DIR *dir; + direntry *d; + struct stat st; +- datetime_sec time; ++ datetime_sec tnow; + +- time = now(); ++ tnow = now(); + dir = opendir("pid"); + if (!dir) return; +- while (d = readdir(dir)) ++ while ((d = readdir(dir))) + { + if (str_equal(d->d_name,".")) continue; + if (str_equal(d->d_name,"..")) continue; +@@ -39,7 +40,7 @@ void cleanuppid() + if (!stralloc_cats(&line,d->d_name)) continue; + if (!stralloc_0(&line)) continue; + if (stat(line.s,&st) == -1) continue; +- if (time < st.st_atime + OSSIFIED) continue; ++ if (tnow < st.st_atime + OSSIFIED) continue; + unlink(line.s); + } + closedir(dir); +@@ -49,9 +50,9 @@ char fnbuf[FMTQFN]; + + void respond(s) char *s; { if (substdio_putflush(subfdoutsmall,s,1) == -1) _exit(100); } + +-void main() ++int main() + { +- int i; ++ unsigned int i; + int match; + int cleanuploop; + unsigned long id; +@@ -73,26 +74,47 @@ void main() + if (line.len < 7) { respond("x"); continue; } + if (line.len > 100) { respond("x"); continue; } + if (line.s[line.len - 1]) { respond("x"); continue; } /* impossible */ ++#ifndef BIGTODO + for (i = 5;i < line.len - 1;++i) ++#else ++ for (i = line.len - 2;i > 4;--i) ++ { ++ if (line.s[i] == '/') break; ++#endif + if ((unsigned char) (line.s[i] - '0') > 9) + { respond("x"); continue; } ++#ifndef BIGTODO + if (!scan_ulong(line.s + 5,&id)) { respond("x"); continue; } ++#else ++ } ++ if (line.s[i] == '/') ++ if (!scan_ulong(line.s + i + 1,&id)) { respond("x"); continue; } ++#endif + if (byte_equal(line.s,5,"foop/")) + { + #define U(prefix,flag) fmtqfn(fnbuf,prefix,id,flag); \ + if (unlink(fnbuf) == -1) if (errno != error_noent) { respond("!"); continue; } ++#ifndef BIGTODO + U("intd/",0) ++#else ++ U("intd/",1) ++#endif + U("mess/",1) + respond("+"); + } +- else if (byte_equal(line.s,4,"todo/")) ++ else if (byte_equal(line.s,5,"todo/")) + { ++#ifndef BIGTODO + U("intd/",0) + U("todo/",0) ++#else ++ U("intd/",1) ++ U("todo/",1) ++#endif + respond("+"); + } + else + respond("x"); + } +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-forward.c qmail-ldap/qmail-forward.c +--- qmail-1.03/qmail-forward.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-forward.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,179 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include "auto_qmail.h" ++#include "control.h" ++#include "error.h" ++#include "fmt.h" ++#include "getln.h" ++#include "now.h" ++#include "qmail.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++ ++ ++#define FATAL "qmail-forward: fatal: " ++ ++void ++usage(void) ++{ ++ strerr_die1x(100, ++ "qmail-forward: usage: qmail-forward host sender recipient"); ++} ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)"); ++} ++void ++temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)"); ++} ++void ++temp_read(void) ++{ ++ strerr_die3x(111, "Unable to read message: ", ++ error_str(errno), ". (#4.3.0)"); ++} ++void ++temp_fork(void) ++{ ++ strerr_die3x(111, "Unable to fork: ", error_str(errno), ". (#4.3.0)"); ++} ++ ++ ++ ++char buf[4096]; ++ ++stralloc me = {0}; ++stralloc dtline = {0}; ++stralloc messline = {0}; ++ ++void bouncexf(void) ++{ ++ substdio ss; ++ int match; ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ for (;;) ++ { ++ if (getln(&ss, &messline, &match, '\n') != 0) temp_read(); ++ if (!match) break; ++ if (messline.len <= 1) ++ break; ++ if (messline.len == dtline.len) ++ if (!str_diffn(messline.s, dtline.s, dtline.len)) ++ strerr_die2x(100, FATAL, ++ "This message is looping: " ++ "it already has my Cluster-Delivered-To " ++ "line. (#5.4.6)\n"); ++ } ++} ++ ++char strnum1[FMT_ULONG]; ++char strnum2[FMT_ULONG]; ++ ++int ++main (int argc, char **argv) ++{ ++ struct qmail qqt; ++ substdio ss; ++ char *remote, *to, *from; ++ const char *qqx; ++ unsigned long qp; ++ datetime_sec when; ++ int match; ++ unsigned int i; ++ ++ if (!(remote = argv[1])) usage(); ++ if (!(from = argv[2])) usage(); ++ if (!(to = argv[3])) usage(); ++ if (argv[4]) usage(); ++ ++ if (chdir(auto_qmail) == -1) ++ strerr_die4sys(111, FATAL, "Unable to switch to ", ++ auto_qmail, ": "); ++ if (control_init() == -1) ++ strerr_die2sys(111, FATAL, "Unable to read controls: "); ++ if (control_readline(&me, "control/me") != 1) ++ strerr_die2sys(111, FATAL, "Unable to read control/me: "); ++ ++ ++ if (!stralloc_copys(&dtline, "Delivered-To: CLUSTERHOST ")) ++ temp_nomem(); ++ if (!stralloc_cat(&dtline, &me)) temp_nomem(); ++ if (!stralloc_cats(&dtline, " ")) temp_nomem(); ++ if (!stralloc_cats(&dtline, to)) temp_nomem(); ++ for (i = 0; i < dtline.len; ++i) ++ if (dtline.s[i] == '\n') ++ dtline.s[i] = '_'; ++ if (!stralloc_cats(&dtline, "\n")) temp_nomem(); ++ ++ bouncexf(); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ ++ if (qmail_remote(&qqt, remote) == -1) temp_fork(); ++ qp = qmail_qp(&qqt); ++ ++ qmail_put(&qqt, dtline.s, dtline.len); ++ do { ++ if (getln(&ss, &messline, &match, '\n') != 0) { ++ qmail_fail(&qqt); ++ break; ++ } ++ qmail_put(&qqt, messline.s, messline.len); ++ } while (match); ++ qmail_from(&qqt, from); ++ qmail_to(&qqt, to); ++ qqx = qmail_close(&qqt); ++ if (*qqx) ++ strerr_die3x(*qqx == 'D' ? 100 : 111, ++ "Unable to cluster-forward message: ", qqx + 1, "."); ++ when = now(); ++ strnum1[fmt_ulong(strnum1, (unsigned long) when)] = 0; ++ strnum2[fmt_ulong(strnum2, qp)] = 0; ++ strerr_die5x(0, "qmail-forward: ok ", strnum1, " qp ", strnum2, "."); ++ /* NOTREACHED */ ++ return 0; ++} ++ +diff -upN qmail-1.03/qmail-getpw.c qmail-ldap/qmail-getpw.c +--- qmail-1.03/qmail-getpw.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-getpw.c Tue Oct 28 18:21:32 2003 +@@ -18,7 +18,7 @@ + + char *local; + struct passwd *pw; +-char *dash; ++const char *dash; + char *extension; + + int userext() +@@ -37,7 +37,7 @@ int userext() + pw = getpwnam(username); + if (errno == error_txtbsy) _exit(QLX_SYS); + if (pw) +- if (pw->pw_uid) ++ if (pw->pw_uid) { + if (stat(pw->pw_dir,&st) == 0) { + if (st.st_uid == pw->pw_uid) { + dash = ""; +@@ -47,6 +47,7 @@ int userext() + } + else + if (error_temp(errno)) _exit(QLX_NFS); ++ } + } + if (extension == local) return 0; + --extension; +@@ -55,7 +56,7 @@ int userext() + + char num[FMT_ULONG]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -84,5 +85,5 @@ char **argv; + substdio_put(subfdoutsmall,"",1); + substdio_flush(subfdoutsmall); + +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-group.c qmail-ldap/qmail-group.c +--- qmail-1.03/qmail-group.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-group.c Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,974 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++ ++#include "alloc.h" ++#include "auto_break.h" ++#include "byte.h" ++#include "case.h" ++#include "coe.h" ++#include "control.h" ++#include "env.h" ++#include "error.h" ++#include "fd.h" ++#include "fmt.h" ++#include "getln.h" ++#include "ndelay.h" ++#include "now.h" ++#include "open.h" ++#include "qldap.h" ++#include "qldap-errno.h" ++#include "qmail.h" ++#include "qmail-ldap.h" ++#include "read-ctrl.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++#include "wait.h" ++ ++#define FATAL "qmail-group: fatal: " ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory. (#4.3.0)"); ++} ++void ++temp_qmail(char *fn) ++{ ++ strerr_die4sys(111, FATAL, "Unable to open ", fn, ": "); ++} ++void ++temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message. (#4.3.0)"); ++} ++void ++temp_read(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to read message. (#4.3.0)"); ++} ++void ++temp_fork(void) ++{ ++ strerr_die2sys(111, FATAL, "Unable to fork: "); ++} ++void usage(void) ++{ ++ strerr_die1x(100, "qmail-group: usage: qmail-group Maildir"); ++} ++ ++void init(void); ++void bouncefx(void); ++void blast(stralloc *, int); ++void reopen(void); ++void trydelete(void); ++void secretary(char *, int); ++void explode(qldap *); ++void subscribed(qldap *, int); ++qldap *ldapgroup(char *, int *, int *, int *); ++ ++char *local; ++char *host; ++char *sender; ++stralloc base = {0}; ++stralloc action = {0}; ++char *ext; ++char *dname; ++ ++stralloc recips = {0}; ++stralloc bounceadmin = {0}; ++stralloc moderators = {0}; ++unsigned int nummoderators; ++ ++ ++int ++main(int argc, char **argv) ++{ ++ qldap *qlc; ++ char *maildir; ++ int flagm, flagc, flags, flagS; ++ ++ if (argv[1] == 0) usage(); ++ if (argv[2] != 0) usage(); ++ maildir = argv[1]; ++ ++ init(); ++ /* filter out loops as soon as poosible */ ++ bouncefx(); ++ ++ flagc = flags = flagS = flagm = 0; ++ qlc = ldapgroup(dname, &flagc, &flags, &flagS); ++ ++ /* need to distinguish between new messages and responses */ ++ if (action.s) { ++ if (!case_diffs(action.s, "confirm") || ++ !case_diffs(action.s, "approve") || ++ !case_diffs(action.s, "reject")) ++ secretary(maildir, flagc); ++ else if (moderators.s && moderators.len && ++ !case_diffs(action.s, "moderators") && !(ext && *ext)) { ++ /* mail to moderators */ ++ blast(&moderators, 0); ++ } else if (!case_diffs(action.s, "return") && ext && *ext) { ++ /* bounce form subscribed user */ ++ blast(&bounceadmin, 0); ++ } else if (!case_diffs(action.s, "bounce") && ext && *ext) { ++ /* bounce from moderator */ ++ if (bounceadmin.s && bounceadmin.len) ++ blast(&bounceadmin, 0); ++ secretary(maildir, flagc); ++ } else ++ /* bad address */ ++ strerr_die2x(100, FATAL, "Sorry, no mailbox here " ++ "by that name. (#5.1.1)"); ++ } else { ++ if (flags) ++ subscribed(qlc, flagS); ++ if (flagc || nummoderators) ++ secretary(maildir, flagc); ++ } ++ ++ reopen(); ++ explode(qlc); ++ qldap_free(qlc); ++ ++ /* does not return */ ++ blast(&recips, 1); ++ return 111; ++} ++ ++stralloc grouplogin = {0}; ++stralloc grouppassword = {0}; ++ ++int ++init_controls(void) ++{ ++ switch (control_readline(&grouplogin, "control/ldapgrouplogin")) { ++ case 0: ++ return 0; ++ case 1: ++ break; ++ default: ++ return -1; ++ } ++ if (!stralloc_0(&grouplogin)) return -1; ++ ++ if (control_rldef(&grouppassword, "control/ldapgrouppassword", ++ 0, "") == -1) ++ return -1; ++ if (!stralloc_0(&grouppassword)) return -1; ++ ++ return 0; ++} ++ ++ctrlfunc ctrls[] = { ++ qldap_ctrl_trylogin, ++ qldap_ctrl_generic, ++ init_controls, ++ 0 ++}; ++ ++stralloc dtline = {0}; ++ ++void ++init(void) ++{ ++ char *t; ++ unsigned int i; ++ ++ /* read some control files */ ++ if (read_controls(ctrls) == -1) ++ strerr_die2x(100, FATAL, "unable to read controls"); ++ ++ sender = env_get("SENDER"); ++ if (!sender) strerr_die2x(100, FATAL, "SENDER not set"); ++ local = env_get("LOCAL"); ++ if (!local) strerr_die2x(100, FATAL, "LOCAL not set"); ++ host = env_get("HOST"); ++ if (!host) strerr_die2x(100, FATAL, "HOST not set"); ++ dname = env_get(ENV_GROUP); ++ if (!dname) strerr_die2x(100, FATAL, "QLDAPGROUP not set"); ++ ++ ++ t = env_get("EXT"); ++ if (t != 0 && *t != '\0') { ++ if (!stralloc_copyb(&base, local, ++ str_len(local) - str_len(t) - 1)) ++ temp_nomem(); ++ ext = t; ++ ext += str_chr(ext, '-'); ++ if (!stralloc_copyb(&action, t, ext - t)) temp_nomem(); ++ if (!stralloc_0(&action)) temp_nomem(); ++ if (*ext) ++ext; ++ } else { ++ if (!stralloc_copys(&base, local)) temp_nomem(); ++ ext = 0; ++ } ++ if (!stralloc_copys(&dtline, "Delivered-To: ")) temp_nomem(); ++ if (!stralloc_cat(&dtline, &base)) temp_nomem(); ++ if (!stralloc_cats(&dtline, "@")) temp_nomem(); ++ if (!stralloc_cats(&dtline, host)) temp_nomem(); ++ for (i = 0; i < dtline.len; ++i) ++ if (dtline.s[i] == '\n') ++ dtline.s[i] = '_'; ++ if (!stralloc_cats(&dtline,"\n")) temp_nomem(); ++} ++ ++char buf[4096]; ++stralloc line = {0}; ++ ++void ++bouncefx(void) ++{ ++ substdio ss; ++ int match; ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ for (;;) ++ { ++ if (getln(&ss, &line, &match, '\n') != 0) temp_read(); ++ if (!match) break; ++ if (line.len <= 1) break; ++ if (line.len == dtline.len) ++ if (byte_equal(line.s, line.len, dtline.s)) ++ strerr_die2x(100, FATAL, ++ "this message is looping: " ++ "it already has my Delivered-To line. " ++ "(#5.4.6)"); ++ } ++} ++ ++char strnum1[FMT_ULONG]; ++char strnum2[FMT_ULONG]; ++ ++void ++blast(stralloc *r, int flagb) ++{ ++ struct qmail qqt; ++ substdio ss; ++ char *s, *smax; ++ const char *qqx; ++ unsigned long qp; ++ datetime_sec when; ++ int match; ++ ++ if (r->s == (char *)0 || r->len == 0) ++ strerr_die2x(100, FATAL, "no recipients found in this group."); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ ++ if (qmail_open(&qqt) == -1) temp_fork(); ++ qp = qmail_qp(&qqt); ++ /* mail header */ ++ qmail_put(&qqt, dtline.s, dtline.len); ++ qmail_puts(&qqt,"Precedence: bulk\n"); ++ do { ++ if (getln(&ss, &line, &match, '\n') != 0) { ++ qmail_fail(&qqt); ++ break; ++ } ++ qmail_put(&qqt, line.s, line.len); ++ } while (match); ++ ++ if (flagb && bounceadmin.s && bounceadmin.len) { ++ if (!stralloc_copy(&line,&base)) temp_nomem(); ++ if (!stralloc_cats(&line,"-return-@")) temp_nomem(); ++ if (!stralloc_cats(&line,host)) temp_nomem(); ++ if (!stralloc_cats(&line,"-@[]")) temp_nomem(); ++ if (!stralloc_0(&line)) temp_nomem(); ++ qmail_from(&qqt, line.s); ++ } else ++ /* if no bounce admin specified forward with sender address */ ++ qmail_from(&qqt, sender); ++ ++ for (s = r->s, smax = r->s + r->len; s < smax; s += str_len(s) + 1) ++ qmail_to(&qqt,s); ++ qqx = qmail_close(&qqt); ++ if (*qqx) ++ strerr_die3x(*qqx == 'D' ? 100 : 111, ++ "Unable to blast message: ", qqx + 1, "."); ++ when = now(); ++ strnum1[fmt_ulong(strnum1, (unsigned long) when)] = 0; ++ strnum2[fmt_ulong(strnum2, qp)] = 0; ++ trydelete(); ++ strerr_die5x(0, "qmail-group: ok ", strnum1, " qp ", strnum2, "."); ++} ++ ++stralloc fname = {0}; ++char sbuf[1024]; ++ ++void ++reopen(void) ++{ ++ int fd; ++ ++ if (!(fname.s && fname.len > 1)) ++ return; ++ if (!stralloc_0(&fname)) temp_nomem(); ++ fd = open_read(fname.s); ++ if (fd == -1) ++ strerr_die2sys(111, FATAL, "Unable to reopen old message: "); ++ if (fd_move(0,fd) == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to reopen old message: fd_move: "); ++} ++ ++void ++trydelete(void) ++{ ++ if (fname.s && fname.len > 1) ++ unlink(fname.s); ++} ++ ++void ++secretary(char *maildir, int flagcheck) ++{ ++ const char **args; ++ char *s, *smax; ++ int child, wstat; ++ unsigned int i, numargs; ++ int pi[2]; ++ int r; ++ ++ if (!stralloc_copys(&fname, "")) temp_nomem(); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ numargs = 4 + 2 * nummoderators; ++ ++ args = (const char **) alloc(numargs * sizeof(char *)); ++ if (!args) temp_nomem(); ++ i = 0; ++ args[i++] = "qmail-secretary"; ++ if (flagcheck == 1) ++ args[i++] = "-Zc"; ++ else ++ args[i++] = "-ZC"; ++ for (s = moderators.s, smax = moderators.s + moderators.len; ++ s < smax; s += str_len(s) + 1) { ++ args[i++] = "-m"; ++ args[i++] = s; ++ if (i + 2 > numargs) ++ strerr_die2x(111, FATAL, "internal error."); ++ } ++ args[i++] = maildir; ++ args[i++] = 0; ++ ++ if (pipe(pi) == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to run secretary: pipe: "); ++ ++ coe(pi[0]); ++ switch(child = fork()) { ++ case -1: ++ temp_fork(); ++ case 0: ++ if (fd_move(1,pi[1]) == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to run secretary: fd_move: "); ++ sig_pipedefault(); ++ execvp(*args, (char **)args); ++ strerr_die3x(111,"Unable to run secretary: ", ++ error_str(errno), ". (#4.3.0)"); ++ } ++ close(pi[1]); ++ alloc_free(args); ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) ++ strerr_die2x(111, FATAL, "Aack, child crashed."); ++ switch(wait_exitcode(wstat)) { ++ case 100: ++ case 64: case 65: case 70: ++ case 76: case 77: case 78: case 112: ++ _exit(100); ++ case 0: case 99: ++ /* XXX a for(;;) loop would be great */ ++ r = read(pi[0], sbuf, sizeof(sbuf)); ++ if (r == -1) /* read error on a readable pipe, be serious */ ++ strerr_die2sys(111, FATAL, ++ "Unable to read secretary result: "); ++ if (r == 0) ++ /* need to wait for confirmation */ ++ _exit(0); ++ for (i = 0; i < r; i++) { ++ if (i == 0) { ++ if (sbuf[i] != 'K') ++ strerr_die2x(111, FATAL, ++ "Strange secretary dialect"); ++ else ++ continue; ++ } ++ if (!stralloc_append(&fname, &sbuf[i])) temp_nomem(); ++ } ++ close(pi[0]); ++ return; ++ default: _exit(111); ++ } ++} ++ ++/************ LDAP FUNCTIONS AND HELPER FUNCTIONS *************/ ++ ++stralloc ldapval = {0}; ++stralloc tmpval = {0}; ++ ++static void getmoderators(qldap *); ++static int unescape(char *, stralloc *, unsigned int *); ++static void extract_addrs822(qldap *, const char *, stralloc *, unsigned int *); ++static void extract_addrsdn(qldap *, qldap *, const char *, stralloc *, ++ unsigned int *); ++static void extract_addrsfilter(qldap *, qldap *, const char *, stralloc *, ++ unsigned int *); ++static int getentry(qldap *, char *); ++ ++static void ++getmoderators(qldap *q) ++{ ++ qldap *sq; ++ int r; ++ ++ nummoderators = 0; sq = (qldap *)0; ++ if (!stralloc_copys(&moderators, "")) { r = ERRNO; goto fail; } ++ ++ extract_addrs822(q, LDAP_GROUPMODERAT822, ++ &moderators, &nummoderators); ++ ++ /* open a second connection and do some dn lookups */ ++ sq = qldap_new(); ++ if (sq == 0) temp_nomem(); ++ ++ r = qldap_open(sq); ++ if (r != OK) goto fail; ++ r = qldap_bind(sq, grouplogin.s, grouppassword.s); ++ if (r != OK) goto fail; ++ ++ extract_addrsdn(q, sq, LDAP_GROUPMODERATDN, ++ &moderators, &nummoderators); ++ ++ qldap_free(sq); ++ return; ++ ++fail: ++ if (sq) qldap_free(sq); ++ qldap_free(q); ++ strerr_die3x(111, FATAL, "expand group: moderators: ", ++ qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++void ++explode(qldap *q) ++{ ++ qldap *sq; ++ int r; ++ ++ sq = 0; ++ if (!stralloc_copys(&recips, "")) { r = ERRNO; goto fail; } ++ extract_addrs822(q, LDAP_GROUPMEMBER822, &recips, 0); ++ ++ /* open a second connection and do some dn lookups */ ++ sq = qldap_new(); ++ if (sq == 0) temp_nomem(); ++ ++ r = qldap_open(sq); ++ if (r != OK) goto fail; ++ r = qldap_bind(sq, grouplogin.s, grouppassword.s); ++ if (r != OK) goto fail; ++ ++ extract_addrsdn(q, sq, LDAP_GROUPMEMBERDN, &recips, 0); ++ extract_addrsfilter(q, sq, LDAP_GROUPMEMBERFILTER, &recips, 0); ++ ++ qldap_free(sq); ++ return; ++fail: ++ if (sq) qldap_free(sq); ++ qldap_free(q); ++ strerr_die3x(111, FATAL, "expand group: members: ", qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++stralloc founddn = {0}; ++ ++void ++subscribed(qldap *q, int flagS) ++{ ++ qldap *sq; ++ const char *attrs[] = { ++ LDAP_MAIL, ++ 0 }; ++ char *s, *smax; ++ int r; ++ ++ sq = 0; ++ if (!stralloc_copys(&recips, "")) { r = ERRNO; goto fail; } ++ extract_addrs822(q, flagS ? LDAP_GROUPSENDER822 : LDAP_GROUPMEMBER822, ++ &recips, 0); ++ ++ for (s = recips.s, smax = recips.s + recips.len; s < smax; ++ s += str_len(s) + 1) ++ if (!case_diffs(sender, s)) return; ++ ++ /* open a second connection and do some dn lookups */ ++ sq = qldap_new(); ++ if (sq == 0) temp_nomem(); ++ ++ r = qldap_open(sq); ++ if (r != OK) goto fail; ++ r = qldap_bind(sq, grouplogin.s, grouppassword.s); ++ if (r != OK) goto fail; ++ ++ r = getentry(sq, sender); ++ if (r == NOSUCH) { ++ qldap_free(sq); ++ qldap_free(q); ++ strerr_die2x(100, FATAL, ++ "You are not allowed to post to this list. (#5.7.2)"); ++ } ++ if (r != OK) goto fail; ++ ++ r = qldap_get_dn(sq, &founddn); ++ if (r != OK) goto fail; ++ ++ r = qldap_get_attr(q, flagS ? LDAP_GROUPSENDERDN : LDAP_GROUPMEMBERDN, ++ &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, &tmpval, 0); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ for (s = tmpval.s, smax = tmpval.s + tmpval.len; ++ s < smax; s += str_len(s) + 1) ++ if (!case_diffs(s, founddn.s)) { ++ qldap_free(sq); ++ return; ++ } ++ ++ r = qldap_get_attr(q, ++ flagS ? LDAP_GROUPSENDERFILTER : LDAP_GROUPMEMBERFILTER, ++ &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, &tmpval, 0); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ for (s = tmpval.s, smax = tmpval.s + tmpval.len; ++ s < smax; s += str_len(s) + 1) { ++ r = qldap_filter(sq, s, attrs, founddn.s, SCOPE_BASE); ++ if (r == NOSUCH) continue; ++ if (r != OK) goto fail; ++ if (qldap_count(sq) < 1) continue; ++ /* match found */ ++ qldap_free(sq); ++ return; ++ } ++ qldap_free(sq); ++ qldap_free(q); ++ strerr_die2x(100, FATAL, ++ "You are not allowed to post to this list. (#5.7.2)"); ++fail: ++ if (sq) qldap_free(sq); ++ qldap_free(q); ++ strerr_die5x(111, FATAL, "sender ", sender, " verification failed: ", ++ qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++ ++qldap * ++ldapgroup(char *dn, int *flagc, int *flags, int *flagS) ++{ ++ qldap *q; ++ const char *attrs[] = { ++ LDAP_GROUPCONFIRM, ++ LDAP_GROUPMEMONLY, ++ LDAP_GROUPCONFRIMTEXT, ++ LDAP_GROUPMODERATTEXT, ++ LDAP_GROUPMODERATDN, ++ LDAP_GROUPMODERAT822, ++ LDAP_GROUPMEMBERDN, ++ LDAP_GROUPMEMBER822, ++ LDAP_GROUPMEMBERFILTER, ++ LDAP_GROUPSENDERDN, ++ LDAP_GROUPSENDER822, ++ LDAP_GROUPSENDERFILTER, ++ LDAP_GROUPBOUNCEADMIN, ++ 0 }; ++ int r; ++ ++ q = qldap_new(); ++ if (q == 0) temp_nomem(); ++ ++ r = qldap_open(q); ++ if (r != OK) goto fail; ++ r = qldap_bind(q, grouplogin.s, grouppassword.s); ++ if (r != OK) goto fail; ++ ++ r = qldap_filter(q, "objectclass=*", attrs, dn, SCOPE_BASE); ++ if (r != OK) goto fail; ++ r = qldap_count(q); ++ if (r != 1) { ++ /* TOOMANY should be impossible with SCOPE_BASE */ ++ r = r==0 ? NOSUCH : TOOMANY; ++ goto fail; ++ } ++ r = qldap_first(q); /* and only */ ++ if (r != OK) goto fail; ++ ++ r = qldap_get_bool(q, LDAP_GROUPCONFIRM, flagc); ++ if (r != OK && r != NOSUCH) goto fail; ++ ++ r = qldap_get_bool(q, LDAP_GROUPMEMONLY, flags); ++ if (r != OK && r != NOSUCH) goto fail; ++ ++ r = qldap_get_attr(q, LDAP_GROUPCONFRIMTEXT, &ldapval, SINGLE_VALUE); ++ switch (r) { ++ case OK: ++ if (!env_put2("CONFIRMMESS", ldapval.s)) { ++ r = ERRNO; ++ goto fail; ++ } ++ break; ++ case NOSUCH: ++ if (!env_unset("CONFIRMMESS")) { ++ r = ERRNO; ++ goto fail; ++ } ++ break; ++ default: ++ goto fail; ++ } ++ ++ r = qldap_get_attr(q, LDAP_GROUPMODERATTEXT, &ldapval, SINGLE_VALUE); ++ switch (r) { ++ case OK: ++ if (!env_put2("APPROVEMESS", ldapval.s)) { ++ r = ERRNO; ++ goto fail; ++ } ++ break; ++ case NOSUCH: ++ if (!env_unset("APPROVEMESS")) { ++ r = ERRNO; ++ goto fail; ++ } ++ break; ++ default: ++ goto fail; ++ } ++ ++ r = qldap_get_attr(q, LDAP_GROUPBOUNCEADMIN, &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, &bounceadmin, 0); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ ++ getmoderators(q); ++ ++ if (*flags) { ++ r = qldap_get_attr(q, LDAP_GROUPSENDERDN, ++ &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ *flagS = 1; ++ return q; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ r = qldap_get_attr(q, LDAP_GROUPSENDER822, ++ &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ *flagS = 1; ++ return q; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ r = qldap_get_attr(q, LDAP_GROUPSENDERFILTER, ++ &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ *flagS = 1; ++ return q; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ } ++ ++ return q; ++fail: ++ qldap_free(q); ++ strerr_die3x(111, FATAL, "get ldap group entry: ", qldap_err_str(r)); ++ /* NOTREACHED */ ++ return 0; ++} ++ ++static int ++unescape(char *s, stralloc *t, unsigned int *count) ++{ ++ do { ++ if (s[0] == '\\' && s[1] == ':') s++; ++ else if (s[0] == ':') { ++ if (count) *count += 1; ++ if (!stralloc_0(t)) return ERRNO; ++ continue; ++ } ++ if (!stralloc_append(t, s)) return ERRNO; ++ } while (*s++); ++ if (count) *count += 1; ++ return OK; ++} ++ ++static void ++extract_addrs822(qldap *q, const char *attr, stralloc *list, ++ unsigned int *numlist) ++{ ++ int r; ++ ++ r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, list, numlist); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ return; ++fail: ++ qldap_free(q); ++ strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ", ++ qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++static void ++extract_addrsdn(qldap *q, qldap *sq, const char *attr, ++ stralloc *list, unsigned int *numlist) ++{ ++ const char *attrs[] = { ++ LDAP_MAIL, ++ 0 }; ++ char *s, *smax; ++ int r; ++ ++ if (!stralloc_copys(&tmpval, "")) { r = ERRNO; goto fail; } ++ r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, &tmpval, 0); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ for (s = tmpval.s, smax = tmpval.s + tmpval.len; ++ s < smax; s += str_len(s) + 1) { ++ r = qldap_filter(sq, "objectclass=*", attrs, s, SCOPE_BASE); ++ if (r == NOSUCH) continue; ++ if (r != OK) goto fail; ++ r = qldap_count(sq); ++ if (r > 1) { ++ /* TOOMANY should be impossible with SCOPE_BASE */ ++ r = TOOMANY; ++ goto fail; ++ } else if (r <= 0) ++ continue; ++ r = qldap_first(sq); /* and only */ ++ if (r != OK) goto fail; ++ /* get mail address */ ++ r = qldap_get_attr(sq, LDAP_MAIL, &ldapval, SINGLE_VALUE); ++ switch (r) { ++ case OK: ++ if (!stralloc_cat(list, &ldapval)) { ++ r = ERRNO; ++ goto fail; ++ } ++ if (numlist) *numlist += 1; ++ break; ++ case NOSUCH: ++ /* WTF! Ignore. */ ++ break; ++ default: ++ goto fail; ++ } ++ /* free stuff for next search */ ++ qldap_free_results(sq); ++ } ++ return; ++ ++fail: ++ qldap_free(sq); ++ qldap_free(q); ++ strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ", ++ qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++static void ++extract_addrsfilter(qldap *q, qldap *sq, const char *attr, ++ stralloc *list, unsigned int *numlist) ++{ ++ const char *attrs[] = { ++ LDAP_MAIL, ++ 0 }; ++ char *s, *smax; ++ int r; ++ ++ if (!stralloc_copys(&tmpval, "")) { r = ERRNO; goto fail; } ++ r = qldap_get_attr(q, attr, &ldapval, MULTI_VALUE); ++ switch (r) { ++ case OK: ++ r = unescape(ldapval.s, &tmpval, 0); ++ if (r != OK) goto fail; ++ break; ++ case NOSUCH: ++ break; ++ default: ++ goto fail; ++ } ++ ++ for (s = tmpval.s, smax = tmpval.s + tmpval.len; ++ s < smax; s += str_len(s) + 1) { ++ r = qldap_filter(sq, s, attrs, qldap_basedn(), SCOPE_SUBTREE); ++ if (r == NOSUCH) continue; ++ if (r != OK) goto fail; ++ r = qldap_first(sq); ++ if (r != OK && r != NOSUCH) goto fail; ++ if (r == NOSUCH) { ++ qldap_free_results(sq); ++ continue; ++ } ++ do { ++ /* get mail address */ ++ r = qldap_get_attr(sq, LDAP_MAIL, &ldapval, ++ SINGLE_VALUE); ++ switch (r) { ++ case OK: ++ if (!stralloc_cat(list, &ldapval)) { ++ r = ERRNO; ++ goto fail; ++ } ++ if (numlist) *numlist += 1; ++ break; ++ case NOSUCH: ++ /* WTF! Ignore. */ ++ break; ++ default: ++ goto fail; ++ } ++ r = qldap_next(sq); ++ } while (r == OK); ++ if (r != NOSUCH) goto fail; ++ ++ /* free stuff for next search */ ++ qldap_free_results(sq); ++ } ++ return; ++ ++fail: ++ qldap_free(sq); ++ qldap_free(q); ++ strerr_die5x(111, FATAL, "expand group attr: ", attr, ": ", ++ qldap_err_str(r)); ++ /* NOTREACHED */ ++} ++ ++stralloc filter = {0}; ++ ++static int ++getentry(qldap *sq, char *mail) ++{ ++ const char *attrs[] = { ++ LDAP_MAIL, ++ 0 }; ++ char *f; ++ int done, rv; ++ ++ done = 0; ++ do { ++ /* build the search string for the email address */ ++ f = filter_mail(mail, &done); ++ if (f == (char *)0) return ERRNO; ++ ++ /* do the search for the email address */ ++ rv = qldap_lookup(sq, f, attrs); ++ switch (rv) { ++ case OK: ++ return OK; ++ case NOSUCH: ++ break; ++ default: ++ return rv; ++ } ++ } while (!done); ++ return NOSUCH; ++} +diff -upN qmail-1.03/qmail-imapd-ssl.sh qmail-ldap/qmail-imapd-ssl.sh +--- qmail-1.03/qmail-imapd-ssl.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-imapd-ssl.sh Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,40 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# IMAP service: this script is for courier-imap ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++if [ -e $QMAIL/control/defaultdelivery ]; then ++ ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null` ++else ++ ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null` ++fi ++ALIASEMPTY=${ALIASEMPTY:="./Maildir/"} ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++COURIER=${COURIER:="/usr/local"} ++TLSCERT=${TLSCERT:="$QMAIL/control/cert.pem"} ++PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"} ++ ++if [ X${NOPBS+"true"} = X"true" ]; then ++ unset PBSTOOL ++fi ++ ++exec \ ++ tcpserver -v -HRl $ME -x$QMAIL/control/qmail-imapd.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} \ ++ -s ${TLSCERT:+"-n$TLSCERT"} 0 imaps \ ++ $COURIER/sbin/imaplogin \ ++ $QMAIL/bin/auth_imap ${PBSTOOL:+"-d$PBSTOOL"}\ ++ $COURIER/bin/imapd "$ALIASEMPTY" +diff -upN qmail-1.03/qmail-imapd.rules qmail-ldap/qmail-imapd.rules +--- qmail-1.03/qmail-imapd.rules Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-imapd.rules Thu Oct 30 11:11:13 2003 +@@ -0,0 +1,6 @@ ++# ++# IMAP Server rules. ++# Normaly you allow from everyware and the only useful env vars are probably ++# IMAPCAPAPBILITY, NOPBS and LOGLEVEL ++# ++:allow,IMAP_CAPABILITY="IMAP4rev1 CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA" +diff -upN qmail-1.03/qmail-imapd.sh qmail-ldap/qmail-imapd.sh +--- qmail-1.03/qmail-imapd.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-imapd.sh Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,38 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# IMAP service: this script is for courier-imap ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++if [ -e $QMAIL/control/defaultdelivery ]; then ++ ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null` ++else ++ ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null` ++fi ++ALIASEMPTY=${ALIASEMPTY:="./Maildir/"} ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++COURIER=${COURIER:="/usr/local"} ++PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"} ++ ++if [ X${NOPBSR+"true"} = X"true" ]; then ++ unset PBSTOOL ++fi ++ ++exec \ ++ tcpserver -v -HRl $ME -x$QMAIL/control/qmail-imapd.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 imap \ ++ $COURIER/sbin/imaplogin \ ++ $QMAIL/bin/auth_imap ${PBSTOOL:+"-d$PBSTOOL"} \ ++ $COURIER/bin/imapd "$ALIASEMPTY" +diff -upN qmail-1.03/qmail-inject.c qmail-ldap/qmail-inject.c +--- qmail-1.03/qmail-inject.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-inject.c Tue Feb 17 15:31:30 2004 +@@ -1,3 +1,4 @@ ++#include + #include "sig.h" + #include "substdio.h" + #include "stralloc.h" +@@ -35,10 +36,10 @@ int flagnamecomment = 0; + int flaghackmess = 0; + int flaghackrecip = 0; + char *mailhost; +-char *mailuser; ++const char *mailuser; + int mailusertokentype; + char *mailrhost; +-char *mailruser; ++const char *mailruser; + + stralloc control_idhost = {0}; + stralloc control_defaultdomain = {0}; +@@ -53,9 +54,9 @@ int flagrh; + int flagqueue; + struct qmail qqt; + +-void put(s,len) char *s; int len; ++void put(const char *s, unsigned int len) + { if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); } +-void puts(s) char *s; { put(s,str_len(s)); } ++void putstr(const char *s) { put(s,str_len(s)); } + + void perm() { _exit(100); } + void temp() { _exit(111); } +@@ -90,13 +91,13 @@ int flagresent; + + void exitnicely() + { +- char *qqx; ++ const char *qqx; + + if (!flagqueue) substdio_flush(subfdout); + + if (flagqueue) + { +- int i; ++ unsigned int i; + + if (!stralloc_0(&sender)) die_nomem(); + qmail_from(&qqt,sender.s); +@@ -106,7 +107,7 @@ void exitnicely() + if (!stralloc_0(&reciplist.sa[i])) die_nomem(); + qmail_to(&qqt,reciplist.sa[i].s); + } +- if (flagrh) ++ if (flagrh) { + if (flagresent) + for (i = 0;i < hrrlist.len;++i) + { +@@ -119,9 +120,9 @@ void exitnicely() + if (!stralloc_0(&hrlist.sa[i])) die_nomem(); + qmail_to(&qqt,hrlist.sa[i].s); + } +- ++ } + qqx = qmail_close(&qqt); +- if (*qqx) ++ if (*qqx) { + if (*qqx == 'D') { + substdio_puts(subfderr,"qmail-inject: fatal: "); + substdio_puts(subfderr,qqx + 1); +@@ -136,6 +137,7 @@ void exitnicely() + substdio_flush(subfderr); + temp(); + } ++ } + } + + _exit(0); +@@ -152,7 +154,7 @@ stralloc *h; + + void savedh_print() + { +- int i; ++ unsigned int i; + + for (i = 0;i < savedh.len;++i) + put(savedh.sa[i].s,savedh.sa[i].len); +@@ -177,7 +179,7 @@ token822_alloc *addr; + void rwextraat(addr) + token822_alloc *addr; + { +- int i; ++ unsigned int i; + if (addr->t[0].type == TOKEN822_AT) + { + --addr->len; +@@ -189,7 +191,7 @@ token822_alloc *addr; + void rwextradot(addr) + token822_alloc *addr; + { +- int i; ++ unsigned int i; + if (addr->t[0].type == TOKEN822_DOT) + { + --addr->len; +@@ -201,17 +203,17 @@ token822_alloc *addr; + void rwnoat(addr) + token822_alloc *addr; + { +- int i; +- int shift; ++ unsigned int i; ++ unsigned int shift; + + for (i = 0;i < addr->len;++i) + if (addr->t[i].type == TOKEN822_AT) + return; + shift = defaulthost.len; + if (!token822_readyplus(addr,shift)) die_nomem(); +- for (i = addr->len - 1;i >= 0;--i) +- addr->t[i + shift] = addr->t[i]; + addr->len += shift; ++ for (i = addr->len - 1;i >= shift;--i) ++ addr->t[i] = addr->t[i - shift]; + for (i = 0;i < shift;++i) + addr->t[i] = defaulthost.t[shift - 1 - i]; + } +@@ -219,8 +221,8 @@ token822_alloc *addr; + void rwnodot(addr) + token822_alloc *addr; + { +- int i; +- int shift; ++ unsigned int i; ++ unsigned int shift; + for (i = 0;i < addr->len;++i) + { + if (addr->t[i].type == TOKEN822_DOT) +@@ -237,9 +239,9 @@ token822_alloc *addr; + } + shift = defaultdomain.len; + if (!token822_readyplus(addr,shift)) die_nomem(); +- for (i = addr->len - 1;i >= 0;--i) +- addr->t[i + shift] = addr->t[i]; + addr->len += shift; ++ for (i = addr->len - 1;i >= shift;--i) ++ addr->t[i] = addr->t[i - shift]; + for (i = 0;i < shift;++i) + addr->t[i] = defaultdomain.t[shift - 1 - i]; + } +@@ -247,8 +249,8 @@ token822_alloc *addr; + void rwplus(addr) + token822_alloc *addr; + { +- int i; +- int shift; ++ unsigned int i; ++ unsigned int shift; + + if (addr->t[0].type != TOKEN822_ATOM) return; + if (!addr->t[0].slen) return; +@@ -258,9 +260,9 @@ token822_alloc *addr; + + shift = plusdomain.len; + if (!token822_readyplus(addr,shift)) die_nomem(); +- for (i = addr->len - 1;i >= 0;--i) +- addr->t[i + shift] = addr->t[i]; + addr->len += shift; ++ for (i = addr->len - 1;i >= shift;--i) ++ addr->t[i] = addr->t[i - shift]; + for (i = 0;i < shift;++i) + addr->t[i] = plusdomain.t[shift - 1 - i]; + } +@@ -536,7 +538,7 @@ void mft_init() + + void finishmft() + { +- int i; ++ unsigned int i; + static stralloc sa = {0}; + static stralloc sa2 = {0}; + +@@ -549,16 +551,16 @@ void finishmft() + + if (i == tocclist.len) return; + +- puts("Mail-Followup-To: "); ++ putstr("Mail-Followup-To: "); + i = tocclist.len; + while (i--) { + if (!stralloc_copy(&sa,&tocclist.sa[i])) die_nomem(); + if (!stralloc_0(&sa)) die_nomem(); + if (!quote2(&sa2,sa.s)) die_nomem(); + put(sa2.s,sa2.len); +- if (i) puts(",\n "); ++ if (i) putstr(",\n "); + } +- puts("\n"); ++ putstr("\n"); + } + + void finishheader() +@@ -580,9 +582,9 @@ void finishheader() + if (!stralloc_0(&sa)) die_nomem(); + if (!quote2(&sa2,sa.s)) die_nomem(); + +- puts("Return-Path: <"); ++ putstr("Return-Path: <"); + put(sa2.s,sa2.len); +- puts(">\n"); ++ putstr(">\n"); + } + + /* could check at this point whether there are any recipients */ +@@ -594,23 +596,23 @@ void finishheader() + if (!htypeseen[H_R_DATE]) + { + if (!newfield_datemake(starttime)) die_nomem(); +- puts("Resent-"); ++ putstr("Resent-"); + put(newfield_date.s,newfield_date.len); + } + if (!htypeseen[H_R_MESSAGEID]) + { + if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem(); +- puts("Resent-"); ++ putstr("Resent-"); + put(newfield_msgid.s,newfield_msgid.len); + } + if (!htypeseen[H_R_FROM]) + { + defaultfrommake(); +- puts("Resent-"); ++ putstr("Resent-"); + put(defaultfrom.s,defaultfrom.len); + } + if (!htypeseen[H_R_TO] && !htypeseen[H_R_CC]) +- puts("Resent-Cc: recipient list not shown: ;\n"); ++ putstr("Resent-Cc: recipient list not shown: ;\n"); + } + else + { +@@ -630,7 +632,7 @@ void finishheader() + put(defaultfrom.s,defaultfrom.len); + } + if (!htypeseen[H_TO] && !htypeseen[H_CC]) +- puts("Cc: recipient list not shown: ;\n"); ++ putstr("Cc: recipient list not shown: ;\n"); + finishmft(); + } + +@@ -682,11 +684,11 @@ void getcontrols() + #define RECIP_HEADER 3 + #define RECIP_AH 4 + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +- int i; ++ unsigned int i; + int opt; + int recipstrategy; + +@@ -770,4 +772,6 @@ char **argv; + if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) + die_read(); + exitnicely(); ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/qmail-ldap.h qmail-ldap/qmail-ldap.h +--- qmail-1.03/qmail-ldap.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-ldap.h Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,190 @@ ++/* ++ * Copyright (c) 1999-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef _QMAIL_LDAP_H_ ++#define _QMAIL_LDAP_H_ ++ ++/* this is the "catch all" string ++ * ATTN: escape the string correctly, remember ++ * '(', ')', '\', and '*' have to be escaped with '\' ++ */ ++#define LDAP_CATCH_ALL "catchall" ++ ++/* triger level for quotawarning (0-100) */ ++#define QUOTA_WARNING_LEVEL 70 ++ ++/* reply subject for mails without subjects. */ ++#define REPLY_SUBJ "Your Mail" ++/* timeout for one delivery per sender */ ++#define REPLY_TIMEOUT 1209600 /* 1 Week */ ++/* default content type (don't forget the '\n' at the end) */ ++#define REPLY_CT "text/plain; charset=utf-8\n" ++/* default content transfer encoding (don't forget the '\n' at the end) */ ++#define REPLY_CTE "8bit\n" ++ ++/* the maximum and minimum uid allowed */ ++#define UID_MIN 100 ++#define UID_MAX 65535 ++ ++/* the maximum and minimum gid allowed */ ++#define GID_MIN 100 ++#define GID_MAX 65535 ++ ++/* if the sanitycheck function should be less restricted for ++ * program pathes, this means especially that most special chars ++ * of the shell are allowed (like &, &, ;, and <,|,>) ++ * You should know what you are doing when disallowing this */ ++/* 1 = restriced sanitycheck; 0 = less restriced sanitycheck */ ++#define RESTRICT_PROG 1 ++ ++/* ALIASDEVNULL replacement for the std. aliasempty for user with ++ * neither homeDirectory nor mailMessageStore defined */ ++#define ALIASDEVNULL "|echo \"Unable to deliver mail: account incorrectly configured. (#5.3.5)\"; exit 100" ++/* just echo a warning to notify the user and exit 100. ++ * It's up to the reader to write a simple script with ++ * postmaster notification. */ ++ ++/* Default ldap search timeout. In seconds */ ++#define QLDAP_TIMEOUT 30 ++ ++/* This needs DASH_EXT option. ++ * Limit dash ext to the first DASH_EXT_LEVELS extensions. ++ * Search only for (DASH_EXT_LEVELS = 4): ++ * a-b-c-d-e-f-g-...@foobar.com ++ * a-b-c-d-catchall@foobar.com ++ * a-b-c-catchall@foobar.com ++ * a-b-catchall@foobar.com ++ * a-catchall@foobar.com ++ * catchall@foobar.com ++ */ ++#define DASH_EXT_LEVELS 4 ++ ++/********************************************************************* ++ ldap variables used in qmail-lspawn and auth_* ++*********************************************************************/ ++#define LDAP_MAIL "mail" ++#define LDAP_MAILALTERNATE "mailAlternateAddress" ++#define LDAP_QMAILUID "qmailUID" ++#define LDAP_QMAILGID "qmailGID" ++#define LDAP_MAILSTORE "mailMessageStore" ++#define LDAP_HOMEDIR "homeDirectory" ++#define LDAP_QUOTA "mailQuota" ++#define LDAP_QUOTA_SIZE "mailQuotaSize" ++#define LDAP_QUOTA_COUNT "mailQuotaCount" ++#define LDAP_MAXMSIZE "mailSizeMax" ++#define LDAP_FORWARDS "mailForwardingAddress" ++#define LDAP_PROGRAM "deliveryProgramPath" ++#define LDAP_MAILHOST "mailHost" ++#define LDAP_MODE "deliveryMode" ++#define LDAP_REPLYTEXT "mailReplyText" ++#define LDAP_DOTMODE "qmailDotMode" ++#define LDAP_UID "uid" ++#define LDAP_PASSWD "userPassword" ++#define LDAP_OBJECTCLASS "objectClass" ++#define LDAP_ISACTIVE "accountStatus" ++#define LDAP_PURGE "qmailAccountPurge" ++ ++#define DOTMODE_LDAPONLY "ldaponly" ++#define DOTMODE_LDAPWITHPROG "ldapwithprog" ++#define DOTMODE_DOTONLY "dotonly" ++#define DOTMODE_BOTH "both" ++#define DOTMODE_NONE "none" ++ ++#define MODE_FONLY "forwardonly" ++#define MODE_NOFORWARD "noforward" ++#define MODE_NOMBOX "nombox" ++#define MODE_NOLOCAL "nolocal" ++#define MODE_NOPROG "noprogram" ++#define MODE_REPLY "reply" ++/* these are silently ignored */ ++#define MODE_LOCAL "local" ++#define MODE_FORWARD "forward" ++#define MODE_PROG "program" ++#define MODE_NOREPLY "noreply" ++ ++#define ISACTIVE_BOUNCE "disabled" ++#define ISACTIVE_DELETE "deleted" ++#define ISACTIVE_NOACCESS "noaccess" ++#define ISACTIVE_ACTIVE "active" ++ ++/********************************************************************* ++ ldap variables used in qmail-group ++*********************************************************************/ ++#define LDAP_GROUPOBJECTCLASS "qmailGroup" ++#define LDAP_GROUPMEMONLY "membersonly" ++#define LDAP_GROUPCONFIRM "senderconfirm" ++#define LDAP_GROUPCONFRIMTEXT "confirmtext" ++#define LDAP_GROUPMODERATTEXT "moderatortext" ++#define LDAP_GROUPMODERATDN "dnmoderator" ++#define LDAP_GROUPMODERAT822 "rfc822moderator" ++#define LDAP_GROUPMEMBERDN "dnmember" ++#define LDAP_GROUPMEMBER822 "rfc822member" ++#define LDAP_GROUPMEMBERFILTER "filtermember" ++#define LDAP_GROUPSENDERDN "dnsender" ++#define LDAP_GROUPSENDER822 "rfc822sender" ++#define LDAP_GROUPSENDERFILTER "filtersender" ++#define LDAP_GROUPBOUNCEADMIN "bounceadmin" ++ ++ ++/********************************************************************* ++ normaly you can stop editing here ++*********************************************************************/ ++/* the same values as ints */ ++#define STATUS_DELETE 3 ++#define STATUS_BOUNCE 2 ++#define STATUS_NOACCESS 1 ++#define STATUS_OK 0 ++#define STATUS_UNDEF -1 ++ ++/* environment variables used between qmail-lspan and qmail-local ++ * and some other tools ++ */ ++#define ENV_HOMEDIRMAKE "QLDAPAUTOHOMEDIRMAKE" ++ ++#define ENV_QUOTA "MAILDIRQUOTA" ++#define ENV_QUOTAWARNING "QMAILQUOTAWARNING" ++ ++#define ENV_DOTMODE "QMAILDOTMODE" ++#define ENV_MODE "QMAILMODE" ++#define ENV_REPLYTEXT "QMAILREPLYTEXT" ++#define ENV_FORWARDS "QMAILFORWARDS" ++#define ENV_PROGRAM "QMAILDELIVERYPROGRAM" ++ ++#define ENV_GROUP "QLDAPGROUP" ++ ++/* qmail-local.c only */ ++#define DO_LDAP 0x01 ++#define DO_DOT 0x02 ++#define DO_BOTH (DO_LDAP | DO_DOT) ++ ++#endif +diff -upN qmail-1.03/qmail-ldaplookup.c qmail-ldap/qmail-ldaplookup.c +--- qmail-1.03/qmail-ldaplookup.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-ldaplookup.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,548 @@ ++/* ++ * Copyright (c) 2000-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++ ++#include "alloc.h" ++#include "auto_usera.h" ++#include "byte.h" ++#include "case.h" ++#include "env.h" ++#include "error.h" ++#include "localdelivery.h" ++#include "output.h" ++#include "passwd.h" ++#include "qldap.h" ++#include "qldap-cluster.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "read-ctrl.h" ++#include "scan.h" ++#include "sgetopt.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "subfd.h" ++#include "substdio.h" ++#ifdef AUTOHOMEDIRMAKE ++#include "dirmaker.h" ++#endif ++ ++#define FATAL "qmail-ldaplookup: fatal: " ++#define WARN "qmail-ldaplookup: warning: " ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory."); ++} ++ ++void ++usage(void) ++{ ++ output(subfderr, ++ "usage:" ++ "\t%s [-d level] [-D binddn -w passwd] -u uid [-p passwd]\n" ++ "\t%s [-d level] [-D binddn -w passwd] -m mail\n" ++ "\t%s [-d level] [-D binddn -w passwd] -f ldapfilter\n", ++ optprogname, optprogname, optprogname, optprogname); ++ output(subfderr, "options:\n" ++ "\t-d level \tsets log-level to level\n" ++ "\t-u uid \tsearch for user id uid (pop3/imap lookup)\n" ++ "\t-p passwd\tpassword for user id lookups (only by root)\n" ++ "\t-m mail \tlookup the mailaddress\n" ++ "\t-D binddn\tbind DN\n" ++ "\t-w passwd\tbind password\n"); ++ _exit(1); ++} ++ ++void fail(qldap *, const char *, int); ++void unescape(char *, stralloc *); ++ ++ ++ctrlfunc ctrls[] = { ++ qldap_ctrl_trylogin, ++ qldap_ctrl_generic, ++ localdelivery_init, ++#ifdef QLDAP_CLUSTER ++ cluster_init, ++#endif ++#ifdef AUTOHOMEDIRMAKE ++ dirmaker_init, ++#endif ++ 0 ++}; ++ ++stralloc dn = {0}; ++stralloc foo = {0}; ++stralloc bar = {0}; ++ ++int main(int argc, char **argv) ++{ ++ enum { unset, uid, mail, filter } mode = unset; ++ qldap *q, *qpw; ++ struct passwd *pw; ++ char *passwd = 0, *value = 0; ++ char *bindpw = 0, *binddn = 0; ++ char *f, *s; ++ int opt, r, done, status, id; ++ unsigned int j, slen; ++ unsigned long size, count, maxsize; ++ ++ const char *attrs[] = { LDAP_MAIL, ++ LDAP_MAILALTERNATE, ++ LDAP_UID, ++ LDAP_QMAILUID, ++ LDAP_QMAILGID, ++ LDAP_ISACTIVE, ++ LDAP_MAILHOST, ++ LDAP_MAILSTORE, ++ LDAP_HOMEDIR, ++ LDAP_QUOTA_SIZE, ++ LDAP_QUOTA_COUNT, ++ LDAP_FORWARDS, ++ LDAP_PROGRAM, ++ LDAP_MODE, ++ LDAP_REPLYTEXT, ++ LDAP_DOTMODE, ++ LDAP_MAXMSIZE, ++ LDAP_OBJECTCLASS, ++#if 0 ++ LDAP_GROUPCONFIRM, ++ LDAP_GROUPMEMONLY, ++ LDAP_GROUPCONFRIMTEXT, ++ LDAP_GROUPMODERATTEXT, ++ LDAP_GROUPMODERATDN, ++ LDAP_GROUPMODERAT822, ++ LDAP_GROUPMEMBERDN, ++ LDAP_GROUPMEMBER822, ++ LDAP_GROUPMEMBERFILTER, ++#endif ++ LDAP_PASSWD, ++ 0}; ++ ++ while ((opt = getopt(argc, argv, "d:D:u:m:p:f:w:")) != opteof) ++ switch (opt) { ++ case 'd': ++ if (env_put2("LOGLEVEL", optarg) == 0) ++ strerr_die2sys(1, FATAL, "setting loglevel: "); ++ break; ++ case 'D': ++ binddn = optarg; ++ break; ++ case 'u': ++ if (value != 0) ++ usage(); ++ value = optarg; ++ mode = uid; ++ break; ++ case 'm': ++ if (value != 0) ++ usage(); ++ value = optarg; ++ mode = mail; ++ break; ++ case 'f': ++ if (value != 0) ++ usage(); ++ value = optarg; ++ mode = filter; ++ break; ++ case 'p': ++ if (geteuid() != 0) ++ strerr_die2x(1, FATAL, ++ "only the superuser may comapre passwords"); ++ passwd = optarg; ++ break; ++ case 'w': ++ bindpw = optarg; ++ break; ++ default: ++ usage(); ++ } ++ if (argc != optind) usage(); ++ if (bindpw && !binddn) usage(); ++ ++ log_init(STDERR, -1, 0); ++ ++ if (read_controls(ctrls) != 0) ++ strerr_die2sys(111, FATAL, "unable to read controls: "); ++ ++ q = qldap_new(); ++ if (q == 0) ++ strerr_die2sys(111, FATAL, "qldap_new failed: "); ++ qpw = qldap_new(); ++ if (qpw == 0) ++ strerr_die2sys(111, FATAL, "qldap_new failed: "); ++ ++ r = qldap_open(q); ++ if (r != OK) fail(q, "qldap_open", r); ++ r = qldap_open(qpw); ++ if (r != OK) fail(qpw, "qldap_open", r); ++ r = qldap_bind(q, binddn, bindpw); ++ if (r != OK) fail(q, "qldap_bind", r); ++ ++ if (passwd == 0 || mode != uid || qldap_need_rebind() != 0) ++ attrs[sizeof(attrs)/4 - 2] = 0; /* password */ ++ done = 0; ++ f = 0; ++ do { ++ switch (mode) { ++ case mail: ++ f = filter_mail(value, &done); ++ if (value == 0) ++ strerr_die2sys(1, FATAL, "building filter: "); ++ break; ++ case uid: ++ f = filter_uid(value); ++ done = 1; ++ if (value == 0) ++ strerr_die2sys(1, FATAL, "building filter: "); ++ break; ++ case filter: ++ f = value; ++ break; ++ default: ++ usage(); ++ } ++ output(subfdout, "Searching ldap for: %s\nunder dn: %s\n", ++ f, qldap_basedn()); ++ r = qldap_filter(q, f, attrs, qldap_basedn(), SCOPE_SUBTREE); ++ if (r != OK) fail(q, "qldap_filter", r); ++ ++ r = qldap_count(q); ++ switch (r) { ++ case -1: ++ fail(q, "qldap_count", FAILED); ++ case 0: ++ output(subfdout, "No entries found.\n"); ++ qldap_free(q); ++ /* TODO hook for local lookups. */ ++ return 0; ++ case 1: ++ output(subfdout, "Found %i entry:\n", r); ++ break; ++ default: ++ output(subfdout, "Found %i entries:\n", r); ++ if (mode == uid || mode == uid) { ++ output(subfdout, ++ "Uh-oh: multiple entries found but " ++ "should be unique!\n"); ++ passwd = 0; ++ } ++ break; ++ } ++ output(subfdout, "\n"); ++ } while (r == 0 && !done); ++ ++ r = qldap_first(q); ++ if (r != OK) fail(q, "qldap_first", r);; ++ do { ++ r = qldap_get_dn(q, &dn); ++ if (r != OK) fail(q, "qldap_get_dn", r); ++ output(subfdout, "dn: %s\n" ++ "-------------------------------------------------------\n", ++ dn.s); ++ ++ r = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE); ++ if (r != OK) fail(q, "qldap_get_attr(" LDAP_OBJECTCLASS ")", r); ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ output(subfdout, "%s: %s\n",LDAP_OBJECTCLASS ,s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ ++ r = qldap_get_attr(q, LDAP_MAIL, &foo, SINGLE_VALUE); ++ if (r != OK) fail(q, "qldap_get_attr(" LDAP_MAIL ")", r); ++ output(subfdout, "%s: %s\n", LDAP_MAIL, foo.s); ++ ++ r = qldap_get_attr(q, LDAP_MAILALTERNATE, &foo, MULTI_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_MAILALTERNATE ")", r); ++ if (r == OK) { ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ output(subfdout, "%s: %s\n", ++ LDAP_MAILALTERNATE, s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ } ++ ++ r = qldap_get_user(q, &foo); ++ if (r != OK && r != NOSUCH) fail(q, "qldap_get_user", r); ++ if (r == OK) ++ output(subfdout, "%s: %s\n", LDAP_UID, foo.s); ++ else ++ output(subfdout, "%s: undefined " ++ "(forward only account required)\n", LDAP_UID); ++ ++ r = qldap_get_status(q, &status); ++ if (r != OK) fail(q, "qldap_get_status", r); ++ switch (status) { ++ case STATUS_BOUNCE: ++ output(subfdout, "%s: %s\n", ++ LDAP_ISACTIVE, ISACTIVE_BOUNCE); ++ break; ++ case STATUS_NOACCESS: ++ output(subfdout, "%s: %s\n", ++ LDAP_ISACTIVE, ISACTIVE_NOACCESS); ++ break; ++ case STATUS_OK: ++ output(subfdout, "%s: %s\n", ++ LDAP_ISACTIVE, ISACTIVE_ACTIVE); ++ break; ++ case STATUS_UNDEF: ++ output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ++ "undefined -> active"); ++ break; ++ default: ++ strerr_warn2(WARN, ++ "qldap_get_status returned unknown status", 0); ++ } ++ ++ r = qldap_get_attr(q, LDAP_MAILHOST, &foo, SINGLE_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_MAILHOST ")", r); ++ if (r == OK) { ++ output(subfdout, "%s: %s\n", LDAP_MAILHOST, foo.s); ++ /* ++ * TODO we could check if we are in cluster mode and ++ * if we would redirect to a differnet host ++ */ ++ } else ++ output(subfdout, "%s: undefined\n", LDAP_MAILHOST); ++ ++ /* get the path of the maildir or mbox */ ++ r = qldap_get_mailstore(q, &foo, &bar); ++ switch (r) { ++ case OK: ++ output(subfdout, "homeDirectory: %s\n", foo.s); ++ if (bar.len > 0) ++ output(subfdout, "aliasEmpty: %s\n", bar.s); ++ else ++ output(subfdout, "aliasEmpty: using default\n"); ++ break; ++ case NEEDED: ++ output(subfdout, ++ "forward only delivery via alias user\n"); ++ pw = getpwnam(auto_usera); ++ if (!pw) ++ strerr_die4x(100, FATAL, ++ "Aiiieeeee, now alias user '", ++ auto_usera, "'found in /etc/passwd."); ++ output(subfdout, "alias user: %s\n", pw->pw_name); ++ output(subfdout, "alias user uid: %i\n", pw->pw_uid); ++ output(subfdout, "alias user gid: %i\n", pw->pw_gid); ++ output(subfdout, "alias user home: %s\n", pw->pw_dir); ++ output(subfdout, "alias user aliasempty: %s\n", ++ ALIASDEVNULL); ++ /* get the forwarding addresses */ ++ r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); ++ if (r != OK) ++ fail(q, "qldap_get_attr(" ++ LDAP_FORWARDS ") for forward only user", r); ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ goto next; ++ default: ++ fail(q, "qldap_get_mailstore", r); ++ } ++ ++ r = qldap_get_dotmode(q, &foo); ++ if (r != OK) fail(q, "qldap_get_dotmode", r); ++ output(subfdout, "%s: %s\n", LDAP_DOTMODE, foo.s); ++ ++ r = qldap_get_uid(q, &id); ++ if (r != OK) fail(q, "qldap_get_uid", r); ++ output(subfdout, "%s: %i\n", LDAP_QMAILUID, id); ++ ++ r = qldap_get_gid(q, &id); ++ if (r != OK) fail(q, "qldap_get_gid", r); ++ output(subfdout, "%s: %i\n", LDAP_QMAILGID, id); ++ ++ r = qldap_get_quota(q, &size, &count, &maxsize); ++ if (r != OK) fail(q, "qldap_get_quota", r); ++ output(subfdout, "%s: %u%s\n", LDAP_QUOTA_SIZE, size, ++ size==0?" (unlimited)":""); ++ output(subfdout, "%s: %u%s\n", LDAP_QUOTA_COUNT, count, ++ count==0?" (unlimited)":""); ++ output(subfdout, "%s: %u%s\n", LDAP_MAXMSIZE, maxsize, ++ maxsize==0?" (unlimited)":""); ++ ++ r = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_MODE ")", r); ++ if (r == OK) { ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ if (case_diffs(MODE_FORWARD, s) && ++ case_diffs(MODE_REPLY, s) && ++ case_diffs(MODE_NOLOCAL, s) && ++ case_diffs(MODE_NOMBOX, s) && ++ case_diffs(MODE_NOFORWARD, s) && ++ case_diffs(MODE_NOPROG, s) && ++ case_diffs(MODE_LOCAL, s) && ++ case_diffs(MODE_FORWARD, s) && ++ case_diffs(MODE_PROG, s) && ++ case_diffs(MODE_NOREPLY, s)) ++ strerr_warn4(WARN, ++ "undefined mail delivery mode: ", ++ s," (ignored).", 0); ++ else if (!case_diffs(MODE_FORWARD, s)) ++ strerr_warn4(WARN, ++ "mail delivery mode: ", ++ s," should not be used " ++ "(used internally).", 0); ++ output(subfdout, "%s: %s\n", LDAP_MODE, s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ } ++ ++ r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_FORWARDS ")", r); ++ if (r == OK) { ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ } ++ ++ r = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_PROGRAM ")", r); ++ if (r == OK) { ++ unescape(foo.s, &bar); ++ s = bar.s; ++ slen = bar.len-1; ++ for(;;) { ++ output(subfdout, "%s: %s\n", LDAP_PROGRAM, s); ++ j = byte_chr(s,slen,0); ++ if (j++ >= slen) break; ++ s += j; slen -= j; ++ } ++ } ++ ++ r = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE); ++ if (r != OK && r != NOSUCH) ++ fail(q, "qldap_get_attr(" LDAP_REPLYTEXT ")", r); ++ if (r == OK) ++ output(subfdout, "%s:\n=== begin ===\n%s\n" ++ "=== end ===\n", LDAP_REPLYTEXT, foo.s); ++ else ++ output(subfdout, "%s: undefined\n", LDAP_REPLYTEXT); ++ ++ if (mode == uid && passwd != 0) { ++ if (qldap_need_rebind() == 0) { ++ r = qldap_get_attr(q, LDAP_PASSWD, ++ &foo, SINGLE_VALUE); ++ if (r != OK) fail(q, "qldap_get_attr(" ++ LDAP_PASSWD ")", r); ++ r = cmp_passwd(passwd, foo.s); ++ } else { ++ r = qldap_rebind(qpw, dn.s, passwd); ++ switch (r) { ++ case OK: ++ r = OK; ++ break; ++ case LDAP_BIND_AUTH: ++ r = BADPASS; ++ break; ++ default: ++ break; ++ } ++ } ++ output(subfdout, "\nPASSWORD COMPARE was %s.\n", ++ r == OK?"successful":"NOT successful"); ++ if (r != OK) ++ output(subfdout, "\terror was: %s\n", ++ qldap_err_str(r)); ++ } ++ ++next: ++ r = qldap_next(q); ++ output(subfdout, "\n\n"); ++ } while (r == OK); ++ if (r != NOSUCH) fail(q, "qldap_next", r); ++ qldap_free(q); ++ return 0; ++} ++ ++void ++fail(qldap *q, const char *f, int r) ++{ ++ qldap_free(q); ++ strerr_die4x(111, FATAL, f ,": ", qldap_err_str(r)); ++} ++ ++void ++unescape(char *s, stralloc *t) ++{ ++ if (!stralloc_copys(t, "")) temp_nomem(); ++ do { ++ if (s[0] == '\\' && s[1] == ':') s++; ++ else if (s[0] == ':') { ++ if (!stralloc_0(t)) temp_nomem(); ++ continue; ++ } ++ if (!stralloc_append(t, s)) temp_nomem(); ++ } while (*s++); ++} ++ +diff -upN qmail-1.03/qmail-local.c qmail-ldap/qmail-local.c +--- qmail-1.03/qmail-local.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-local.c Thu Jul 1 16:28:31 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "readwrite.h" + #include "sig.h" + #include "env.h" +@@ -29,6 +30,15 @@ + #include "gfrom.h" + #include "auto_patrn.h" + ++#include "qmail-ldap.h" ++#include "qldap-errno.h" ++#include "auto_qmail.h" ++#include "scan.h" ++#include "maildir++.h" ++#ifdef AUTOMAILDIRMAKE ++#include "mailmaker.h" ++#endif ++ + void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } + + void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } +@@ -38,7 +48,7 @@ void temp_fork() { strerr_die3x(111,"Una + void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } + void temp_slowlock() + { strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); } +-void temp_qmail(fn) char *fn; ++void temp_qmail(fn) const char *fn; + { strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); } + + int flagdoit; +@@ -53,6 +63,9 @@ char *host; + char *sender; + char *aliasempty; + ++/* define the global variables */ ++char *quotastring; ++ + stralloc safeext = {0}; + stralloc ufline = {0}; + stralloc rpline = {0}; +@@ -63,23 +76,24 @@ stralloc ueo = {0}; + stralloc cmds = {0}; + stralloc messline = {0}; + stralloc foo = {0}; ++stralloc qapp = {0}; + + char buf[1024]; + char outbuf[1024]; + + /* child process */ +- + char fntmptph[80 + FMT_ULONG * 2]; +-char fnnewtph[80 + FMT_ULONG * 2]; ++char fnnewtph[83 + FMT_ULONG * 3]; + void tryunlinktmp() { unlink(fntmptph); } + void sigalrm() { tryunlinktmp(); _exit(3); } ++int msfd = -1; /* global filedescriptor to the quota file */ + + void maildir_child(dir) + char *dir; + { + unsigned long pid; +- unsigned long time; +- char host[64]; ++ unsigned long tnow; ++ char hostname[64]; + char *s; + int loop; + struct stat st; +@@ -88,18 +102,22 @@ char *dir; + substdio ssout; + + sig_alarmcatch(sigalrm); +- if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } ++ if (chdir(dir) == -1) { ++ if (error_temp(errno)) _exit(1); else _exit(2); ++ } ++ + pid = getpid(); +- host[0] = 0; +- gethostname(host,sizeof(host)); ++ hostname[0] = 0; ++ gethostname(hostname,sizeof(hostname)); + for (loop = 0;;++loop) + { +- time = now(); ++ tnow = now(); + s = fntmptph; + s += fmt_str(s,"tmp/"); +- s += fmt_ulong(s,time); *s++ = '.'; ++ s += fmt_ulong(s,tnow); *s++ = '.'; + s += fmt_ulong(s,pid); *s++ = '.'; +- s += fmt_strn(s,host,sizeof(host)); *s++ = 0; ++ s += fmt_strn(s,hostname,sizeof(hostname)); ++ *s++ = 0; + if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; + /* really should never get to this point */ + if (loop == 2) _exit(1); +@@ -112,8 +130,8 @@ char *dir; + fd = open_excl(fntmptph); + if (fd == -1) _exit(1); + +- substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); +- substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf)); + if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; + if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; + +@@ -125,8 +143,21 @@ char *dir; + + if (substdio_flush(&ssout) == -1) goto fail; + if (fsync(fd) == -1) goto fail; ++ if (fstat(fd, &st) == -1) goto fail; + if (close(fd) == -1) goto fail; /* NFS dorks */ + ++ s = fnnewtph; ++ while( *s ) s++; ++ s += fmt_str(s,",S="); ++ s += fmt_ulong(s,(unsigned long) st.st_size); ++ *s++ = 0; ++ ++ if( quotastring && *quotastring ) { ++ /* finally update the quota file "maildirsize" */ ++ quota_add(msfd, (unsigned long) st.st_size, 1); ++ close(msfd); ++ } ++ + if (link(fntmptph,fnnewtph) == -1) goto fail; + /* if it was error_exist, almost certainly successful; i hate NFS */ + tryunlinktmp(); _exit(0); +@@ -136,12 +167,115 @@ char *dir; + + /* end child process */ + ++/* quota handling warning and bounce */ ++void quota_bounce(const char *type) ++{ ++ strerr_die3x(100, "The users ", type, ++ " is over the allowed quota (size). (#5.2.2)"); ++} ++ ++void quota_warning(char *fn) ++{ ++ int child; ++ char *(args[3]); ++ int wstat; ++ ++ if (!stralloc_copys(&qapp, auto_qmail)) temp_nomem(); ++ if (!stralloc_cats(&qapp, "/bin/qmail-quotawarn")) temp_nomem(); ++ if (!stralloc_0(&qapp)) temp_nomem(); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ switch(child = fork()) ++ { ++ case -1: ++ temp_fork(); ++ case 0: ++ args[0] = qapp.s; args[1] = fn; args[2] = 0; ++ sig_pipedefault(); ++ execv(*args,args); ++ _exit(2); ++ } ++ ++ wait_pid(&wstat,child); ++ if (wait_crashed(wstat)) ++ temp_childcrashed(); ++ switch(wait_exitcode(wstat)) ++ { ++ case 2: ++ strerr_die5x(111,"Unable to run quotawarn program: ", ++ qapp.s, ": ",error_str(errno),". (#4.2.2)"); ++ case 111: _exit(111); ++ case 0: break; ++ default: _exit(100); ++ } ++ ++} ++/* end -- quota handling warning and bounce */ ++ + void maildir(fn) + char *fn; + { + int child; + int wstat; + ++ /* quota handling maildir */ ++ struct stat mailst; ++ int perc; ++ quota_t q; ++ unsigned long mailsize; ++ ++#ifdef AUTOMAILDIRMAKE ++ switch (maildir_make(fn)) { ++ case OK: ++ break; ++ case MAILDIR_CORRUPT: ++ strerr_die3x(111,"The maildir '", fn, "' seems to be corrupted. (#4.2.1)"); ++ case ERRNO: ++ default: ++ strerr_die3x(111,"Unable to create maildir '", fn, "' (#4.3.0)"); ++ } ++#endif ++ ++ if (quotastring && *quotastring) { ++ if (fstat(0, &mailst) != 0) ++ strerr_die3x(111,"Can not stat mail for quota: ", ++ error_str(errno),". (#4.3.0)"); ++ mailsize = mailst.st_size; ++ quota_get(&q, quotastring); ++ if (quota_calc(fn, &msfd, &q) == -1) { ++ /* second chance */ ++ sleep(3); ++ if (quota_calc(fn, &msfd, &q) == -1) { ++ strerr_die1x(111, ++ "Temporary race condition while calculating quota. (#4.3.0)"); ++ } ++ } ++ /* fd can be -1 when retval = 0 quota_add/rm take care of that */ ++ ++ if (quota_check(&q, mailsize, 1, &perc) != 0) { /* 0 if OK */ ++ if (quota_recalc(fn, &msfd, &q) == -1) { ++ /* second chance */ ++ sleep(3); ++ if (quota_recalc(fn, &msfd, &q) == -1) ++ strerr_die1x(111, ++ "Temporary race condition while recalculating quota. (#4.3.0)"); ++ } ++ if (quota_check(&q, mailsize, 1, &perc) != 0) { ++ /* bounce mail but drop a warning first */ ++ quota_warning(fn); ++ quota_bounce("mailfolder"); ++ } ++ } ++ /* fd can be -1 when retval = 0 quota_add/rm take care of that */ ++ ++ if (perc >= QUOTA_WARNING_LEVEL) ++ /* drop a warning when mailbox is around 80% full */ ++ quota_warning(fn); ++ } ++ ++ /* end -- quota handling maildir */ ++ + if (seek_begin(0) == -1) temp_rewind(); + + switch(child = fork()) +@@ -153,6 +287,8 @@ char *fn; + _exit(111); + } + ++ if (msfd != -1) close(msfd); /* close the maildirsize fd in the parent */ ++ + wait_pid(&wstat,child); + if (wait_crashed(wstat)) + temp_childcrashed(); +@@ -176,6 +312,32 @@ char *fn; + seek_pos pos; + int flaglocked; + ++ /* quota handling mbox */ ++ struct stat filest, mailst; ++ long totalsize; ++ quota_t q; ++ ++ if( quotastring && *quotastring ) { ++ quota_get(&q, quotastring); ++ if (stat(fn, &filest) == -1) { ++ filest.st_size = 0; /* size of nonexisting mailfile */ ++ if ( errno != error_noent) { /* FALSE if file doesn't exist */ ++ strerr_die5x(111,"Unable to quota ", fn, ": ",error_str(errno), ". (#4.3.0)"); ++ } ++ } ++ if (fstat(0, &mailst) != 0) ++ strerr_die3x(111,"Unable to quota mail: ",error_str(errno), ". (#4.3.0)"); ++ ++ totalsize = (long) filest.st_size + (long) mailst.st_size; ++ if ( totalsize*100/q.quota_size >= QUOTA_WARNING_LEVEL) ++ /* drop a warning when mailbox is around 80% full */ ++ quota_warning(fn); ++ if ( totalsize > q.quota_size ) ++ quota_bounce("mailbox"); ++ } ++ ++ /* end -- quota handling mbox */ ++ + if (seek_begin(0) == -1) temp_rewind(); + + fd = open_append(fn); +@@ -191,8 +353,8 @@ char *fn; + seek_end(fd); + pos = seek_cur(fd); + +- substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); +- substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ssout,subwrite,fd,outbuf,sizeof(outbuf)); + if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; + if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; + if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; +@@ -241,7 +403,8 @@ char *prog; + case -1: + temp_fork(); + case 0: +- args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; ++ args[0] = (char *)"/bin/sh"; args[1] = (char *)"-c"; ++ args[2] = prog; args[3] = 0; + sig_pipedefault(); + execv(*args,args); + strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)"); +@@ -266,16 +429,21 @@ void mailforward(recips) + char **recips; + { + struct qmail qqt; +- char *qqx; ++ const char *qqx; + substdio ss; + int match; + + if (seek_begin(0) == -1) temp_rewind(); +- substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); + + if (qmail_open(&qqt) == -1) temp_fork(); + mailforward_qp = qmail_qp(&qqt); ++ + qmail_put(&qqt,dtline.s,dtline.len); ++ ++ if (recips[1]) ++ qmail_puts(&qqt,"Precedence: bulk\n"); ++ + do + { + if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; } +@@ -295,7 +463,7 @@ void bouncexf() + substdio ss; + + if (seek_begin(0) == -1) temp_rewind(); +- substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); ++ substdio_fdbuf(&ss,subread,0,buf,sizeof(buf)); + for (;;) + { + if (getln(&ss,&messline,&match,'\n') != 0) temp_read(); +@@ -316,11 +484,12 @@ void checkhome() + strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)"); + if (st.st_mode & auto_patrn) + strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)"); +- if (st.st_mode & 01000) ++ if (st.st_mode & 01000) { + if (flagdoit) + strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)"); + else + strerr_warn1("Warning: home directory is sticky.",0); ++ } + } + + int qmeox(dashowner) +@@ -437,28 +606,52 @@ void count_print() + void sayit(type,cmd,len) + char *type; + char *cmd; +-int len; ++unsigned int len; + { + substdio_puts(subfdoutsmall,type); + substdio_put(subfdoutsmall,cmd,len); + substdio_putsflush(subfdoutsmall,"\n"); + } + +-void main(argc,argv) ++void unescape(char *s) ++{ ++ if (!stralloc_copys(&foo, "")) temp_nomem(); ++ do { ++ if (s[0] == '\\' && s[1] == ':') s++; ++ else if (s[0] == ':') { ++ if (!stralloc_0(&foo)) temp_nomem(); ++ continue; ++ } ++ if (!stralloc_append(&foo, s)) temp_nomem(); ++ } while (*s++); ++} ++ ++int main(argc,argv) + int argc; + char **argv; + { + int opt; +- int i; +- int j; +- int k; ++ unsigned int i; ++ unsigned int j; ++ unsigned int k; + int fd; +- int numforward; ++ unsigned int numforward; + char **recips; + datetime_sec starttime; + int flagforwardonly; + char *x; + ++ /* set up the variables for qmail-ldap */ ++ unsigned int slen; ++ int qmode; ++ int flagforwardonly2; ++ int flagnoforward; ++ int flagnolocal; ++ int flagnoprog; ++ int allowldapprog; ++ char *s; ++ char *rt; ++ + umask(077); + sig_pipeignore(); + +@@ -531,7 +724,7 @@ char **argv; + if (!stralloc_copys(&ufline,"From ")) temp_nomem(); + if (*sender) + { +- int len; int i; char ch; ++ unsigned int len; char ch; + + len = str_len(sender); + if (!stralloc_readyplus(&ufline,len)) temp_nomem(); +@@ -582,38 +775,168 @@ char **argv; + if (!stralloc_0(&foo)) temp_nomem(); + if (!env_put2("HOST4",foo.s)) temp_nomem(); + +- flagforwardonly = 0; +- qmesearch(&fd,&flagforwardonly); +- if (fd == -1) +- if (*dash) +- strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)"); +- +- if (!stralloc_copys(&ueo,sender)) temp_nomem(); +- if (str_diff(sender,"")) +- if (str_diff(sender,"#@[]")) +- if (qmeox("-owner") == 0) +- { +- if (qmeox("-owner-default") == 0) +- { +- if (!stralloc_copys(&ueo,local)) temp_nomem(); +- if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem(); +- if (!stralloc_cats(&ueo,host)) temp_nomem(); +- if (!stralloc_cats(&ueo,"-@[]")) temp_nomem(); +- } +- else +- { +- if (!stralloc_copys(&ueo,local)) temp_nomem(); +- if (!stralloc_cats(&ueo,"-owner@")) temp_nomem(); +- if (!stralloc_cats(&ueo,host)) temp_nomem(); +- } +- } +- if (!stralloc_0(&ueo)) temp_nomem(); +- if (!env_put2("NEWSENDER",ueo.s)) temp_nomem(); ++ flagforwardonly = 0; flagforwardonly2 = 0; allowldapprog = 0; ++ flagnoforward = 0; flagnolocal = 0; flagnoprog = 0; + ++ if (env_get(ENV_GROUP)) { ++ if (flagdoit) { ++ ++count_program; ++ if (!stralloc_copys(&foo,"qmail-group ")) temp_nomem(); ++ if (*aliasempty == '.' || *aliasempty == '/') ++ if (!stralloc_cats(&foo,aliasempty)) temp_nomem(); ++ if (!stralloc_0(&foo)) temp_nomem(); ++ mailprogram(foo.s); ++ } else ++ sayit("group delivery","",0); ++ count_print(); ++ _exit(0); ++ } ++ /* quota, dotmode and forwarding handling - part 1 */ ++ /* setting the quota */ ++ if ((quotastring = env_get(ENV_QUOTA) ) && *quotastring) { ++ if (!flagdoit) sayit("quota defined as: ",quotastring,str_len(quotastring)); ++ } else { ++ if (!flagdoit) sayit("unlimited quota",quotastring,0 ); ++ } ++ ++ qmode = DO_DOT; /* default is to use standard .qmail */ ++ if ((s = env_get(ENV_DOTMODE))) { ++ if (!case_diffs(DOTMODE_LDAPONLY, s)) { ++ if (!flagdoit) sayit("DOTMODE_LDAPONLY ",s,0); ++ qmode = DO_LDAP; ++ } else if (!case_diffs(DOTMODE_LDAPWITHPROG, s)) { ++ if (!flagdoit) sayit("DOTMODE_LDAPWITHPROG ",s,0); ++ qmode = DO_LDAP; ++ allowldapprog = 1; ++ } else if (!case_diffs(DOTMODE_DOTONLY, s)) { ++ if (!flagdoit) sayit("DOTMODE_DOTONLY ",s,0); ++ qmode = DO_DOT; ++ } else if (!case_diffs(DOTMODE_BOTH, s)) { ++ if (!flagdoit) sayit("DOTMODE_BOTH ",s,0); ++ qmode = DO_BOTH; ++ allowldapprog = 1; ++ } else ++ strerr_die3x(100,"Error: Non valid dot-mode found: ", s, ". (#5.3.5)"); ++ } ++ ++ /* prepare the cmds string to hold all the commands from the ++ * ldap server and the .qmail file */ + if (!stralloc_ready(&cmds,0)) temp_nomem(); + cmds.len = 0; +- if (fd != -1) +- if (slurpclose(fd,&cmds,256) == -1) temp_nomem(); ++ ++ if (qmode & DO_LDAP) { ++ /* get the infos from the ldap server (environment) */ ++ /* setting the NEWSENDER so echo and forward will work */ ++ if (!stralloc_copys(&ueo,sender)) temp_nomem(); ++ if (!stralloc_0(&ueo)) temp_nomem(); ++ if (!env_put2("NEWSENDER",ueo.s)) temp_nomem(); ++ ++ if ((s = env_get(ENV_MODE))) { ++ unescape(s); ++ s = foo.s; ++ slen = foo.len-1; ++ for(;;) { ++ if (!case_diffs(MODE_FONLY, s)) { ++ if (!flagdoit) sayit("force forward only ",s,0); ++ flagforwardonly2 = 1; ++ flagnolocal = 1; ++ flagnoprog = 1; ++ } else if (!case_diffs(MODE_REPLY, s)) { ++ if(*sender) { ++ if ((rt = env_get(ENV_REPLYTEXT))) { ++ ++count_forward; ++ if (flagdoit) { ++ if (!stralloc_copys(&qapp,"qmail-reply ")) temp_nomem(); ++ if (*aliasempty == '.' || *aliasempty == '/') ++ if (!stralloc_cats(&qapp,aliasempty)) temp_nomem(); ++ if (!stralloc_0(&qapp)) temp_nomem(); ++ mailprogram(qapp.s); ++ } else { ++ sayit("reply to ",sender,str_len(sender)); ++ sayit("replytext ",rt,str_len(rt)); ++ } ++ } else { ++ strerr_warn1("Warning: Reply mode is on but there is no reply text.", 0); ++ } ++ } ++ } else if (!case_diffs(MODE_NOLOCAL, s) || !case_diffs(MODE_NOMBOX, s)) { ++ if (!flagdoit) sayit("no file delivery ",s,0); ++ flagnolocal = 1; ++ } else if (!case_diffs(MODE_NOFORWARD, s)) { ++ if (!flagdoit) sayit("no mail forwarding ",s,0); ++ flagnoforward = 1; ++ } else if (!case_diffs(MODE_NOPROG, s)) { ++ if (!flagdoit) sayit("no program delivery ",s,0); ++ flagnoprog = 1; ++ } else if (!case_diffs(MODE_LOCAL, s) || ++ !case_diffs(MODE_FORWARD, s) || ++ !case_diffs(MODE_PROG, s) || ++ !case_diffs(MODE_NOREPLY, s)) { ++ /* ignore */; ++ } else strerr_warn3("Warning: undefined mail delivery mode: ", ++ s," (ignored).", 0); ++ j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j; ++ } ++ } ++ if (allowldapprog && !flagnoprog && (s = env_get(ENV_PROGRAM))) { ++ unescape(s); ++ s = foo.s; ++ slen = foo.len-1; ++ for (;;) { ++ if (!stralloc_cats(&cmds, "|")) temp_nomem(); ++ if (!stralloc_cats(&cmds, s)) temp_nomem(); ++ if (!stralloc_cats(&cmds, "\n")) temp_nomem(); ++ j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j; ++ } ++ } ++ if (!flagnoforward && (s = env_get(ENV_FORWARDS))) { ++ unescape(s); ++ s = foo.s; ++ slen = foo.len-1; ++ for (;;) { ++ if (!stralloc_cats(&cmds, "&")) temp_nomem(); ++ if (!stralloc_cats(&cmds, s)) temp_nomem(); ++ if (!stralloc_cats(&cmds, "\n")) temp_nomem(); ++ j = byte_chr(s,slen,0); if (j++ == slen) break; s += j; slen -= j; ++ } ++ } ++ if (!flagnolocal) { ++ if (!stralloc_cats(&cmds,aliasempty)) temp_nomem(); ++ if (!stralloc_cats(&cmds, "\n")) temp_nomem(); ++ } ++ if (!stralloc_cats(&cmds, "#\n")) temp_nomem(); ++ } ++ if (qmode & DO_DOT) { /* start dotqmail */ ++ qmesearch(&fd,&flagforwardonly); ++ if (fd == -1) ++ if (*dash) ++ if (qmode == DO_DOT) /* XXX: OK ??? */ ++ strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)"); ++ ++ if (!stralloc_copys(&ueo,sender)) temp_nomem(); ++ if (str_diff(sender,"")) ++ if (str_diff(sender,"#@[]")) ++ if (qmeox("-owner") == 0) { ++ if (qmeox("-owner-default") == 0) { ++ if (!stralloc_copys(&ueo,local)) temp_nomem(); ++ if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem(); ++ if (!stralloc_cats(&ueo,host)) temp_nomem(); ++ if (!stralloc_cats(&ueo,"-@[]")) temp_nomem(); ++ } else { ++ if (!stralloc_copys(&ueo,local)) temp_nomem(); ++ if (!stralloc_cats(&ueo,"-owner@")) temp_nomem(); ++ if (!stralloc_cats(&ueo,host)) temp_nomem(); ++ } ++ } ++ ++ if (!stralloc_0(&ueo)) temp_nomem(); ++ if (!env_put2("NEWSENDER",ueo.s)) temp_nomem(); ++ ++ if (fd != -1) ++ if (slurpclose(fd,&cmds,256) == -1) temp_nomem(); ++ ++ } else if (!qmode & DO_LDAP) /* impossible see dotmode handling */ ++ strerr_die1x(100,"Error: No valid delivery mode selected. (#5.3.5)"); + + if (!cmds.len) + { +@@ -633,6 +956,8 @@ char **argv; + i = j + 1; + } + ++ if (flagnoforward) numforward = 0; ++ + recips = (char **) alloc((numforward + 1) * sizeof(char *)); + if (!recips) temp_nomem(); + numforward = 0; +@@ -645,7 +970,7 @@ char **argv; + { + cmds.s[j] = 0; + k = j; +- while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')) ++ while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))) + cmds.s[--k] = 0; + switch(cmds.s[i]) + { +@@ -656,8 +981,14 @@ char **argv; + break; + case '.': + case '/': ++ if (flagnolocal) { ++ if (flagdoit) break; ++ else { sayit("disabled file delivery ", cmds.s + i, k - i); break; } ++ } + ++count_file; + if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)"); ++ if (flagforwardonly2) ++ strerr_die1x(111,"Uh-oh: user has file delivery but is not allowed to. (#4.7.0)"); + if (cmds.s[k - 1] == '/') + if (flagdoit) maildir(cmds.s + i); + else sayit("maildir ",cmds.s + i,k - i); +@@ -666,8 +997,14 @@ char **argv; + else sayit("mbox ",cmds.s + i,k - i); + break; + case '|': ++ if (flagnoprog) { ++ if (flagdoit) break; ++ else { sayit("disabled program ", cmds.s + i, k - i); break; } ++ } + ++count_program; + if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)"); ++ if (flagforwardonly2) ++ strerr_die1x(111,"Uh-oh: user has prog delivery but is not allowed to. (#4.7.0)"); + if (flagdoit) mailprogram(cmds.s + i + 1); + else sayit("program ",cmds.s + i + 1,k - i - 1); + break; +@@ -679,6 +1016,10 @@ char **argv; + ++i; + default: + ++count_forward; ++ if (flagnoforward) { ++ if (flagdoit) break; ++ else { sayit("disabled forward ", cmds.s + i, k - i); break; } ++ } + if (flagdoit) recips[numforward++] = cmds.s + i; + else sayit("forward ",cmds.s + i,k - i); + break; +@@ -687,12 +1028,12 @@ char **argv; + if (flag99) break; + } + +- if (numforward) if (flagdoit) ++ if (numforward) if (flagdoit) if (!flagnoforward) + { + recips[numforward] = 0; + mailforward(recips); + } + + count_print(); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-lspawn.c qmail-ldap/qmail-lspawn.c +--- qmail-1.03/qmail-lspawn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-lspawn.c Wed May 5 17:42:12 2004 +@@ -14,76 +14,615 @@ + #include "auto_uids.h" + #include "qlx.h" + +-char *aliasempty; ++#include ++#include ++#include ++#include ++#include "auto_break.h" ++#include "auto_usera.h" ++#include "byte.h" ++#include "check.h" ++#include "env.h" ++#include "fmt.h" ++#include "localdelivery.h" ++#include "open.h" ++#include "qldap.h" ++#include "qldap-debug.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "read-ctrl.h" ++#include "sig.h" ++#include "str.h" ++#ifdef QLDAP_CLUSTER ++#include "qldap-cluster.h" ++#include "getln.h" ++#include "seek.h" ++#endif ++#ifdef AUTOHOMEDIRMAKE ++#include "dirmaker.h" ++#endif ++ ++const char *aliasempty; ++ ++#ifdef QLDAP_CLUSTER ++/* declaration of the mail forwarder function */ ++void forward_mail(char *, char *, char *, int , int); ++#endif + ++#ifdef AUTOHOMEDIRMAKE ++void check_home(const char *home, const char *maildir) ++{ ++ struct stat st; ++ ++ if (stat(home, &st) == 0) return; ++ if (errno == error_noent) ++ switch (dirmaker_make(home, maildir)) { ++ case 0: ++ break; ++ case ERRNO: ++ if (error_temp(errno)) _exit(QLX_DIRMAKESOFT); ++ _exit(QLX_DIRMAKEHARD); ++ case MAILDIR_CRASHED: ++ _exit(QLX_DIRMAKECRASH); ++ case MAILDIR_HARD: ++ _exit(QLX_DIRMAKEHARD); ++ case MAILDIR_UNCONF: ++ /* qmail-local will return a nice error */ ++ break; ++ default: ++ _exit(QLX_DIRMAKESOFT); ++ } ++} ++#endif ++ ++ctrlfunc ctrls[] = { ++ qldap_ctrl_login, ++ qldap_ctrl_generic, ++ localdelivery_init, ++#ifdef QLDAP_CLUSTER ++ cluster_init, ++#endif ++#ifdef AUTOHOMEDIRMAKE ++ dirmaker_init, ++#endif ++ 0 ++}; ++ ++/* here it is not possible to log something */ + void initialize(argc,argv) + int argc; + char **argv; + { +- aliasempty = argv[1]; +- if (!aliasempty) _exit(100); ++ aliasempty = argv[1]; ++ if (!aliasempty) { ++ _exit(100); ++ } ++ ++ if (read_controls(ctrls) == -1) ++ _exit(QLX_USAGE); ++ + } + +-int truncreport = 3000; ++unsigned int truncreport = 3000; + + void report(ss,wstat,s,len) + substdio *ss; + int wstat; + char *s; +-int len; ++unsigned int len; + { +- int i; +- if (wait_crashed(wstat)) +- { substdio_puts(ss,"Zqmail-local crashed.\n"); return; } +- switch(wait_exitcode(wstat)) +- { ++ unsigned int i; ++ if (wait_crashed(wstat)) { ++ substdio_puts(ss,"Zqmail-local crashed.\n"); ++ return; ++ } ++ switch(wait_exitcode(wstat)) { + case QLX_CDB: +- substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n"); return; ++ substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n"); ++ return; + case QLX_NOMEM: +- substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n"); return; ++ substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n"); ++ return; + case QLX_SYS: +- substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n"); return; ++ substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n"); ++ return; + case QLX_NOALIAS: +- substdio_puts(ss,"ZUnable to find alias user!\n"); return; ++ substdio_puts(ss,"ZUnable to find alias user!\n"); ++ return; + case QLX_ROOT: +- substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n"); return; ++ substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n"); ++ return; + case QLX_USAGE: +- substdio_puts(ss,"ZInternal qmail-lspawn bug.\n"); return; ++ substdio_puts(ss,"ZInternal qmail-lspawn bug.\n"); ++ return; + case QLX_NFS: +- substdio_puts(ss,"ZNFS failure in qmail-local.\n"); return; ++ substdio_puts(ss,"ZNFS failure in qmail-local.\n"); ++ return; + case QLX_EXECHARD: +- substdio_puts(ss,"DUnable to run qmail-local.\n"); return; ++ substdio_puts(ss,"DUnable to run qmail-local.\n"); ++ return; + case QLX_EXECSOFT: +- substdio_puts(ss,"ZUnable to run qmail-local.\n"); return; ++ substdio_puts(ss,"ZUnable to run qmail-local.\n"); ++ return; + case QLX_EXECPW: +- substdio_puts(ss,"ZUnable to run qmail-getpw.\n"); return; ++ substdio_puts(ss,"ZUnable to run qmail-getpw.\n"); ++ return; + case 111: case 71: case 74: case 75: +- substdio_put(ss,"Z",1); break; ++ substdio_put(ss,"Z",1); ++ break; + case 0: +- substdio_put(ss,"K",1); break; ++ substdio_put(ss,"K",1); ++ break; ++ ++ /* report LDAP errors */ ++ case QLX_DISABLED: ++ substdio_puts(ss, "DMailaddress is administratively disabled. (#5.2.1)\n"); ++ return; ++ case QLX_DELETED: ++ substdio_puts(ss, "DSorry, no mailbox here by that name. (#5.1.1)\n"); ++ return; ++ case QLX_MAXSIZE: ++ substdio_puts(ss, "DThe message exeeded the maximum size the user accepts. (#5.2.3)\n"); ++ return; ++ case QLX_LDAPFAIL: ++ substdio_puts(ss, "ZTemporary failure in LDAP lookup. (#4.4.3).\n"); ++ return; ++ case QLX_LDAPAUTH: ++ substdio_puts(ss, "ZUnable to login into LDAP server, bad credentials. (#4.4.3)\n"); ++ return; ++ case QLX_SEARCHTIMEOUT: ++ substdio_puts(ss, "ZTimeout while performing search on LDAP server. (#4.4.3)"); ++ return; ++ case QLX_BINDTIMEOUT: ++ substdio_puts(ss, "ZUnable to contact LDAP server. (#4.4.3)"); ++ return; ++ case QLX_TOOMANY: ++ substdio_puts(ss, "DToo many results returned but needs to be unique. (#5.3.5)\n"); ++ return; ++ case QLX_NEEDED: ++ substdio_puts(ss, "DLDAP attribute is not given but mandatory. (#5.3.5)\n"); ++ return; ++ case QLX_ILLVAL: ++ substdio_puts(ss, "DIllegal value in LDAP attribute. (#5.3.5)\n"); ++ return; ++#ifdef QLDAP_CLUSTER ++ case QLX_CLUSTERSOFT: ++ substdio_puts(ss, "ZTemporary error while executing qmail-forward. (#4.4.4)\n"); ++ return; ++ case QLX_CLUSTERHARD: ++ substdio_puts(ss, "DPermanent error while executing qmail-forward. (#5.4.4)\n"); ++ return; ++#endif /* QLDAP_CLUSTER */ ++#ifdef AUTOHOMEDIRMAKE ++ case QLX_DIRMAKECRASH: ++ substdio_puts(ss, "ZAutomatic homedir creator crashed (#4.3.0)\n"); ++ return; ++ case QLX_DIRMAKESOFT: ++ substdio_puts(ss, "ZTemporary error in automatic homedir creation. (#4.3.0)\n"); ++ return; ++ case QLX_DIRMAKEHARD: ++ substdio_puts(ss, "DPermanent error in automatic homedir creation. (#5.3.0)\n"); ++ return; ++#endif ++ + case 100: + default: +- substdio_put(ss,"D",1); break; ++ substdio_put(ss,"D",1); ++ break; + } + +- for (i = 0;i < len;++i) if (!s[i]) break; +- substdio_put(ss,s,i); ++ for (i = 0;i < len;++i) if (!s[i]) break; ++ substdio_put(ss,s,i); + } + +-stralloc lower = {0}; + stralloc nughde = {0}; ++stralloc host = {0}; ++stralloc user = {0}; ++stralloc homedir = {0}; ++stralloc maildir = {0}; ++stralloc foo = {0}; /* stralloc for temporary stuff */ ++ ++/* LDAP server query routines */ ++ ++void cae(qldap *q, int n) ++{ ++ qldap_free(q); ++ _exit(n); ++} ++ ++int qldap_get(stralloc *mail, unsigned int at, int fdmess) ++{ ++ const char *attrs[] = { /* LDAP_MAIL, */ /* not needed */ ++ /* LDAP_MAILALTERNATE, */ ++ LDAP_UID, ++ LDAP_QMAILUID, ++ LDAP_QMAILGID, ++ LDAP_ISACTIVE, ++ LDAP_MAILHOST, ++ LDAP_MAILSTORE, ++ LDAP_HOMEDIR, ++ LDAP_QUOTA_SIZE, ++ LDAP_QUOTA_COUNT, ++ LDAP_FORWARDS, ++ LDAP_PROGRAM, ++ LDAP_MODE, ++ LDAP_REPLYTEXT, ++ LDAP_DOTMODE, ++ LDAP_MAXMSIZE, ++ LDAP_OBJECTCLASS, 0}; ++ char num[FMT_ULONG]; ++ char *f; ++ struct passwd *pw; ++ struct qldap *q; ++ struct stat st; ++ unsigned long count; ++ unsigned long maxsize; ++ unsigned long size; ++ unsigned int len; ++ int done; ++ int id; ++ int status; ++ int rv; ++ ++ /* TODO more debug output is needed */ ++ q = qldap_new(); ++ if (q == 0) ++ _exit(QLX_NOMEM); ++ ++ rv = qldap_open(q); ++ if (rv != OK) goto fail; ++ rv = qldap_bind(q, 0, 0); ++ if (rv != OK) goto fail; ++ ++ /* ++ * this handles the "catch all" and "-default" extension ++ * but also the normal eMail address. ++ * Code handels also mail addresses with multiple '@' safely. ++ * at = index to last @ sign in mail address ++ * escaped = ldap escaped mailaddress ++ * len = length of escaped mailaddress ++ * i = position of current '-' or '@' ++ */ ++ done = 0; ++ do { ++ f = filter_mail(mail->s, &done); ++ if (f == (char *)0) cae(q, QLX_NOMEM); ++ ++ logit(16, "ldapfilter: '%s'\n", f); ++ ++ /* do the search for the email address */ ++ rv = qldap_lookup(q, f, attrs); ++ switch (rv) { ++ case OK: ++ break; /* something found */ ++ case TIMEOUT: ++ /* don't try an other address, retry later, hopefully ... */ ++ cae(q, QLX_SEARCHTIMEOUT); ++ case TOOMANY: ++#ifdef DUPEALIAS ++ /* ++ * we are going to deliver this to a special alias user for ++ * further processing ++ */ ++ qldap_free(q); ++ return 3; ++#else ++ /* admin error, don't try a lower precedence addresses */ ++ cae(q, QLX_TOOMANY); ++#endif ++ case FAILED: ++ /* ... again do not retry lower precedence addresses */ ++ cae(q, QLX_LDAPFAIL); ++ case NOSUCH: ++ break; ++ } ++ } while (rv != OK && !done); ++ ++ /* nothing found, try a local lookup or a alias delivery */ ++ if (rv == NOSUCH) { ++ qldap_free(q); ++ return 1; ++ } ++ ++ ++ /* ++ * Search was successful. ++ * Now go through the attributes and set the proper args for qmail-local. ++ * But first check account status, the mail size and forward the message ++ * to the correct cluster host if needed. ++ * ++ */ ++ ++ ++ /* check if the ldap entry is active */ ++ rv = qldap_get_status(q, &status); ++ if (rv != OK) goto fail; ++ if (status == STATUS_BOUNCE) { ++ logit(2, "warning: %s's account status is bounce\n", mail->s); ++ cae(q, QLX_DISABLED); ++ } else if (status == STATUS_DELETE) { ++ logit(2, "warning: %s's account status is deleted\n", mail->s); ++ cae(q, QLX_DELETED); ++ } ++ ++ /* get the quota for the user of that maildir mbox */ ++ rv = qldap_get_quota(q, &size, &count, &maxsize); ++ if (rv != OK) goto fail; ++ /* check if incomming mail is smaller than max mail size */ ++ if (maxsize != 0) { ++ if (fstat(fdmess, &st) != 0) { ++ logit(2, "warning: can not stat mail: %s\n", error_str(errno)); ++ cae(q, QLX_SYS); ++ } ++ if ((unsigned long)st.st_size > maxsize) { ++ cae(q, QLX_MAXSIZE); ++ } ++ } ++ ++#ifdef QLDAP_CLUSTER ++ rv = qldap_get_attr(q, LDAP_MAILHOST, &host, SINGLE_VALUE); ++ if (rv != OK && rv != NOSUCH) goto fail; ++ ++ /* check if the I'm the right host */ ++ if (rv == OK && cluster(host.s) == 1) { ++ logit(8, "cluster: forwarding session to %s\n", host.s); ++ /* hostname is different, so I reconnect */ ++ return 2; ++ } ++#endif ++ ++ /* get the path of the maildir or mbox */ ++ rv = qldap_get_mailstore(q, &homedir, &maildir); ++ switch (rv) { ++ case OK: ++ if (maildir.len > 0) ++ aliasempty = maildir.s; ++ break; ++ case NEEDED: ++ /* ++ * nothing defined use alias user for delivery and ++ * ALIASDEVNULL as aliasempty ++ */ ++ logit(32, "forward only delivery via alias user\n"); ++ pw = getpwnam(auto_usera); ++ if (!pw) cae(q, QLX_NOALIAS); ++ if (!stralloc_copys(&nughde, pw->pw_name)) cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid))) ++ cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid))) ++ cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (!stralloc_cats(&nughde, pw->pw_dir)) cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (!stralloc_cats(&nughde, "-")) cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (!stralloc_catb(&nughde, mail->s, at)) cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ aliasempty = ALIASDEVNULL; ++ /* get the forwarding addresses */ ++ rv = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); ++ if (rv != OK) goto fail; ++ if (!env_put2(ENV_FORWARDS, foo.s)) cae(q, QLX_NOMEM); ++ logit(32, "%s: %s\n", ENV_FORWARDS, foo.s); ++ /* setup strict env */ ++ if (!env_put2(ENV_DOTMODE, DOTMODE_LDAPONLY)) _exit(QLX_NOMEM); ++ if (!env_put2(ENV_MODE, MODE_FONLY)) _exit(QLX_NOMEM); ++ qldap_free(q); ++ return 0; ++ default: ++ goto fail; ++ } ++ ++ /* get the user name */ ++ rv = qldap_get_user(q, &user); ++ if (rv != OK) goto fail; ++ if (!stralloc_copy(&nughde, &user)) _exit(QLX_NOMEM); ++ ++ /* get the UID for delivery on the local system */ ++ rv = qldap_get_uid(q, &id); ++ if (rv != OK) goto fail; ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, id))) ++ cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ ++ ++ /* get the GID for delivery on the local system */ ++ rv = qldap_get_gid(q, &id); ++ if (rv != OK) goto fail; ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, id))) ++ cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ ++ /* homedir saved earlier */ ++ if (!stralloc_cat(&nughde, &homedir)) cae(q, QLX_NOMEM); ++ ++ /* ++ * Fill up the dash-field and the extension field with the values ++ * used for the dash-ext search. ++ */ ++ rv = filter_mail_ext(); ++ if (rv != -1) ++ if (!stralloc_cats(&nughde,"-")) cae(q, QLX_NOMEM); ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ if (rv != -1) { ++ unsigned int ext; ++ int i; ++ for (ext = 0, i = 0; i < rv && ext < at; ext++) ++ if (mail->s[ext] == *auto_break) i++; ++ if (!stralloc_catb(&nughde, mail->s+ext,at-ext)) cae(q, QLX_NOMEM); ++ } ++ if (!stralloc_0(&nughde)) cae(q, QLX_NOMEM); ++ ++ /* ++ * nughde is filled now setup the environment, with: ++ * quota string (already done while checking mail size) ++ * mail group handling ++ * mail forwarders ++ * delivery programs ++ * reply text ++ * delivery mode ++ * dot mode ++ */ ++ ++ rv = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE); ++ if (rv != OK) goto fail; /* objectclass is a must */ ++ if (!env_unset(ENV_GROUP)) cae(q, QLX_NOMEM); ++ for (len = 0; len < foo.len; ++ len += byte_chr(foo.s + len, foo.len - len, ':') + 1) { ++ if (case_startb(foo.s + len, foo.len - len, LDAP_GROUPOBJECTCLASS)) { ++ rv = qldap_get_dn(q, &foo); ++ if (rv != OK) goto fail; ++ logit(32, "%s: %s\n", ENV_GROUP, foo.s); ++ if (!env_put2(ENV_GROUP, foo.s )) cae(q, QLX_NOMEM); ++ break; ++ } ++ } ++ ++ /* ++ * set the quota environment ++ */ ++ if (size != 0 || count != 0) { ++ if (!stralloc_copys(&foo, "")) cae(q, QLX_NOMEM); ++ if (size != 0) { ++ if (!stralloc_catb(&foo, num, fmt_ulong(num, size))) cae(q, QLX_NOMEM); ++ if (!stralloc_append(&foo, "S")) cae(q, QLX_NOMEM); ++ } ++ if (count != 0) { ++ if (size != 0) ++ if (!stralloc_append(&foo, ",")) cae(q, QLX_NOMEM); ++ if (!stralloc_catb(&foo, num, fmt_ulong(num, count))) cae(q, QLX_NOMEM); ++ if (!stralloc_append(&foo, "C")) cae(q, QLX_NOMEM); ++ } ++ if (!stralloc_0(&foo)) cae(q, QLX_NOMEM); ++ logit(32, "%s: %s\n", ENV_QUOTA, foo.s); ++ if (!env_put2(ENV_QUOTA, foo.s )) cae(q, QLX_NOMEM); ++ } else { ++ logit(32, "no quota set\n"); ++ if (!env_unset(ENV_QUOTA)) cae(q, QLX_NOMEM); ++ } ++ ++ /* ++ * get the forwarding addresses and build a list ++ * equals to &jdoe@heaven.af.mil in .qmail ++ */ ++ rv = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); ++ switch (rv) { ++ case OK: ++ logit(32, "%s: %s\n", ENV_FORWARDS, foo.s); ++ if (!env_put2(ENV_FORWARDS, foo.s)) cae(q, QLX_NOMEM); ++ break; ++ case NOSUCH: ++ if (!env_unset(ENV_FORWARDS)) cae(q, QLX_NOMEM); ++ break; ++ default: ++ goto fail; ++ } ++ ++ /* ++ * get the path of the local delivery program ++ * equals to |/usr/bin/program in .qmail ++ */ ++ rv = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE); ++ switch (rv) { ++ case OK: ++ logit(32, "%s: %s\n", ENV_PROGRAM, foo.s); ++ if (check_progs(foo.s) == 0) cae(q, QLX_ILLVAL); ++ if (!env_put2(ENV_PROGRAM, foo.s)) cae(q, QLX_NOMEM); ++ break; ++ case NOSUCH: ++ if (!env_unset(ENV_PROGRAM)) cae(q, QLX_NOMEM); ++ break; ++ default: ++ goto fail; ++ } ++ ++ /* ++ * prefetch the reply text so we can remove it if no deliverymode ++ * is set. ++ */ ++ rv = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE); ++ switch (rv) { ++ case OK: ++ logit(32, "%s: %s\n", ENV_REPLYTEXT, foo.s); ++ if (!env_put2(ENV_REPLYTEXT, foo.s)) cae(q, QLX_NOMEM); ++ break; ++ case NOSUCH: ++ if (!env_unset(ENV_REPLYTEXT)) cae(q, QLX_NOMEM); ++ break; ++ default: ++ goto fail; ++ } ++ ++ /* ++ * get the deliverymode of the mailbox: ++ * reply, noprogram, noforward, nolocal (nombox) ++ */ ++ rv = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE); ++ switch (rv) { ++ case OK: ++ case_lowers(foo.s); ++ logit(32, "%s: %s\n", ENV_MODE, foo.s); ++ if (!env_put2(ENV_MODE, foo.s)) cae(q, QLX_NOMEM); ++ break; ++ case NOSUCH: ++ if (!env_unset(ENV_MODE)) cae(q, QLX_NOMEM); ++ if (!env_unset(ENV_REPLYTEXT)) cae(q, QLX_NOMEM); ++ break; ++ default: ++ goto fail; ++ } ++ ++ /* get the mode of the .qmail interpretion: ldaponly, dotonly, both, none */ ++ rv = qldap_get_dotmode(q, &foo); ++ if (rv != OK) goto fail; ++ logit(32, "%s: %s\n", ENV_DOTMODE, foo.s); ++ if (!env_put2(ENV_DOTMODE, foo.s)) cae(q, QLX_NOMEM); ++ ++ /* ok, we finished, lets clean up and disconnect from the LDAP server */ ++ qldap_free(q); ++ return 0; ++ ++fail: ++ switch (rv) { ++ case LDAP_BIND_UNREACH: ++ cae(q, QLX_BINDTIMEOUT); ++ case LDAP_BIND_AUTH: ++ cae(q, QLX_LDAPAUTH); ++ case NOSUCH: ++ case NEEDED: ++ cae(q, QLX_NEEDED); ++ case BADVAL: ++ case ILLVAL: ++ cae(q, QLX_ILLVAL); ++ case ERRNO: ++ /* in most cases this error was a due to missing resources */ ++ cae(q, QLX_NOMEM); ++ case TOOMANY: ++ cae(q, QLX_TOOMANY); ++ default: ++ cae(q, QLX_LDAPFAIL); ++ } ++ /* NOTREACHED */ ++ return -1; ++} ++/* end -- LDAP server query routines */ ++ ++stralloc lower = {0}; + stralloc wildchars = {0}; ++struct cdb cdb; + + void nughde_get(local) + char *local; + { + char *(args[3]); +- int pi[2]; +- int gpwpid; +- int gpwstat; +- int r; +- int fd; +- int flagwild; ++ int pi[2], ++ gpwpid, ++ gpwstat, ++ r, ++ fd, ++ flagwild; + + if (!stralloc_copys(&lower,"!")) _exit(QLX_NOMEM); + if (!stralloc_cats(&lower,local)) _exit(QLX_NOMEM); +@@ -102,11 +641,12 @@ char *local; + uint32 dlen; + unsigned int i; + +- r = cdb_seek(fd,"",0,&dlen); ++ cdb_init(&cdb, fd); ++ r = cdb_seek(&cdb,"",0,&dlen); + if (r != 1) _exit(QLX_CDB); + if (!stralloc_ready(&wildchars,(unsigned int) dlen)) _exit(QLX_NOMEM); + wildchars.len = dlen; +- if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB); ++ if (cdb_bread(&cdb,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB); + + i = lower.len; + flagwild = 0; +@@ -116,16 +656,17 @@ char *local; + /* 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); ++ r = cdb_seek(&cdb,lower.s,i,&dlen); + if (r == -1) _exit(QLX_CDB); + if (r == 1) + { + if (!stralloc_ready(&nughde,(unsigned int) dlen)) _exit(QLX_NOMEM); + nughde.len = dlen; +- if (cdb_bread(fd,nughde.s,nughde.len) == -1) _exit(QLX_CDB); ++ if (cdb_bread(&cdb,nughde.s,nughde.len) == -1) _exit(QLX_CDB); + if (flagwild) + if (!stralloc_cats(&nughde,local + i - 1)) _exit(QLX_NOMEM); + if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ cdb_free(&cdb); + close(fd); + return; + } +@@ -139,7 +680,7 @@ char *local; + } + + if (pipe(pi) == -1) _exit(QLX_SYS); +- args[0] = "bin/qmail-getpw"; ++ args[0] = (char *)"bin/qmail-getpw"; + args[1] = local; + args[2] = 0; + switch(gpwpid = vfork()) +@@ -165,34 +706,124 @@ char *local; + } + } + ++stralloc ra = {0}; ++ + int spawn(fdmess,fdout,s,r,at) + int fdmess; int fdout; +-char *s; char *r; int at; ++char *s; char *r; unsigned int at; + { + int f; + + if (!(f = fork())) + { + char *(args[11]); ++ char *x; + unsigned long u; +- int n; ++ unsigned int xlen; ++ unsigned int n; + int uid; + int gid; +- char *x; +- unsigned int xlen; ++ int rv; + ++ log_init(fdout, -1, 1); ++ ++ sig_hangupdefault(); /* clear the hup sig handler for the child */ ++ ++ /* copy the whole email address before the @ gets destroyed */ ++ if (!stralloc_copys(&ra,r)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&ra)) _exit(QLX_NOMEM); ++ logit(16, "mailaddr: %S\n", &ra); ++ + r[at] = 0; + if (!r[0]) _exit(0); /* <> */ + + if (chdir(auto_qmail) == -1) _exit(QLX_USAGE); + +- nughde_get(r); ++ /* do the address lookup */ ++ rv = qldap_get(&ra, at, fdmess); ++ switch (rv) { ++ case 0: ++ logit(16, "LDAP lookup succeeded\n"); ++ break; ++ case 1: ++ if (!stralloc_copys(&nughde,"")) _exit(QLX_NOMEM); ++ if (localdelivery()) { ++ /* ++ * Do the local address lookup. ++ * This is the standart qmail lookup funktion. ++ */ ++ logit(4, "LDAP lookup failed, using local db\n"); ++ nughde_get(r); ++ } else { ++ /* the alias-user handling for LDAP only mode */ ++ struct passwd *pw; ++ char num[FMT_ULONG]; ++ ++ logit(4, "LDAP lookup failed, using alias (no local db)\n"); ++ pw = getpwnam(auto_usera); ++ if (!pw) _exit(QLX_NOALIAS); ++ ++ if (!stralloc_copys(&nughde, pw->pw_name)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid))) ++ _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid))) ++ _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde, pw->pw_dir)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde,"-")) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde,r)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ } ++ break; ++#ifdef QLDAP_CLUSTER ++ case 2: ++ /* hostname is different, so I reconnect */ ++ forward_mail(host.s, ra.s, s, fdmess, fdout); ++ /* that's it. Function does not return */ ++#endif ++#ifdef DUPEALIAS ++ case 3: ++ /* the alias-user handling for dupe handling */ ++ { ++ struct passwd *pw; ++ char num[FMT_ULONG]; ++ ++ logit(4, "LDAP lookup got too many hits, using dupe alias\n"); ++ pw = getpwnam("dupealias"); ++ if (!pw) _exit(QLX_NOALIAS); ++ ++ if (!stralloc_copys(&nughde, pw->pw_name)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_uid))) ++ _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_catb(&nughde,num,fmt_uint(num, pw->pw_gid))) ++ _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde, pw->pw_dir)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde,"-")) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ if (!stralloc_cats(&nughde,r)) _exit(QLX_NOMEM); ++ if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); ++ } ++ break; ++#endif ++ default: ++ logit(2, "warning: ldap lookup freaky return value (%i)\n", rv); ++ _exit(QLX_USAGE); ++ break; ++ } /* end switch */ + + x = nughde.s; + xlen = nughde.len; + +- args[0] = "bin/qmail-local"; +- args[1] = "--"; ++ args[0] = (char *)"bin/qmail-local"; ++ args[1] = (char *)"--"; + args[2] = x; + n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; + +@@ -216,9 +847,13 @@ char *s; char *r; int at; + + args[7] = r + at + 1; + args[8] = s; +- args[9] = aliasempty; ++ args[9] = (char *)aliasempty; + args[10] = 0; + ++ logit(8, "executing 'qmail-local -- %s %s %s %s %s %s %s %s' under uid=%i, gid=%i\n", ++ args[2], args[3], args[4], args[5], args[6], args[7], ++ args[8], args[9], uid, gid); ++ + if (fd_move(0,fdmess) == -1) _exit(QLX_SYS); + if (fd_move(1,fdout) == -1) _exit(QLX_SYS); + if (fd_copy(2,1) == -1) _exit(QLX_SYS); +@@ -226,9 +861,42 @@ char *s; char *r; int at; + if (prot_uid(uid) == -1) _exit(QLX_USAGE); + if (!getuid()) _exit(QLX_ROOT); + ++#ifdef AUTOHOMEDIRMAKE ++ check_home(args[3], aliasempty); ++#endif ++ + execv(*args,args); + if (error_temp(errno)) _exit(QLX_EXECSOFT); + _exit(QLX_EXECHARD); + } + return f; + } ++ ++#ifdef QLDAP_CLUSTER ++ ++void forward_mail(char *remote, char *to, char *from, int fdmess, int fdout) ++{ ++ char *(args[5]); ++ ++ logit(8, "Forwarding to %s at host %s from %s ", to, remote, from); ++ ++ if (fd_move(0,fdmess) == -1) _exit(QLX_SYS); ++ if (fd_move(1,fdout) == -1) _exit(QLX_SYS); ++ if (fd_copy(2,1) == -1) _exit(QLX_SYS); ++ if (prot_gid(auto_uida) == -1) _exit(QLX_USAGE); ++ if (prot_uid(auto_gidn) == -1) _exit(QLX_USAGE); ++ if (!getuid()) _exit(QLX_ROOT); ++ ++ args[0] = (char *)"bin/qmail-forward"; ++ args[1] = remote; ++ args[2] = from; ++ args[3] = to; ++ args[4] = 0; ++ ++ execv(*args,args); ++ if (error_temp(errno)) _exit(QLX_CLUSTERSOFT); ++ _exit(QLX_CLUSTERHARD); ++} ++ ++#endif ++ +diff -upN qmail-1.03/qmail-newmrh.c qmail-ldap/qmail-newmrh.c +--- qmail-1.03/qmail-newmrh.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-newmrh.c Wed May 5 17:42:12 2004 +@@ -1,3 +1,7 @@ ++#include ++#include ++#include ++#include + #include "strerr.h" + #include "stralloc.h" + #include "substdio.h" +@@ -6,7 +10,8 @@ + #include "readwrite.h" + #include "open.h" + #include "auto_qmail.h" +-#include "cdbmss.h" ++#include "cdb_make.h" ++#include "case.h" + + #define FATAL "qmail-newmrh: fatal: " + +@@ -25,11 +30,11 @@ substdio ssin; + int fd; + int fdtemp; + +-struct cdbmss cdbmss; ++struct cdb_make cdbm; + stralloc line = {0}; + int match; + +-void main() ++int main() + { + umask(033); + if (chdir(auto_qmail) == -1) +@@ -38,12 +43,12 @@ void main() + fd = open_read("control/morercpthosts"); + if (fd == -1) die_read(); + +- substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); ++ substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof inbuf); + + fdtemp = open_trunc("control/morercpthosts.tmp"); + if (fdtemp == -1) die_write(); + +- if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write(); ++ if (cdb_make_start(&cdbm,fdtemp) == -1) die_write(); + + for (;;) { + if (getln(&ssin,&line,&match,'\n') != 0) die_read(); +@@ -53,18 +58,18 @@ void main() + if (line.s[line.len - 1] == '\n') { --line.len; continue; } + if (line.s[line.len - 1] == '\t') { --line.len; continue; } + if (line.s[0] != '#') +- if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1) ++ if (cdb_make_add(&cdbm,line.s,line.len,"",0) == -1) + die_write(); + break; + } + if (!match) break; + } + +- if (cdbmss_finish(&cdbmss) == -1) die_write(); ++ if (cdb_make_finish(&cdbm) == -1) die_write(); + if (fsync(fdtemp) == -1) die_write(); + if (close(fdtemp) == -1) die_write(); /* NFS stupidity */ + if (rename("control/morercpthosts.tmp","control/morercpthosts.cdb") == -1) + strerr_die2sys(111,FATAL,"unable to move control/morercpthosts.tmp to control/morercpthosts.cdb"); + +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-newu.c qmail-ldap/qmail-newu.c +--- qmail-1.03/qmail-newu.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-newu.c Wed May 5 17:42:12 2004 +@@ -1,14 +1,19 @@ ++#include ++#include ++#include ++#include + #include "stralloc.h" + #include "subfd.h" + #include "getln.h" + #include "substdio.h" +-#include "cdbmss.h" ++#include "cdb_make.h" + #include "exit.h" + #include "readwrite.h" + #include "open.h" + #include "error.h" + #include "case.h" + #include "auto_qmail.h" ++#include "byte.h" + + void die_temp() { _exit(111); } + +@@ -53,7 +58,7 @@ void die_rename() + die_temp(); + } + +-struct cdbmss cdbmss; ++struct cdb_make cdbm; + stralloc key = {0}; + stralloc data = {0}; + +@@ -68,10 +73,10 @@ int match; + + stralloc wildchars = {0}; + +-void main() ++int main() + { +- int i; +- int numcolons; ++ unsigned int i; ++ unsigned int numcolons; + + umask(033); + if (chdir(auto_qmail) == -1) die_chdir(); +@@ -79,12 +84,12 @@ void main() + fd = open_read("users/assign"); + if (fd == -1) die_opena(); + +- substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssin,subread,fd,inbuf,sizeof(inbuf)); + + fdtemp = open_trunc("users/cdb.tmp"); + if (fdtemp == -1) die_opent(); + +- if (cdbmss_start(&cdbmss,fdtemp) == -1) die_writet(); ++ if (cdb_make_start(&cdbm,fdtemp) == -1) die_writet(); + + if (!stralloc_copys(&wildchars,"")) die_nomem(); + +@@ -123,15 +128,15 @@ void main() + if (numcolons < 6) die_format(); + data.len = i; + +- if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_writet(); ++ if (cdb_make_add(&cdbm,key.s,key.len,data.s,data.len) == -1) die_writet(); + } + +- if (cdbmss_add(&cdbmss,"",0,wildchars.s,wildchars.len) == -1) die_writet(); ++ if (cdb_make_add(&cdbm,"",0,wildchars.s,wildchars.len) == -1) die_writet(); + +- if (cdbmss_finish(&cdbmss) == -1) die_writet(); ++ if (cdb_make_finish(&cdbm) == -1) die_writet(); + if (fsync(fdtemp) == -1) die_writet(); + if (close(fdtemp) == -1) die_writet(); /* NFS stupidity */ + if (rename("users/cdb.tmp","users/cdb") == -1) die_rename(); + +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-pbsdbd.sh qmail-ldap/qmail-pbsdbd.sh +--- qmail-1.03/qmail-pbsdbd.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-pbsdbd.sh Wed Aug 18 11:27:12 2004 +@@ -0,0 +1,25 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# pop before smtp database daemon ++# ++QMAIL="%QMAIL%" ++QUSER="qmaild" ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++QUSER=${QUSER:="qmaild"} ++ ++exec \ ++ setuidgid $QUSER \ ++ $QMAIL/bin/pbsdbd ++ +diff -upN qmail-1.03/qmail-pop3d-ssl.sh qmail-ldap/qmail-pop3d-ssl.sh +--- qmail-1.03/qmail-pop3d-ssl.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-pop3d-ssl.sh Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,40 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# POP3 service ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++if [ -e $QMAIL/control/defaultdelivery ]; then ++ ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null` ++else ++ ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null` ++fi ++ALIASEMPTY=${ALIASEMPTY:="./Maildir/"} ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++TLSCERT=${TLSCERT:="$QMAIL/control/cert.pem"} ++PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"} ++ ++if [ X${NOPBS+"true"} = X"true" ]; then ++ unset PBSTOOL ++fi ++ ++exec \ ++ tcpserver -v -HRl $ME -x$QMAIL/control/qmail-pop3d.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} \ ++ -s ${TLSCERT:+"-n$TLSCERT"} 0 pop3s \ ++ $QMAIL/bin/qmail-popup $ME \ ++ $QMAIL/bin/auth_pop ${PBSTOOL:+"-d$PBSTOOL"}\ ++ $QMAIL/bin/qmail-pop3d "$ALIASEMPTY" ++ +diff -upN qmail-1.03/qmail-pop3d.c qmail-ldap/qmail-pop3d.c +--- qmail-1.03/qmail-pop3d.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-pop3d.c Thu Jan 29 16:48:14 2004 +@@ -1,10 +1,13 @@ + #include + #include ++#include ++#include + #include "commands.h" + #include "sig.h" + #include "getln.h" + #include "stralloc.h" + #include "substdio.h" ++#include "subfd.h" + #include "alloc.h" + #include "open.h" + #include "prioq.h" +@@ -17,9 +20,48 @@ + #include "timeoutread.h" + #include "timeoutwrite.h" + +-void die() { _exit(0); } ++#include "env.h" ++#include "maildir++.h" ++#include "qmail-ldap.h" + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++int qfd; ++ ++/* level 0 = no logging ++ 1 = fatal errors ++ 2 = login/logout accounting ++ 3 = session errors ++ 4 = verbose ++ */ ++int loglevel = 0; ++stralloc logs_pidhostinfo = {0}; ++unsigned long log_bytes = 0; ++ ++void logit(int l, const char *s) ++{ ++ if(l <= loglevel) ++ substdio_puts(subfderr,s); ++} ++void logitf(int l, const char *s) ++{ ++ if(l > loglevel) return; ++ substdio_puts(subfderr,s); ++ substdio_putsflush(subfderr,"\n"); ++} ++ ++void log_quit(void) ++{ ++ char strnum[FMT_ULONG]; ++ ++ logit(2, "acct:"); ++ logit(2, logs_pidhostinfo.s); ++ logit(2, "logout "); ++ strnum[fmt_ulong(strnum,log_bytes)] = 0; ++ logit(2, strnum); logitf(2, " bytes transferred"); ++} ++ ++void die(void) { log_quit(); _exit(0); } ++ ++int saferead(int fd, void *buf, int len) + { + int r; + r = timeoutread(1200,fd,buf,len); +@@ -27,7 +69,7 @@ int saferead(fd,buf,len) int fd; char *b + return r; + } + +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; + r = timeoutwrite(1200,fd,buf,len); +@@ -41,52 +83,94 @@ substdio ssout = SUBSTDIO_FDBUF(safewrit + char ssinbuf[128]; + substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +-void put(buf,len) char *buf; int len; ++void put(const char *buf, int len) + { + substdio_put(&ssout,buf,len); + } +-void puts(s) char *s; ++void putstr(const char *s) + { + substdio_puts(&ssout,s); + } +-void flush() ++void flush(void) + { + substdio_flush(&ssout); + } +-void err(s) char *s; ++void err(const char *s) + { +- puts("-ERR "); +- puts(s); +- puts("\r\n"); ++ putstr("-ERR "); ++ putstr(s); ++ putstr("\r\n"); + flush(); + } + +-void die_nomem() { err("out of memory"); die(); } +-void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); } +-void die_scan() { err("unable to scan $HOME/Maildir"); die(); } +- +-void err_syntax() { err("syntax error"); } +-void err_unimpl() { err("unimplemented"); } +-void err_deleted() { err("already deleted"); } +-void err_nozero() { err("messages are counted from 1"); } +-void err_toobig() { err("not that many messages"); } +-void err_nosuch() { err("unable to open that message"); } +-void err_nounlink() { err("unable to unlink all deleted messages"); } ++void die_nomem(void) { err("out of memory"); ++ logitf(1, "panic: out of memory"); die(); } ++void die_nomaildir(void) { err("this user has no $HOME/Maildir"); ++ logitf(1, "panic: this user has no $HOME/Maildir"); die(); } ++void die_scan(void) { err("unable to scan $HOME/Maildir"); ++ logitf(1, "unable to scan $HOME/Maildir"); die(); } ++ ++void err_syntax(void) { err("syntax error"); logitf(3, "error: syntax error"); } ++void err_unimpl(void) { err("unimplemented"); logitf(3, "error: unimplemented"); } ++void err_deleted(void) { err("already deleted"); logitf(3, "already deleted"); } ++void err_nozero(void) { err("messages are counted from 1"); logitf(3, "messages are counted from 1"); } ++void err_toobig(void) { err("not that many messages"); logitf(3, "not that many messages"); } ++void err_nosuch(void) { err("unable to open that message"); logitf(3, "unable to open that message"); } ++void err_nounlink(void) { err("unable to unlink all deleted messages"); logitf(3, "unable to unlink all deleted messages"); } + +-void okay() { puts("+OK \r\n"); flush(); } ++void okay(void) { putstr("+OK \r\n"); flush(); } + +-void printfn(fn) char *fn; ++void printfn(const char *fn) + { + fn += 4; + put(fn,str_chr(fn,':')); + } + ++void log_init(void) ++{ ++ char strnum[FMT_ULONG]; ++ const char *remotehost; ++ const char *remoteip; ++ const char *remoteinfo; ++ const char *user; ++ char *l; ++ unsigned long v; ++ ++ l = env_get("POP3_LOGLEVEL"); ++ if (l) { scan_ulong(l,&v); loglevel = v; }; ++ ++ remoteip = env_get("TCPREMOTEIP"); ++ if (!remoteip) remoteip = "unknown"; ++ remotehost = env_get("TCPREMOTEHOST"); ++ if (!remotehost) remotehost = "unknown"; ++ remoteinfo = env_get("TCPREMOTEINFO"); ++ if (!remoteinfo) remoteinfo = ""; ++ user = env_get("USER"); ++ if (!user) user = "unknown"; ++ ++ if (!stralloc_copys(&logs_pidhostinfo, " pid ")) die_nomem(); ++ strnum[fmt_ulong(strnum,getpid())] = 0; ++ if (!stralloc_cats(&logs_pidhostinfo, strnum)) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, ": ")) die_nomem(); ++ ++ if (!stralloc_cats(&logs_pidhostinfo, remotehost)) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, ":")) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, remoteip)) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, ":")) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, remoteinfo)) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, " ")) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, user)) die_nomem(); ++ if (!stralloc_cats(&logs_pidhostinfo, " ")) die_nomem(); ++ if (!stralloc_0(&logs_pidhostinfo)) die_nomem(); ++ ++ logit(2, "acct:"); logit(2, logs_pidhostinfo.s); logitf(2, "login"); ++} ++ ++ + char strnum[FMT_ULONG]; + stralloc line = {0}; + +-void blast(ssfrom,limit) +-substdio *ssfrom; +-unsigned long limit; ++void blast(substdio *ssfrom, unsigned long limit) + { + int match; + int inheaders = 1; +@@ -103,6 +187,7 @@ unsigned long limit; + put(".",1); + put(line.s,line.len); + put("\r\n",2); ++ log_bytes += line.len + 2; + if (!match) break; + } + put("\r\n.\r\n",5); +@@ -117,15 +202,15 @@ struct message { + unsigned long size; + char *fn; + } *m; +-int numm; ++unsigned int numm; + +-int last = 0; ++unsigned int last = 0; + +-void getlist() ++void getlist(void) + { + struct prioq_elt pe; + struct stat st; +- int i; ++ unsigned int i; + + maildir_clean(&line); + if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan(); +@@ -146,42 +231,64 @@ void getlist() + } + } + +-void pop3_stat() ++void pop3_stat(char *arg) + { +- int i; ++ unsigned int i; + unsigned long total; ++ unsigned int count; + ++ logitf(4, "comm: stat"); + total = 0; +- for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; +- puts("+OK "); +- put(strnum,fmt_uint(strnum,numm)); +- puts(" "); ++ count = 0; ++ for (i = 0;i < numm;++i) if (!m[i].flagdeleted) { ++ total += m[i].size; ++ count += 1; ++ } ++ putstr("+OK "); ++ put(strnum,fmt_uint(strnum,count)); ++ putstr(" "); + put(strnum,fmt_ulong(strnum,total)); +- puts("\r\n"); ++ putstr("\r\n"); + flush(); + } + +-void pop3_rset() ++void pop3_rset(char *arg) + { +- int i; ++ unsigned int i; ++ ++ logitf(4, "comm: rset"); + for (i = 0;i < numm;++i) m[i].flagdeleted = 0; + last = 0; + okay(); + } + +-void pop3_last() ++void pop3_last(char *arg) + { +- puts("+OK "); ++ logitf(4, "comm: last"); ++ putstr("+OK "); + put(strnum,fmt_uint(strnum,last)); +- puts("\r\n"); ++ putstr("\r\n"); + flush(); + } + +-void pop3_quit() ++void pop3_quit(char *arg) + { +- int i; ++ unsigned int i; ++ quota_t q; ++ ++ logitf(4, "comm: quit"); ++/* qmail-ldap stuff */ ++/* this is just minimal support, because pop3 can not produce new mail */ ++ quota_get(&q, env_get(ENV_QUOTA)); ++ if (quota_calc(".",&qfd, &q) == -1) { ++ /* second chance */ ++ sleep(3); ++ quota_calc(".",&qfd, &q); ++ } + for (i = 0;i < numm;++i) + if (m[i].flagdeleted) { ++ if ( qfd != -1 ) quota_rm(qfd, m[i].size, 1); ++/* end qmail-ldap stuff */ + if (unlink(m[i].fn) == -1) err_nounlink(); + } + else +@@ -193,10 +300,11 @@ void pop3_quit() + rename(m[i].fn,line.s); /* if it fails, bummer */ + } + okay(); ++ if ( qfd != -1 ) close(qfd); + die(); + } + +-int msgno(arg) char *arg; ++unsigned int msgno(char *arg) + { + unsigned long u; + if (!scan_ulong(arg,&u)) { err_syntax(); return -1; } +@@ -207,9 +315,11 @@ int msgno(arg) char *arg; + return u; + } + +-void pop3_dele(arg) char *arg; ++void pop3_dele(char *arg) + { +- int i; ++ unsigned int i; ++ ++ logit(4, "comm: dele: "); logitf(4, arg); + i = msgno(arg); + if (i == -1) return; + m[i].flagdeleted = 1; +@@ -217,24 +327,22 @@ void pop3_dele(arg) char *arg; + okay(); + } + +-void list(i,flaguidl) +-int i; +-int flaguidl; ++void list(unsigned int i, int flaguidl) + { + put(strnum,fmt_uint(strnum,i + 1)); +- puts(" "); ++ putstr(" "); + if (flaguidl) printfn(m[i].fn); + else put(strnum,fmt_ulong(strnum,m[i].size)); +- puts("\r\n"); ++ putstr("\r\n"); + } + +-void dolisting(arg,flaguidl) char *arg; int flaguidl; ++void dolisting(char *arg, int flaguidl) + { + unsigned int i; + if (*arg) { + i = msgno(arg); + if (i == -1) return; +- puts("+OK "); ++ putstr("+OK "); + list(i,flaguidl); + } + else { +@@ -242,22 +350,28 @@ void dolisting(arg,flaguidl) char *arg; + for (i = 0;i < numm;++i) + if (!m[i].flagdeleted) + list(i,flaguidl); +- puts(".\r\n"); ++ putstr(".\r\n"); + } + flush(); + } + +-void pop3_uidl(arg) char *arg; { dolisting(arg,1); } +-void pop3_list(arg) char *arg; { dolisting(arg,0); } ++void pop3_uidl(char *arg) { ++ logit(4, "comm: uidl: "); logitf(4, arg); dolisting(arg,1); } ++void pop3_list(char *arg) { ++ logit(4, "comm: list: "); logitf(4, arg); dolisting(arg,0); } + + substdio ssmsg; char ssmsgbuf[1024]; + +-void pop3_top(arg) char *arg; ++void pop3_top(char *arg) + { +- int i; ++ unsigned int i; + unsigned long limit; + int fd; ++#ifdef MAKE_NETSCAPE_WORK /* Based on a patch by sven@megabit.net */ ++ char foo[FMT_ULONG]; ++#endif + ++ logit(4, "comm: retr/top: "); logitf(4, arg); + i = msgno(arg); + if (i == -1) return; + +@@ -267,8 +381,19 @@ void pop3_top(arg) char *arg; + + fd = open_read(m[i].fn); + if (fd == -1) { err_nosuch(); return; } ++ ++#ifdef MAKE_NETSCAPE_WORK /* Based on a patch by sven@megabit.net */ ++ putstr("+OK "); ++ foo[fmt_uint(foo,m[i].size)] = 0; ++ putstr(foo); ++ ++ putstr(" octets \r\n"); ++ flush(); ++#else + okay(); +- substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); ++#endif ++ ++ substdio_fdbuf(&ssmsg,subread,fd,ssmsgbuf,sizeof(ssmsgbuf)); + blast(&ssmsg,limit); + close(fd); + } +@@ -287,19 +412,28 @@ struct commands pop3commands[] = { + , { 0, err_unimpl, 0 } + } ; + +-void main(argc,argv) +-int argc; +-char **argv; ++int main(int argc, char **argv) + { ++/* qmail-ldap stuff */ ++ char *env; ++ + sig_alarmcatch(die); + sig_pipeignore(); +- ++ ++ /* if MAILDIR is defined us this as Maildir and not the argument */ ++ if ( (env = env_get("MAILDIR") ) && *env ) argv[1] = env; ++ + if (!argv[1]) die_nomaildir(); +- if (chdir(argv[1]) == -1) die_nomaildir(); +- ++ if (chdir(argv[1]) == -1) { ++ die_nomaildir(); ++ } ++/* qmail-ldap stuff */ ++ ++ log_init(); + getlist(); + + okay(); + commands(&ssin,pop3commands); +- die(); ++ log_quit(); ++ return 0; + } +diff -upN qmail-1.03/qmail-pop3d.rules qmail-ldap/qmail-pop3d.rules +--- qmail-1.03/qmail-pop3d.rules Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-pop3d.rules Thu Oct 30 11:11:13 2003 +@@ -0,0 +1,9 @@ ++# ++# POP3 Server rules. ++# Normaly you allow from everyware and the only useful env vars are ++# NOPBS, LOGLEVEL and POP3_LOGLEVEL. ++# ++# disable pop-befor-smtp on the loopback ++127.0.0.1:allow,NOPBS="" ++# default allow ++:allow +diff -upN qmail-1.03/qmail-pop3d.sh qmail-ldap/qmail-pop3d.sh +--- qmail-1.03/qmail-pop3d.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-pop3d.sh Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,38 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# POP3 service ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++if [ -e $QMAIL/control/defaultdelivery ]; then ++ ALIASEMPTY=`head -1 $QMAIL/control/defaultdelivery 2> /dev/null` ++else ++ ALIASEMPTY=`head -1 $QMAIL/control/aliasempty 2> /dev/null` ++fi ++ALIASEMPTY=${ALIASEMPTY:="./Maildir/"} ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbsadd"} ++ ++if [ X${NOPBS+"true"} = X"true" ]; then ++ unset PBSTOOL ++fi ++ ++exec \ ++ tcpserver -v -HRl $ME -x$QMAIL/control/qmail-pop3d.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 pop3 \ ++ $QMAIL/bin/qmail-popup $ME \ ++ $QMAIL/bin/auth_pop ${PBSTOOL:+"-d$PBSTOOL"} \ ++ $QMAIL/bin/qmail-pop3d "$ALIASEMPTY" ++ +diff -upN qmail-1.03/qmail-popup.c qmail-ldap/qmail-popup.c +--- qmail-1.03/qmail-popup.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-popup.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "commands.h" + #include "fd.h" + #include "sig.h" +@@ -14,9 +15,9 @@ + #include "timeoutread.h" + #include "timeoutwrite.h" + +-void die() { _exit(1); } ++void die(void) { _exit(1); } + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++int saferead(int fd, void *buf, int len) + { + int r; + r = timeoutread(1200,fd,buf,len); +@@ -24,7 +25,7 @@ int saferead(fd,buf,len) int fd; char *b + return r; + } + +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; + r = timeoutwrite(1200,fd,buf,len); +@@ -38,36 +39,62 @@ substdio ssout = SUBSTDIO_FDBUF(safewrit + char ssinbuf[128]; + substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +-void puts(s) char *s; ++void putstr(const char *s) + { + substdio_puts(&ssout,s); + } +-void flush() ++void flush(void) + { + substdio_flush(&ssout); + } +-void err(s) char *s; ++void err(const char *s) + { +- puts("-ERR "); +- puts(s); +- puts("\r\n"); ++ putstr("-ERR "); ++ putstr(s); ++ putstr("\r\n"); + flush(); + } + +-void die_usage() { err("usage: popup hostname subprogram"); die(); } +-void die_nomem() { err("out of memory"); die(); } +-void die_pipe() { err("unable to open pipe"); die(); } +-void die_write() { err("unable to write pipe"); die(); } +-void die_fork() { err("unable to fork"); die(); } +-void die_childcrashed() { err("aack, child crashed"); } +-void die_badauth() { err("authorization failed"); } +- +-void err_syntax() { err("syntax error"); } +-void err_wantuser() { err("USER first"); } +-void err_authoriz() { err("authorization first"); } ++void die_usage(void) { err("usage: popup hostname subprogram"); die(); } ++void die_nomem(void) { err("out of memory"); die(); } ++void die_pipe(void) { err("unable to open pipe"); die(); } ++void die_write(void) { err("unable to write pipe"); die(); } ++void die_fork(void) { err("unable to fork"); die(); } ++void die_childcrashed(void) { err("aack, child crashed"); } ++void die_badauth(void) { err("authorization failed"); } ++ ++/* checkpassword error exit codes: ++ * 1 = error in server configuration ++ * 2 = unable to contact authorization server ++ * 25= user record incorrect ++ * 3 = authorization failed ++ * 4 = account disabled ++ * 5 = mailhost is unreachable ++ * 6 = mailbox is corrupted ++ * 61= mailbox creation failed ++ * 62= the users mailbox does not exist ++ * 7 = unable to start subprogram ++ * 8 = out of memory ++ */ ++ ++void die_1(void) { err("error in server configuration"); die(); } ++void die_2(void) { err("unable to contact authorization server"); die(); } ++void die_25(void) { err("user record incorrect"); die(); } ++void die_3(void) { err("authorization failed"); die(); } ++void die_4(void) { err("account disabled"); die(); } ++void die_5(void) { err("mailhost is unreachable"); die(); } ++void die_6(void) { err("mailbox is corrupted"); die(); } ++void die_61(void) { err("mailbox could not be created"); die(); } ++void die_62(void) { err("the users mailbox does not exist"); die(); } ++void die_7(void) { err("unable to start subprogram"); die(); } ++void die_unknown(void) { err("temporary error"); die(); } ++ ++void err_syntax(void) { err("syntax error"); } ++void err_wantuser(void) { err("USER first"); } ++void err_authoriz(void) { err("authorization first"); } + +-void okay() { puts("+OK \r\n"); flush(); } +-void pop3_quit() { okay(); die(); } ++void okay(void) { putstr("+OK \r\n"); flush(); } ++void pop3_quit(void) { okay(); die(); } + + + char unique[FMT_ULONG + FMT_ULONG + 3]; +@@ -79,16 +106,13 @@ substdio ssup; + char upbuf[128]; + + +-void doanddie(user,userlen,pass) +-char *user; +-unsigned int userlen; /* including 0 byte */ +-char *pass; ++void doanddie(char *user, unsigned int userlen /* including 0 byte */, ++ char *pass) + { + int child; + int wstat; + int pi[2]; + +- if (fd_copy(2,1) == -1) die_pipe(); + close(3); + if (pipe(pi) == -1) die_pipe(); + if (pi[0] != 3) die_pipe(); +@@ -102,7 +126,7 @@ char *pass; + _exit(1); + } + close(pi[0]); +- substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); ++ substdio_fdbuf(&ssup,subwrite,pi[1],upbuf,sizeof upbuf); + if (substdio_put(&ssup,user,userlen) == -1) die_write(); + if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write(); + if (substdio_puts(&ssup,"<") == -1) die_write(); +@@ -115,10 +139,25 @@ char *pass; + byte_zero(upbuf,sizeof upbuf); + if (wait_pid(&wstat,child) == -1) die(); + if (wait_crashed(wstat)) die_childcrashed(); +- if (wait_exitcode(wstat)) die_badauth(); ++ switch (wait_exitcode(wstat)) { ++ case 0: die(); ++ case 1: die_1(); ++ case 2: die_2(); ++ case 25: die_25(); ++ case 3: die_3(); ++ case 4: die_4(); ++ case 5: die_5(); ++ case 6: die_6(); ++ case 61: die_61(); ++ case 62: die_62(); ++ case 7: die_7(); ++ case 8: die_nomem(); ++ default: die_unknown(); ++ } + die(); + } +-void pop3_greet() ++ ++void pop3_greet(void) + { + char *s; + s = unique; +@@ -127,13 +166,13 @@ void pop3_greet() + s += fmt_ulong(s,(unsigned long) now()); + *s++ = '@'; + *s++ = 0; +- puts("+OK <"); +- puts(unique); +- puts(hostname); +- puts(">\r\n"); ++ putstr("+OK <"); ++ putstr(unique); ++ putstr(hostname); ++ putstr(">\r\n"); + flush(); + } +-void pop3_user(arg) char *arg; ++void pop3_user(char *arg) + { + if (!*arg) { err_syntax(); return; } + okay(); +@@ -141,13 +180,13 @@ void pop3_user(arg) char *arg; + if (!stralloc_copys(&username,arg)) die_nomem(); + if (!stralloc_0(&username)) die_nomem(); + } +-void pop3_pass(arg) char *arg; ++void pop3_pass(char *arg) + { + if (!seenuser) { err_wantuser(); return; } + if (!*arg) { err_syntax(); return; } + doanddie(username.s,username.len,arg); + } +-void pop3_apop(arg) char *arg; ++void pop3_apop(char *arg) + { + char *space; + space = arg + str_chr(arg,' '); +@@ -165,9 +204,7 @@ struct commands pop3commands[] = { + , { 0, err_authoriz, 0 } + } ; + +-void main(argc,argv) +-int argc; +-char **argv; ++int main(int argc, char **argv) + { + sig_alarmcatch(die); + sig_pipeignore(); +@@ -179,5 +216,5 @@ char **argv; + + pop3_greet(); + commands(&ssin,pop3commands); +- die(); ++ return 1; + } +diff -upN qmail-1.03/qmail-pw2u.c qmail-ldap/qmail-pw2u.c +--- qmail-1.03/qmail-pw2u.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-pw2u.c Thu Jan 29 16:48:14 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "substdio.h" + #include "readwrite.h" + #include "subfd.h" +@@ -16,6 +17,7 @@ + #include "auto_break.h" + #include "auto_qmail.h" + #include "auto_usera.h" ++#include "byte.h" + + void die_chdir() + { +@@ -67,7 +69,7 @@ void die_user(s,len) char *s; unsigned i + _exit(111); + } + +-char *dashcolon = "-:"; ++const char *dashcolon = "-:"; + int flagalias = 0; + int flagnoupper = 1; + int homestrategy = 2; +@@ -93,8 +95,8 @@ stralloc line = {0}; + void doaccount() + { + struct stat st; +- int i; +- char *mailnames; ++ unsigned int i; ++ const char *mailnames; + char *x; + unsigned int xlen; + +@@ -194,21 +196,21 @@ stralloc sub = {0}; + + void dosubuser() + { +- int i; ++ unsigned int i; + char *x; + unsigned int xlen; +- char *uugh; ++ const char *uughs; + + x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return; + if (!stralloc_copyb(&sub,x,i)) die_nomem(); + ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; +- uugh = constmap(&mapuser,x,i); +- if (!uugh) die_user(x,i); ++ uughs = constmap(&mapuser,x,i); ++ if (!uughs) die_user(x,i); + ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; + + if (substdio_puts(subfdout,"=") == -1) die_write(); + if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); +- if (substdio_puts(subfdout,uugh) == -1) die_write(); ++ if (substdio_puts(subfdout,uughs) == -1) die_write(); + if (substdio_puts(subfdout,dashcolon) == -1) die_write(); + if (substdio_put(subfdout,x,i) == -1) die_write(); + if (substdio_puts(subfdout,":\n") == -1) die_write(); +@@ -217,7 +219,7 @@ void dosubuser() + if (substdio_puts(subfdout,"+") == -1) die_write(); + if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); + if (substdio_put(subfdout,auto_break,1) == -1) die_write(); +- if (substdio_puts(subfdout,uugh) == -1) die_write(); ++ if (substdio_puts(subfdout,uughs) == -1) die_write(); + if (substdio_puts(subfdout,dashcolon) == -1) die_write(); + if (substdio_put(subfdout,x,i) == -1) die_write(); + if (substdio_puts(subfdout,"-:\n") == -1) die_write(); +@@ -228,7 +230,7 @@ int fd; + substdio ss; + char ssbuf[SUBSTDIO_INSIZE]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -280,7 +282,7 @@ char **argv; + if (errno != error_noent) die_control(); + } + else { +- substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); ++ substdio_fdbuf(&ss,subread,fd,ssbuf,sizeof(ssbuf)); + + if (!constmap_init(&mapuser,allusers.s,allusers.len,1)) die_nomem(); + +@@ -298,7 +300,7 @@ char **argv; + if (errno != error_noent) die_control(); + } + else { +- substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); ++ substdio_fdbuf(&ss,subread,fd,ssbuf,sizeof(ssbuf)); + for (;;) { + if (getln(&ss,&line,&match,'\n') == -1) die_read(); + if (substdio_put(subfdout,line.s,line.len) == -1) die_write(); +@@ -308,5 +310,5 @@ char **argv; + + if (substdio_puts(subfdout,".\n") == -1) die_write(); + if (substdio_flush(subfdout) == -1) die_write(); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-qmqpc.c qmail-ldap/qmail-qmqpc.c +--- qmail-1.03/qmail-qmqpc.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-qmqpc.c Tue Apr 6 15:12:00 2004 +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include "substdio.h" + #include "getln.h" + #include "readwrite.h" +@@ -17,33 +18,105 @@ + #include "auto_qmail.h" + #include "control.h" + #include "fmt.h" ++#ifdef QMQP_COMPRESS ++#include ++#endif + ++ ++#ifndef PORT_QMQP /* this is for testing purposes */ + #define PORT_QMQP 628 ++#endif + +-void die_success() { _exit(0); } +-void die_perm() { _exit(31); } +-void nomem() { _exit(51); } +-void die_read() { if (errno == error_nomem) nomem(); _exit(54); } +-void die_control() { _exit(55); } +-void die_socket() { _exit(56); } +-void die_home() { _exit(61); } +-void die_temp() { _exit(71); } +-void die_conn() { _exit(74); } +-void die_format() { _exit(91); } ++void die_success(void) { _exit(0); } ++void die_perm(void) { _exit(31); } ++void nomem(void) { _exit(51); } ++void die_read(void) { if (errno == error_nomem) nomem(); _exit(54); } ++void die_control(void) { _exit(55); } ++void die_socket(void) { _exit(56); } ++void die_home(void) { _exit(61); } ++void die_temp(void) { _exit(71); } ++void die_conn(void) { _exit(74); } ++void die_format(void) { _exit(91); } + ++int timeoutconnect = 60; + int lasterror = 55; + int qmqpfd; + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++#ifdef QMQP_COMPRESS ++z_stream stream; ++char zbuf[4096]; ++ ++void compression_init(void) ++{ ++ stream.zalloc = Z_NULL; ++ stream.zfree = Z_NULL; ++ stream.opaque = Z_NULL; ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ if (deflateInit(&stream,Z_DEFAULT_COMPRESSION) != Z_OK) ++ die_format(); ++} ++void compression_done(void) ++{ ++ int r; ++ ++ do { ++ r = deflate(&stream,Z_FINISH); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) { ++ r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf)); ++ if (r <= 0) die_conn(); ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ r = Z_OK; ++ } ++ break; ++ case Z_STREAM_END: ++ break; ++ default: ++ die_format(); ++ } ++ } while (r!=Z_STREAM_END); ++ if (stream.avail_out != sizeof(zbuf)) { ++ /* write left data */ ++ r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf)-stream.avail_out); ++ if (r <= 0) die_conn(); ++ } ++ if (deflateEnd(&stream) != Z_OK) die_format(); ++} ++#endif ++ ++int saferead(int fd, void *buf, int len) + { + int r; + r = timeoutread(60,qmqpfd,buf,len); + if (r <= 0) die_conn(); + return r; + } +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; ++#ifdef QMQP_COMPRESS ++ stream.avail_in = len; ++ stream.next_in = buf; ++ do { ++ r = deflate(&stream, 0); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) { ++ r = timeoutwrite(60,qmqpfd,zbuf,sizeof(zbuf)); ++ if (r <= 0) die_conn(); ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ } ++ break; ++ default: ++ die_format(); ++ } ++ } while (stream.avail_in != 0); ++ return len; ++#endif + r = timeoutwrite(60,qmqpfd,buf,len); + if (r <= 0) die_conn(); + return r; +@@ -52,7 +125,7 @@ int safewrite(fd,buf,len) int fd; char * + char buf[1024]; + substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof buf); + substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof buf); +-substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof buf); ++substdio envelope = SUBSTDIO_FDBUF(subread,1,buf,sizeof buf); + /* WARNING: can use only one of these at a time! */ + + stralloc beforemessage = {0}; +@@ -68,7 +141,7 @@ void getmess() + + if (slurpclose(0,&message,1024) == -1) die_read(); + +- strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0; ++ strnum[fmt_uint(strnum,message.len)] = 0; + if (!stralloc_copys(&beforemessage,strnum)) nomem(); + if (!stralloc_cats(&beforemessage,":")) nomem(); + if (!stralloc_copys(&aftermessage,",")) nomem(); +@@ -78,7 +151,7 @@ void getmess() + if (line.len < 2) die_format(); + if (line.s[0] != 'F') die_format(); + +- strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; ++ strnum[fmt_uint(strnum,line.len - 2)] = 0; + if (!stralloc_cats(&aftermessage,strnum)) nomem(); + if (!stralloc_cats(&aftermessage,":")) nomem(); + if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); +@@ -90,7 +163,7 @@ void getmess() + if (line.len < 2) break; + if (line.s[0] != 'T') die_format(); + +- strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; ++ strnum[fmt_uint(strnum,line.len - 2)] = 0; + if (!stralloc_cats(&aftermessage,strnum)) nomem(); + if (!stralloc_cats(&aftermessage,":")) nomem(); + if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); +@@ -98,6 +171,8 @@ void getmess() + } + } + ++struct ip_address outip; ++ + void doit(server) + char *server; + { +@@ -109,14 +184,18 @@ char *server; + qmqpfd = socket(AF_INET,SOCK_STREAM,0); + if (qmqpfd == -1) die_socket(); + +- if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) { ++ if (timeoutconn(qmqpfd,&ip,&outip,PORT_QMQP,timeoutconnect) != 0) { + lasterror = 73; + if (errno == error_timeout) lasterror = 72; + close(qmqpfd); + return; + } + +- strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0; ++#ifdef QMQP_COMPRESS ++ compression_init(); ++#endif ++ strnum[fmt_uint(strnum, ++ (beforemessage.len + message.len + aftermessage.len))] = 0; + substdio_puts(&to,strnum); + substdio_puts(&to,":"); + substdio_put(&to,beforemessage.s,beforemessage.len); +@@ -124,6 +203,9 @@ char *server; + substdio_put(&to,aftermessage.s,aftermessage.len); + substdio_puts(&to,","); + substdio_flush(&to); ++#ifdef QMQP_COMPRESS ++ compression_done(); ++#endif + + for (;;) { + substdio_get(&from,&ch,1); +@@ -134,18 +216,48 @@ char *server; + } + + stralloc servers = {0}; ++stralloc outgoingip = {0}; ++ ++#include "dns.h" ++#include "ipalloc.h" ++ ++ipalloc ia = {0}; + +-main() ++int main(argc,argv) ++int argc; ++char **argv; + { +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + + sig_pipeignore(); + + if (chdir(auto_qmail) == -1) die_home(); + if (control_init() == -1) die_control(); ++ if ( argv[1] ) { ++ char temp[IPFMT]; ++ if (!stralloc_copys(&servers,argv[1])) nomem(); ++ dns_init(0); ++ switch (dns_ip(&ia,&servers)) { ++ case DNS_HARD: die_perm(); ++ case DNS_SOFT: die_temp(); ++ case DNS_MEM: nomem(); ++ } ++ ++ temp[ip_fmt(temp,&ia.ix[0].ip)]=0; ++ if (!stralloc_copys(&servers, temp)) nomem(); ++ if (!stralloc_0(&servers)) nomem(); ++ } else + if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control(); + ++ if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) ++ die_control(); ++ ++ if (control_rldef(&outgoingip, "control/qmqpcip", 0, "0.0.0.0") == -1) ++ die_control(); ++ if (!stralloc_0(&outgoingip)) nomem(); ++ if (!ip_scan(outgoingip.s,&outip)) die_control(); ++ + getmess(); + + i = 0; +@@ -155,5 +267,5 @@ main() + i = j + 1; + } + +- _exit(lasterror); ++ return lasterror; + } +diff -upN qmail-1.03/qmail-qmqpd.c qmail-ldap/qmail-qmqpd.c +--- qmail-1.03/qmail-qmqpd.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-qmqpd.c Thu Mar 4 14:30:49 2004 +@@ -1,26 +1,132 @@ ++#include + #include "auto_qmail.h" ++#include "byte.h" + #include "qmail.h" + #include "received.h" + #include "sig.h" ++#include "subfd.h" + #include "substdio.h" + #include "readwrite.h" + #include "exit.h" + #include "now.h" + #include "fmt.h" + #include "env.h" ++#include "str.h" ++#ifdef QMQP_COMPRESS ++#include ++ ++z_stream stream; ++char zbuf[4096]; ++int percent; ++int compressed = 0; ++extern substdio ssout; ++ ++void out(const char *s1, const char *s2, const char *s3) ++{ ++ char strnum[FMT_ULONG]; ++ unsigned long len; ++ ++ len = str_len(s1); ++ if (s2) len += str_len(s2); ++ if (s3) len += str_len(s3); ++ substdio_put(&ssout,strnum,fmt_ulong(strnum,len)); ++ substdio_puts(&ssout,":"); ++ substdio_puts(&ssout,s1); ++ substdio_puts(subfderr,s1+1); ++ if (s2) { substdio_puts(&ssout,s2); substdio_puts(subfderr,s2); } ++ if (s3) { substdio_puts(&ssout,s3); substdio_puts(subfderr,s3); } ++ substdio_puts(subfderr, "\n"); ++ substdio_flush(subfderr); ++ substdio_puts(&ssout,","); ++ substdio_flush(&ssout); ++} ++void compression_init(int avail) ++{ ++ stream.zalloc = Z_NULL; ++ stream.zfree = Z_NULL; ++ stream.opaque = Z_NULL; ++ stream.avail_in = avail; ++ stream.next_in = zbuf; ++ if (inflateInit(&stream) != Z_OK) { ++ out("ZInitalizing data compression failed: ", stream.msg, " #(4.3.0)"); ++ _exit(111); ++ } ++} ++void compression_done(void) ++{ ++ if (stream.avail_out != sizeof(zbuf)) { ++ /* there is some data left, ignore */ ++ } ++ if (inflateEnd(&stream) != Z_OK) { ++ out("ZFinishing data compression failed: ", stream.msg, " #(4.3.0)"); ++ _exit(111); ++ } ++ percent = 100 - (int)(100.0*stream.total_in/stream.total_out); ++} ++#endif + + void resources() { _exit(111); } ++void badproto() { _exit(100); } + +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; + r = write(fd,buf,len); + if (r <= 0) _exit(0); + return r; + } +-int saferead(fd,buf,len) int fd; char *buf; int len; ++int saferead(int fd, void *buf,int len) + { + int r; ++#ifdef QMQP_COMPRESS ++ if (compressed == 0) { ++ int i; ++ char ch; ++ r = read(0,zbuf,len); ++ if (r <= 0) _exit(0); ++ for (i = 0; i < r; i++) { ++ ch = zbuf[i]; ++ if (ch >= '0' && ch <= '9') continue; ++ if (ch == ':') { ++ byte_copy(buf, r, zbuf); ++ compressed = -1; ++ return r; ++ } ++ compressed = 1; ++ compression_init(r); ++ break; ++ } ++ } ++ if (compressed < 0) goto uncompressed; ++ if (compressed == 2) _exit(0); ++ stream.avail_out = len; ++ stream.next_out = buf; ++ do { ++ if (stream.avail_in == 0) { ++ r = read(fd,zbuf,sizeof(zbuf)); ++ if (r <= 0) _exit(0); /* XXX ??? */ ++ stream.avail_in = r; ++ stream.next_in = zbuf; ++ } ++ r = inflate(&stream, 0); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) ++ return len; ++ break; ++ case Z_STREAM_END: ++ compression_done(); ++ compressed = 2; ++ return len - stream.avail_out; ++ default: ++ out("ZReceiving compressed data failed: ", stream.msg, " #(4.3.0)"); ++ return -1; ++ } ++ if (stream.avail_out == len) continue; ++ return len - stream.avail_out; ++ } while (1); ++uncompressed: ++#endif + r = read(fd,buf,len); + if (r <= 0) _exit(0); + return r; +@@ -47,8 +153,9 @@ unsigned long getlen() + + for (;;) { + getbyte(&ch); +- if (ch == ':') return len; + if (len > 200000000) resources(); ++ if (ch == ':') return len; ++ if (ch < '0' || ch > '9') badproto(); + len = 10 * len + (ch - '0'); + } + } +@@ -57,17 +164,17 @@ void getcomma() + { + char ch; + getbyte(&ch); +- if (ch != ',') _exit(100); ++ if (ch != ',') badproto(); + } + + struct qmail qq; + + void identify() + { +- char *remotehost; +- char *remoteinfo; +- char *remoteip; +- char *local; ++ const char *remotehost; ++ const char *remoteinfo; ++ const char *remoteip; ++ const char *local; + + remotehost = env_get("TCPREMOTEHOST"); + if (!remotehost) remotehost = "unknown"; +@@ -78,16 +185,21 @@ void identify() + if (!local) local = env_get("TCPLOCALIP"); + if (!local) local = "unknown"; + +- received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0); ++#ifdef QMQP_COMPRESS ++ if (compressed > 0) ++ received(&qq,"compressed QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0); ++ else ++#endif ++ received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0); + } + +-char buf[1000]; ++char buf[1000 + 20 + FMT_ULONG]; + char strnum[FMT_ULONG]; + +-int getbuf() ++int getbuf(void) + { + unsigned long len; +- int i; ++ unsigned long i; + + len = getlen(); + if (len >= 1000) { +@@ -105,9 +217,9 @@ int getbuf() + + int flagok = 1; + +-main() ++int main(int argc, char **argv) + { +- char *result; ++ const char *result; + unsigned long qp; + unsigned long len; + char ch; +@@ -116,6 +228,10 @@ main() + sig_alarmcatch(resources); + alarm(3600); + ++#ifdef QMQP_COMPRESS ++ if (env_get("NOCOMPRESS")) compressed = -1; ++#endif ++ + bytesleft = getlen(); + + len = getlen(); +@@ -158,6 +274,17 @@ main() + len += fmt_ulong(buf + len,(unsigned long) now()); + len += fmt_str(buf + len," qp "); + len += fmt_ulong(buf + len,qp); ++#ifdef QMQP_COMPRESS ++ if (compressed > 0) { ++ len += fmt_str(buf + len, " DDC saved "); ++ if (percent < 0) { ++ len += fmt_str(buf + len, "-"); ++ percent *= -1; ++ } ++ len += fmt_uint(buf + len, percent); ++ len += fmt_str(buf + len, " percent"); ++ } ++#endif + buf[len] = 0; + result = buf; + } +@@ -165,10 +292,13 @@ main() + if (!flagok) + result = "Dsorry, I can't accept addresses like that (#5.1.3)"; + +- substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result))); ++ substdio_put(&ssout,strnum,fmt_uint(strnum,str_len(result))); + substdio_puts(&ssout,":"); + substdio_puts(&ssout,result); ++ substdio_puts(subfderr,result + 1); ++ substdio_puts(subfderr, "\n"); ++ substdio_flush(subfderr); + substdio_puts(&ssout,","); + substdio_flush(&ssout); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-qmqpd.rules qmail-ldap/qmail-qmqpd.rules +--- qmail-1.03/qmail-qmqpd.rules Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-qmqpd.rules Thu Oct 30 11:11:13 2003 +@@ -0,0 +1,10 @@ ++# ++# QMQP (qmail mail queueing protocol) server rules. ++# QMQP is mainly used in clusters to forward mails. The protocol accepts all ++# mails by default and so it is necessary to disable this service by default. ++# Only allow it for cluster hosts. ++# Currently there are no useful env vars for qmail-qmqpd. ++# ++#192.168.0.2:allow ++:deny ++ +diff -upN qmail-1.03/qmail-qmqpd.sh qmail-ldap/qmail-qmqpd.sh +--- qmail-1.03/qmail-qmqpd.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-qmqpd.sh Wed Aug 18 11:27:12 2004 +@@ -0,0 +1,28 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# QMQP service ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++QUSER="qmaild" ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++QUSER=${QUSER:="qmaild"} ++ ++exec \ ++ envuidgid $QUSER \ ++ tcpserver -v -URl $ME -x$QMAIL/control/qmail-qmqpd.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 628 \ ++ $QMAIL/bin/qmail-qmqpd ++ +diff -upN qmail-1.03/qmail-qmtpd.c qmail-ldap/qmail-qmtpd.c +--- qmail-1.03/qmail-qmtpd.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-qmtpd.c Thu Mar 4 14:30:49 2004 +@@ -1,3 +1,4 @@ ++#include + #include "stralloc.h" + #include "substdio.h" + #include "qmail.h" +@@ -11,11 +12,12 @@ + #include "readwrite.h" + #include "control.h" + #include "received.h" ++#include "scan.h" + + void badproto() { _exit(100); } + void resources() { _exit(111); } + +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; + r = write(fd,buf,len); +@@ -26,7 +28,7 @@ int safewrite(fd,buf,len) int fd; char * + char ssoutbuf[256]; + substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++int saferead(int fd, void *buf, int len) + { + int r; + substdio_flush(&ssout); +@@ -38,14 +40,15 @@ int saferead(fd,buf,len) int fd; char *b + char ssinbuf[512]; + substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +-unsigned long getlen() ++unsigned long getlen(void) + { + unsigned long len = 0; + char ch; + for (;;) { + substdio_get(&ssin,&ch,1); +- if (ch == ':') return len; + if (len > 200000000) resources(); ++ if (ch == ':') return len; ++ if (ch < '0' || ch > '9') badproto(); + len = 10 * len + (ch - '0'); + } + } +@@ -57,36 +60,35 @@ void getcomma() + if (ch != ',') badproto(); + } + +-unsigned int databytes = 0; +-unsigned int bytestooverflow = 0; ++unsigned long databytes = 0; ++unsigned long bytestooverflow = 0; + struct qmail qq; + + char buf[1000]; + char buf2[100]; + +-char *remotehost; +-char *remoteinfo; +-char *remoteip; +-char *local; ++const char *remotehost; ++const char *remoteinfo; ++const char *remoteip; ++const char *local; + + stralloc failure = {0}; + + char *relayclient; +-int relayclientlen; ++unsigned int relayclientlen; + +-main() ++int main() + { + char ch; +- int i; ++ unsigned int i; + unsigned long biglen; + unsigned long len; + int flagdos; + int flagsenderok; + int flagbother; + unsigned long qp; +- char *result; ++ const char *result; + char *x; +- unsigned long u; + + sig_pipeignore(); + sig_alarmcatch(resources); +@@ -99,9 +101,9 @@ main() + relayclient = env_get("RELAYCLIENT"); + relayclientlen = relayclient ? str_len(relayclient) : 0; + +- if (control_readint(&databytes,"control/databytes") == -1) resources(); ++ if (control_readulong(&databytes,"control/databytes") == -1) resources(); + x = env_get("DATABYTES"); +- if (x) { scan_ulong(x,&u); databytes = u; } ++ if (x) scan_ulong(x,&databytes); + if (!(databytes + 1)) --databytes; + + remotehost = env_get("TCPREMOTEHOST"); +@@ -113,6 +115,7 @@ main() + if (!local) local = env_get("TCPLOCALIP"); + if (!local) local = "unknown"; + ++ flagdos = 0; + for (;;) { + if (!stralloc_copys(&failure,"")) resources(); + flagsenderok = 1; +@@ -130,7 +133,7 @@ main() + else if (ch == 13) flagdos = 1; + else badproto(); + +- received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0); ++ received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0); + + /* XXX: check for loops? only if len is big? */ + +@@ -192,8 +195,9 @@ main() + if (!biglen) badproto(); + substdio_get(&ssin,&ch,1); + --biglen; +- if (ch == ':') break; + if (len > 200000000) resources(); ++ if (ch == ':') break; ++ if (ch < '0' || ch > '9') badproto(); + len = 10 * len + (ch - '0'); + } + if (len >= biglen) badproto(); +@@ -265,4 +269,6 @@ main() + + /* ssout will be flushed when we read from the network again */ + } ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/qmail-qread.c qmail-ldap/qmail-qread.c +--- qmail-1.03/qmail-qread.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-qread.c Tue Oct 28 18:21:32 2003 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "stralloc.h" + #include "substdio.h" + #include "subfd.h" +@@ -20,9 +21,9 @@ readsubdir rs; + + void die(n) int n; { substdio_flush(subfdout); _exit(n); } + +-void warn(s1,s2) char *s1; char *s2; ++void warn(s1,s2) const char *s1; const char *s2; + { +- char *x; ++ const char *x; + x = error_str(errno); + substdio_puts(subfdout,s1); + substdio_puts(subfdout,s2); +@@ -105,7 +106,7 @@ void putstats() + + stralloc line = {0}; + +-void main() ++int main() + { + int channel; + int match; +@@ -118,7 +119,7 @@ void main() + if (chdir("queue") == -1) die_chdir(); + readsubdir_init(&rs,"info",die_opendir); + +- while (x = readsubdir_next(&rs,&id)) ++ while ((x = readsubdir_next(&rs,&id))) + if (x > 0) + { + fmtqfn(fnmess,"mess/",id,1); +@@ -133,7 +134,7 @@ void main() + + fd = open_read(fninfo); + if (fd == -1) { err(id); continue; } +- substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ss,subread,fd,inbuf,sizeof(inbuf)); + if (getln(&ss,&sender,&match,0) == -1) die_nomem(); + if (fstat(fd,&st) == -1) { close(fd); err(id); continue; } + close(fd); +@@ -172,4 +173,5 @@ void main() + } + + die(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-qstat.sh qmail-ldap/qmail-qstat.sh +--- qmail-1.03/qmail-qstat.sh Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-qstat.sh Sat Mar 29 12:00:02 2003 +@@ -1,7 +1,13 @@ + cd QMAIL + messdirs=`echo queue/mess/* | wc -w` + messfiles=`find queue/mess/* -print | wc -w` ++if test -d "queue/todo/0" ++then ++tododirs=`echo queue/todo/* | wc -w` ++todofiles=`find queue/todo/* -print | wc -w` ++else + tododirs=`echo queue/todo | wc -w` + todofiles=`find queue/todo -print | wc -w` ++fi + echo messages in queue: `expr $messfiles - $messdirs` + echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs` +diff -upN qmail-1.03/qmail-queue.c qmail-ldap/qmail-queue.c +--- qmail-1.03/qmail-queue.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-queue.c Tue Oct 28 18:21:32 2003 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "readwrite.h" + #include "sig.h" + #include "exit.h" +@@ -20,6 +21,19 @@ + #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */ + #define ADDR 1003 + ++#ifdef BIGBROTHER ++#include "byte.h" ++#include "constmap.h" ++#include "control.h" ++#include "stralloc.h" ++ ++int bbon = 0; ++stralloc bbs = {0}; ++stralloc bbaddr = {0}; ++struct constmap mapbb; ++ ++#endif ++ + char inbuf[2048]; + struct substdio ssin; + char outbuf[256]; +@@ -57,6 +71,9 @@ void cleanup() + void die(e) int e; { _exit(e); } + void die_write() { cleanup(); die(53); } + void die_read() { cleanup(); die(54); } ++#ifdef BIGBROTHER ++void die_bb() { cleanup(); die(51); } ++#endif + void sigalrm() { /* thou shalt not clean up here */ die(52); } + void sigbug() { die(81); } + +@@ -151,14 +168,30 @@ void pidopen() + + char tmp[FMT_ULONG]; + +-void main() ++int main() + { + unsigned int len; + char ch; ++#ifdef BIGBROTHER ++ unsigned int xlen, n; ++ char *x; ++ const char *b; ++#endif + + sig_blocknone(); + umask(033); + if (chdir(auto_qmail) == -1) die(61); ++ ++#ifdef BIGBROTHER ++ if (control_init() == -1) die(55); ++ switch (control_readfile(&bbs,"control/bigbrother",0)) ++ { ++ case -1: die(55); ++ case 0: bbon = 0; if (!constmap_init(&mapbb,"",0,1)) die(51); break; ++ case 1: bbon = 1; if (!constmap_init(&mapbb,bbs.s,bbs.len,1)) die(51); break; ++ } ++#endif ++ + if (chdir("queue") == -1) die(62); + + mypid = getpid(); +@@ -180,15 +213,20 @@ void main() + + messnum = pidst.st_ino; + messfn = fnnum("mess/",1); ++#ifndef BIGTODO + todofn = fnnum("todo/",0); + intdfn = fnnum("intd/",0); ++#else ++ todofn = fnnum("todo/",1); ++ intdfn = fnnum("intd/",1); ++#endif + + if (link(pidfn,messfn) == -1) die(64); + if (unlink(pidfn) == -1) die(63); + flagmademess = 1; + +- substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf)); +- substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssout,subwrite,messfd,outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ssin,subread,0,inbuf,sizeof(inbuf)); + + if (substdio_bput(&ssout,received,receivedlen) == -1) die_write(); + +@@ -205,8 +243,8 @@ void main() + if (intdfd == -1) die(65); + flagmadeintd = 1; + +- substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf)); +- substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssout,subwrite,intdfd,outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ssin,subread,1,inbuf,sizeof(inbuf)); + + if (substdio_bput(&ssout,"u",1) == -1) die_write(); + if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write(); +@@ -223,6 +261,9 @@ void main() + { + if (substdio_get(&ssin,&ch,1) < 1) die_read(); + if (substdio_put(&ssout,&ch,1) == -1) die_write(); ++#ifdef BIGBROTHER ++ if (bbon) if (!stralloc_catb(&bbaddr, &ch, 1)) die_bb(); ++#endif + if (!ch) break; + } + if (len >= ADDR) die(11); +@@ -239,16 +280,39 @@ void main() + { + if (substdio_get(&ssin,&ch,1) < 1) die_read(); + if (substdio_bput(&ssout,&ch,1) == -1) die_write(); ++#ifdef BIGBROTHER ++ if (bbon) if (!stralloc_catb(&bbaddr, &ch, 1)) die_bb(); ++#endif + if (!ch) break; + } + if (len >= ADDR) die(11); + } +- ++ ++#ifdef BIGBROTHER ++ if (bbon) { ++ x = bbaddr.s; ++ xlen = bbaddr.len; ++ do ++ { ++ n = byte_chr(x,xlen,0); ++ if ((b = constmap(&mapbb, x, n))) { ++ if (*b) { ++ if (substdio_bput(&ssout,"T", 1) == -1) die_write(); ++ if (substdio_bputs(&ssout,b) == -1) die_write(); ++ if (substdio_bput(&ssout,"",1) == -1) die_write(); ++ } ++ } ++ if (n++ >= xlen) break; ++ x += n; xlen -= n; ++ } while (xlen > 0); ++ } ++#endif ++ + if (substdio_flush(&ssout) == -1) die_write(); + if (fsync(intdfd) == -1) die_write(); + + if (link(intdfn,todofn) == -1) die(66); + + triggerpull(); +- die(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-quotawarn.c qmail-ldap/qmail-quotawarn.c +--- qmail-1.03/qmail-quotawarn.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-quotawarn.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,423 @@ ++/* ++ * Copyright (c) 1999-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++ ++#include "auto_qmail.h" ++#include "byte.h" ++#include "case.h" ++#include "control.h" ++#include "date822fmt.h" ++#include "datetime.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "getln.h" ++#include "mailmagic.h" ++#include "myctime.h" ++#include "newfield.h" ++#include "now.h" ++#include "open.h" ++#include "qmail-ldap.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "sig.h" ++#include "str.h" ++#include "strerr.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "wait.h" ++#include "lock.h" ++ ++/* global vars */ ++stralloc warning = {0}; ++stralloc me = {0}; ++stralloc to = {0}; ++stralloc from = {0}; ++stralloc subject = {0}; ++stralloc header = {0}; ++stralloc qwline = {0}; ++stralloc temp = {0}; ++ ++#define FATAL "qmail-quotawarn: fatal: " ++#define WARN "qmail-quotawarn: warn: " ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory."); ++} ++void ++temp_qmail(char *fn) ++{ ++ strerr_die4sys(111, FATAL, "Unable to open ", fn, ": "); ++} ++void ++temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message."); ++} ++void ++temp_slowlock() ++{ ++ strerr_die2x(111, FATAL, ++ "File has been locked for 30 seconds straight. (#4.3.0)"); ++} ++ ++void check_maildir(void); ++void write_maildir(void); ++void check_mailfile(char* fn); ++void write_mailfile(char* fn); ++ ++void ++readcontrol(void) ++{ ++ int fddir; ++ ++ fddir = open_read("."); ++ if (fddir == -1) ++ strerr_die2sys(111, FATAL, "Unable to open cwd: "); ++ if (chdir(auto_qmail) == -1) ++ strerr_die4sys(111, FATAL, "Unable to switch to ", ++ auto_qmail, ": "); ++ ++ if (control_init() == -1) ++ strerr_die2sys(111, FATAL, "Unable to read controls: "); ++ if (control_readline(&me, "control/me") != 1) ++ strerr_die2sys(111, FATAL, "Unable to read control/me: "); ++ if (control_readrawfile(&warning, "control/quotawarning") == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to read control/quotawarning: "); ++ else if (warning.len == 0) ++ _exit(0); ++ ++ if (fchdir(fddir) == -1) ++ strerr_die2sys(111,FATAL,"unable to switch back to cwd: "); ++ close(fddir); ++} ++ ++int ++main(int argc, char **argv) ++{ ++ char *s; ++ char *fn; ++ ++ ++ if(!argv[1] || argv[2]) ++ strerr_die1x(100, ++ "qmail-quotawarn: usage: qmail-quotawarn mailbox."); ++ ++ fn = argv[1]; ++ ++ readcontrol(); ++ ++ if (!env_init()) temp_nomem(); ++ if (!(s = env_get("USER"))) ++ strerr_die1x(100, "UESR environment not present."); ++ if (!stralloc_copys(&qwline, "Qmail-QuotaWarning: ")) temp_nomem(); ++ if (!stralloc_cats(&qwline, s)) temp_nomem(); ++ if (!stralloc_append(&qwline, "@")) temp_nomem(); ++ if (!(s = env_get("HOST"))) ++ strerr_die1x(100, "HOST environment not present."); ++ if (!stralloc_cats(&qwline, s)) temp_nomem(); ++ if (!stralloc_append(&qwline, "\n")) temp_nomem(); ++ ++ if (fn[str_len(fn)-1] == '/') { ++ if (chdir(fn) == -1) ++ strerr_die3sys(111, "Unable to switch to ", fn, ": "); ++ check_maildir(); ++ write_maildir(); ++ } else { ++ check_mailfile(fn); ++ write_mailfile(fn); ++ } ++ /* NOTREACHED */ ++ return 1; ++} ++ ++static char timebuf[DATE822FMT]; ++ ++struct mheader mheader[] = { ++ { "From:", 0, ALLOW, 0 }, ++ { "To:", 0, FORCE, 0 }, ++ { "Subject:", "QUOTA-WARNING!\n", ALLOW, 0 }, ++ { "MIME-Version:", "1.0", FORCE, 0 }, ++ { "Content-Type:", "text/plain; charset=\"iso-8859-1\"\n", ALLOW, 0 }, ++ { "Content-Transfer-Encoding:", "8bit", ALLOW, 0 }, ++ { "X-", 0, ALLOW, 0 }, ++ { DEFAULT, 0, DENY, 0 }, ++ { 0, 0, 0, 0 } ++}; ++ ++int ++writemail(substdio *ssout, datetime_sec starttime) ++{ ++ struct datetime dt; ++ char *t; ++ int offset; ++ ++ /* store default To: From: Subject: */ ++ if (! (t = env_get("RECIPIENT"))) ++ strerr_die2x(111, FATAL, "RECIPIENT not present"); ++ mheader[1].v = t; ++ ++ if (!stralloc_copys(&from, "Qmail-QUOTAGUARD \n")) temp_nomem(); ++ if (!stralloc_0(&from)) temp_nomem(); ++ mheader[0].v = from.s; ++ ++ ++ offset = headermagic(&warning, &header, 0, mheader); ++ if (offset == -1) { ++ if (errno == error_nomem) temp_nomem(); ++ return 0; ++ } ++ ++ /* ++ * start writing header, first set: ++ * Return-Path: Delivered-to: Qmail-QuotaWarning: ++ * Received: Message-ID: Date: ++ */ ++ if (substdio_puts(ssout, "Return-Path: <>\n") == -1) return 0; ++ ++ if (!(t = env_get("DTLINE"))) ++ strerr_die2x(111, FATAL, "DTLINE not present"); ++ if (substdio_puts(ssout, t) == -1) return 0; ++ /* Qmail-QuotaWarning: line */ ++ if (substdio_put(ssout, qwline.s, qwline.len)) return 0; ++ /* Received: line */ ++ if (substdio_puts(ssout, ++ "Received: (directly through the " ++ "qmail-quotawarning program);\n\t")) ++ return 0; ++ datetime_tai(&dt, starttime); ++ if (substdio_put(ssout, timebuf, date822fmt(timebuf, &dt))) return 0; ++ ++ /* message-id and date line */ ++ if (!newfield_datemake(starttime)) temp_nomem(); ++ if (!newfield_msgidmake(me.s, me.len, starttime)) temp_nomem(); ++ if (substdio_put(ssout, newfield_msgid.s, newfield_msgid.len)) ++ return 0; ++ if (substdio_put(ssout, newfield_date.s, newfield_date.len)) ++ return 0; ++ ++ ++ /* To: From: and Subject: */ ++ if (substdio_put(ssout, header.s, header.len)) return 0; ++ /* don't forget the single \n */ ++ if (substdio_puts(ssout, "\n")) return 0; ++ /* the Warning */ ++ if (substdio_put(ssout, warning.s + offset, warning.len - offset)) ++ return 0; ++ if (warning.s[warning.len-1] == '\n') ++ if (substdio_bputs(ssout, "\n")) return 0; ++ ++ return 1; ++} ++ ++void ++check_maildir(void) ++{ ++ char const *(dirs[2]); ++ DIR *folder; ++ struct dirent *entry; ++ int i; ++ unsigned int j; ++ ++ dirs[0]="new"; dirs[1]="cur"; ++ for (i=0; i<2; i++) { ++ /* checking for old mail */ ++ if ((folder = opendir(dirs[i])) == 0) ++ strerr_die3sys(111, "Unable to opendir ", dirs[i], ": "); ++ while ((entry = readdir(folder)) != 0) { ++ if (*entry->d_name == '.') continue; ++ j = str_rchr(entry->d_name, '.'); ++ if (entry->d_name[j++] == '\0') continue; ++ if (!str_diffn("QUOTA_WARNING", &entry->d_name[j], 13)) ++ _exit(0); ++ } ++ closedir(folder); ++ } ++} ++ ++char fntmptph[80 + FMT_ULONG * 2]; ++char fnnewtph[83 + FMT_ULONG * 3]; ++void tryunlinktmp(void) { unlink(fntmptph); } ++void sigalrm(void) ++{ ++ tryunlinktmp(); ++ strerr_die1x(111, "Timeout on quota-warning delivery."); ++} ++ ++char buf[1024]; ++ ++void ++write_maildir(void) ++{ ++ char *s; ++ int loop; ++ int pid; ++ int fd; ++ datetime_sec starttime; ++ struct stat st; ++ substdio ssout; ++ ++ sig_alarmcatch(sigalrm); ++ ++ pid = getpid(); ++ starttime = now(); ++ for (loop = 0;;++loop) { ++ s = fntmptph; ++ s += fmt_str(s, "tmp/"); ++ s += fmt_ulong(s, starttime); *s++ = '.'; ++ s += fmt_ulong(s, pid); *s++ = '.'; ++ s += fmt_str(s, "QUOTA_WARNING"); ++ *s++ = 0; ++ if (stat(fntmptph, &st) == -1) if (errno == error_noent) break; ++ /* really should never get to this point */ ++ if (loop == 2) ++ strerr_die2sys(111, FATAL, "Could not stat tmp file: "); ++ sleep(2); ++ } ++ str_copy(fnnewtph, fntmptph); ++ byte_copy(fnnewtph, 3, "new"); ++ ++ alarm(86400); ++ fd = open_excl(fntmptph); ++ if (fd == -1) ++ strerr_die2sys(111, FATAL, "Unable to open tmp file: "); ++ ++ substdio_fdbuf(&ssout, subwrite, fd, buf, sizeof(buf)); ++ if (writemail(&ssout, starttime) == 0) goto fail; ++ if (substdio_flush(&ssout) == -1) goto fail; ++ ++ if (fsync(fd) == -1) goto fail; ++ if (fstat(fd, &st) == -1) goto fail; ++ if (close(fd) == -1) goto fail; /* NFS dorks */ ++ ++ s = fnnewtph; ++ while( *s ) s++; ++ s += fmt_str(s, ",S="); ++ s += fmt_ulong(s, (unsigned long) st.st_size); ++ *s++ = 0; ++ ++ if (link(fntmptph, fnnewtph) == -1) ++ /* if error_exist unlink and exit(0), ++ * strange things can happen */ ++ if ( errno != error_exist) goto fail; ++ ++ tryunlinktmp(); ++ _exit(0); ++ ++fail: ++ strerr_warn2(FATAL, "Writing Quota-Warning to maildir failed: ", ++ &strerr_sys); ++ tryunlinktmp(); ++ _exit(111); ++} ++ ++void ++check_mailfile(char* fn) ++{ ++ int fd; ++ int match; ++ substdio ss; ++ ++ fd = open_read(fn); ++ if (seek_begin(fd) == -1) temp_rewind(); ++ ++ substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf)); ++ do { ++ if(getln(&ss, &temp, &match, '\n') != 0) { ++ strerr_warn2(WARN, "Unable to read message: ", ++ &strerr_sys); ++ break; ++ } ++ if (temp.len == qwline.len) ++ if (!case_diffb(qwline.s, qwline.len, temp.s)) { ++ /* quota warning already in mailbox */ ++ close(fd); ++ _exit(0); ++ } ++ } while (match); ++ /* no quota warning found */ ++ close(fd); ++} ++ ++void ++write_mailfile(char* fn) ++{ ++ int fd; ++ substdio ssout; ++ seek_pos pos; ++ int flaglocked; ++ datetime_sec starttime; ++ ++ starttime = now(); ++ ++ fd = open_append(fn); ++ if (fd == -1) ++ strerr_die4sys(111, FATAL, "Unable to open ", fn, ": "); ++ ++ sig_alarmcatch(temp_slowlock); ++ alarm(30); ++ flaglocked = (lock_ex(fd) != -1); ++ alarm(0); ++ sig_alarmdefault(); ++ ++ seek_end(fd); ++ pos = seek_cur(fd); ++ ++ substdio_fdbuf(&ssout, subwrite, fd, buf, sizeof(buf)); ++ if (substdio_puts(&ssout, "From MAILER-DAEMON ")) goto writeerrs; ++ if (substdio_puts(&ssout, myctime(starttime))) goto writeerrs; ++ if (writemail(&ssout, starttime) == 0) goto writeerrs; ++ if (substdio_bputs(&ssout, "\n")) goto writeerrs; ++ if (substdio_flush(&ssout)) goto writeerrs; ++ if (fsync(fd) == -1) goto writeerrs; ++ close(fd); ++ _exit(0); ++ ++writeerrs: ++ strerr_warn4(FATAL, "Unable to write ", fn, ": ", &strerr_sys); ++ if (flaglocked) seek_trunc(fd, pos); ++ close(fd); ++ _exit(111); ++} ++ +diff -upN qmail-1.03/qmail-remote.c qmail-ldap/qmail-remote.c +--- qmail-1.03/qmail-remote.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-remote.c Wed Nov 3 15:53:14 2004 +@@ -1,7 +1,10 @@ + #include ++#include + #include + #include ++#include + #include ++#include + #include "sig.h" + #include "stralloc.h" + #include "substdio.h" +@@ -14,6 +17,7 @@ + #include "dns.h" + #include "alloc.h" + #include "quote.h" ++#include "fmt.h" + #include "ip.h" + #include "ipalloc.h" + #include "ipme.h" +@@ -28,65 +32,96 @@ + #include "timeoutconn.h" + #include "timeoutread.h" + #include "timeoutwrite.h" ++#include "base64.h" ++#ifdef TLS_REMOTE /* openssl/ssh.h needs to be included befor zlib.h else ... */ ++#include ++#include ++#ifdef TLSDEBUG ++#include ++#endif ++#endif ++#ifdef DATA_COMPRESS ++#include ++#endif ++ ++#ifdef TLS_REMOTE ++SSL *ssl = 0; ++#endif + + #define HUGESMTPTEXT 5000 + ++#ifndef PORT_SMTP /* this is for testing purposes, so you can overwrite it */ + #define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ +-unsigned long port = PORT_SMTP; ++#endif ++#ifndef PORT_QMTP /* this is for testing purposes, so you can overwrite it */ ++#define PORT_QMTP 209 /* silly rabbit, /etc/services is for users */ ++#endif ++unsigned long smtp_port = PORT_SMTP; ++unsigned long qmtp_port = PORT_QMTP; + + GEN_ALLOC_typedef(saa,stralloc,sa,len,a) + GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) + static stralloc sauninit = {0}; + + stralloc helohost = {0}; ++stralloc outgoingip = {0}; + stralloc routes = {0}; + struct constmap maproutes; + stralloc host = {0}; + stralloc sender = {0}; ++stralloc auth_login = {0}; ++stralloc auth_passwd = {0}; + + 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); } +-void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); } +-void outsafe(sa) stralloc *sa; { int i; char ch; ++void out(const char *s) { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } ++void zero(void) { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } ++void zerodie(void) { zero(); substdio_flush(subfdoutsmall); _exit(0); } ++void outsafe(stralloc *sa) { int i; char ch; + for (i = 0;i < sa->len;++i) { + ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; + if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } + +-void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } +-void temp_oserr() { out("Z\ ++void temp_noip(void) { out("Zinvalid ipaddr in control/outgoingip (#4.3.0)\n"); zerodie(); } ++void temp_nomem(void) { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } ++void temp_oserr(void) { out("Z\ + System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); } +-void temp_noconn() { out("Z\ ++void temp_noconn(void) { out("Z\ + Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); } +-void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } +-void temp_dnscanon() { out("Z\ ++void temp_read(void) { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } ++void temp_dnscanon(void) { out("Z\ + CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); } +-void temp_dns() { out("Z\ ++void temp_dns(void) { out("Z\ + Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie(); } +-void temp_chdir() { out("Z\ ++void temp_chdir(void) { out("Z\ + Unable to switch to home directory. (#4.3.0)\n"); zerodie(); } +-void temp_control() { out("Z\ ++void temp_control(void) { out("Z\ + Unable to read control files. (#4.3.0)\n"); zerodie(); } +-void perm_partialline() { out("D\ ++void temp_proto(void) { out("Z\ ++recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); } ++void perm_partialline(void) { out("D\ + SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); } +-void perm_usage() { out("D\ ++void perm_usage(void) { out("D\ + I (qmail-remote) was invoked improperly. (#5.3.5)\n"); zerodie(); } +-void perm_dns() { out("D\ ++void perm_dns(void) { out("D\ + Sorry, I couldn't find any host named "); + outsafe(&host); + out(". (#5.1.2)\n"); zerodie(); } +-void perm_nomx() { out("D\ ++void perm_nomx(void) { out("D\ + Sorry, I couldn't find a mail exchanger or IP address. (#5.4.4)\n"); + zerodie(); } +-void perm_ambigmx() { out("D\ ++void perm_ambigmx(void) { out("D\ + Sorry. Although I'm listed as a best-preference MX or A for that host,\n\ + it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n"); + zerodie(); } ++void perm_looping(void) { out("D\ ++Sorry. Message is looping within cluster, giving up. (#5.4.6)\n"); ++zerodie(); } + +-void outhost() ++void outhost(void) + { + char x[IPFMT]; + if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0); +@@ -94,7 +129,7 @@ void outhost() + + int flagcritical = 0; + +-void dropped() { ++void dropped(void) { + out("ZConnected to "); + outhost(); + out(" but connection died. "); +@@ -107,32 +142,174 @@ int timeoutconnect = 60; + int smtpfd; + int timeout = 1200; + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++#ifdef TLS_REMOTE ++int flagtimedout = 0; ++void sigalrm(int sig) ++{ ++ flagtimedout = 1; ++} ++int ssl_timeoutread(int tout, int fd, void *buf, int n) ++{ ++ int r; int saveerrno; ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ alarm(tout); ++ r = SSL_read(ssl,buf,n); ++ saveerrno = errno; ++ alarm(0); ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ errno = saveerrno; ++ return r; ++} ++int ssl_timeoutwrite(int tout, int fd, void *buf, int n) ++{ ++ int r; int saveerrno; ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ alarm(tout); ++ r = SSL_write(ssl,buf,n); ++ saveerrno = errno; ++ alarm(0); ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ errno = saveerrno; ++ return r; ++} ++#endif ++ ++#ifdef DATA_COMPRESS ++z_stream stream; ++char zbuf[4096]; ++int compdata = 0; ++int wantcomp = 0; ++ ++void compression_init(void) ++{ ++ compdata = 1; ++ stream.zalloc = Z_NULL; ++ stream.zfree = Z_NULL; ++ stream.opaque = Z_NULL; ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ if (deflateInit(&stream,Z_DEFAULT_COMPRESSION) != Z_OK) { ++ out("ZInitalizing data compression failed: "); ++ out(stream.msg); out(" #(4.3.0)\n"); ++ zerodie(); ++ } ++} ++void compression_done(void) ++{ ++ int r; ++ ++ compdata = 0; ++ do { ++ r = deflate(&stream,Z_FINISH); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) { ++#ifdef TLS_REMOTE ++ if (ssl) ++ r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)); ++ else ++#endif ++ r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)); ++ if (r <= 0) dropped(); ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ r = Z_OK; ++ } ++ break; ++ case Z_STREAM_END: ++ break; ++ default: ++ out("ZSending compressed data to "); outhost(); ++ out("but compression failed: "); ++ out(stream.msg); out(" (#4.4.2)\n"); ++ zerodie(); ++ } ++ } while (r!=Z_STREAM_END); ++ if (stream.avail_out != sizeof(zbuf)) { ++ /* write left data */ ++#ifdef TLS_REMOTE ++ if (ssl) ++ r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)-stream.avail_out); ++ else ++#endif ++ r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)-stream.avail_out); ++ if (r <= 0) dropped(); ++ } ++ if (deflateEnd(&stream) != Z_OK) { ++ out("ZFinishing data compression failed: "); ++ if (stream.msg) out(stream.msg); else out("unknown error"); ++ if (flagcritical) out(". Possible duplicate!"); ++ out(" #(4.3.0)\n"); ++ zerodie(); ++ } ++} ++#endif ++ ++int saferead(int fd, void *buf, int len) + { + int r; ++#ifdef TLS_REMOTE ++ if (ssl) ++ r = ssl_timeoutread(timeout,smtpfd,buf,len); ++ else ++#endif + r = timeoutread(timeout,smtpfd,buf,len); + if (r <= 0) dropped(); + return r; + } +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++int safewrite(int fd, void *buf, int len) + { + int r; ++#ifdef DATA_COMPRESS ++ if (compdata == 1) { ++ stream.avail_in = len; ++ stream.next_in = buf; ++ do { ++ r = deflate(&stream, 0); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) { ++#ifdef TLS_REMOTE ++ if (ssl) ++ r = ssl_timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)); ++ else ++#endif ++ r = timeoutwrite(timeout,smtpfd,zbuf,sizeof(zbuf)); ++ if (r <= 0) dropped(); ++ stream.avail_out = sizeof(zbuf); ++ stream.next_out = zbuf; ++ } ++ break; ++ default: ++ out("ZSending compressed data to "); outhost(); ++ out("but compression failed: "); ++ out(stream.msg); out(" (#4.4.2)\n"); ++ zerodie(); ++ } ++ } while (stream.avail_in != 0); ++ return len; ++ } ++#endif ++#ifdef TLS_REMOTE ++ if (ssl) ++ r = ssl_timeoutwrite(timeout,smtpfd,buf,len); ++ else ++#endif + r = timeoutwrite(timeout,smtpfd,buf,len); + if (r <= 0) dropped(); + return r; + } + +-char inbuf[1024]; +-substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); +-char smtptobuf[1024]; ++char inbuf[1500]; ++substdio ssin = SUBSTDIO_FDBUF(subread,0,inbuf,sizeof inbuf); ++char smtptobuf[1500]; + substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf); + char smtpfrombuf[128]; + substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf); + + stralloc smtptext = {0}; + +-void get(ch) +-char *ch; ++void get(char *ch) + { + substdio_get(&smtpfrom,ch,1); + if (*ch != '\r') +@@ -140,7 +317,7 @@ char *ch; + if (!stralloc_append(&smtptext,ch)) temp_nomem(); + } + +-unsigned long smtpcode() ++unsigned long smtpcode(void) + { + unsigned char ch; + unsigned long code; +@@ -163,9 +340,9 @@ unsigned long smtpcode() + return code; + } + +-void outsmtptext() ++void outsmtptext(void) + { +- int i; ++ unsigned int i; + if (smtptext.s) if (smtptext.len) { + out("Remote host said: "); + for (i = 0;i < smtptext.len;++i) +@@ -175,21 +352,62 @@ void outsmtptext() + } + } + +-void quit(prepend,append) +-char *prepend; +-char *append; ++void quit(const char *prepend, const char *append) + { ++#ifdef DATA_COMPRESS ++ int r; ++ char num[FMT_ULONG]; ++#endif + substdio_putsflush(&smtpto,"QUIT\r\n"); + /* waiting for remote side is just too ridiculous */ + out(prepend); + outhost(); + out(append); + out(".\n"); ++#ifdef DATA_COMPRESS ++ if (wantcomp == 2) { ++ r = 100 - (int)(100.0*stream.total_out/stream.total_in); ++ if (r < 0) { ++ num[0] = '-'; r*= -1; ++ } else ++ num[0] = ' '; ++ num[fmt_uint(num+1,r) + 1] = 0; ++ out("DDC saved "); ++ out(num); out(" percent.\n"); ++ } ++#endif ++/* TAG */ ++#if defined(TLS_REMOTE) && defined(TLSDEBUG) ++#define ONELINE_NAME(X) X509_NAME_oneline(X,NULL,0) ++ ++ if (ssl) { ++ X509 *peer; ++ ++ out("STARTTLS proto="); out(SSL_get_version(ssl)); ++ out("; cipher="); out(SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); ++ ++ /* we want certificate details */ ++ peer=SSL_get_peer_certificate(ssl); ++ if (peer != NULL) { ++ char *str; ++ ++ str=ONELINE_NAME(X509_get_subject_name(peer)); ++ out("; subject="); out(str); ++ OPENSSL_free(str); ++ str=ONELINE_NAME(X509_get_issuer_name(peer)); ++ out("; issuer="); out(str); ++ OPENSSL_free(str); ++ X509_free(peer); ++ } ++ out(";\n"); ++ } ++#endif ++ + outsmtptext(); + zerodie(); + } + +-void blast() ++void blast(void) + { + int r; + char ch; +@@ -214,25 +432,218 @@ void blast() + substdio_flush(&smtpto); + } + ++stralloc cookie = {0}; + stralloc recip = {0}; ++#ifdef TLS_REMOTE ++stralloc sslcert = {0}; ++#endif + +-void smtp() ++void smtp(void) + { ++ struct stat st; ++ unsigned long len; + unsigned long code; + int flagbother; +- int i; +- +- if (smtpcode() != 220) quit("ZConnected to "," but greeting failed"); +- +- substdio_puts(&smtpto,"HELO "); ++ int flagsize; ++ int flagauth; ++ unsigned int i, j; ++ char num[FMT_ULONG]; ++#ifdef TLS_REMOTE ++ int flagtls; ++ SSL_CTX *ctx; ++ int saveerrno, r; ++#ifdef TLSDEBUG ++ char buf[1024]; ++#endif ++ ++ flagtls = 0; ++#endif ++ ++ code = smtpcode(); ++ if (code >= 500) quit("DConnected to "," but greeting failed"); ++ if (code >= 400) return; ++ if (code != 220) quit("ZConnected to "," but greeting failed"); ++ ++ if (cookie.len > 0) ++ if (smtptext.len > cookie.len + 1) ++ if (!str_diffn(smtptext.s + smtptext.len - cookie.len - 1, ++ cookie.s, cookie.len)) ++ perm_looping(); ++ ++ flagsize = 0; ++ flagauth = 0; ++ substdio_puts(&smtpto,"EHLO "); + 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 != 250) { ++ substdio_puts(&smtpto,"HELO "); ++ substdio_put(&smtpto,helohost.s,helohost.len); ++ substdio_puts(&smtpto,"\r\n"); ++ substdio_flush(&smtpto); ++ code = smtpcode(); ++ if (code >= 500) quit("DConnected to "," but my name was rejected"); ++ if (code >= 400) return; ++ if (code != 250) quit("ZConnected to "," but my name was rejected"); ++ } ++ ++ /* extension handling */ ++ for (i = 0; i < smtptext.len; i += str_chr(smtptext.s+i,'\n') + 1) { ++ if (i+8 < smtptext.len && !case_diffb("SIZE", 4, smtptext.s+i+4) ) ++ flagsize = 1; ++#ifdef DATA_COMPRESS ++ else if (i+9 < smtptext.len && !case_diffb("DATAZ", 5, smtptext.s+i+4)) ++ wantcomp = 1; ++#endif ++#ifdef TLS_REMOTE ++ else if (i+12 < smtptext.len && !case_diffb("STARTTLS", 8, smtptext.s+i+4)) ++ flagtls = 1; ++#endif ++ else if (i+9 < smtptext.len && !case_diffb("AUTH ", 5, smtptext.s+i+4)) { ++ for (j = i+4; j < smtptext.len; j++) ++ if (j == ' ') ++ if (j + 6 < smtptext.len && !case_diffb("LOGIN", 5, smtptext.s+j+1)) ++ flagauth = 1; ++ } ++ } ++ ++#ifdef TLS_REMOTE ++ if (flagtls) { ++ substdio_puts(&smtpto,"STARTTLS\r\n"); ++ substdio_flush(&smtpto); ++ if (smtpcode() == 220) { ++#ifdef TLSDEBUG ++ SSL_load_error_strings(); ++#endif ++ SSLeay_add_ssl_algorithms(); ++ if (!(ctx=SSL_CTX_new(SSLv23_client_method()))) { ++#ifdef TLSDEBUG ++ out("ZTLS not available: error initializing ctx"); ++ out(": "); ++ out(ERR_error_string(ERR_get_error(), buf)); ++ out("\n"); ++#else ++ out("ZTLS not available: error initializing ctx\n"); ++#endif ++ out("\n"); ++ zerodie(); ++ } ++ ++ if (sslcert.s && *sslcert.s) { ++ SSL_CTX_use_RSAPrivateKey_file(ctx, sslcert.s, SSL_FILETYPE_PEM); ++ SSL_CTX_use_certificate_file(ctx, sslcert.s, SSL_FILETYPE_PEM); ++ } ++ /*SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);*/ ++ ++ if (!(ssl=SSL_new(ctx))) { ++#ifdef TLSDEBUG ++ out("ZTLS not available: error initializing ssl"); ++ out(": "); ++ out(ERR_error_string(ERR_get_error(), buf)); ++#else ++ out("ZTLS not available: error initializing ssl"); ++#endif ++ out("\n"); ++ zerodie(); ++ } ++ SSL_set_fd(ssl,smtpfd); ++ ++ alarm(timeout); ++ r = SSL_connect(ssl); saveerrno = errno; ++ alarm(0); ++ if (flagtimedout) { ++ out("ZTLS not available: connect timed out\n"); ++ zerodie(); ++ } ++ errno = saveerrno; ++ if (r<=0) { ++#ifdef TLSDEBUG ++ out("ZTLS not available: connect failed"); ++ out(": "); ++ out(ERR_error_string(ERR_get_error(), buf)); ++ out("\n"); ++#else ++ out("ZTLS not available: connect failed\n"); ++#endif ++ zerodie(); ++ } ++ ++ /* re-EHLO as per RFC */ ++ substdio_puts(&smtpto,"EHLO "); ++ substdio_put(&smtpto,helohost.s,helohost.len); ++ substdio_puts(&smtpto,"\r\n"); ++ substdio_flush(&smtpto); ++ ++ if (smtpcode() != 250) { ++ quit("ZTLS connected to "," but my name was rejected"); ++ } ++ ++ /* extension handling */ ++ for (i = 0; i < smtptext.len; i += str_chr(smtptext.s+i,'\n') + 1) { ++ if (i+8 < smtptext.len && !case_diffb("SIZE", 4, smtptext.s+i+4) ) ++ flagsize = 1; ++#ifdef DATA_COMPRESS ++ else if (i+9 < smtptext.len && !case_diffb("DATAZ", 5, smtptext.s+i+4)) ++ wantcomp = 1; ++#endif ++ else if (i+9 < smtptext.len && ++ !case_diffb("AUTH ", 5, smtptext.s+i+4)) { ++ for (j = i+4; j < smtptext.len; j++) ++ if (smtptext.s[j] == ' ') ++ if (j + 6 < smtptext.len && ++ !case_diffb("LOGIN", 5, smtptext.s+j+1)) ++ flagauth = 1; ++ } ++ } ++ } ++ } ++#endif ++ ++ if (flagauth && auth_login.len && auth_passwd.len) { ++ substdio_putsflush(&smtpto,"AUTH LOGIN\r\n"); ++ code = smtpcode(); ++ if (code >= 500) ++ quit("DConnected to "," but authentication was rejected (AUTH LOGIN)"); ++ if (code >= 400) ++ quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)"); ++ ++ substdio_put(&smtpto,auth_login.s,auth_login.len); ++ substdio_putsflush(&smtpto,"\r\n"); ++ code = smtpcode(); ++ if (code >= 500) ++ quit("DConnected to "," but authentication was rejected (username)"); ++ if (code >= 400) ++ quit("ZConnected to "," but authentication was rejected (username)"); ++ ++ substdio_put(&smtpto,auth_passwd.s,auth_passwd.len); ++ substdio_putsflush(&smtpto,"\r\n"); ++ code = smtpcode(); ++ if (code >= 500) ++ quit("DConnected to "," but authentication was rejected (password)"); ++ if (code >= 400) ++ quit("ZConnected to "," but authentication was rejected (password)"); ++ } else if (auth_login.len && auth_passwd.len) { ++ quit("ZConnected to "," but no SMTP AUTH support detected but needed."); ++ } ++ + substdio_puts(&smtpto,"MAIL FROM:<"); + substdio_put(&smtpto,sender.s,sender.len); +- substdio_puts(&smtpto,">\r\n"); ++ substdio_puts(&smtpto,">"); ++ if (flagsize) { ++ substdio_puts(&smtpto," SIZE="); ++ if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin"); ++ len = st.st_size; ++ len += len>>5; /* add some size for the \r chars see rcf 1870 */ ++ substdio_put(&smtpto,num,fmt_ulong(num,len+1)); ++ } ++ if (flagauth && auth_login.len && auth_passwd.len) { ++ substdio_puts(&smtpto, " AUTH=<"); ++ substdio_put(&smtpto,sender.s,sender.len); ++ substdio_puts(&smtpto,">"); ++ } ++ substdio_puts(&smtpto,"\r\n"); + substdio_flush(&smtpto); + code = smtpcode(); + if (code >= 500) quit("DConnected to "," but sender was rejected"); +@@ -260,19 +671,147 @@ void smtp() + } + if (!flagbother) quit("DGiving up on ",""); + ++#ifdef DATA_COMPRESS ++ if (wantcomp == 1) { ++ substdio_putsflush(&smtpto,"DATAZ\r\n"); ++ compression_init(); ++ } else ++#endif + substdio_putsflush(&smtpto,"DATA\r\n"); + code = smtpcode(); ++#ifdef DATA_COMPRESS ++ if (wantcomp == 1) { ++ if (code >= 500) quit("D"," failed on DATAZ command"); ++ if (code >= 400) quit("Z"," failed on DATAZ command"); ++ } else { ++#endif + if (code >= 500) quit("D"," failed on DATA command"); + if (code >= 400) quit("Z"," failed on DATA command"); ++#ifdef DATA_COMPRESS ++ } ++#endif + + blast(); ++#ifdef DATA_COMPRESS ++ if (wantcomp == 1) ++ compression_done(); ++#endif + code = smtpcode(); + flagcritical = 0; + if (code >= 500) quit("D"," failed after I sent the message"); + if (code >= 400) quit("Z"," failed after I sent the message"); ++#ifdef DATA_COMPRESS ++ wantcomp++; ++#endif + quit("K"," accepted message"); + } + ++int qmtp_priority(int pref) ++{ ++ if (pref < 12800) return 0; ++ if (pref > 13055) return 0; ++ if (pref % 16 == 1) return 1; ++ return 0; ++} ++ ++void qmtp(void) ++{ ++ struct stat st; ++ unsigned long len; ++ char *x; ++ unsigned int i; ++ int n; ++ unsigned char ch; ++ unsigned char rv; ++ char num[FMT_ULONG]; ++ int flagbother; ++ ++ if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin"); ++ len = st.st_size; ++ ++ /* the following code was substantially taken from serialmail's serialqmtp.c */ ++ substdio_put(&smtpto,num,fmt_ulong(num,len+1)); ++ substdio_put(&smtpto,":\n",2); ++ while (len > 0) { ++ n = substdio_feed(&ssin); ++ if (n <= 0) temp_read(); /* wise guy again */ ++ x = substdio_PEEK(&ssin); ++ substdio_put(&smtpto,x,n); ++ substdio_SEEK(&ssin,n); ++ len -= n; ++ } ++ substdio_put(&smtpto,",",1); ++ ++ len = sender.len; ++ substdio_put(&smtpto,num,fmt_ulong(num,len)); ++ substdio_put(&smtpto,":",1); ++ substdio_put(&smtpto,sender.s,sender.len); ++ substdio_put(&smtpto,",",1); ++ ++ len = 0; ++ for (i = 0;i < reciplist.len;++i) ++ len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1; ++ substdio_put(&smtpto,num,fmt_ulong(num,len)); ++ substdio_put(&smtpto,":",1); ++ for (i = 0;i < reciplist.len;++i) { ++ substdio_put(&smtpto,num,fmt_ulong(num,reciplist.sa[i].len)); ++ substdio_put(&smtpto,":",1); ++ substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); ++ substdio_put(&smtpto,",",1); ++ } ++ substdio_put(&smtpto,",",1); ++ substdio_flush(&smtpto); ++ ++ flagbother = 0; ++ ++ for (i = 0;i < reciplist.len;++i) { ++ len = 0; ++ for (;;) { ++ get(&ch); ++ if (ch == ':') break; ++ if (len > 200000000) temp_proto(); ++ if (ch - '0' > 9) temp_proto(); ++ len = 10 * len + (ch - '0'); ++ } ++ if (!len) temp_proto(); ++ get(&ch); --len; ++ if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto(); ++ ++ rv = ch; ++ if (!stralloc_copys(&smtptext,"qmtp: ")) temp_nomem(); ++ ++ /* read message */ ++ while (len > 0) { ++ get(&ch); ++ --len; ++ } ++ get(&ch); ++ if (ch != ',') temp_proto(); ++ smtptext.s[smtptext.len-1] = '\n'; ++ ++ switch (rv) { ++ case 'K': ++ out("r"); zero(); ++ flagbother = 1; ++ break; ++ case 'D': ++ out("h"); outhost(); out(" does not like recipient.\n"); ++ outsmtptext(); zero(); ++ break; ++ case 'Z': ++ out("h"); outhost(); out(" does not like recipient.\n"); ++ outsmtptext(); zero(); ++ break; ++ } ++ } ++ if (!flagbother) { ++ out("DGiving up on "); outhost(); out(".\n"); outsmtptext(); ++ } else { ++ out("K");outhost();out(" accepted message.\n"); outsmtptext(); ++ } ++ zerodie(); ++} ++ + stralloc canonhost = {0}; + stralloc canonbox = {0}; + +@@ -282,7 +821,7 @@ char *s; + int *flagalias; + int flagcname; + { +- int j; ++ unsigned int j; + + *flagalias = flagcname; + +@@ -308,9 +847,12 @@ int flagcname; + if (!stralloc_cat(saout,&canonhost)) temp_nomem(); + } + +-void getcontrols() ++void getcontrols(void) + { + if (control_init() == -1) temp_control(); ++ if (control_rldef(&cookie,"control/smtpclustercookie",0,"") == -1) ++ temp_control(); ++ if (cookie.len > 32) cookie.len = 32; + if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control(); + if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) + temp_control(); +@@ -324,21 +866,33 @@ void getcontrols() + case 1: + if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; + } ++ if (control_rldef(&outgoingip, "control/outgoingip", 0, "0.0.0.0") == -1) ++ temp_control(); ++ if (!stralloc_0(&outgoingip)) temp_nomem(); ++ if (!ip_scan(outgoingip.s, &outip)) temp_noip(); ++ ++#ifdef TLS_REMOTE ++ if (control_readline(&sslcert, "control/remotecert") == -1) ++ temp_control(); ++ if (!stralloc_0(&sslcert)) temp_nomem(); ++#endif ++ + } + +-void main(argc,argv) +-int argc; +-char **argv; ++int main(int argc, char **argv) + { + static ipalloc ip = {0}; +- int i; +- unsigned long random; ++ unsigned int i, j; ++ unsigned long randm; + char **recips; + unsigned long prefme; + int flagallaliases; + int flagalias; +- char *relayhost; +- ++ const char *relayhost; ++ ++#ifdef TLS_REMOTE ++ sig_alarmcatch(sigalrm); ++#endif + sig_pipeignore(); + if (argc < 4) perm_usage(); + if (chdir(auto_qmail) == -1) temp_chdir(); +@@ -346,21 +900,33 @@ char **argv; + + + if (!stralloc_copys(&host,argv[1])) temp_nomem(); ++ if (!stralloc_copys(&auth_login, "")) temp_nomem(); ++ if (!stralloc_copys(&auth_passwd, "")) temp_nomem(); + + relayhost = 0; + for (i = 0;i <= host.len;++i) + if ((i == 0) || (i == host.len) || (host.s[i] == '.')) +- if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) ++ if ((relayhost = constmap(&maproutes,host.s + i,host.len - i))) + break; + if (relayhost && !*relayhost) relayhost = 0; + + if (relayhost) { +- i = str_chr(relayhost,':'); +- if (relayhost[i]) { +- scan_ulong(relayhost + i + 1,&port); +- relayhost[i] = 0; ++ j = str_chr(relayhost,' '); ++ if (relayhost[j]) { ++ i = str_chr(relayhost + j + 1,' '); ++ if (relayhost[i]) { ++ if (b64_ntops(relayhost + j + 1, i, &auth_login) == -1) ++ temp_nomem(); ++ if (b64_ntops(relayhost + j + i + 2, str_len(relayhost + j + i + 2), ++ &auth_passwd)) ++ temp_nomem(); ++ } + } +- if (!stralloc_copys(&host,relayhost)) temp_nomem(); ++ i = str_chr(relayhost,':'); ++ if (relayhost[i]) ++ scan_ulong(relayhost + i + 1,&smtp_port); ++ if (i > j) i = j; ++ if (!stralloc_copyb(&host,relayhost, i)) temp_nomem(); + } + + +@@ -381,8 +947,8 @@ char **argv; + } + + +- random = now() + (getpid() << 16); +- switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { ++ randm = now() + (getpid() << 16); ++ switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,randm)) { + case DNS_MEM: temp_nomem(); + case DNS_SOFT: temp_dns(); + case DNS_HARD: perm_dns(); +@@ -413,15 +979,28 @@ char **argv; + + 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 (qmtp_priority(ip.ix[i].pref)) { ++ if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) qmtp_port,timeoutconnect) == 0) { ++ tcpto_err(&ip.ix[i].ip,0); ++ partner = ip.ix[i].ip; ++ qmtp(); /* does not return */ ++ } ++ close(smtpfd); ++ smtpfd = socket(AF_INET,SOCK_STREAM,0); ++ if (smtpfd == -1) temp_oserr(); ++ } ++ if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) smtp_port,timeoutconnect) == 0) { + tcpto_err(&ip.ix[i].ip,0); + partner = ip.ix[i].ip; +- smtp(); /* does not return */ ++ smtp(); /* should not return unless the start code or the HELO code ++ returns a temporary failure. */ + } + tcpto_err(&ip.ix[i].ip,errno == error_timeout); + close(smtpfd); + } + + temp_noconn(); ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/qmail-reply.c qmail-ldap/qmail-reply.c +--- qmail-1.03/qmail-reply.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-reply.c Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,843 @@ ++/* ++ * Copyright (c) 1999-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include "base64.h" ++#include "byte.h" ++#include "case.h" ++#include "control.h" ++#include "constmap.h" ++#include "digest_md5.h" ++#include "direntry.h" ++#include "env.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "getln.h" ++#include "mailmagic.h" ++#include "newfield.h" ++#include "now.h" ++#include "open.h" ++#include "qmail.h" ++#include "qmail-ldap.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "sgetopt.h" ++#include "sig.h" ++#include "str.h" ++#include "strerr.h" ++#include "stralloc.h" ++#include "substdio.h" ++ ++#define FATAL "qmail-reply: fatal: " ++#define WARN "qmail-reply: warn: " ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory."); ++} ++void ++temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message."); ++} ++void ++temp_fork(void) ++{ ++ strerr_die2sys(111, FATAL, "Unable to fork: "); ++} ++ ++void usage(void) ++{ ++ strerr_die1x(100, ++ "qmail-reply: usage: qmail-reply [-f mailfile] [-j junkfile] " ++ "[maildir]"); ++} ++ ++stralloc replytext = {0}; ++stralloc hashed = {0}; ++ ++void hashreplytext(void) ++{ ++ MD5_CTX ctx; ++ unsigned char buffer[MD5_LEN]; ++ ++ MD5Init(&ctx); ++ MD5Update(&ctx, replytext.s, replytext.len); ++ MD5Final(buffer,&ctx); ++ ++ if (hex_ntops(buffer, sizeof(buffer), &hashed) == -1) temp_nomem(); ++ if (!stralloc_0(&hashed) == -1) temp_nomem(); ++} ++ ++void envmail(void) ++{ ++ char *s; ++ ++ if ((s = env_get(ENV_REPLYTEXT))) { ++ if (!stralloc_copys(&replytext, s)) temp_nomem(); ++ } else { ++ strerr_die3x(100, FATAL, ENV_REPLYTEXT, ++ " not present."); ++ } ++ hashreplytext(); ++} ++ ++char buffer[1024]; ++stralloc line = {0}; ++ ++void readmail(char *file) ++{ ++ substdio ss; ++ int fd; ++ int match; ++ ++ if (!stralloc_copys(&replytext, "")) temp_nomem(); ++ ++ fd = open_read(file); ++ if (fd == -1) ++ strerr_die4sys(100, FATAL, "Unable to open '", file, "': "); ++ ++ substdio_fdbuf(&ss, subread, fd, buffer, sizeof(buffer)); ++ for (;;) { ++ if (getln(&ss, &line, &match, '\n') == -1) ++ strerr_die4sys(100, FATAL, "Unable to read '", ++ file, "': "); ++ if (!match) { ++ close(fd); ++ return; ++ } ++ if (!stralloc_cat(&replytext, &line)) temp_nomem(); ++ } ++ hashreplytext(); ++} ++ ++stralloc to={0}; ++stralloc from={0}; ++stralloc host={0}; ++stralloc dtline={0}; ++ ++void get_env(void) ++{ ++ char *s; ++ unsigned int i; ++ ++ if ((s = env_get("DTLINE")) == (char *)0) ++ strerr_die2x(100, FATAL, "Environment DTLINE not present."); ++ if (!stralloc_copys(&dtline, s)) temp_nomem(); ++ ++ if ((s = env_get("SENDER")) == (char *)0) ++ strerr_die2x(100, FATAL, "Environment SENDER not present."); ++ if (!stralloc_copys(&to, s)) temp_nomem(); ++ ++ if ((s = env_get("RECIPIENT")) == (char *)0) ++ strerr_die2x(100, FATAL, "Environment RECIPIENT not present."); ++ if (!stralloc_copys(&from, s)) temp_nomem(); ++ ++ i = byte_chr(from.s, from.len, '@'); ++ if (i == 0 || i >= from.len) ++ strerr_die2x(100, FATAL, "Bad RECIPIENT address."); ++ ++ if (!(s = env_get("HOST"))) ++ strerr_die2x(100, FATAL, "Environment HOST not present."); ++ if (!stralloc_copys(&host, s)) temp_nomem(); ++} ++ ++stralloc junkfrom={0}; ++struct constmap mapjunk; ++ ++void junkread(char *path) ++{ ++ if (control_readfile(&junkfrom, path, 0) != 1) ++ strerr_die4sys(100, FATAL, "Unable to read '", path, "': "); ++} ++ ++int junksender(char *addr, int len) ++{ ++ unsigned int at, dash, i; ++ static const char *(junkignore[]) = { ++ /* don't reply to bots */ ++ "-request", ++ "daemon", ++ "-daemon", ++ "uucp", ++ "mailer-daemon", ++ "mailer", ++ /* don't bother admins */ ++ "postmaster", ++ "root", ++ /* from vacation(1) */ ++ "-relay", ++ 0 } ; ++ /* TODO support for -return- dash extensions */ ++ ++ for (i = 0; junkignore[i] != 0; i++) { ++ if (!stralloc_cats(&junkfrom, junkignore[i])) temp_nomem(); ++ if (!stralloc_0(&junkfrom)) temp_nomem(); ++ } ++ ++ if (!constmap_init(&mapjunk, junkfrom.s, junkfrom.len, 0)) ++ strerr_die2sys(111, FATAL, "Constmap_init: "); ++ ++ at = byte_rchr(addr, len, '@'); ++ if (at >= len) ++ strerr_die2x(111, FATAL, "Bad SENDER address."); ++ ++ /* ++ 1. user@host ++ 2. user ++ 3. @host ++ 4. -part ++ */ ++ if (constmap(&mapjunk, addr, len)) return 1; ++ if (constmap(&mapjunk, addr, at)) return 1; ++ if (constmap(&mapjunk, addr+at, len-at)) return 1; ++ ++ for (dash = 0; dash < at; dash++) { ++ dash += byte_chr(addr+dash, at-dash, '-'); ++ if (constmap(&mapjunk, addr+dash, at-dash)) return 1; ++ } ++ return 0; ++} ++ ++datetime_sec get_stamp(char const *hex) ++{ ++ unsigned long t; ++ unsigned char c; ++ ++ t = 0; ++ while((c = *hex++)) { ++ if (c >= '0' && c <= '9') ++ c -= '0'; ++ else if (c >= 'a') ++ c -= ('a' - 10); ++ else ++ c -= ('A' - 10); ++ if (c > 15) ++ break; ++ t = (t<<4) + c; ++ } ++ ++ return (datetime_sec) t; ++} ++ ++char* stamp(datetime_sec tm) ++{ ++ static char stampbuf[10]; ++ static const char* digit = "0123456789abcdef"; ++ char *s; ++ unsigned long t; ++ ++ t = (unsigned long) tm; ++ s = stampbuf; ++ *s++ = ':'; ++ *s++ = digit[(t >> 28) & 0x0f]; ++ *s++ = digit[(t >> 24) & 0x0f]; ++ *s++ = digit[(t >> 20) & 0x0f]; ++ *s++ = digit[(t >> 16) & 0x0f]; ++ *s++ = digit[(t >> 12) & 0x0f]; ++ *s++ = digit[(t >> 8) & 0x0f]; ++ *s++ = digit[(t >> 4) & 0x0f]; ++ *s++ = digit[ t & 0x0f]; ++ *s = '\0'; ++ return stampbuf; ++} ++ ++stralloc rs = {0}; /* recent sender */ ++datetime_sec timeout; ++#ifndef REPLY_TIMEOUT ++#define REPLY_TIMEOUT 1209600 /* 2 weeks */ ++#endif ++#define MAX_SIZE (128 * 1024) /* 128kB space for recent sender db */ ++ ++int checkstamp(char *, unsigned int); ++ ++int recent_lookup(char *buf, unsigned int len) ++{ ++ char *s; ++ datetime_sec last; ++ unsigned int i, slen; ++ ++ switch (control_readfile(&rs,"qmail-reply.db",1)) { ++ case 1: ++ break; ++ case 0: ++ goto done; ++ default: ++ strerr_die2sys(111, FATAL, ++ "Read database file failed: "); ++ } ++ ++ slen = rs.len; s = rs.s; ++ if (!case_startb(s, slen, "QRDBv1:")) goto done; ++ s += 7; slen -= 7; ++ if (slen < hashed.len || case_diffb(s, hashed.len, hashed.s) != 0) ++ return 0; ++ s += hashed.len; slen -= hashed.len; ++ ++ for (i = 0; i < slen; i += str_len(s+i) + 1) { ++ if (case_diffb(buf, len, s+i) == 0) { ++ /* match found, look at timeval */ ++ i += len; ++ if (s[i++] != ':') { ++ strerr_warn2(WARN, ++ "Database file corrupted", 0); ++ unlink("qmail-reply.db"); ++ stralloc_copys(&rs, ""); ++ return 0; ++ } ++ last = get_stamp(s+i); ++ if (last + timeout < now()) goto done; ++ else return 1; ++ } ++ } ++done: ++ return checkstamp(buf, len); ++} ++ ++int trylock(void) ++{ ++ struct stat st; ++ int fd; ++ ++retry: ++ if ((fd = open_excl("qmail-reply.lock")) == -1) { ++ if (errno == error_exist) { ++ if (stat("qmail-reply.lock", &st) == -1) { ++ strerr_warn2(WARN, "Unable to stat lock: ", ++ &strerr_sys); ++ return -1; ++ } ++ /* ... should never get to this point */ ++ if (st.st_mtime + 900 < now()) { ++ /* stale lock file */ ++ if (unlink("qmail-reply.lock") == -1) { ++ strerr_warn2(WARN, ++ "Unable to unlink lock: ", ++ &strerr_sys); ++ return -1; ++ } ++ goto retry; ++ } ++ return 0; ++ } ++ strerr_warn2(WARN, "Unable to get lock: ", &strerr_sys); ++ return -1; ++ } ++ close(fd); ++ return 1; ++} ++ ++void unlock(void) ++{ ++ if (unlink("qmail-reply.lock") == -1) ++ strerr_warn2(WARN, "Unable to unlock: ", &strerr_sys); ++} ++ ++stralloc sfs = {0}; ++stralloc spath = {0}; ++ ++int checkstamp(char *buf, unsigned int len) ++{ ++ struct stat st; ++ ++ if (!stralloc_copys(&spath, "tmp/@") || ++ !stralloc_catb(&spath, buf, len) || ++ !stralloc_0(&spath)) temp_nomem(); ++ if (stat(spath.s,&st) == -1) { ++ if (errno == error_noent) return 0; ++ strerr_warn4(WARN, "Can't stat stamp file: ", ++ spath.s, ": ", &strerr_sys); ++ return 0; ++ } ++ if (st.st_mtime + timeout < now()) return 0; ++ return 1; ++} ++ ++void addstamps(void) ++{ ++ DIR *dir; ++ direntry *d; ++ struct stat st; ++ ++ if (!stralloc_copys(&sfs, "")) { ++ strerr_warn2(WARN, "Out of memory.", 0); ++ return; ++ } ++ dir = opendir("tmp"); ++ if (!dir) { ++ strerr_warn2(WARN, "Unable to opendir ./tmp: ", &strerr_sys); ++ return; ++ } ++ while ((d = readdir(dir))) { ++ if (d->d_name[0] != '@') continue; ++ /* this is a possible stamp file */ ++ if (d->d_name[str_chr(d->d_name+1, '@')+1] != '@') { ++ strerr_warn3(WARN, "Strange stamp file: ", ++ d->d_name, 0); ++ continue; ++ } ++ if (!stralloc_copys(&spath, "tmp/") || ++ !stralloc_cats(&spath, d->d_name) || ++ !stralloc_0(&spath)) break; ++ if (stat(spath.s,&st) == -1) { ++ strerr_warn4(WARN, "Can't stat stamp file: ", ++ d->d_name, ": ", &strerr_sys); ++ continue; ++ } ++ if (!stralloc_cat(&sfs, &spath)) break; ++ if (!stralloc_cats(&rs, d->d_name+1) || ++ !stralloc_cats(&rs, stamp(st.st_mtime)) || ++ !stralloc_0(&rs)) break; ++ } ++ closedir(dir); ++ if (d) strerr_warn2(WARN, "Out of memory.", 0); ++} ++ ++void deletestamps(void) ++{ ++ unsigned int i; ++ char *s; ++ ++ s = sfs.s; ++ for(i = 0; i < sfs.len; i += str_len(s+i) + 1) { ++ unlink(s + i); ++ } ++} ++ ++char rsoutbuf[SUBSTDIO_OUTSIZE]; ++char fntmptph[32 + 2*FMT_ULONG]; ++ ++void sigalrm(void) ++{ ++ unlink(fntmptph); ++ unlock(); ++ strerr_die2x(111, FATAL, "Timeout while writing db file"); ++} ++ ++void recent_update(char *buf, unsigned int len) ++{ ++ struct stat st; ++ substdio ss; ++ char *s, *t; ++ datetime_sec tm, last; ++ unsigned long pid; ++ unsigned int slen, i, n; ++ int fd, loop; ++ ++ addstamps(); ++ ++ /* first limit database length to MAX_SIZE */ ++ s = rs.s; slen = rs.len; ++ /* hop over possible header */ ++ if (case_startb(s, slen, "QRDBv1:")) { ++ i = str_len(s); ++ slen -= i; ++ s += i; ++ } ++ for(; slen > MAX_SIZE; ) { ++ i = str_len(s) + 1; ++ slen -= i; ++ s += i; ++ } ++ ++ /* optain a temp file */ ++ pid = getpid(); ++ for (loop = 0;;++loop) { ++ tm = now(); ++ t = fntmptph; ++ t += fmt_str(t, "tmp/qmail-reply."); ++ t += fmt_ulong(t, pid); *t++ = '.'; ++ t += fmt_ulong(t, tm); *t++ = 0; ++ ++ if (stat(fntmptph, &st) == -1) if (errno == error_noent) break; ++ /* ... should never get to this point */ ++ if (loop == 2) { ++ strerr_warn2(WARN, "Could not stat tmp file:", ++ &strerr_sys); ++ return; ++ } ++ sleep(2); ++ } ++ ++ sig_alarmcatch(sigalrm); ++ alarm(600); /* give up after 10 min */ ++ fd = open_excl(fntmptph); ++ if (fd == -1) { ++ strerr_warn2(WARN, "Unable to open tmp file: ", &strerr_sys); ++ return; ++ } ++ ++ substdio_fdbuf(&ss, subwrite, fd, rsoutbuf, sizeof(rsoutbuf)); ++ ++ if (substdio_puts(&ss, "QRDBv1:") == -1) goto fail; ++ if (substdio_puts(&ss, hashed.s) == -1) goto fail; ++ if (substdio_put(&ss, "\n", 1) == -1) goto fail; ++ ++ /* dump database */ ++ for (i = 0; i < slen; i += str_len(s+i) + 1) { ++ n = byte_chr(s+i, slen, ':'); ++ if (n++ < slen) { ++ last = get_stamp(s + i + n); ++ if (last + timeout < tm) continue; ++ } else goto fail; /* database corrupted */ ++ if (substdio_puts(&ss, s+i) == -1) goto fail; ++ if (substdio_put(&ss, "\n", 1) == -1) goto fail; ++ } ++ if (substdio_flush(&ss) == -1) goto fail; ++ if (fsync(fd) == -1) goto fail; ++ if (close(fd) == -1) goto fail; /* NFS dorks */ ++ ++ if (unlink("qmail-reply.db") == -1 && errno != error_noent) goto fail; ++ if (link(fntmptph, "qmail-reply.db") == -1) goto fail; ++ /* if it was error_exist, almost certainly successful; i hate NFS */ ++ ++ unlink(fntmptph); ++ deletestamps(); ++ sig_alarmdefault(); ++ return; ++ ++fail: ++ strerr_warn2(WARN, "Database update failed: ", &strerr_sys); ++ unlink(fntmptph); ++ sig_alarmdefault(); ++ return; ++} ++ ++void touchstamp(char *buf, unsigned int len) ++{ ++ int fd; ++ ++ if (!stralloc_copys(&sfs, "tmp/@")) temp_nomem(); ++ if (!stralloc_catb(&sfs, buf, len)) temp_nomem(); ++ if (!stralloc_0(&sfs)) temp_nomem(); ++ ++ if ((fd = open_trunc(sfs.s)) == -1) ++ strerr_warn4(WARN, "Unable to create stamp ", ++ sfs.s, ": ", &strerr_sys); ++ close(fd); ++} ++ ++int recent(char *buf, unsigned int len, char *dir) ++{ ++ if (dir == 0) return 0; ++ ++ if (chdir(dir) == -1) { ++ strerr_warn4(WARN, "Unable to switch to ", dir, ": ", ++ &strerr_sys); ++ return 0; ++ } ++ ++ switch (trylock()) { ++ case 0: ++ if (recent_lookup(buf, len) == 1) ++ return 1; ++ /* touch stamp file */ ++ touchstamp(buf, len); ++ return 0; ++ case 1: ++ if (recent_lookup(buf, len) == 1) { ++ unlock(); ++ return 1; ++ } ++ touchstamp(buf, len); ++ recent_update(buf, len); ++ unlock(); ++ return 0; ++ default: ++ /* warning print in trylock() */ ++ return 0; ++ } ++} ++ ++unsigned int getfield(char *s, unsigned int len) ++{ ++ unsigned int l; ++ ++ l = len; ++ for(;;) { ++ if (l-- == 0) break; if (*s++ == ':') break; ++ if (l-- == 0) break; if (*s++ == ':') break; ++ if (l-- == 0) break; if (*s++ == ':') break; ++ if (l-- == 0) break; if (*s++ == ':') break; ++ } ++ for(;;) { ++ if (l == 0) break; if (*s != ' ' && *s != '\t') break; ++ l--; s++; ++ if (l == 0) break; if (*s != ' ' && *s != '\t') break; ++ l--; s++; ++ if (l == 0) break; if (*s != ' ' && *s != '\t') break; ++ l--; s++; ++ if (l == 0) break; if (*s != ' ' && *s != '\t') break; ++ l--; s++; ++ } ++ return len - l; ++} ++ ++#ifndef REPLY_SUBJ ++#define REPLY_SUBJ "Your Mail" ++#endif ++ ++stralloc subject = {0}; ++ ++int parseheader(/* TODO names for to/cc checking */ void) ++{ ++ substdio ss; ++ char *s; ++ int match, subj_set; ++ unsigned int len, i; ++ ++ subj_set = 0; ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buffer, sizeof(buffer) ); ++ do { ++ if(getln(&ss, &line, &match, '\n') != 0) { ++ strerr_warn3(WARN, "Unable to read message: ", ++ error_str(errno), 0); ++ break; /* something bad happend, but we ignore it */ ++ } ++ if (line.len == 0) /* something is wrong, bad message */ ++ break; ++ s = line.s; len = line.len; ++ switch(*s) { ++ case '\n': /* end of header */ ++ if (subj_set == 0) ++ if (!stralloc_copys(&subject, REPLY_SUBJ)) ++ temp_nomem(); ++ return 0; ++ case 'M': ++ case 'm': /* Mailing-List: */ ++ if (case_startb(s, len, "Mailing-List:")) { ++ return 1; ++ /* don't reply to mailing-lists */ ++ } ++ break; ++ case 'P': ++ case 'p': /* Precedence: */ ++ if (case_startb(s, len, "Precedence:")) { ++ i = getfield(s, len); ++ if (i >= len) break; ++ s += i; len -= i; ++ if (case_startb(s, len, "junk") || ++ case_startb(s, len, "bulk") || ++ case_startb(s, len, "list")) ++ return 1; ++ } ++ break; ++ case 'S': ++ case 's': /* Subject: */ ++ if (case_startb(s, len, "Subject:")) { ++ i = getfield(s, len); ++ if (i >= len) break; ++ s += i; len -= i; ++ ++ if (len > 1) { ++ /* subject has to be more than ++ 1 char (normaly a \n) ++ */ ++ if (!stralloc_copyb(&subject, s, len-1)) ++ temp_nomem(); ++ subj_set=1; ++ } ++ } ++ break; ++ case 'C': ++ case 'c': /* Cc: */ ++ case 'T': ++ case 't': /* To: */ ++ /* TODO check if address is listed in To or Cc field */ ++#if 0 ++ if (case_diffb("To:" ++ sizeof("To:") - 1, s) == 0 || ++ case_diffb("Cc:" ++ sizeof("Cc:") - 1, s) == 0) { ++ i = getfield(s, len); ++ if (i >= len) break; ++ s += i; len -= i; ++ } ++#endif ++ break; ++ case 'X': ++ case 'x': /* X-RBL: */ ++ if (case_startb(s, len, "X-RBL:")) { ++ return 1; ++ /* don't reply to messages tagged as spam */ ++ } ++ if (case_startb(s, len, "X-Spam-Status: Yes")) { ++ return 1; ++ /* don't reply to messages tagged as spam */ ++ } ++ break; ++ case ' ': ++ case '\t': ++ /* TODO multiline header Precedence, Subject, To and Cc */ ++ default: ++ break; ++ } ++ } while (match); ++ strerr_warn2(WARN, ++ "Premature end of header. The message has no body.", 0); ++ if ( subj_set == 0 ) ++ if (!stralloc_copys(&subject, REPLY_SUBJ)) temp_nomem(); ++ ++ return 0; ++} ++ ++stralloc header = {0}; ++ ++#ifndef REPLY_CT ++#define REPLY_CT "text/plain; charset=iso-8859-1\n" ++#endif ++#ifndef REPLY_CTE ++#define REPLY_CTE "8bit\n" ++#endif ++ ++struct mheader mheader[] = { ++ { "From:", 0, ALLOW, 0 }, /* envelope sender is fixed */ ++ { "To:", 0, FORCE, 0 }, ++ { "Subject:", "[Auto-Reply] %SUBJECT%\n", SUBJECT, 0 }, ++ { "MIME-Version:", "1.0", FORCE, 0 }, ++ { "Content-Type:", REPLY_CT, ALLOW, 0 }, ++ { "Content-Transfer-Encoding:", REPLY_CTE, ALLOW, 0 }, ++ { "X-Mailer:", "qmail-reply (by qmail-ldap)", FORCE, 0 }, ++ { "Precedence:", "junk", FORCE, 0 }, ++ { "X-", 0, ALLOW, 0 }, ++ { DEFAULT, 0, DENY, 0 }, ++ { 0, 0, 0, 0 } ++}; ++ ++void sendmail(void) ++{ ++ struct qmail qqt; ++ const char *qqx; ++ datetime_sec starttime; ++ unsigned long qp; ++ int offset; ++ ++ if (!stralloc_0(&from)) temp_nomem(); ++ if (!stralloc_0(&to)) temp_nomem(); ++ ++ mheader[0].v = from.s; ++ mheader[1].v = to.s; ++ offset = headermagic(&replytext, &header, &subject, mheader); ++ if (offset == -1) ++ strerr_die2sys(111, FATAL, "Header magic failed: "); ++ ++ if (qmail_open(&qqt) == -1) temp_fork(); ++ qp = qmail_qp(&qqt); ++ qmail_put(&qqt,dtline.s,dtline.len); ++ ++ /* XXX Date: qmail uses GMT based dates which is sometimes confusing */ ++ /* message-id and date line */ ++ starttime = now(); ++ if (!newfield_datemake(starttime)) goto fail_nomem; ++ if (!newfield_msgidmake(host.s, host.len, starttime)) goto fail_nomem; ++ qmail_put(&qqt, newfield_msgid.s, newfield_msgid.len); ++ qmail_put(&qqt, newfield_date.s, newfield_date.len); ++ ++ /* write parsed header */ ++ qmail_put(&qqt, header.s, header.len); ++ /* end of header marker */ ++ qmail_puts(&qqt, "\n"); ++ ++ /* body */ ++ qmail_put(&qqt, replytext.s + offset, replytext.len - offset); ++ /* add a empty newline, just to be sure */ ++ qmail_puts(&qqt, "\n"); ++ /* use <> as envelope sender as we are not interested in bounces */ ++ qmail_from(&qqt, ""); ++ qmail_to(&qqt, to.s); ++ qqx = qmail_close(&qqt); ++ if (!*qqx) return; ++ strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL, ++ "Unable to send reply message: ", qqx + 1, "."); ++ ++fail_nomem: ++ qmail_fail(&qqt); ++ qmail_close(&qqt); ++ temp_nomem(); ++} ++ ++int main(int argc, char **argv) ++{ ++ char *maildir; ++ int flagenv; ++ int opt; ++ ++ if (!env_init()) temp_nomem(); ++ ++ flagenv = 1; ++ timeout = REPLY_TIMEOUT; ++ ++ while((opt = getopt(argc,argv,"f:j:")) != opteof) ++ switch (opt) { ++ case 'f': ++ readmail(optarg); ++ flagenv = 0; ++ break; ++ case 'j': ++ junkread(optarg); ++ break; ++ default: ++ usage(); ++ /* NOTREACHED */ ++ } ++ ++ /* if more arguments are used */ ++ argc -= optind; ++ argv += optind; ++ maildir = *argv; ++ ++ if (flagenv == 1) ++ envmail(); ++ ++ /* get environment RECIPIENT, SENDER and DTLINE */ ++ get_env(); ++ ++ /* check if a reply is needed */ ++ if (junksender(to.s, to.len)) _exit(0); ++ /* parse header, exit if a precedence or mailinglist field ++ has been found or the mail is not directly sent to us. */ ++ if (parseheader()) _exit(0); ++ /* already sent a message recently? */ ++ if (maildir && (*maildir == '.' || *maildir == '/') && ++ maildir[str_len(maildir)-1] == '/') ++ if (recent(to.s, to.len, maildir)) _exit(0); ++ ++ sendmail(); ++ return 0; ++} ++ +diff -upN qmail-1.03/qmail-rspawn.c qmail-ldap/qmail-rspawn.c +--- qmail-1.03/qmail-rspawn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-rspawn.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "fd.h" + #include "wait.h" + #include "substdio.h" +@@ -10,19 +11,25 @@ void initialize(argc,argv) + int argc; + char **argv; + { ++#if 0 ++ extern int flagreinit; ++ ++ if (flagreinit) ++ return; ++#endif + tcpto_clean(); + } + +-int truncreport = 0; ++unsigned int truncreport = 0; + + void report(ss,wstat,s,len) + substdio *ss; + int wstat; + char *s; +-int len; ++unsigned int len; + { +- int j; +- int k; ++ unsigned int j; ++ unsigned int k; + int result; + int orr; + +@@ -79,12 +86,12 @@ int len; + + int spawn(fdmess,fdout,s,r,at) + int fdmess; int fdout; +-char *s; char *r; int at; ++char *s; char *r; unsigned int at; + { + int f; + char *(args[5]); + +- args[0] = "qmail-remote"; ++ args[0] = (char *)"qmail-remote"; + args[1] = r + at + 1; + args[2] = s; + args[3] = r; +diff -upN qmail-1.03/qmail-secretary.c qmail-ldap/qmail-secretary.c +--- qmail-1.03/qmail-secretary.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-secretary.c Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,1130 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++ ++#include "base64.h" ++#include "byte.h" ++#include "case.h" ++#include "control.h" ++#include "digest_sha1.h" ++#include "direntry.h" ++#include "env.h" ++#include "error.h" ++#include "fd.h" ++#include "fmt.h" ++#include "getln.h" ++#include "mailmagic.h" ++#include "newfield.h" ++#include "now.h" ++#include "open.h" ++#include "qmail.h" ++#include "readwrite.h" ++#include "seek.h" ++#include "sgetopt.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "strerr.h" ++#include "substdio.h" ++#include "wait.h" ++#ifdef AUTOMAILDIRMAKE ++#include "qldap-errno.h" ++#include "mailmaker.h" ++#endif ++ ++#define FATAL "qmail-secretary: fatal: " ++#define WARN "qmail-secretary: warn: " ++ ++const char *confirmmess = "Hi,\n\n\ ++I'm mailgroup secretary, an automated mail-handling program.\n\ ++I received a message from you addressed to %LIST%\n\ ++for which I'm responsible. The top of your message is shown below.\n\ ++\n\ ++I'm here to protect the address %LIST% from\n\ ++all anonymous messages and bulk mail messages.\n\ ++\n\ ++If you reply to this notice, you are acknowledging that your message\n\ ++identifies you and is not part of a bulk mailing.\n\ ++I won't look at the contents of your reply. A simple OK is fine.\n\ ++\n\ ++If you do not reply to this notice, your message will be dropped\n\ ++and the recipient will not receive it.\n\ ++\n\ ++I realize that this confirmation process is inconvenient. I'm sorry for\n\ ++the hassle.\n\ ++\n\ ++Sincerely,\n\ ++The mailgroup secretary program\n\ ++\n\ ++"; ++ ++const char *approvemess = "Hi,\n\n\ ++I'm mailgroup secretary, an automated mail-handling program.\n\ ++I need an approval that the attached message is allowed to be sent\n\ ++to the %LIST% mailinglist.\n\ ++\n\ ++To approve a message you must reply to this message. I won't look at\n\ ++the contents of your reply. A simple OK is fine.\n\ ++\n\ ++To deny a message no action must be taken. The message will be rejected\n\ ++automaticaliy after a few days.\n\ ++\n\ ++Sincerely,\n\ ++The mailgroup secretary program\n\ ++\n\ ++"; ++ ++void ++temp_nomem(void) ++{ ++ strerr_die2x(111, FATAL, "Out of memory."); ++} ++void ++temp_qmail(const char *fn) ++{ ++ strerr_die4sys(111, FATAL, "Unable to open ", fn, ": "); ++} ++void ++temp_rewind(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to rewind message."); ++} ++void ++temp_read(void) ++{ ++ strerr_die2x(111, FATAL, "Unable to read message."); ++} ++void ++temp_fork(void) ++{ ++ strerr_die2sys(111, FATAL, "Unable to fork: "); ++} ++void ++die_badaddr(void) ++{ ++ strerr_die2x(100, FATAL, ++ "I do not accept messages at this address (#5.1.1)"); ++} ++void usage(void) ++{ ++ strerr_die1x(100, ++ "qmail-secretary: usage:\n " ++ "qmail-secretary [ -Z ] [ -c | -C ] [[ -m addr ] ... ] " ++ "[ -M file ] maildir\n " ++ "qmail-secretary -z ezmlmdir [ -c | -C ] [[ -m addr ] ... ] " ++ "[ -M file ]\n maildir [ ezmlm-send ... ]\n"); ++} ++ ++char *sender; ++char *host; ++char *local; ++ ++stralloc mailinglist = {0}; ++stralloc inhost = {0}; ++stralloc inlocal = {0}; ++stralloc outhost = {0}; ++stralloc outlocal = {0}; ++stralloc messline = {0}; ++stralloc moderators = {0}; ++stralloc hashid = {0}; ++stralloc action = {0}; ++stralloc dtline = {0}; ++stralloc confirmtext = {0}; ++stralloc approvetext = {0}; ++ ++int flagconfirm = 0; ++int flagezmlm = 0; ++ ++void nullsender(void); ++void qgroupinit(void); ++void ezmlminit(char *); ++void extractrcpt(stralloc *, stralloc *); ++void getconf_line(stralloc *, const char *, const char *); ++void getconf_file(stralloc *, const char *, const char *); ++void getconf_text(stralloc *, const char *, const char *, const char *); ++void blast(stralloc *, const char *, const char *, char **); ++char *replyaddr(stralloc *, const char *); ++char *fromaddr(const char *); ++char *moderatoraddr(void); ++void sendconfirm(stralloc *, int); ++void sendmoderator(stralloc *, int); ++int sendmail(struct qmail *, int, int, stralloc *, stralloc *, stralloc *); ++void attachmail(struct qmail *, int, int); ++void bouncefx(void); ++void createhash(int, stralloc *); ++char *createname(stralloc *, const char *, const char *, stralloc *); ++void checkmessage(stralloc *, const char *, const char *); ++void delmessage(stralloc *, const char *, const char *); ++int mvmessage(stralloc *, stralloc *, const char *); ++void savemessage(stralloc *, const char *, const char *); ++void clean(const char *); ++ ++int ++main(int argc, char **argv) ++{ ++ char *ezmlmdir; ++ char *maildir; ++ char *modfile; ++ int opt; ++ unsigned int i; ++ ++ sender = env_get("SENDER"); ++ if (!sender) strerr_die2x(100, FATAL, "SENDER not set"); ++ local = env_get("LOCAL"); ++ if (!local) strerr_die2x(100, FATAL, "LOCAL not set"); ++ host = env_get("HOST"); ++ if (!host) strerr_die2x(100, FATAL, "HOST not set"); ++ ++ if (!stralloc_copys(&moderators, "")) temp_nomem(); ++ modfile = 0; ++ ezmlmdir = 0; ++ ++ while((opt = getopt(argc,argv,"cCm:M:z:Z")) != opteof) ++ switch (opt) { ++ case 'c': ++ flagconfirm = 1; ++ break; ++ case 'C': ++ flagconfirm = 0; ++ break; ++ case 'm': ++ if (!stralloc_cats(&moderators, optarg)) temp_nomem(); ++ if (!stralloc_0(&moderators)) temp_nomem(); ++ break; ++ case 'M': ++ modfile = optarg; ++ break; ++ case 'z': ++ flagezmlm = 1; ++ ezmlmdir = optarg; ++ break; ++ case 'Z': ++ flagezmlm = 0; ++ break; ++ default: ++ usage(); ++ /* NOTREACHED */ ++ } ++ ++ argc -= optind; ++ argv += optind; ++ if (!(maildir = *argv++)) usage(); ++ if (!flagezmlm && *argv) usage(); ++ if (flagezmlm && !*argv) usage(); ++ ++ if (flagezmlm == 0) ++ qgroupinit(); ++ else ++ ezmlminit(ezmlmdir); /* does a chdir to ezmlm dir */ ++ ++ if (modfile != 0) { ++ getconf_file(&messline, modfile, ezmlmdir); ++ if (!stralloc_cat(&moderators, &messline)) temp_nomem(); ++ if (!stralloc_copys(&messline, "")) temp_nomem(); ++ } ++ ++ if (!stralloc_copys(&dtline, "Delivered-To: secretary for ")) ++ temp_nomem(); ++ if (!stralloc_cat(&dtline, &outlocal)) temp_nomem(); ++ if (!stralloc_cats(&dtline, "@")) temp_nomem(); ++ if (!stralloc_cat(&dtline, &outhost)) temp_nomem(); ++ for (i = 0; i < dtline.len; ++i) ++ if (dtline.s[i] == '\n') ++ dtline.s[i] = '_'; ++ if (!stralloc_cats(&dtline,"\n")) temp_nomem(); ++ ++ ++ extractrcpt(&action, &hashid); ++#ifdef AUTOMAILDIRMAKE ++ switch (maildir_make(maildir)) { ++ case OK: ++ break; ++ case MAILDIR_CORRUPT: ++ strerr_die4x(111,FATAL, "The maildir '", maildir, ++ "' seems to be corrupted. (#4.2.1)"); ++ case ERRNO: ++ default: ++ strerr_die4x(111,FATAL, "Unable to create maildir '", maildir, ++ "' (#4.3.0)"); ++ } ++#endif ++ ++ if (action.len == 0) { ++ nullsender(); ++ bouncefx(); ++ if (flagconfirm == 1) { ++ savemessage(&hashid, maildir, "new/"); ++ sendconfirm(&hashid, 0); ++ } else { ++ savemessage(&hashid, maildir, "cur/"); ++ sendmoderator(&hashid, 0); ++ } ++ clean(maildir); ++ _exit(99); ++ } else if (case_startb(action.s, action.len, "approve")) { ++ nullsender(); ++ bouncefx(); ++ if (hashid.len == 0) ++ strerr_die2x(100, FATAL, "Approve message without id."); ++ checkmessage(&hashid, maildir, "cur/"); ++ blast(&hashid, maildir, "cur/", argv); ++ clean(maildir); ++ _exit(99); ++ } else if (case_startb(action.s, action.len, "confirm")) { ++ nullsender(); ++ bouncefx(); ++ if (hashid.len == 0) ++ strerr_die2x(100, FATAL, "Confirm message without id."); ++ checkmessage(&hashid, maildir, "new/"); ++ if (moderators.len == 0) ++ blast(&hashid, maildir, "new/", argv); ++ else ++ sendmoderator(&hashid, ++ mvmessage(&hashid, &hashid, maildir)); ++ clean(maildir); ++ _exit(99); ++ } else if (case_startb(action.s, action.len, "reject")) { ++ delmessage(&hashid, maildir, "new/"); ++ clean(maildir); ++ strerr_die2x(99, WARN, "confirmation to sender bounced."); ++ } else if (case_startb(action.s, action.len, "bounce")) { ++ clean(maildir); ++ strerr_die2x(99, WARN, "message to moderator bounced."); ++ } else if (case_startb(action.s, action.len, "moderators")) { ++ clean(maildir); ++ die_badaddr(); ++ } ++ /* unknown action, pass mail to the next tool */ ++ clean(maildir); ++ return 0; ++} ++ ++void ++nullsender(void) ++{ ++ if (!*sender) ++ strerr_die2x(100, FATAL, ++ "I don't reply to bounce messages. (#5.7.2)"); ++ if (!sender[str_chr(sender,'@')]) ++ strerr_die2x(100, FATAL, ++ "I don't reply to senders without host names." ++ " (#5.7.2)"); ++ if (str_diff(sender,"#@[]") == 0) ++ strerr_die2x(100, FATAL, ++ "I don't reply to bounce messages. (#5.7.2)"); ++} ++ ++void ++qgroupinit(void) ++{ ++ char *t; ++ ++ /* ++ * following vars need to be set: ++ * inhost and outhost will be set to $HOST ++ * inlocal and outlocal will set to the base address of the group ++ * in other words: $LOCAL[0]..$LOCAL[strlen($LOCAL) - strlen($EXT) - 1] ++ * but only if EXT is non null else inlocal and outlocal are eq $LOCAL ++ */ ++ if (!stralloc_copys(&inhost, host)) temp_nomem(); ++ if (!stralloc_copys(&outhost, host)) temp_nomem(); ++ ++ t = env_get("EXT"); ++ if (t != 0 && *t != '\0') { ++ if (!stralloc_copyb(&inlocal, local, ++ str_len(local) - str_len(t) - 1)) ++ temp_nomem(); ++ if (!stralloc_copy(&outlocal, &inlocal)) temp_nomem(); ++ } else { ++ if (!stralloc_copys(&inlocal, local)) temp_nomem(); ++ if (!stralloc_copys(&outlocal, local)) temp_nomem(); ++ } ++ if (!stralloc_copy(&mailinglist, &outlocal)) temp_nomem(); ++ if (!stralloc_append(&mailinglist, "@")) temp_nomem(); ++ if (!stralloc_cat(&mailinglist, &outhost)) temp_nomem(); ++ ++ t = env_get("APPROVEMESS"); ++ if (t != 0) { ++ if (!stralloc_copys(&approvetext, t)) temp_nomem(); ++ } else { ++ if (!stralloc_copys(&approvetext, approvemess)) temp_nomem(); ++ } ++ t = env_get("CONFIRMMESS"); ++ if (t != 0) { ++ if (!stralloc_copys(&confirmtext, t)) temp_nomem(); ++ } else { ++ if (!stralloc_copys(&confirmtext, confirmmess)) temp_nomem(); ++ } ++} ++ ++void ++ezmlminit(char *dir) ++{ ++ if (chdir(dir) == -1) ++ strerr_die4sys(111,FATAL,"unable to switch to ",dir,": "); ++ ++ getconf_line(&mailinglist,"mailinglist", dir); ++ getconf_line(&inhost,"inhost", dir); ++ getconf_line(&inlocal,"inlocal", dir); ++ getconf_line(&outhost,"outhost", dir); ++ getconf_line(&outlocal,"outlocal", dir); ++ ++ getconf_text(&approvetext, "text/approve", dir, approvemess); ++ getconf_text(&confirmtext, "text/confirm", dir, confirmmess); ++} ++ ++void ++extractrcpt(stralloc *a, stralloc *h) ++{ ++ char *s; ++ unsigned int i; ++ ++ if (!stralloc_copys(a, "")) temp_nomem(); ++ if (!stralloc_copys(h, "")) temp_nomem(); ++ ++ if (inhost.len != str_len(host)) die_badaddr(); ++ if (case_diffb(inhost.s,inhost.len,host)) die_badaddr(); ++ if (inlocal.len > str_len(local)) die_badaddr(); ++ if (case_diffb(inlocal.s,inlocal.len,local)) die_badaddr(); ++ ++ /* ++ * action is $LOCAL + inlocal.len + 1 but only if ++ * $LOCAL + inlocal.len == '-' ++ * and action.len is limited to str_chr(action.s, '-') - 1 ++ * hash is $LOCAL + inlocal.len + 1 + action.len + 1 ++ */ ++ s = local + inlocal.len; ++ if (*s == '\0') return; /* no action, no hash */ ++ if (*s != '-') /* WTF, give up and let a other tool try */ ++ strerr_die2x(0, WARN, "mail address has bad extension."); ++ s++; ++ i = str_chr(s,'-'); ++ if (!stralloc_copyb(a, s, i)) temp_nomem(); ++ if (s[i] == '\0') ++ return; /* just a action (e.g. moderators) */ ++ if (!stralloc_copys(h, s+i+1)) temp_nomem(); ++} ++ ++void ++getconf_line(stralloc *sa, const char *fn, const char *dir) ++{ ++ switch (control_readline(sa, fn)) { ++ case 0: ++ strerr_die5x(100, FATAL, dir, "/", fn, " does not exist"); ++ case 1: ++ return; ++ default: ++ strerr_die6sys(111, FATAL, "unable to read ", ++ dir, "/", fn, ": "); ++ } ++} ++ ++void ++getconf_file(stralloc *sa, const char *fn, const char *dir) ++{ ++ switch (control_readfile(sa, fn, 0)) { ++ case 0: ++ strerr_die5x(100, FATAL, dir, "/", fn, " does not exist"); ++ case 1: ++ return; ++ default: ++ strerr_die6sys(111, FATAL, "unable to read ", ++ dir, "/", fn, ": "); ++ } ++} ++ ++void ++getconf_text(stralloc *sa, const char *fn, const char *dir, const char *def) ++{ ++ switch (control_readrawfile(sa, fn)) { ++ case 0: ++ if (!stralloc_copys(sa, def)) temp_nomem(); ++ case 1: ++ return; ++ default: ++ strerr_die6sys(111, FATAL, "unable to read ", ++ dir, "/", fn, ": "); ++ } ++} ++ ++char * ++replyaddr(stralloc *h, const char *a) ++{ ++ static stralloc addr; ++ ++ if (!stralloc_copy(&addr, &outlocal)) temp_nomem(); ++ if (!stralloc_cats(&addr, "-")) temp_nomem(); ++ if (!stralloc_cats(&addr, a)) temp_nomem(); ++ if (!stralloc_cats(&addr, "-")) temp_nomem(); ++ if (!stralloc_cat(&addr, h)) temp_nomem(); ++ if (!stralloc_cats(&addr, "@")) temp_nomem(); ++ if (!stralloc_cat(&addr, &outhost)) temp_nomem(); ++ if (!stralloc_0(&addr)) temp_nomem(); ++ ++ return addr.s; ++} ++ ++char * ++fromaddr(const char *a) ++{ ++ static stralloc from; ++ ++ if (!stralloc_copys(&from, "The mailgroup secretary <")) ++ temp_nomem(); ++ if (!stralloc_cats(&from, a)) temp_nomem(); ++ if (!stralloc_cats(&from, ">\n")) temp_nomem(); ++ if (!stralloc_0(&from)) temp_nomem(); ++ ++ return from.s; ++} ++ ++char * ++moderatoraddr(void) ++{ ++ static stralloc modaddr; ++ ++ if (!stralloc_copys(&modaddr, "The moderators of ")) ++ temp_nomem(); ++ if (!stralloc_cat(&modaddr, &mailinglist)) temp_nomem(); ++ if (!stralloc_cats(&modaddr, " <")) temp_nomem(); ++ if (!stralloc_cat(&modaddr, &outlocal)) temp_nomem(); ++ if (!stralloc_cats(&modaddr, "-moderators@")) temp_nomem(); ++ if (!stralloc_cat(&modaddr, &outhost)) temp_nomem(); ++ if (!stralloc_cats(&modaddr, ">\n")) temp_nomem(); ++ if (!stralloc_0(&modaddr)) temp_nomem(); ++ ++ return modaddr.s; ++} ++ ++struct mheader mheader[] = { ++ { "To:", 0, FORCE, 0 }, ++ { "From:", 0, FORCE, 0 }, /* envelope sender is fixed */ ++ { "Subject:", 0, ALLOW, 0 }, ++// { "Reply-To:", 0, FORCE, 0 }, /* controversial RFC2076 */ ++ { "MIME-Version:", "1.0", FORCE, 0 }, ++ { "Content-Type:", 0, FORCE, 0 }, ++ { "Content-Transfer-Encoding:", 0, FORCE, 0 }, ++ { "X-Mailer:", "qmail-secretary (by qmail-ldap)", FORCE, 0 }, ++ { "Precedence:", "junk", FORCE, 0 }, ++ { "X-", 0, ALLOW, 0 }, ++ { DEFAULT, 0, DENY, 0 }, ++ { 0, 0, 0, 0 } ++}; ++ ++stralloc header = {0}; ++char strnum[FMT_ULONG]; ++ ++void ++sendconfirm(stralloc *hash, int fd) ++{ ++ struct qmail qqt; ++ const char *qqx; ++ unsigned long qp; ++ int r; ++ ++ mheader[0].v = sender; ++ mheader[1].v = fromaddr(replyaddr(hash, "confirm")); ++ mheader[2].v = "Message sender confirmation"; ++ ++ r = headermagic(&confirmtext, &header, 0, mheader); ++ if (r == -1) ++ strerr_die2sys(111, FATAL, "Header magic failed: "); ++ ++ if (qmail_open(&qqt) == -1) temp_fork(); ++ qp = qmail_qp(&qqt); ++ ++ if (sendmail(&qqt, fd, 10*1024, &header, &confirmtext, hash) == -1) ++ goto fail_nomem; ++ ++ qmail_from(&qqt, replyaddr(hash, "reject")); ++ qmail_to(&qqt, sender); ++ qqx = qmail_close(&qqt); ++ if (!*qqx) { ++ strnum[fmt_ulong(strnum, qp)] = 0; ++ strerr_warn2("qmail-secretary: info: qp ", strnum, 0); ++ return; ++ } ++ strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL, ++ "Unable to send reply message: ", qqx + 1, "."); ++ ++fail_nomem: ++ qmail_fail(&qqt); ++ qmail_close(&qqt); ++ temp_nomem(); ++} ++ ++void ++sendmoderator(stralloc *hash, int fd) ++{ ++ struct qmail qqt; ++ char *s, *smax; ++ const char *qqx; ++ unsigned long qp; ++ int r; ++ ++ mheader[0].v = moderatoraddr(); ++ mheader[1].v = fromaddr(replyaddr(hash, "approve")); ++ mheader[2].v = "Moderation request"; ++ ++ r = headermagic(&approvetext, &header, 0, mheader); ++ if (r == -1) ++ strerr_die2sys(111, FATAL, "Header magic failed: "); ++ ++ if (moderators.s == NULL || moderators.len == 0) ++ strerr_die2x(100, FATAL, ++ "no moderators found but needed."); ++ ++ if (qmail_open(&qqt) == -1) temp_fork(); ++ qp = qmail_qp(&qqt); ++ ++ if (sendmail(&qqt, fd, 128*1024, &header, &approvetext, hash) == -1) ++ goto fail_nomem; ++ ++ qmail_from(&qqt, replyaddr(hash, "bounce")); ++ ++ /* first check if the mail is comming from a moderator */ ++ for (s = moderators.s, smax = moderators.s + moderators.len; s < smax; ++ s += str_len(s) + 1) { ++ if (!str_diff(sender, s)) { ++ qmail_to(&qqt, s); ++ break; ++ } ++ } ++ /* not from a moderator so send to all moderators */ ++ if (s >= smax) ++ for (s = moderators.s, smax = moderators.s + moderators.len; ++ s < smax; s += str_len(s) + 1) { ++ qmail_to(&qqt, s); ++ } ++ ++ qqx = qmail_close(&qqt); ++ if (!*qqx) { ++ strnum[fmt_ulong(strnum,qmail_qp(&qqt))] = 0; ++ strerr_warn2("qmail-secretary: info: qp ", strnum, 0); ++ return; ++ } ++ strerr_die4x(*qqx == 'D' ? 100 : 111, FATAL, ++ "Unable to send approve message: ", qqx + 1, "."); ++ ++fail_nomem: ++ qmail_fail(&qqt); ++ qmail_close(&qqt); ++ temp_nomem(); ++} ++ ++struct mheader cheader[] = { ++ { "Content-Type:", "text/plain; charset=\"iso-8859-1\"\n", ALLOW, 0 }, ++ { "Content-Transfer-Encoding:", "8bit", ALLOW, 0 }, ++ { DEFAULT, 0, DENY, 0 }, ++ { 0, 0, 0, 0 } ++}; ++ ++int ++sendmail(struct qmail *qq, int fd, int maxsize, ++ stralloc *head, stralloc *message, stralloc *hash) ++{ ++ datetime_sec starttime; ++ int offset; ++ unsigned int len, i, j; ++ ++ /* mail header */ ++ qmail_put(qq, dtline.s, dtline.len); ++ /* XXX Date: qmail uses GMT based dates which is sometimes confusing */ ++ /* message-id and date line */ ++ starttime = now(); ++ if (!newfield_datemake(starttime)) return -1; ++ if (!newfield_msgidmake(inhost.s, inhost.len, starttime)) return -1; ++ qmail_put(qq, newfield_msgid.s, newfield_msgid.len); ++ qmail_put(qq, newfield_date.s, newfield_date.len); ++ ++ if (flagezmlm) { ++ qmail_puts(qq, "Mailing-List: "); ++ qmail_put(qq, mailinglist.s, mailinglist.len); ++ qmail_puts(qq, "\n"); ++ } ++ /* mime magic (multipart/mixed) header*/ ++ mimemagichead(head, hash); ++ ++ /* write parsed header */ ++ qmail_put(qq, head->s, head->len); ++ ++ /* end of header marker */ ++ qmail_puts(qq, "\n"); ++ ++ /* mime magic (first attachement secretary text)*/ ++ qmail_puts(qq, mimemagic()); ++ qmail_puts(qq, "\n"); ++ ++ offset = headermagic(message, head, 0, cheader); ++ if (offset == -1) return -1; ++ qmail_put(qq, head->s, head->len); ++ qmail_puts(qq, "\n"); ++ ++ /* body, expand %LIST% to list name. */ ++ len = message->len; ++ for (i = offset; i < len; i += j) { ++ j = byte_chr(message->s + i, len - i, '%'); ++ qmail_put(qq, message->s + i, j); ++ if (*(message->s + i + j) == '%') { ++ if (case_startb(message->s + i + j, ++ len - i -j, "%LIST%")) { ++ qmail_put(qq, outlocal.s, outlocal.len); ++ qmail_puts(qq, "@"); ++ qmail_put(qq, outhost.s, outhost.len); ++ i += 6; ++ } else { ++ qmail_put(qq, message->s + i + j, 1); ++ j++; ++ } ++ } ++ } ++ /* add a empty newline, just to be sure */ ++ qmail_puts(qq, "\n"); ++ ++ /* mime magic (second attachement user message) */ ++ qmail_puts(qq, mimemagic()); ++ qmail_puts(qq, "\n"); ++ qmail_puts(qq, "Content-Type: message/rfc822\n\n"); ++ ++ /* attach ~10kB of message */ ++ attachmail(qq, fd, maxsize); ++ ++ /* mime magic end */ ++ qmail_puts(qq, mimemagic()); ++ qmail_puts(qq, "--\n\n"); ++ return 0; ++} ++ ++char buf[4096]; ++ ++void ++attachmail(struct qmail *qq, int fd, int maxsize) ++{ ++ substdio ss; ++ int match; ++ ++ if (seek_begin(fd) == -1) { ++ qmail_fail(qq); ++ qmail_close(qq); ++ temp_rewind(); ++ } ++ substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf)); ++ for (;;) { ++ if (getln(&ss, &messline, &match, '\n') != 0) { ++ qmail_fail(qq); ++ qmail_close(qq); ++ temp_read(); ++ } ++ if (!match) break; ++ if (messline.len > maxsize && messline.len > 100) ++ messline.len = maxsize; ++ qmail_put(qq, messline.s, messline.len); ++ maxsize -= messline.len; ++ if (maxsize <= 0) { ++ qmail_puts(qq,"\n\n--- End of message stripped.\n"); ++ break; ++ } ++ } ++ qmail_puts(qq, "\n"); ++} ++ ++void ++bouncefx(void) ++{ ++ substdio ss; ++ int match; ++ unsigned int l; ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ for (;;) ++ { ++ if (getln(&ss, &messline, &match, '\n') != 0) temp_read(); ++ if (!match) break; ++ if (messline.len <= 1) break; ++ if (case_startb(messline.s, messline.len, "mailing-list:")) ++ strerr_die2x(100, FATAL, ++ "incoming message has Mailing-List. (#5.7.2)"); ++ if (case_startb(messline.s, messline.len, "precedence:")) { ++ for (l = 11; l < messline.len; l++) ++ if (messline.s[l] != ' ' && ++ messline.s[l] != '\t') ++ break; ++ if (case_startb(messline.s + l, messline.len - l, ++ "junk") || ++ case_startb(messline.s + l, messline.len - l, ++ "bulk") || ++ case_startb(messline.s + l, messline.len - l, ++ "list")) ++ strerr_die2x(100, FATAL, ++ "incoming message has bad precedence. " ++ "(#5.7.2)"); ++ } ++ if (messline.len == dtline.len) ++ if (byte_equal(messline.s, messline.len, dtline.s)) ++ strerr_die2x(100, FATAL, ++ "this message is looping: " ++ "it already has my Delivered-To line. " ++ "(#5.4.6)"); ++ } ++} ++ ++unsigned char sha1_hash[SHA1_LEN]; ++ ++void ++createhash(int fd, stralloc *hash) ++{ ++ SHA1_CTX ctx; ++ substdio ss; ++ unsigned long ul; ++ int match; ++ ++ if (!stralloc_copys(hash, "")) temp_nomem(); ++ SHA1Init(&ctx); ++ /* ++ * XXX this is neither 64bit clean nor endian safe but ++ * I don't care. The hash is calculated only once and needs ++ * to include enough entropy to make it almost impossible to ++ * guess or bruteforce attack the hash. ++ */ ++ ul = (unsigned long) now(); ++ SHA1Update(&ctx, (unsigned char *)&ul, sizeof(unsigned long)); ++ ul = (unsigned long) getpid(); ++ SHA1Update(&ctx, (unsigned char *)&ul, sizeof(unsigned long)); ++ ++ ++ if (seek_begin(fd) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf)); ++ for (;;) ++ { ++ if (getln(&ss, &messline, &match, '\n') != 0) temp_read(); ++ if (!match) break; ++ SHA1Update(&ctx, messline.s, messline.len); ++ } ++ ++ SHA1Final(sha1_hash, &ctx); ++ if (hex_ntops(sha1_hash, sizeof(sha1_hash), hash) == -1) ++ temp_nomem(); ++} ++ ++stralloc fname = {0}; ++stralloc nname = {0}; ++ ++char * ++createname(stralloc *sa, const char *maildir, const char *subdir, stralloc *h) ++{ ++ if (!stralloc_copys(sa, maildir)) temp_nomem(); ++ if (sa->s[sa->len-1] != '/') ++ if (!stralloc_append(sa, "/")) temp_nomem(); ++ if (!stralloc_cats(sa, subdir)) temp_nomem(); ++ if (sa->s[sa->len-1] != '/') ++ if (!stralloc_append(sa, "/")) temp_nomem(); ++ if (!stralloc_cat(sa, h)) temp_nomem(); ++ if (!stralloc_0(sa)) temp_nomem(); ++ return sa->s; ++} ++ ++void ++checkmessage(stralloc *hash, const char *maildir, const char *subdir) ++{ ++ struct stat st; ++ char *s; ++ ++ s = createname(&fname, maildir, subdir, hash); ++ ++ if (stat(s,&st) == -1) { ++ if (errno == error_noent) ++ strerr_die2x(99, WARN, ++ "Message no longer in repository."); ++ strerr_die2sys(111, FATAL, ++ "Could not stat message: "); ++ } ++} ++ ++void ++delmessage(stralloc *hash, const char *maildir, const char *subdir) ++{ ++ struct stat st; ++ char *s; ++ ++ s = createname(&fname, maildir, subdir, hash); ++ ++ if (stat(s,&st) == -1) { ++ if (errno == error_noent) return; ++ strerr_die2sys(111, FATAL, "Could not stat message: "); ++ } ++ if (unlink(s) == -1) ++ strerr_warn2(WARN, "Could not unlink message: ", &strerr_sys); ++} ++ ++int ++mvmessage(stralloc *hash, stralloc *newhash, const char *maildir) ++{ ++ struct stat st; ++ char *s, *t; ++ int loop, fd; ++ ++ s = createname(&fname, maildir, "new/", hash); ++ ++ if (stat(s,&st) == -1) { ++ if (errno == error_noent) ++ strerr_die2x(99, WARN, ++ "Message no longer in repository."); ++ strerr_die2sys(111, FATAL, ++ "Could not stat message: "); ++ } ++ for (loop = 0;; ++loop) { ++ createhash(0, hash); ++ t = createname(&nname, maildir, "cur/", hash); ++ if (stat(t, &st) == -1 && errno == error_noent) ++ break; ++ /* really should never get to this point */ ++ if (loop == 2) ++ strerr_die2sys(111, FATAL, "Could not stat new file: "); ++ sleep(2); ++ } ++ ++ if (rename(s, t) == -1) ++ strerr_die2sys(111, FATAL, "Could not move file: "); ++ ++ fd = open_read(t); ++ if (fd == -1) ++ strerr_die2sys(111, FATAL, "Unable to open message: "); ++ ++ return fd; ++} ++ ++char outbuf[4096]; ++ ++void tryunlinktmp(void) { unlink(fname.s); } ++void sigalrm(void) ++{ ++ tryunlinktmp(); ++ strerr_die1x(111, "Timeout on maildir delivery."); ++} ++ ++void ++savemessage(stralloc *hash, const char *maildir, const char *subdir) ++{ ++ struct stat st; ++ substdio ss, ssout; ++ char *s, *t; ++ int loop, fd; ++ ++ sig_alarmcatch(sigalrm); ++ ++ for (loop = 0;; ++loop) { ++ createhash(0, hash); ++ s = createname(&nname, maildir, subdir, hash); ++ t = createname(&fname, maildir, "tmp/", hash); ++ if (stat(s, &st) == -1 && errno == error_noent) ++ if (stat(t, &st) == -1 && errno == error_noent) ++ break; ++ /* really should never get to this point */ ++ if (loop == 2) ++ strerr_die2sys(111, FATAL, "Could not stat tmp file: "); ++ sleep(2); ++ } ++ alarm(86400); ++ fd = open_excl(t); ++ if (fd == -1) ++ strerr_die2sys(111, FATAL, "Unable to open tmp file: "); ++ ++ if (seek_begin(0) == -1) temp_rewind(); ++ substdio_fdbuf(&ss, subread, 0, buf, sizeof(buf)); ++ substdio_fdbuf(&ssout, subwrite, fd, outbuf, sizeof(outbuf)); ++ if (substdio_put(&ssout, dtline.s, dtline.len) == -1) goto fail; ++ ++ switch(substdio_copy(&ssout, &ss)) { ++ case -2: ++ strerr_warn2(FATAL, "Unable to read message: ", ++ &strerr_sys); ++ tryunlinktmp(); ++ _exit(111); ++ case -3: ++ goto fail; ++ } ++ ++ if (substdio_flush(&ssout) == -1) goto fail; ++ if (fsync(fd) == -1) goto fail; ++ if (close(fd) == -1) goto fail; /* NFS dorks */ ++ ++ if (link(t, s) == -1) goto fail; ++ /* if it was error_exist, almost certainly successful; i hate NFS */ ++ tryunlinktmp(); ++ sig_alarmdefault(); ++ return; ++ ++fail: ++ strerr_warn2(FATAL, "Unable to store message: ", ++ &strerr_sys); ++ tryunlinktmp(); ++ _exit(111); ++} ++ ++void ++blast(stralloc *hash, const char *maildir, const char *subdir, char **args) ++{ ++ substdio ssout; ++ char *s; ++ int child, fd, wstat; ++ ++ s = createname(&nname, maildir, subdir, hash); ++ ++ if (flagezmlm) { ++ switch (child = fork()) { ++ case -1: ++ temp_fork(); ++ case 0: ++ fd = open_read(s); ++ if (fd == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to open message: "); ++ if (fd_move(0,fd) == -1) ++ strerr_die2sys(111, FATAL, ++ "Unable to move fd: "); ++ if (seek_begin(0) == -1) temp_rewind(); ++ ++ sig_pipedefault(); ++ execv(*args, args); ++ strerr_die2sys(111, FATAL, "Unable to exec: "); ++ } ++ wait_pid(&wstat, child); ++ if (wait_crashed(wstat)) ++ strerr_die2x(111, FATAL, "Aack, child crashed."); ++ switch(wait_exitcode(wstat)) { ++ case 0: ++ case 99: ++ if (unlink(s) == -1) ++ strerr_warn2(WARN, ++ "Could not unlink message: ", &strerr_sys); ++ return; ++ case 100: ++ case 64: ++ case 65: ++ case 70: ++ case 76: ++ case 77: ++ case 78: ++ case 112: ++ _exit(100); ++ default: ++ _exit(111); ++ } ++ } else { ++ substdio_fdbuf(&ssout, subwrite, 1, outbuf, sizeof(outbuf)); ++ if (substdio_puts(&ssout, "K") == -1) goto fail; ++ if (substdio_puts(&ssout, s) == -1) goto fail; ++ if (substdio_put(&ssout, "", 1) == -1) goto fail; ++ if (substdio_flush(&ssout) == -1) goto fail; ++ ++ return; ++fail: ++ strerr_die2x(111, FATAL, "Unable to write to stdout: "); ++ } ++} ++ ++static void clean_child(void); ++ ++static void ++clean_child(void) ++{ ++ char const *(dirs[3]); ++ struct stat st; ++ DIR *folder; ++ struct dirent *entry; ++ datetime_sec t; ++ unsigned int i; ++ ++ t = now(); ++ ++ dirs[0]="new/"; dirs[1]="cur/"; dirs[2]="tmp/"; ++ for (i=0; i<3; i++) { ++ /* checking for outdated mail */ ++ if ((folder = opendir(dirs[i])) == 0) { ++ strerr_warn4(WARN, "Cleanup: Unable to opendir ", ++ dirs[i], ": ", &strerr_sys); ++ _exit(2); ++ } ++ while ((entry = readdir(folder)) != 0) { ++ if (*entry->d_name == '.') continue; ++ if (!stralloc_copys(&fname, dirs[i])) _exit(1); ++ if (!stralloc_cats(&fname, entry->d_name)) _exit(1); ++ if (!stralloc_0(&fname)) _exit(1); ++ /* remove files after a week */ ++ if (stat(fname.s,&st) == 0) ++ if (t > st.st_mtime + 604800) ++ unlink(fname.s); ++ } ++ closedir(folder); ++ } ++ _exit(0); ++} ++ ++void ++clean(const char *maildir) ++{ ++ int child, wstat; ++ ++ switch (child = fork()) { ++ case -1: ++ strerr_warn2(WARN, "Cleanup: Unable to fork: ", &strerr_sys); ++ return; ++ case 0: ++ if (chdir(maildir) == -1) ++ _exit(3); ++ clean_child(); ++ } ++ ++ wait_pid(&wstat, child); ++ if (wait_crashed(wstat)) ++ strerr_warn2(WARN, "Cleanup: Aack, child crashed.", 0); ++ switch(wait_exitcode(wstat)) { ++ case 0: ++ break; ++ case 1: ++ strerr_warn2(WARN, "Cleanup: Aack, child out of memory.", 0); ++ break; ++ case 2: ++ break; ++ case 3: ++ strerr_warn4(WARN, "Cleanup: Unable to switch to ", ++ maildir, ": ", &strerr_sys); ++ break; ++ } ++} ++ +diff -upN qmail-1.03/qmail-send.c qmail-ldap/qmail-send.c +--- qmail-1.03/qmail-send.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-send.c Wed Aug 18 11:27:12 2004 +@@ -1,5 +1,7 @@ + #include + #include ++#include ++#include + #include "readwrite.h" + #include "sig.h" + #include "direntry.h" +@@ -31,6 +33,7 @@ + #include "constmap.h" + #include "fmtqfn.h" + #include "readsubdir.h" ++#include "cdb.h" + + /* critical timing feature #1: if not triggered, do not busy-loop */ + /* critical timing feature #2: if triggered, respond within fixed time */ +@@ -56,13 +59,15 @@ stralloc bouncehost = {0}; + stralloc doublebounceto = {0}; + stralloc doublebouncehost = {0}; + ++stralloc custombouncetext = {0}; ++ + char strnum2[FMT_ULONG]; + char strnum3[FMT_ULONG]; + + #define CHANNELS 2 +-char *chanaddr[CHANNELS] = { "local/", "remote/" }; +-char *chanstatusmsg[CHANNELS] = { " local ", " remote " }; +-char *tochan[CHANNELS] = { " to local ", " to remote " }; ++const char *chanaddr[CHANNELS] = { "local/", "remote/" }; ++const char *chanstatusmsg[CHANNELS] = { " local ", " remote " }; ++const char *tochan[CHANNELS] = { " to local ", " to remote " }; + int chanfdout[CHANNELS] = { 1, 3 }; + int chanfdin[CHANNELS] = { 2, 4 }; + int chanskip[CHANNELS] = { 10, 20 }; +@@ -96,7 +101,11 @@ void fnmake_init() + } + + void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); } ++#ifndef BIGTODO + void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); } ++#else ++void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,1); } ++#endif + void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); } + void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); } + void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); } +@@ -108,18 +117,20 @@ void fnmake_chanaddr(id,c) unsigned long + + /* this file is too long ----------------------------------------- REWRITING */ + ++stralloc localscdb = {0}; + stralloc rwline = {0}; ++struct cdb cdb; + + /* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */ + /* may trash recip. must set up rwline, between a T and a \0. */ + int rewrite(recip) + char *recip; + { +- int i; +- int j; +- char *x; ++ unsigned int i; ++ unsigned int j; ++ const char *x; + static stralloc addr = {0}; +- int at; ++ unsigned int at; + + if (!stralloc_copys(&rwline,"T")) return 0; + if (!stralloc_copys(&addr,recip)) return 0; +@@ -140,15 +151,35 @@ char *recip; + + at = byte_rchr(addr.s,addr.len,'@'); + +- if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) { +- if (!stralloc_cat(&rwline,&addr)) return 0; +- if (!stralloc_0(&rwline)) return 0; +- return 1; +- } ++ if (localscdb.s && localscdb.len > 1) { ++ static stralloc lowaddr = {0}; ++ int fd, r; ++ uint32 dlen; ++ ++ if (!stralloc_copyb(&lowaddr,addr.s + at + 1,addr.len - at - 1)) return 0; ++ case_lowerb(lowaddr.s, lowaddr.len); ++ fd = open_read(localscdb.s); ++ if (fd == -1) return 0; ++ cdb_init(&cdb, fd); ++ r = cdb_seek(&cdb, lowaddr.s,lowaddr.len, &dlen); ++ cdb_free(&cdb); ++ close(fd); ++ if (r == -1) return 0; ++ if (r == 1) { ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 1; ++ } ++ } else ++ if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) { ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 1; ++ } + + for (i = 0;i <= addr.len;++i) + if (!i || (i == at + 1) || (i == addr.len) || ((i > at) && (addr.s[i] == '.'))) +- if (x = constmap(&mapvdoms,addr.s + i,addr.len - i)) { ++ if ((x = constmap(&mapvdoms,addr.s + i,addr.len - i))) { + if (!*x) break; + if (!stralloc_cats(&rwline,x)) return 0; + if (!stralloc_cats(&rwline,"-")) return 0; +@@ -167,9 +198,9 @@ stralloc *sa; + char *sender; + char *recip; + { +- int i; +- int j; +- int k; ++ unsigned int i; ++ unsigned int j; ++ unsigned int k; + + i = str_len(sender); + if (i >= 4) +@@ -211,7 +242,7 @@ unsigned long id; + fdinfo = open_read(fn.s); + if (fdinfo == -1) return 0; + if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; } +- substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf)); ++ substdio_fdbuf(&ss,subread,fdinfo,buf,sizeof(buf)); + if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; } + close(fdinfo); + if (!match) return 0; +@@ -230,12 +261,13 @@ substdio sstoqc; char sstoqcbuf[1024]; + substdio ssfromqc; char ssfromqcbuf[1024]; + stralloc comm_buf[CHANNELS] = { {0}, {0} }; + int comm_pos[CHANNELS]; ++int comm_needshup[CHANNELS]; + + void comm_init() + { + int c; +- substdio_fdbuf(&sstoqc,write,5,sstoqcbuf,sizeof(sstoqcbuf)); +- substdio_fdbuf(&ssfromqc,read,6,ssfromqcbuf,sizeof(ssfromqcbuf)); ++ substdio_fdbuf(&sstoqc,subwrite,5,sstoqcbuf,sizeof(sstoqcbuf)); ++ substdio_fdbuf(&ssfromqc,subread,6,ssfromqcbuf,sizeof(ssfromqcbuf)); + for (c = 0;c < CHANNELS;++c) + if (ndelay_on(chanfdout[c]) == -1) + /* this is so stupid: NDELAY semantics should be default on write */ +@@ -250,9 +282,37 @@ int c; + return 1; + } + ++void comm_hup(c) ++int c; ++{ ++ unsigned int delnum = 0xbeef; ++ unsigned char ch; ++ ++ /* ++ * send a empty message with delivery number 0xbeef (48879) to the ++ * spawn process. This may cause trouble if you have a concurrency ++ * bigger than this. Acctually it should be save but who has such ++ * a high concurrency anyway. ++ */ ++ if (comm_buf[c].s && comm_buf[c].len) { ++ comm_needshup[c] = 1; ++ return; ++ } ++ while (!stralloc_copys(&comm_buf[c],"")) nomem(); ++ ch = delnum; ++ while (!stralloc_append(&comm_buf[c],&ch)) nomem(); ++ ch = delnum >> 8; ++ while (!stralloc_append(&comm_buf[c],&ch)) nomem(); ++ while (!stralloc_0(&comm_buf[c])) nomem(); ++ while (!stralloc_0(&comm_buf[c])) nomem(); ++ while (!stralloc_0(&comm_buf[c])) nomem(); ++ comm_pos[c] = 0; ++ comm_needshup[c] = 0; ++} ++ + void comm_write(c,delnum,id,sender,recip) + int c; +-int delnum; ++unsigned int delnum; + unsigned long id; + char *sender; + char *recip; +@@ -262,6 +322,8 @@ char *recip; + while (!stralloc_copys(&comm_buf[c],"")) nomem(); + ch = delnum; + while (!stralloc_append(&comm_buf[c],&ch)) nomem(); ++ ch = delnum >> 8; ++ while (!stralloc_append(&comm_buf[c],&ch)) nomem(); + fnmake_split(id); + while (!stralloc_cats(&comm_buf[c],fn.s)) nomem(); + while (!stralloc_0(&comm_buf[c])) nomem(); +@@ -310,8 +372,11 @@ fd_set *wfds; + else + { + comm_pos[c] += w; +- if (comm_pos[c] == len) ++ if (comm_pos[c] == len) { + comm_buf[c].len = 0; ++ if (comm_needshup[c]) ++ comm_hup(c); ++ } + } + } + } +@@ -443,7 +508,7 @@ void pqstart() + + readsubdir_init(&rs,"info",pausedir); + +- while (x = readsubdir_next(&rs,&id)) ++ while ((x = readsubdir_next(&rs,&id))) + if (x > 0) + pqadd(id); + } +@@ -452,15 +517,16 @@ void pqfinish() + { + int c; + struct prioq_elt pe; +- time_t ut[2]; /* XXX: more portable than utimbuf, but still worrisome */ ++ struct timeval tvv[2]; + + for (c = 0;c < CHANNELS;++c) + while (prioq_min(&pqchan[c],&pe)) + { + prioq_delmin(&pqchan[c]); + fnmake_chanaddr(pe.id,c); +- ut[0] = ut[1] = pe.dt; +- if (utime(fn.s,ut) == -1) ++ tvv[0].tv_sec = tvv[1].tv_sec = pe.dt; ++ tvv[0].tv_usec = tvv[1].tv_usec = 0; ++ if (utimes(fn.s,tvv) == -1) + log3("warning: unable to utime ",fn.s,"; message will be retried too soon\n"); + } + } +@@ -468,7 +534,7 @@ void pqfinish() + void pqrun() + { + int c; +- int i; ++ unsigned int i; + for (c = 0;c < CHANNELS;++c) + if (pqchan[c].p) + if (pqchan[c].len) +@@ -492,12 +558,12 @@ struct job + } + ; + +-int numjobs; ++unsigned int numjobs; + struct job *jo; + + void job_init() + { +- int j; ++ unsigned int j; + while (!(jo = (struct job *) alloc(numjobs * sizeof(struct job)))) nomem(); + for (j = 0;j < numjobs;++j) + { +@@ -508,7 +574,7 @@ void job_init() + + int job_avail() + { +- int j; ++ unsigned int j; + for (j = 0;j < numjobs;++j) if (!jo[j].refs) return 1; + return 0; + } +@@ -517,7 +583,7 @@ int job_open(id,channel) + unsigned long id; + int channel; + { +- int j; ++ unsigned int j; + for (j = 0;j < numjobs;++j) if (!jo[j].refs) break; + if (j == numjobs) return -1; + jo[j].refs = 1; +@@ -574,10 +640,10 @@ int j; + char *stripvdomprepend(recip) + char *recip; + { +- int i; ++ unsigned int i; + char *domain; +- int domainlen; +- char *prepend; ++ unsigned int domainlen; ++ const char *prepend; + + i = str_rchr(recip,'@'); + if (!recip[i]) return recip; +@@ -586,7 +652,7 @@ char *recip; + + for (i = 0;i <= domainlen;++i) + if ((i == 0) || (i == domainlen) || (domain[i] == '.')) +- if (prepend = constmap(&mapvdoms,domain + i,domainlen - i)) ++ if ((prepend = constmap(&mapvdoms,domain + i,domainlen - i))) + { + if (!*prepend) break; + i = str_len(prepend); +@@ -598,6 +664,7 @@ char *recip; + } + + stralloc bouncetext = {0}; ++unsigned int bouncemaxbytes = 0; + + void addbounce(id,recip,report) + unsigned long id; +@@ -605,7 +672,7 @@ char *recip; + char *report; + { + int fd; +- int pos; ++ unsigned int pos; + int w; + while (!stralloc_copys(&bouncetext,"<")) nomem(); + while (!stralloc_cats(&bouncetext,stripvdomprepend(recip))) nomem(); +@@ -650,7 +717,7 @@ unsigned long id; + { + struct qmail qqt; + struct stat st; +- char *bouncesender; ++ const char *bouncesender; + char *bouncerecip; + int r; + int fd; +@@ -710,18 +777,25 @@ Hi. This is the qmail-send program at ") + qmail_puts(&qqt,*sender.s ? ".\n\ + I'm afraid I wasn't able to deliver your message to the following addresses.\n\ + This is a permanent error; I've given up. Sorry it didn't work out.\n\ +-\n\ + " : ".\n\ + I tried to deliver a bounce message to this address, but the bounce bounced!\n\ +-\n\ + "); + ++ if (custombouncetext.len > 1) ++ { ++ qmail_puts(&qqt,custombouncetext.s); ++ if (custombouncetext.s[custombouncetext.len-2] != '\n') ++ qmail_puts(&qqt,"\n"); /* I don't think we get here but anyway */ ++ } ++ ++ qmail_puts(&qqt,"\n"); ++ + fd = open_read(fn2.s); + if (fd == -1) + qmail_fail(&qqt); + else + { +- substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssread,subread,fd,inbuf,sizeof(inbuf)); + while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0) + qmail_put(&qqt,buf,r); + close(fd); +@@ -740,9 +814,20 @@ I tried to deliver a bounce message to t + qmail_fail(&qqt); + else + { +- substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf)); +- while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0) ++ unsigned int bytestogo; ++ unsigned int bytestoget; ++ bytestogo = bouncemaxbytes; ++ bytestoget = (bytestogo < sizeof(buf) && bouncemaxbytes != 0) ? bytestogo : sizeof(buf); ++ substdio_fdbuf(&ssread,subread,fd,inbuf,sizeof(inbuf)); ++ while ((r = substdio_get(&ssread,buf,bytestoget)) > 0) { + qmail_put(&qqt,buf,r); ++ bytestogo -= r; ++ if (bouncemaxbytes != 0 && bytestogo <= 0) { ++ qmail_puts(&qqt,"\n\n--- End of message stripped.\n"); ++ break; ++ } ++ bytestoget = (bytestogo < sizeof(buf) && bouncemaxbytes != 0) ? bytestogo : sizeof(buf); ++ } + close(fd); + if (r == -1) + qmail_fail(&qqt); +@@ -804,7 +889,7 @@ void del_status() + void del_init() + { + int c; +- int i; ++ unsigned int i; + for (c = 0;c < CHANNELS;++c) + { + flagspawnalive[c] = 1; +@@ -834,11 +919,11 @@ int c; + } + + void del_start(j,mpos,recip) +-int j; ++unsigned int j; + seek_pos mpos; + char *recip; + { +- int i; ++ unsigned int i; + int c; + + c = jo[j].channel; +@@ -894,7 +979,7 @@ int c; + int r; + char ch; + int i; +- int delnum; ++ unsigned int delnum; + r = read(chanfdin[c],delbuf,sizeof(delbuf)); + if (r == -1) return; + if (r == 0) { spawndied(c); return; } +@@ -906,50 +991,67 @@ int c; + dline[c].len = REPORTMAX; + /* qmail-lspawn and qmail-rspawn are responsible for keeping it short */ + /* but from a security point of view, we don't trust rspawn */ +- if (!ch && (dline[c].len > 1)) ++ if (!ch && (dline[c].len > 2)) + { +- delnum = (unsigned int) (unsigned char) dline[c].s[0]; ++ delnum = (unsigned int)(unsigned char)dline[c].s[0]; ++ delnum += (unsigned int)(unsigned char)dline[c].s[1] << 8; ++#if 0 ++ /* A hup is sent as delivery num 0xBEEF = 48879 */ ++ if (delnum == 0xBEEF) { ++ log1("sighup response: "); ++ logsafe(dline[c].s + 3); ++ log1("\n"); ++ } else ++#endif + if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used) + log1("warning: internal error: delivery report out of range\n"); + else + { + strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0; +- if (dline[c].s[1] == 'Z') ++ if (dline[c].s[2] == 'Z') + if (jo[d[c][delnum].j].flagdying) + { +- dline[c].s[1] = 'D'; ++ dline[c].s[2] = 'D'; + --dline[c].len; + while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem(); + while (!stralloc_0(&dline[c])) nomem(); + } +- switch(dline[c].s[1]) ++ switch(dline[c].s[2]) + { + case 'K': + log3("delivery ",strnum3,": success: "); +- logsafe(dline[c].s + 2); ++ logsafe(dline[c].s + 3); + log1("\n"); + markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos); + --jo[d[c][delnum].j].numtodo; + break; + case 'Z': + log3("delivery ",strnum3,": deferral: "); +- logsafe(dline[c].s + 2); ++ logsafe(dline[c].s + 3); + log1("\n"); + break; + case 'D': + log3("delivery ",strnum3,": failure: "); +- logsafe(dline[c].s + 2); ++ logsafe(dline[c].s + 3); + log1("\n"); +- addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2); ++ addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 3); + markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos); + --jo[d[c][delnum].j].numtodo; + break; ++ case 'L': ++ log3("delivery ",strnum3,": log: "); ++ logsafe(dline[c].s + 3); ++ log1("\n"); ++ dline[c].len = 0; ++ break; + default: + log3("delivery ",strnum3,": report mangled, will defer\n"); + } +- job_close(d[c][delnum].j); +- d[c][delnum].used = 0; --concurrencyused[c]; +- del_status(); ++ if (dline[c].s[2] != 'L') { ++ job_close(d[c][delnum].j); ++ d[c][delnum].used = 0; --concurrencyused[c]; ++ del_status(); ++ } + } + dline[c].len = 0; + } +@@ -1045,10 +1147,19 @@ datetime_sec nextretry(birth,c) + datetime_sec birth; + int c; + { +- int n; ++ unsigned int n; + + if (birth > recent) n = 0; +- else n = squareroot(recent - birth); /* no need to add fuzz to recent */ ++ else { ++#ifdef notyet ++ /* ++ * add some fuzz to recent so that storms to a single host are ++ * dampened over the time. ++ */ ++ recent += (int)random() % (((recent - birth) >> 2) + 1); ++#endif ++ n = squareroot(recent - birth); ++ } + n += chanskip[c]; + return birth + n * n; + } +@@ -1076,9 +1187,10 @@ int c; + if (pass[c].fd == -1) goto trouble; + if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; } + pass[c].id = pe.id; +- substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf)); ++ substdio_fdbuf(&pass[c].ss,subread,pass[c].fd,pass[c].buf,sizeof(pass[c].buf)); + pass[c].j = job_open(pe.id,c); + jo[pass[c].j].retry = nextretry(birth,c); ++ /* XXX add fast timeouts for bounce double bounce here */ + jo[pass[c].j].flagdying = (recent > birth + lifetime); + while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem(); + } +@@ -1215,8 +1327,14 @@ void pass_do() + + /* this file is too long ---------------------------------------------- TODO */ + ++#ifndef EXTERNAL_TODO + datetime_sec nexttodorun; ++#ifndef BIGTODO + DIR *tododir; /* if 0, have to opendir again */ ++#else ++int flagtododir = 0; /* if 0, have to readsubdir_init again */ ++readsubdir todosubdir; ++#endif + stralloc todoline = {0}; + char todobuf[SUBSTDIO_INSIZE]; + char todobufinfo[512]; +@@ -1224,7 +1342,11 @@ char todobufchan[CHANNELS][1024]; + + void todo_init() + { ++#ifndef BIGTODO + tododir = 0; ++#else ++ flagtododir = 0; ++#endif + nexttodorun = now(); + trigger_set(); + } +@@ -1236,7 +1358,11 @@ datetime_sec *wakeup; + { + if (flagexitasap) return; + trigger_selprep(nfds,rfds); ++#ifndef BIGTODO + if (tododir) *wakeup = 0; ++#else ++ if (flagtododir) *wakeup = 0; ++#endif + if (*wakeup > nexttodorun) *wakeup = nexttodorun; + } + +@@ -1253,8 +1379,10 @@ fd_set *rfds; + char ch; + int match; + unsigned long id; ++#ifndef BIGTODO + unsigned int len; + direntry *d; ++#endif + int c; + unsigned long uid; + unsigned long pid; +@@ -1265,21 +1393,31 @@ fd_set *rfds; + + if (flagexitasap) return; + ++#ifndef BIGTODO + if (!tododir) ++#else ++ if (!flagtododir) ++#endif + { + if (!trigger_pulled(rfds)) + if (recent < nexttodorun) + return; + trigger_set(); ++#ifndef BIGTODO + tododir = opendir("todo"); + if (!tododir) + { + pausedir("todo"); + return; + } ++#else ++ readsubdir_init(&todosubdir, "todo", pausedir); ++ flagtododir = 1; ++#endif + nexttodorun = recent + SLEEP_TODO; + } + ++#ifndef BIGTODO + d = readdir(tododir); + if (!d) + { +@@ -1291,6 +1429,15 @@ fd_set *rfds; + if (str_equal(d->d_name,"..")) return; + len = scan_ulong(d->d_name,&id); + if (!len || d->d_name[len]) return; ++#else ++ switch(readsubdir_next(&todosubdir, &id)) ++ { ++ case 1: break; ++ case 0: flagtododir = 0; ++ default: return; ++ } ++#endif ++ + + fnmake_todo(id); + +@@ -1438,10 +1585,156 @@ fd_set *rfds; + if (fdchan[c] != -1) close(fdchan[c]); + } + ++#endif ++ ++/* this file is too long ------------------------------------- EXTERNAL TODO */ ++ ++#ifdef EXTERNAL_TODO ++stralloc todoline = {0}; ++char todobuf[2048]; ++int todofdin; ++int todofdout; ++int flagtodoalive; ++ ++void tododied() { log1("alert: oh no! lost qmail-todo connection! dying...\n"); ++ flagexitasap = 1; flagtodoalive = 0; } ++ ++void todo_init() ++{ ++ todofdout = 7; ++ todofdin = 8; ++ flagtodoalive = 1; ++ /* sync with external todo */ ++ if (write(todofdout, "S", 1) != 1) tododied(); ++ ++ return; ++} ++ ++void todo_selprep(nfds,rfds,wakeup) ++int *nfds; ++fd_set *rfds; ++datetime_sec *wakeup; ++{ ++ if (flagexitasap) { ++ if (flagtodoalive) { ++ write(todofdout, "X", 1); ++ } ++ } ++ if (flagtodoalive) { ++ FD_SET(todofdin,rfds); ++ if (*nfds <= todofdin) ++ *nfds = todofdin + 1; ++ } ++} ++ ++void todo_del(char* s) ++{ ++ int flagchan[CHANNELS]; ++ struct prioq_elt pe; ++ unsigned long id; ++ unsigned int len; ++ int c; ++ ++ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0; ++ switch(*s++) { ++ case 'L': ++ flagchan[0] = 1; ++ break; ++ case 'R': ++ flagchan[1] = 1; ++ break; ++ case 'B': ++ flagchan[0] = 1; ++ flagchan[1] = 1; ++ break; ++ case 'X': ++ /* ++ * this is not an error but it is neither correct, ++ * sending messages with no recipients is plain stupid. ++ */ ++ log1("warning: qmail-todo neither by land nor by sea...\n"); ++ break; ++ default: ++ log1("warning: qmail-todo has a unknown feature or dialect.\n"); ++ return; ++ } ++ ++ len = scan_ulong(s,&id); ++ if (!len || s[len]) { ++ log1("warning: qmail-todo please don't muble.\n"); ++ return; ++ } ++ ++ pe.id = id; pe.dt = now(); ++ for (c = 0;c < CHANNELS;++c) ++ if (flagchan[c]) ++ while (!prioq_insert(&pqchan[c],&pe)) nomem(); ++ ++ for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break; ++ if (c == CHANNELS) ++ while (!prioq_insert(&pqdone,&pe)) nomem(); ++ ++ return; ++} ++ ++void todo_do(rfds) ++fd_set *rfds; ++{ ++ int r; ++ char ch; ++ int i; ++ ++ if (!flagtodoalive) return; ++ if (!FD_ISSET(todofdin,rfds)) return; ++ ++ r = read(todofdin,todobuf,sizeof(todobuf)); ++ if (r == -1) return; ++ if (r == 0) { ++ if (flagexitasap) ++ flagtodoalive = 0; ++ else ++ tododied(); ++ return; ++ } ++ for (i = 0;i < r;++i) { ++ ch = todobuf[i]; ++ while (!stralloc_append(&todoline,&ch)) nomem(); ++ if (todoline.len > REPORTMAX) ++ todoline.len = REPORTMAX; ++ /* qmail-todo is responsible for keeping it short */ ++ if (!ch && (todoline.len > 1)) { ++ switch (todoline.s[0]) { ++ case 'D': ++ if (flagexitasap) break; ++ todo_del(todoline.s + 1); ++ break; ++ case 'L': ++ log1(todoline.s + 1); ++ break; ++ case 'X': ++ if (flagexitasap) ++ flagtodoalive = 0; ++ else ++ tododied(); ++ break; ++ default: ++ log1("warning: qmail-send unable to understand qmail-todo: report mangled\n"); ++ break; ++ } ++ todoline.len = 0; ++ } ++ } ++} ++ ++#endif + + /* this file is too long ---------------------------------------------- MAIN */ + +-int getcontrols() { if (control_init() == -1) return 0; ++int getcontrols() ++{ ++ struct stat st; ++ ++ if (control_init() == -1) return 0; + 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; +@@ -1453,8 +1746,20 @@ int getcontrols() { if (control_init() = + if (!stralloc_cats(&doublebounceto,"@")) return 0; + if (!stralloc_cat(&doublebounceto,&doublebouncehost)) return 0; + if (!stralloc_0(&doublebounceto)) return 0; +- if (control_readfile(&locals,"control/locals",1) != 1) return 0; +- if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0; ++ if (control_readint(&bouncemaxbytes,"control/bouncemaxbytes") == -1) return 0; ++ if (control_readrawfile(&custombouncetext,"control/custombouncetext") == -1) return 0; ++ if (!stralloc_0(&custombouncetext) ) return 0; ++ ++ if (stat("control/locals.cdb", &st) == 0) { ++ if (!stralloc_copys(&localscdb, auto_qmail)) return 0; ++ if (!stralloc_cats(&localscdb, "/control/locals.cdb")) return 0; ++ if (!stralloc_0(&localscdb)) return 0; ++ if (!constmap_init(&maplocals,"",0,1)) return 0; ++ } else { ++ if (control_readfile(&locals,"control/locals",1) != 1) return 0; ++ if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0; ++ } ++ + switch(control_readfile(&percenthack,"control/percenthack",0)) + { + case -1: return 0; +@@ -1471,23 +1776,45 @@ int getcontrols() { if (control_init() = + + stralloc newlocals = {0}; + stralloc newvdoms = {0}; ++stralloc newcbtext = {0}; + + void regetcontrols() + { ++ struct stat st; + int r; + +- if (control_readfile(&newlocals,"control/locals",1) != 1) +- { log1("alert: unable to reread control/locals\n"); return; } ++ if (control_readint(&bouncemaxbytes,"control/bouncemaxbytes") == -1) ++ { log1("alert: unable to reread control/bouncemaxbytes\n"); return; } ++ ++ if (control_readrawfile(&newcbtext,"control/custombouncetext") == -1) ++ { log1("alert: unable to reread control/custombouncetext\n"); return; } ++ while (!stralloc_0(&newcbtext)) nomem(); ++ while (!stralloc_copy(&custombouncetext,&newcbtext)) nomem(); ++ ++ if (stat("control/locals.cdb", &st) == 0) { ++ while (!stralloc_copys(&localscdb, auto_qmail)) nomem(); ++ while (!stralloc_cats(&localscdb, "/control/locals.cdb")) nomem(); ++ while (!stralloc_0(&localscdb)) nomem(); ++ ++ constmap_free(&maplocals); ++ while (!constmap_init(&maplocals,"",0,1)) nomem(); ++ } else { ++ if (control_readfile(&newlocals,"control/locals",1) != 1) ++ { log1("alert: unable to reread control/locals\n"); return; } ++ ++ while (!stralloc_copys(&localscdb, "")) nomem(); ++ ++ constmap_free(&maplocals); ++ while (!stralloc_copy(&locals,&newlocals)) nomem(); ++ while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem(); ++ } ++ + r = control_readfile(&newvdoms,"control/virtualdomains",0); + if (r == -1) + { log1("alert: unable to reread control/virtualdomains\n"); return; } + +- constmap_free(&maplocals); + constmap_free(&mapvdoms); + +- while (!stralloc_copy(&locals,&newlocals)) nomem(); +- while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem(); +- + if (r) + { + while (!stralloc_copy(&vdoms,&newvdoms)) nomem(); +@@ -1504,15 +1831,22 @@ void reread() + log1("alert: unable to reread controls: unable to switch to home directory\n"); + return; + } ++#ifdef EXTERNAL_TODO ++ write(todofdout, "H", 1); ++#endif ++ comm_hup(0); /* send hup to qmail-lspawn */ + regetcontrols(); + while (chdir("queue") == -1) + { + log1("alert: unable to switch back to queue directory; HELP! sleeping...\n"); + sleep(10); + } ++#ifdef notyet ++ srandom(now()); ++#endif + } + +-void main() ++int main() + { + int fd; + datetime_sec wakeup; +@@ -1528,6 +1862,9 @@ void main() + { log1("alert: cannot start: unable to read controls\n"); _exit(111); } + if (chdir("queue") == -1) + { log1("alert: cannot start: unable to switch to queue directory\n"); _exit(111); } ++#ifdef notyet ++ srandom(now() + (getpid() << 16)); ++#endif + sig_pipeignore(); + sig_termcatch(sigterm); + sig_alarmcatch(sigalrm); +@@ -1544,15 +1881,22 @@ void main() + numjobs = 0; + for (c = 0;c < CHANNELS;++c) + { +- char ch; +- int u; ++ char ch, ch1; ++ unsigned int u; + int r; + do + r = read(chanfdin[c],&ch,1); + while ((r == -1) && (errno == error_intr)); + if (r < 1) ++ { log1("alert: cannot start qmail-lspawn or it had an error! " ++ "Check if ~control/ldapserver exists.\n"); _exit(111); } ++ do ++ r = read(chanfdin[c],&ch1,1); ++ while ((r == -1) && (errno == error_intr)); ++ if (r < 1) + { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); } + u = (unsigned int) (unsigned char) ch; ++ u += (unsigned int) ((unsigned char) ch1) << 8; + if (concurrency[c] > u) concurrency[c] = u; + numjobs += concurrency[c]; + } +@@ -1568,8 +1912,12 @@ void main() + todo_init(); + cleanup_init(); + ++#ifdef EXTERNAL_TODO ++ while (!flagexitasap || !del_canexit() || flagtodoalive) ++#else + while (!flagexitasap || !del_canexit()) +- { ++#endif ++ { + recent = now(); + + if (flagrunasap) { flagrunasap = 0; pqrun(); } +@@ -1608,5 +1956,5 @@ void main() + } + pqfinish(); + log1("status: exiting\n"); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-showctl.c qmail-ldap/qmail-showctl.c +--- qmail-1.03/qmail-showctl.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-showctl.c Thu Jan 29 16:48:14 2004 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include "substdio.h" + #include "subfd.h" + #include "exit.h" +@@ -15,10 +16,14 @@ + #include "auto_patrn.h" + #include "auto_spawn.h" + #include "auto_split.h" ++#include "byte.h" + + stralloc me = {0}; + int meok; + ++stralloc ldapserver = {0}; ++int ldapok; ++ + stralloc line = {0}; + char num[FMT_ULONG]; + +@@ -68,6 +73,36 @@ char *post; + } + } + ++void do_ulong(fn,def,pre,post) ++char *fn; ++char *def; ++char *pre; ++char *post; ++{ ++ unsigned long i; ++ substdio_puts(subfdout,"\n"); ++ substdio_puts(subfdout,fn); ++ substdio_puts(subfdout,": "); ++ switch(control_readulong(&i,fn)) { ++ case 0: ++ substdio_puts(subfdout,"(Default.) "); ++ substdio_puts(subfdout,pre); ++ substdio_puts(subfdout,def); ++ substdio_puts(subfdout,post); ++ substdio_puts(subfdout,".\n"); ++ break; ++ case 1: ++ substdio_puts(subfdout,pre); ++ substdio_put(subfdout,num,fmt_ulong(num,i)); ++ substdio_puts(subfdout,post); ++ substdio_puts(subfdout,".\n"); ++ break; ++ default: ++ substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); ++ break; ++ } ++} ++ + void do_str(fn,flagme,def,pre) + char *fn; + int flagme; +@@ -106,13 +141,13 @@ char *def; + char *pre; + char *post; + { +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + + substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,fn); + substdio_puts(subfdout,": "); +- switch(control_readfile(&line,fn)) { ++ switch(control_readfile(&line,fn, 0)) { + case 0: + substdio_puts(subfdout,"(Default.) "); + substdio_puts(subfdout,def); +@@ -136,7 +171,7 @@ char *post; + } + } + +-void main() ++int main() + { + DIR *dir; + direntry *d; +@@ -152,39 +187,39 @@ void main() + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"paternalism (in decimal): "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_patrn)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_patrn)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"silent concurrency limit: "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_spawn)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_spawn)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"subdirectory split: "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_split)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_split)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"user ids: "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uida)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uida)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidd)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uidd)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidl)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uidl)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uido)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uido)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidp)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uidp)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidq)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uidq)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidr)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uidr)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uids)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_uids)); + substdio_puts(subfdout,".\n"); + + substdio_puts(subfdout,"group ids: "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidn)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_gidn)); + substdio_puts(subfdout,", "); +- substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidq)); ++ substdio_put(subfdout,num,fmt_uint(num, auto_gidq)); + substdio_puts(subfdout,".\n"); + + if (chdir(auto_qmail) == -1) { +@@ -213,27 +248,60 @@ void main() + substdio_flush(subfdout); + _exit(111); + } ++ ldapok = control_readfile(&ldapserver,"ldapserver",0); ++ byte_repl(ldapserver.s, ldapserver.len, '\0', ' '); ++ if (ldapok == -1) { ++ substdio_puts(subfdout,"Oops! Trouble reading control/ldapserver."); ++ substdio_flush(subfdout); ++ _exit(111); ++ } ++ substdio_puts(subfdout,"me: My name is "); ++ substdio_put(subfdout, me.s, me.len); ++ substdio_puts(subfdout,"\nldapserver: My ldap server is "); ++ substdio_put(subfdout, ldapserver.s, ldapserver.len); ++ substdio_puts(subfdout,"\n\n"); ++ + + do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM."); ++ do_lst("badmailfrom-unknown","Any MAIL FROM from hosts without PTR is allowed.","", ++ " not accepted in MAIL FROM from host without PTR."); ++ do_lst("badrcptto","Any RCPT TO is allowed.",""," not accepted in RCPT TO"); ++ if (stat("bigbrother",&stmrh) == 0) ++ do_lst("bigbrother","No mail addresses are observed.","Observed mail address: ",""); + do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); + do_str("bouncehost",1,"bouncehost","Bounce host name is "); ++ do_ulong("bouncemaxbytes","0","Bounce data limit is "," bytes"); + do_int("concurrencylocal","10","Local concurrency is ",""); + do_int("concurrencyremote","20","Remote concurrency is ",""); +- do_int("databytes","0","SMTP DATA limit is "," bytes"); ++ do_lst("custombouncetext","No custombouncetext.","",""); ++ do_ulong("databytes","0","SMTP DATA limit is "," bytes"); + do_str("defaultdomain",1,"defaultdomain","Default domain name is "); + do_str("defaulthost",1,"defaulthost","Default host name is "); ++ do_str("dirmaker",0,"not defined","Program to create homedirs "); + do_str("doublebouncehost",1,"doublebouncehost","2B recipient host: "); + do_str("doublebounceto",0,"postmaster","2B recipient user: "); + do_str("envnoathost",1,"envnoathost","Presumed domain name is "); ++ do_lst("goodmailaddr","No good mail addresses.",""," is allowed in any case."); + do_str("helohost",1,"helohost","SMTP client HELO host name is "); + do_str("idhost",1,"idhost","Message-ID host name is "); + do_str("localiphost",1,"localiphost","Local IP address becomes "); + do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally."); + do_str("me",0,"undefined! Uh-oh","My name is "); ++ do_str("outgoingip",0,"0.0.0.0","Bind qmail-remote to "); ++ do_ulong("pbscachesize","1048576","PBS cachesize is "," bytes"); ++ do_lst("pbsenv","No environment variables will be passed.","Environment Variable: ",""); ++ do_str("pbsip",0,"0.0.0.0","Bind PBS daemon to "); ++ do_int("pbsport","2821","PBS deamon listens on port ",""); ++ do_str("pbssecret",0,"undefined! Uh-oh","PBS shared secret is "); ++ do_lst("pbsservers","No PBS servers.","PBS server ","."); ++ do_int("pbstimeout","600","PBS entries will be valid for "," seconds"); + do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@","."); + do_str("plusdomain",1,"plusdomain","Plus domain name is "); ++ do_str("qmqpcip",0,"0.0.0.0","Bind qmail-qmqpc to "); + do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); + do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds"); ++ do_lst("quotawarning","No quotawarning.","",""); ++ do_lst("rbllist","No RBL listed.","RBL to check: ","."); + + if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ",".")) + do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ","."); +@@ -255,6 +323,7 @@ void main() + else + substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n"); + ++ do_lst("relaymailfrom","Relaymailfrom not enabled.","Envelope senders allowed to relay: ","."); + do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 "); + do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ",""); + do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds"); +@@ -262,45 +331,111 @@ void main() + do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds"); + do_lst("virtualdomains","No virtual domains.","Virtual domain: ",""); + +- while (d = readdir(dir)) { ++ ++ substdio_puts(subfdout,"\n\n\nNow the qmail-ldap specific files:\n"); ++ do_str("ldapbasedn",0,"NULL","LDAP basedn: "); ++ do_lst("ldapserver","undefined! Uh-oh","",""); ++ do_str("ldaplogin",0,"NULL","LDAP login: "); ++ do_str("ldappassword",0,"NULL","LDAP password: "); ++ do_int("ldaptimeout","30","LDAP server timeout is "," seconds"); ++ do_str("ldapuid",0,"not defined","Default UID is "); ++ do_str("ldapgid",0,"not defined","Default GID is "); ++ do_str("ldapobjectclass",0,"not defined","The objectclass to limit ldap filter is "); ++ do_str("ldapmessagestore",0,"not defined","Prefix for non absolute paths is "); ++ do_str("ldapdefaultdotmode",0,"ldaponly","Default dot mode for ldap users is "); ++ do_ulong("defaultquotasize","0","Mailbox size quota is "," bytes (0 is unlimited)"); ++ do_ulong("defaultquotacount","0","Mailbox count quota is "," messages (0 is unlimited)"); ++ do_int("ldaplocaldelivery","1","Local passwd lookup is "," (1 = on, 0 = off)"); ++ do_int("ldaprebind","0","Ldap rebinding is "," (1 = on, 0 = off)"); ++ do_int("ldapcluster","0","Clustering is "," (1 = on, 0 = off)"); ++ do_lst("ldapclusterhosts","Messages for me are not redirected.", ++ "Messages for "," are not redirected."); ++ ++ substdio_puts(subfdout,"\n"); ++ ++ ++ while ((d = readdir(dir))) { + if (str_equal(d->d_name,".")) continue; + if (str_equal(d->d_name,"..")) continue; +- if (str_equal(d->d_name,"bouncefrom")) continue; +- if (str_equal(d->d_name,"bouncehost")) continue; + if (str_equal(d->d_name,"badmailfrom")) continue; ++ if (str_equal(d->d_name,"badmailfrom-unknown")) continue; ++ if (str_equal(d->d_name,"badrcptto")) continue; ++ if (str_equal(d->d_name,"bigbrother")) continue; + if (str_equal(d->d_name,"bouncefrom")) continue; + if (str_equal(d->d_name,"bouncehost")) continue; ++ if (str_equal(d->d_name,"bouncemaxbytes")) continue; + if (str_equal(d->d_name,"concurrencylocal")) continue; + if (str_equal(d->d_name,"concurrencyremote")) continue; ++ if (str_equal(d->d_name,"custombouncetext")) continue; + if (str_equal(d->d_name,"databytes")) continue; + if (str_equal(d->d_name,"defaultdomain")) continue; + if (str_equal(d->d_name,"defaulthost")) continue; ++ if (str_equal(d->d_name,"defaultquotacount")) continue; ++ if (str_equal(d->d_name,"defaultquotasize")) continue; ++ if (str_equal(d->d_name,"dirmaker")) continue; + if (str_equal(d->d_name,"doublebouncehost")) continue; + if (str_equal(d->d_name,"doublebounceto")) continue; + if (str_equal(d->d_name,"envnoathost")) continue; + if (str_equal(d->d_name,"helohost")) continue; ++ if (str_equal(d->d_name,"goodmailaddr")) continue; + if (str_equal(d->d_name,"idhost")) continue; ++ if (str_equal(d->d_name,"ldapbasedn")) continue; ++ if (str_equal(d->d_name,"ldapcluster")) continue; ++ if (str_equal(d->d_name,"ldapclusterhosts")) continue; ++ if (str_equal(d->d_name,"ldapdefaultdotmode")) continue; ++ if (str_equal(d->d_name,"ldapgid")) continue; ++ if (str_equal(d->d_name,"ldaplocaldelivery")) continue; ++ if (str_equal(d->d_name,"ldaplogin")) continue; ++ if (str_equal(d->d_name,"ldapmessagestore")) continue; ++ if (str_equal(d->d_name,"ldapobjectclass")) continue; ++ if (str_equal(d->d_name,"ldappassword")) continue; ++ if (str_equal(d->d_name,"ldaprebind")) continue; ++ if (str_equal(d->d_name,"ldapserver")) continue; ++ if (str_equal(d->d_name,"ldaptimeout")) continue; ++ if (str_equal(d->d_name,"ldapuid")) continue; + if (str_equal(d->d_name,"localiphost")) continue; + if (str_equal(d->d_name,"locals")) continue; + if (str_equal(d->d_name,"me")) continue; + if (str_equal(d->d_name,"morercpthosts")) continue; + if (str_equal(d->d_name,"morercpthosts.cdb")) continue; ++ if (str_equal(d->d_name,"outgoingip")) continue; ++ if (str_equal(d->d_name,"pbscachesize")) continue; ++ if (str_equal(d->d_name,"pbsenv")) continue; ++ if (str_equal(d->d_name,"pbsip")) continue; ++ if (str_equal(d->d_name,"pbsport")) continue; ++ if (str_equal(d->d_name,"pbssecret")) continue; ++ if (str_equal(d->d_name,"pbsservers")) continue; ++ if (str_equal(d->d_name,"pbstimeout")) continue; + if (str_equal(d->d_name,"percenthack")) continue; + if (str_equal(d->d_name,"plusdomain")) continue; ++ if (str_equal(d->d_name,"qmqpcip")) continue; + if (str_equal(d->d_name,"qmqpservers")) continue; + if (str_equal(d->d_name,"queuelifetime")) continue; ++ if (str_equal(d->d_name,"quotawarning")) continue; ++ if (str_equal(d->d_name,"rbllist")) continue; + if (str_equal(d->d_name,"rcpthosts")) continue; ++ if (str_equal(d->d_name,"relaymailfrom")) continue; + if (str_equal(d->d_name,"smtpgreeting")) continue; + if (str_equal(d->d_name,"smtproutes")) continue; + if (str_equal(d->d_name,"timeoutconnect")) continue; + if (str_equal(d->d_name,"timeoutremote")) continue; + if (str_equal(d->d_name,"timeoutsmtpd")) continue; + if (str_equal(d->d_name,"virtualdomains")) continue; +- substdio_puts(subfdout,"\n"); ++ if (str_equal(d->d_name,"ldapusername") || ++ str_equal(d->d_name,"ldappasswdappend") || ++ str_equal(d->d_name,"ldapdefaultquota") || ++ str_equal(d->d_name,"rblonlyheader") || ++ str_equal(d->d_name,"maxrcptcount") || ++ str_equal(d->d_name,"tarpitdelay") || ++ str_equal(d->d_name,"tarpitcount")) { ++ substdio_puts(subfdout,d->d_name); ++ substdio_puts(subfdout,": No longer used, please remove.\n"); ++ continue; ++ } + substdio_puts(subfdout,d->d_name); + substdio_puts(subfdout,": I have no idea what this file does.\n"); + } + + substdio_flush(subfdout); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-smtpd.c qmail-ldap/qmail-smtpd.c +--- qmail-1.03/qmail-smtpd.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-smtpd.c Wed Aug 18 11:27:12 2004 +@@ -1,7 +1,9 @@ ++#include + #include "sig.h" + #include "readwrite.h" + #include "stralloc.h" + #include "substdio.h" ++#include "subfd.h" + #include "alloc.h" + #include "auto_qmail.h" + #include "control.h" +@@ -20,72 +22,234 @@ + #include "now.h" + #include "exit.h" + #include "rcpthosts.h" ++#include "rbl.h" + #include "timeoutread.h" + #include "timeoutwrite.h" + #include "commands.h" ++#include "dns.h" ++#include "smtpcall.h" ++#include "limit.h" ++#ifdef SMTPEXECCHECK ++#include "execcheck.h" ++#endif ++#ifdef TLS_SMTPD ++#include ++SSL *ssl = NULL; ++#endif ++#ifdef DATA_COMPRESS ++/* zlib needs to be after openssl includes or build will fail */ ++#include ++#endif + + #define MAXHOPS 100 +-unsigned int databytes = 0; ++#define MAXLINELEN 10000 ++unsigned long databytes = 0; + int timeout = 1200; + +-int safewrite(fd,buf,len) int fd; char *buf; int len; ++#ifdef TLS_SMTPD ++int flagtimedout = 0; ++void sigalrm() ++{ ++ flagtimedout = 1; ++} ++int ssl_timeoutread(int tout, int fd, void *buf, int n) ++{ ++ int r; int saveerrno; ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ alarm(tout); ++ r = SSL_read(ssl,buf,n); ++ saveerrno = errno; ++ alarm(0); ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ errno = saveerrno; ++ return r; ++} ++int ssl_timeoutwrite(int tout, int fd, const void *buf, int n) ++{ ++ int r; int saveerrno; ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ alarm(tout); ++ r = SSL_write(ssl,buf,n); ++ saveerrno = errno; ++ alarm(0); ++ if (flagtimedout) { errno = error_timeout; return -1; } ++ errno = saveerrno; ++ return r; ++} ++#endif ++ ++void die_write(void); ++ ++int safewrite(int fd, void *buf, int len) + { + int r; ++#ifdef TLS_SMTPD ++ if (ssl) ++ r = ssl_timeoutwrite(timeout,fd,buf,len); ++ else ++#endif + r = timeoutwrite(timeout,fd,buf,len); +- if (r <= 0) _exit(1); ++ if (r <= 0) die_write(); + return r; + } + + char ssoutbuf[512]; + substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); + +-void flush() { substdio_flush(&ssout); } +-void out(s) char *s; { substdio_puts(&ssout,s); } ++void flush(void) { substdio_flush(&ssout); } ++void out(const char *s) { substdio_puts(&ssout,s); } ++ ++/* level 0 = no logging ++ 1 = fatal errors ++ 2 = connection setup and warnings ++ 3 = verbose */ ++ ++int loglevel = 0; ++ ++void logpid(int level) ++{ ++ char pidstring[FMT_ULONG]; ++ if (level > loglevel) return; ++ substdio_puts(subfderr,"qmail-smtpd "); ++ pidstring[fmt_uint(pidstring, getpid())] = 0; ++ substdio_puts(subfderr,pidstring); ++ substdio_puts(subfderr,": "); ++} ++ ++void logline(int level, const char *string) ++{ ++ if (level > loglevel) return; ++ logpid(level); ++ substdio_puts(subfderr,string); ++ substdio_puts(subfderr,"\n"); ++ substdio_flush(subfderr); ++} ++ ++void logline2(int level, const char *s1, const char *s2) ++{ ++ if (level > loglevel) return; ++ logpid(level); ++ substdio_puts(subfderr,s1); ++ substdio_puts(subfderr,s2); ++ substdio_puts(subfderr,"\n"); ++ substdio_flush(subfderr); ++} ++ ++void logstring(int level, const char *string) ++{ ++ if (level > loglevel) return; ++ substdio_puts(subfderr,string); ++} ++ ++void logflush(int level) ++{ ++ if (level > loglevel) return; ++ substdio_puts(subfderr,"\n"); ++ substdio_flush(subfderr); ++} + +-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 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() { 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() { out("250 ok\r\n"); } +-void err_vrfy() { 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 cleanup(void); + ++const char *remoteip; + ++void die_read(void) { logline(1,"read error or connection closed"); cleanup(); _exit(1); } ++void die_write(void) { logline(1,"write error, connection closed"); cleanup(); _exit(1); } ++void die_alarm(void) { out("451 timeout (#4.4.2)\r\n"); logline(1,"connection timed out, closing connection"); flush(); cleanup(); _exit(1); } ++void die_nomem(void) { out("421 out of memory (#4.3.0)\r\n"); logline(1,"out of memory, closing connection"); flush(); cleanup(); _exit(1); } ++void die_control(void) { out("421 unable to read controls (#4.3.0)\r\n"); logline(1,"unable to read controls, closing connection"); flush(); _exit(1); } ++void die_ipme(void) { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); logline(1,"unable to figure out my IP address, closing connection"); flush(); _exit(1); } ++void straynewline(void) { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); logline(1,"stray new line detected, closing connection"); flush(); _exit(1); } ++void oversizedline(void) { out("500 Text line too long."); logline(1,"Oversized line in data part, closing connection"); flush(); _exit(1); } ++void err_qqt(void) { out("451 qqt failure (#4.3.0)\r\n"); } ++void err_dns(void) { out("421 DNS temporary failure at return MX check, try again later (#4.3.0)\r\n"); } ++void err_ldapsoft(void) { out("451 temporary ldap lookup failure, try again later\r\n"); logline(1,"temporary ldap lookup failure"); } ++void err_bmf(void) { out("553 sorry, your mail was administratively denied. (#5.7.1)\r\n"); } ++void err_bmfunknown(void) { out("553 sorry, your mail from a host ["); out(remoteip); out("] without valid reverse DNS was administratively denied (#5.7.1)\r\n"); } ++void err_maxrcpt(void) { out("553 sorry, too many recipients (#5.7.1)\r\n"); } ++void err_nogateway(void) { out("553 sorry, relaying denied from your location ["); out(remoteip); out("] (#5.7.1)\r\n"); } ++void err_badbounce(void) { out("550 sorry, I don't accept bounce messages with more than one recipient. Go read RFC2821. (#5.7.1)\r\n"); } ++void err_unimpl(const char *arg) { out("502 unimplemented (#5.5.1)\r\n"); logline2(3,"unrecognized command: ",arg); } ++void err_size(void) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); logline(3,"message denied because: 'SMTP SIZE' too big"); } ++void err_syntax(void) { out("555 syntax error (#5.5.4)\r\n"); } ++void err_relay(void) { out("553 sorry, we don't relay for ["); out(remoteip); out("] (#5.7.1)\r\n"); } ++void err_wantmail(void) { out("503 MAIL first (#5.5.1)\r\n"); logline(4,"'mail from' first"); } ++void err_wantrcpt(void) { out("503 RCPT first (#5.5.1)\r\n"); logline(4,"'rcpt to' first"); } ++ ++void err_noop(char *arg) { out("250 ok\r\n"); logline(4,"'noop'"); } ++void err_vrfy(char *arg) { out("252 send some mail, i'll try my best\r\n"); logline2(4,"vrfy for: ",arg); } ++ ++void err_rbl(char *arg) { out("553 sorry, your mailserver ["); out(remoteip); out("] is rejected by "); out(arg); out("\r\n"); } ++void err_deny(void) { out("553 sorry, mail from your location ["); out(remoteip); out("] is administratively denied (#5.7.1)\r\n"); } ++void err_badrcptto(void) { out("553 sorry, mail to that recipient is not accepted (#5.7.1)\r\n"); } ++void err_554msg(const char *arg) ++{ ++ out("554 "); out(arg); out("\r\n"); ++ logline2(3,"message denied because: ",arg); ++} ++ ++ ++stralloc me = {0}; + stralloc greeting = {0}; ++stralloc cookie = {0}; + +-void smtp_greet(code) char *code; ++void smtp_greet(const char *code) + { + substdio_puts(&ssout,code); ++ substdio_puts(&ssout,me.s); ++ substdio_puts(&ssout," ESMTP "); + substdio_put(&ssout,greeting.s,greeting.len); ++ if (cookie.len > 0) { ++ substdio_puts(&ssout," "); ++ substdio_put(&ssout,cookie.s,cookie.len); ++ } ++ out("\r\n"); + } +-void smtp_help() ++void smtp_line(const char *code) + { +- out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); ++ substdio_puts(&ssout,code); ++ substdio_puts(&ssout,me.s); ++ substdio_puts(&ssout," "); ++ substdio_put(&ssout,greeting.s,greeting.len); ++ out("\r\n"); ++} ++void smtp_help(char *arg) ++{ ++ out("214-qmail home page: http://pobox.com/~djb/qmail.html\r\n"); ++ out("214 qmail-ldap patch home page: http://www.nrg4u.com\r\n"); ++ logline(4,"help requested"); + } +-void smtp_quit() ++void smtp_quit(char *arg) + { +- smtp_greet("221 "); out("\r\n"); flush(); _exit(0); ++ if (!stralloc_copys(&greeting,"Goodbye.")) ++ die_nomem(); ++ smtp_line("221 "); ++ logline(4,"quit, closing connection"); ++ flush(); ++ cleanup(); ++ _exit(0); ++} ++void err_quit(void) ++{ ++ logline(4,"force closing connection"); ++ flush(); ++ cleanup(); ++ _exit(0); + } + +-char *remoteip; +-char *remotehost; +-char *remoteinfo; +-char *local; +-char *relayclient; ++const char *remotehost; ++const char *remoteinfo; ++const char *local; ++const char *relayclient; ++const char *relayok; ++const char *greeting550; ++const char *greeting421; ++int spamflag = 0; + + stralloc helohost = {0}; + char *fakehelo; /* pointer into helohost, or 0 */ + +-void dohelo(arg) char *arg; { ++void dohelo(const char *arg) ++{ + if (!stralloc_copys(&helohost,arg)) die_nomem(); + if (!stralloc_0(&helohost)) die_nomem(); + fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0; +@@ -96,51 +260,224 @@ stralloc liphost = {0}; + int bmfok = 0; + stralloc bmf = {0}; + struct constmap mapbmf; ++int bmfunknownok = 0; ++stralloc bmfunknown = {0}; ++struct constmap mapbmfunknown; ++int rmfok = 0; ++stralloc rmf = {0}; ++struct constmap maprmf; ++int brtok = 0; ++stralloc brt = {0}; ++struct constmap mapbadrcptto; ++int gmaok = 0; ++stralloc gma = {0}; ++struct constmap mapgma; ++int rblok = 0; ++int rbloh = 0; ++int errdisconnect = 0; ++int nobounce = 0; ++int sanitycheck = 0; ++int returnmxcheck = 0; ++int blockrelayprobe = 0; ++unsigned int tarpitcount = 0; ++unsigned int tarpitdelay = 5; ++unsigned int maxrcptcount = 0; ++int sendercheck = 0; ++int rcptcheck = 0; ++int ldapsoftok = 0; ++int flagauth = 0; ++int needauth = 0; ++int needssl = 0; ++int flagauthok = 0; ++const char *authprepend; ++#ifdef TLS_SMTPD ++stralloc sslcert = {0}; ++#endif ++char smtpsize[FMT_ULONG]; + +-void setup() ++void setup(void) + { +- char *x; ++#ifdef TLS_SMTPD ++ char *sslpath; ++#endif ++ char *x, *l; + unsigned long u; +- ++ ++ l = env_get("LOGLEVEL"); ++ if (l) { scan_ulong(l,&u); loglevel = u > 4 ? 4 : u; } ++ + if (control_init() == -1) die_control(); +- if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) ++ ++ if (control_readline(&me,"control/me") != 1) ++ die_control(); ++ if (!stralloc_0(&me)) die_nomem(); ++ ++ if (control_rldef(&greeting,"control/smtpgreeting", 0, "") == -1) + die_control(); ++ ++ if (control_rldef(&cookie,"control/smtpclustercookie", 0, "") == -1) ++ die_control(); ++ if (cookie.len > 32) cookie.len = 32; ++ + liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0); + if (liphostok == -1) die_control(); ++ + if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); + if (timeout <= 0) timeout = 1; + ++#ifdef TLS_SMTPD ++ sslpath = env_get("SSLCERT"); ++ if (!sslpath) { ++ sslpath = (char *)"control/smtpcert"; ++ if (control_readline(&sslcert, sslpath) == -1) ++ die_control(); ++ } else ++ if (!stralloc_copys(&sslcert, sslpath)) die_nomem(); ++ if (!stralloc_0(&sslcert)) die_nomem(); ++#endif ++ ++ x = env_get("TARPITCOUNT"); ++ if (x) { scan_ulong(x,&u); tarpitcount = u >= UINT_MAX ? UINT_MAX - 1 : u; } ++ ++ x = env_get("TARPITDELAY"); ++ if (x) { scan_ulong(x,&u); tarpitdelay = u > INT_MAX ? INT_MAX : u; } ++ ++ x = env_get("MAXRCPTCOUNT"); ++ if (x) { scan_ulong(x,&u); maxrcptcount = u >= UINT_MAX ? UINT_MAX - 1 : u; }; ++ + if (rcpthosts_init() == -1) die_control(); + + bmfok = control_readfile(&bmf,"control/badmailfrom",0); + if (bmfok == -1) die_control(); + if (bmfok) + if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); +- +- if (control_readint(&databytes,"control/databytes") == -1) die_control(); ++ ++ bmfunknownok = control_readfile(&bmfunknown,"control/badmailfrom-unknown",0); ++ if (bmfunknownok == -1) die_control(); ++ if (bmfunknownok) ++ if (!constmap_init(&mapbmfunknown,bmfunknown.s,bmfunknown.len,0)) ++ die_nomem(); ++ ++ rmfok = control_readfile(&rmf,"control/relaymailfrom",0); ++ if (rmfok == -1) die_control(); ++ if (rmfok) ++ if (!constmap_init(&maprmf,rmf.s,rmf.len,0)) die_nomem(); ++ ++ brtok = control_readfile(&brt,"control/badrcptto",0); ++ if (brtok == -1) die_control(); ++ if (brtok) ++ if (!constmap_init(&mapbadrcptto,brt.s,brt.len,0)) die_nomem(); ++ ++ gmaok = control_readfile(&gma,"control/goodmailaddr",0); ++ if (gmaok == -1) die_control(); ++ if (gmaok) ++ if (!constmap_init(&mapgma,gma.s,gma.len,0)) die_nomem(); ++ ++ if (env_get("RBL")) { ++ rblok = rblinit(); ++ if (rblok == -1) die_control(); ++ if (env_get("RBLONLYHEADER")) rbloh = 1; ++ } ++ ++ if (env_get("SMTP550DISCONNECT")) errdisconnect = 1; ++ if (env_get("NOBOUNCE")) nobounce = 1; ++ if (env_get("SANITYCHECK")) sanitycheck = 1; ++ if (env_get("RETURNMXCHECK")) returnmxcheck = 1; ++ if (env_get("BLOCKRELAYPROBE")) blockrelayprobe = 1; ++ if (env_get("SENDERCHECK")) { ++ sendercheck = 1; ++ if (!case_diffs("LOOSE",env_get("SENDERCHECK"))) sendercheck = 2; ++ if (!case_diffs("STRICT",env_get("SENDERCHECK"))) sendercheck = 3; ++ } ++ if (env_get("RCPTCHECK")) rcptcheck = 1; ++ if (env_get("LDAPSOFTOK")) ldapsoftok = 1; ++ greeting550 = env_get("550GREETING"); ++ greeting421 = env_get("421GREETING"); ++ relayok = relayclient = env_get("RELAYCLIENT"); ++ ++ if (env_get("SMTPAUTH")) { ++ flagauth = 1; ++ if (!case_diffs("TLSREQUIRED", env_get("SMTPAUTH"))) needssl = 1; ++ } ++ if (env_get("AUTHREQUIRED")) needauth = 1; ++ authprepend = env_get("AUTHPREPEND"); ++ ++#ifdef SMTPEXECCHECK ++ execcheck_setup(); ++#endif ++ ++ if (control_readulong(&databytes,"control/databytes") == -1) die_control(); + x = env_get("DATABYTES"); +- if (x) { scan_ulong(x,&u); databytes = u; } +- if (!(databytes + 1)) --databytes; ++ if (x) scan_ulong(x,&databytes); ++ if (!(databytes + 1)) --databytes; /* poor man overflow detection */ + + remoteip = env_get("TCPREMOTEIP"); + if (!remoteip) remoteip = "unknown"; +- local = env_get("TCPLOCALHOST"); +- if (!local) local = env_get("TCPLOCALIP"); +- if (!local) local = "unknown"; + remotehost = env_get("TCPREMOTEHOST"); + if (!remotehost) remotehost = "unknown"; + remoteinfo = env_get("TCPREMOTEINFO"); +- relayclient = env_get("RELAYCLIENT"); ++ ++ local = env_get("TCPLOCALHOST"); ++ if (!local) local = env_get("TCPLOCALIP"); ++ if (!local) local = "unknown"; ++ ++ logpid(2); ++ logstring(2,"connection from "); logstring(2,remoteip); ++ logstring(2," ("); logstring(2,remotehost); ++ if (remoteinfo) { logstring(2,", "); logstring(2,remoteinfo); } ++ logstring(2,") to "); logstring(2,local); ++ logflush(2); ++ ++ logpid(3); ++ logstring(3, "enabled options: "); ++ if (databytes != 0) { ++ smtpsize[fmt_ulong(smtpsize, databytes)] = 0; ++ logstring(3,"max msg size: "); ++ logstring(3,smtpsize); ++ logstring(3," "); ++ } ++ if (greeting550) logstring(3,"greeting550 "); ++#ifdef TLS_SMTPD ++ if (sslcert.s && *sslcert.s) logstring(3, "starttls "); ++#endif ++ if (relayclient) logstring(3,"relayclient "); ++ if (sanitycheck) logstring(3,"sanitycheck "); ++ if (returnmxcheck) logstring(3,"returnmxcheck "); ++ if (blockrelayprobe) logstring(3,"blockrelayprobe "); ++ if (nobounce) logstring(3,"nobounce "); ++ if (rblok) logstring(3,"rblcheck "); ++ if (rbloh) logstring(3,"rblonlyheader "); ++ if (sendercheck) logstring(3,"sendercheck"); ++ if (sendercheck == 1) logstring(3," "); ++ if (sendercheck == 2) logstring(3,"-loose "); ++ if (sendercheck == 3) logstring(3,"-strict "); ++ if (rcptcheck) logstring(3,"rcptcheck "); ++ if (ldapsoftok) logstring(3,"ldapsoftok "); ++ if (flagauth) logstring(3, "smtp-auth"); ++ if (needssl) logstring(3, "-tls-required "); ++ else logstring(3, " "); ++ if (needauth) logstring(3, "authrequired "); ++#ifdef SMTPEXECCHECK ++ if (execcheck_on()) logstring(3, "rejectexecutables "); ++#endif ++ if (errdisconnect) logstring(3,"smtp550disconnect "); ++#ifdef ALTQUEUE ++ if (env_get("QMAILQUEUE")) { ++ logstring(3,"qmailqueue "); ++ logstring(3,env_get("QMAILQUEUE")); ++ } ++#endif ++ logflush(3); ++ + dohelo(remotehost); + } + + + stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ + +-int addrparse(arg) +-char *arg; ++int addrparse(char *arg) + { +- int i; ++ unsigned int i; + char ch; + char terminator; + struct ip_address ip; +@@ -155,6 +492,7 @@ char *arg; + terminator = ' '; + arg += str_chr(arg,':'); + if (*arg == ':') ++arg; ++ if (*arg == '\0') return 0; + while (*arg == ' ') ++arg; + } + +@@ -164,7 +502,7 @@ char *arg; + if (!stralloc_copys(&addr,"")) die_nomem(); + flagesc = 0; + flagquoted = 0; +- for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ ++ for (i = 0;(ch = arg[i]);++i) { /* copy arg to addr, stripping quotes */ + if (flagesc) { + if (!stralloc_append(&addr,&ch)) die_nomem(); + flagesc = 0; +@@ -197,78 +535,721 @@ char *arg; + return 1; + } + +-int bmfcheck() ++stralloc checkhost = {0}; ++ipalloc checkip = {0}; ++ ++int badmxcheck(char *dom) ++{ ++ int ret = 0; ++ unsigned long r; ++ ++ if (!*dom) return (DNS_HARD); ++ if (!stralloc_copys(&checkhost,dom)) return (DNS_SOFT); ++ ++ r = now() + (getpid() << 16); ++ switch (dns_mxip(&checkip,&checkhost,r)) ++ { ++ case DNS_MEM: ++ case DNS_SOFT: ++ ret = DNS_SOFT; ++ break; ++ case DNS_HARD: ++ ret = DNS_HARD; ++ break; ++ case 1: ++ if (checkip.len <= 0) ret = DNS_SOFT; ++ break; ++ default: ++ if (checkip.len <= 0) ret = DNS_HARD; ++ break; ++ } ++ return (ret); ++} ++ ++stralloc parameter = {0}; ++ ++char *getparameter(char *arg, const char *name) ++{ ++ unsigned int i; ++ char ch; ++ char terminator; ++ int flagesc; ++ int flagquoted; ++ ++ terminator = '>'; ++ i = str_chr(arg,'<'); ++ if (arg[i]) ++ arg += i + 1; ++ else { /* partner should go read rfc 821 */ ++ terminator = ' '; ++ arg += str_chr(arg,':'); ++ if (*arg == ':') ++arg; ++ while (*arg == ' ') ++arg; ++ } ++ ++ flagesc = 0; ++ flagquoted = 0; ++ for (i = 0;(ch = arg[i]);++i) { /* skipping addr, respecting quotes */ ++ if (flagesc) { ++ flagesc = 0; ++ } else { ++ if (!flagquoted && (ch == terminator)) break; ++ switch(ch) { ++ case '\\': flagesc = 1; break; ++ case '"': flagquoted = !flagquoted; break; ++ default: break; ++ } ++ } ++ } ++ if (!arg[i++]) return (char *)0; /* no parameters */ ++ arg += i; ++ do { ++ while (*arg == ' ') if (!*arg++) return (char *)0; ++ if (case_diffb(arg, str_len(name), name) == 0) { ++ arg += str_len(name); ++ if (*arg++ == '=') { ++ i = str_chr(arg, ' '); ++ if (!stralloc_copyb(¶meter, arg, i)) die_nomem(); ++ if (!stralloc_0(¶meter)) die_nomem(); ++ return parameter.s; ++ } ++ } ++ while (*arg != ' ') if (!*arg++) return (char *)0; ++ } while (1); ++} ++ ++int sizelimit(char *arg) + { +- int j; ++ char *size; ++ unsigned long sizebytes = 0; ++ ++ size = getparameter(arg, "SIZE"); ++ if (!size) return 1; ++ ++ scan_ulong(size, &sizebytes); ++ return databytes >= sizebytes; ++} ++ ++ ++int bmfcheck(void) ++{ ++ unsigned int j; ++ + if (!bmfok) return 0; + if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1; + j = byte_rchr(addr.s,addr.len,'@'); + if (j < addr.len) ++ { + if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1; ++ if (constmap(&mapbmf,addr.s, j + 1)) return 1; ++ } + return 0; + } + +-int addrallowed() ++int bmfunknowncheck(void) ++{ ++ unsigned int j; ++ ++ if (!bmfunknownok) return 0; ++ if (case_diffs(remotehost,"unknown")) return 0; ++ if (constmap(&mapbmfunknown,addr.s,addr.len - 1)) return 1; ++ j = byte_rchr(addr.s,addr.len,'@'); ++ if (j < addr.len) ++ if (constmap(&mapbmfunknown,addr.s + j,addr.len - j - 1)) return 1; ++ return 0; ++} ++ ++int seenmail = 0; ++stralloc mailfrom = {0}; ++stralloc rcptto = {0}; ++unsigned int rcptcount; ++ ++int rmfcheck(void) ++{ ++ unsigned int j; ++ ++ if (!rmfok) return 0; ++ if (constmap(&maprmf,addr.s,addr.len - 1)) return 1; ++ j = byte_rchr(addr.s,addr.len,'@'); ++ if (j < addr.len) ++ if (constmap(&maprmf,addr.s + j,addr.len - j - 1)) return 1; ++ return 0; ++} ++ ++int addrallowed(void) + { + int r; +- r = rcpthosts(addr.s,str_len(addr.s)); ++ ++ r = rcpthosts(addr.s,addr.len - 1); + if (r == -1) die_control(); + return r; + } + ++int addrlocals(void) ++{ ++ int r; + +-int seenmail = 0; +-int flagbarf; /* defined if seenmail */ +-stralloc mailfrom = {0}; +-stralloc rcptto = {0}; ++ r = localhosts(addr.s, addr.len - 1); ++ if (r == -1) die_control(); ++ return r; ++} ++ ++int rcptdenied(void) ++{ ++ unsigned int j; ++ ++ if (!brtok) return 0; ++ if (constmap(&mapbadrcptto, addr.s, addr.len - 1)) return 1; ++ j = byte_rchr(addr.s,addr.len,'@'); ++ if (j < addr.len) ++ if (constmap(&mapbadrcptto, addr.s + j, addr.len - j - 1)) ++ return 1; ++ return 0; ++} ++ ++int goodmailaddr(void) ++{ ++ unsigned int j; ++ ++ if (!gmaok) return 0; ++ if (constmap(&mapgma, addr.s, addr.len - 1)) return 1; ++ j = byte_rchr(addr.s,addr.len,'@'); ++ if (j < addr.len) ++ if (constmap(&mapgma, addr.s + j, addr.len - j - 1)) ++ return 1; ++ return 0; ++} ++ ++struct call ccverify; ++stralloc verifyresponse; ++int flagverify = 0; ++ ++void ldaplookupdone(void) ++{ ++ if (flagverify != 1) return; ++ call_close(&ccverify); ++ flagverify = 0; ++ return; ++} ++ ++int ldaplookup(char *address, char **s) ++{ ++ char ch; ++ ++ if (flagverify == -1) return -1; ++ if (flagverify == 0) { ++ if (call_open(&ccverify, "bin/qmail-verify", 30, 0) == -1) { ++ flagverify = -1; ++ return -1; ++ } ++ flagverify = 1; ++ } ++ call_puts(&ccverify, address); call_putflush(&ccverify, "", 1); ++ if (call_getc(&ccverify, &ch) != 1) ++ goto fail; ++ switch (ch) { ++ case 'K': ++ return 1; ++ case 'D': ++ /* get response */ ++ if (!stralloc_copys(&verifyresponse, "")) die_nomem(); ++ while (call_getc(&ccverify, &ch) == 1) { ++ if (!stralloc_append(&verifyresponse, &ch)) die_nomem(); ++ if (ch == 0) { ++ *s = verifyresponse.s; ++ return 0; ++ } ++ } ++ /* FALLTHROUGH */ ++ case 'Z': ++ default: ++ break; ++ } ++fail: ++ flagverify = -1; ++ call_close(&ccverify); ++ return -1; ++} + +-void smtp_helo(arg) char *arg; ++int relayprobe(void) /* relay probes trying stupid old sendwhale bugs */ + { +- smtp_greet("250 "); out("\r\n"); ++ unsigned int j; ++ for (j = byte_rchr(addr.s, addr.len, '@'); j-- > 0; ) { ++ if (addr.s[j] == '@') return 1; /* double @ */ ++ if (addr.s[j] == '%') return 1; /* percent relaying */ ++ if (addr.s[j] == '!') return 1; /* UUCP bang path */ ++ } ++ return 0; ++} ++ ++ ++void smtp_helo(char *arg) ++{ ++ smtp_line("250 "); + seenmail = 0; dohelo(arg); ++ logline2(4, "remote helo: ", arg); + } +-void smtp_ehlo(arg) char *arg; ++ ++void smtp_ehlo(char *arg) + { +- smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); ++ smtp_line("250-"); ++ out("250-PIPELINING\r\n"); ++ if (databytes != 0) { ++ smtpsize[fmt_ulong(smtpsize, databytes)] = 0; ++ out("250-SIZE "); out(smtpsize); out("\r\n"); ++ } ++#ifdef DATA_COMPRESS ++ out("250-DATAZ\r\n"); ++#endif ++#ifdef TLS_SMTPD ++ if (!ssl && sslcert.s && *sslcert.s) ++ out("250-STARTTLS\r\n"); ++#endif ++#ifdef TLS_SMTPD ++ if (!needssl || ssl) ++#endif ++ if (flagauth) ++ out("250-AUTH LOGIN PLAIN\r\n"); ++ out("250 8BITMIME\r\n"); ++ + seenmail = 0; dohelo(arg); ++ logline2(4,"remote ehlo: ",arg); + } +-void smtp_rset() ++ ++void smtp_rset(char *arg) + { + seenmail = 0; ++ relayclient = relayok; /* restore original relayclient setting */ + out("250 flushed\r\n"); ++ logline(4,"remote rset"); + } +-void smtp_mail(arg) char *arg; ++ ++struct qmail qqt; ++ ++void smtp_mail(char *arg) + { +- if (!addrparse(arg)) { err_syntax(); return; } +- flagbarf = bmfcheck(); ++ unsigned int i,j; ++ char *rblname; ++ int bounceflag = 0; ++ ++ /* address syntax check */ ++ if (!addrparse(arg)) ++ { ++ err_syntax(); ++ logline2(3,"RFC2821 syntax error in mail from: ",arg); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ logline2(3,"mail from: ",addr.s); ++ ++ if (needauth && !flagauthok) { ++ out("530 authentication needed\r\n"); ++ logline(3, "auth needed"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* check if we are authenticated, if yes enable relaying */ ++ if (flagauthok && relayclient == 0) ++ relayclient = ""; ++ ++ /* smtp size check */ ++ if (databytes && !sizelimit(arg)) ++ { ++ err_size(); /* logging is done in error routine */ ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* bad mailfrom check */ ++ if (bmfcheck()) ++ { ++ err_bmf(); ++ logline2(3,"bad mailfrom: ",addr.s); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ /* bad mailfrom unknown check */ ++ if (bmfunknowncheck()) ++ { ++ err_bmfunknown(); ++ logline2(3,"bad mailfrom unknown: ",addr.s); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* NOBOUNCE check */ ++ if (!addr.s[0] || !str_diff("#@[]", addr.s)) ++ { ++ bounceflag = 1; ++ if (nobounce) ++ { ++ err_554msg("RFC2821 bounces are administratively denied"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } ++ ++ /* Sanity checks */ ++ if (sanitycheck && !bounceflag) ++ { ++ /* Invalid Mailfrom */ ++ if ((i=byte_rchr(addr.s,addr.len,'@')) >= addr.len) ++ { ++ err_554msg("mailfrom without @ is administratively denied"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ if (i == 0 || addr.s[i+1] == '\0') { ++ err_554msg("mailfrom without user or domain part is " ++ "administratively denied"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ /* No '.' in domain.TLD */ ++ if ((j = byte_rchr(addr.s+i, addr.len-i, '.')) >= addr.len-i) ++ { ++ err_554msg("mailfrom without . in domain part is " ++ "administratively denied"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ /* check tld length */ ++ j = addr.len-(i+1+j+1); ++ if (j < 2 || j > 6) ++ { ++ /* XXX: This needs adjustment when new TLD's are constituded. ++ * OK, now after the candidates are nominated we know new TLD's ++ * may contain up to six characters. ++ */ ++ err_554msg("mailfrom without country or top level domain is " ++ "administratively denied"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } ++ ++ /* relay mail from check (allow relaying based on evelope sender address) */ ++ if (!relayclient) { ++ if (rmfcheck()) { ++ relayclient = ""; ++ logline(4,"relaying allowed via relaymailfrom"); ++ } ++ } ++ ++ /* Check RBL only if relayclient is not set */ ++ if (rblok && !relayclient) ++ { ++ switch(rblcheck(remoteip, &rblname, rbloh)) ++ { ++ case 2: /* soft error lookup */ ++ /* ++ * continue if RBL DNS has a problem. if a RBL is unreachable ++ * we dont want to fail. accept message anyway. a false negative ++ * is better in this case than rejecting every message just ++ * because one RBL failed. play safe, might be an important mail. ++ */ ++ break; ++ case 1: /* host is listed in RBL */ ++ err_rbl(rblname); ++ if (errdisconnect) err_quit(); ++ return; ++ default: /* ok, go ahead */ ++ logline(4,"RBL checking completed"); ++ break; ++ } ++ } ++ ++ /* return MX check */ ++ if (returnmxcheck && !bounceflag) ++ { ++ if ((i=byte_rchr(addr.s,addr.len,'@')) < addr.len) ++ switch (badmxcheck(&addr.s[i+1])) ++ { ++ case 0: ++ break; /* valid */ ++ case DNS_SOFT: ++ err_dns(); ++ logline(3,"refused mailfrom because return MX lookup " ++ "failed temporarly"); ++ if (errdisconnect) err_quit(); ++ return; ++ case DNS_HARD: ++ default: ++ err_554msg("refused mailfrom because return MX does not exist"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } ++ ++ /* check if sender exists in ldap */ ++ if (sendercheck && !bounceflag) { ++ if (!goodmailaddr()) { /* good mail addrs go through anyway */ ++ if (addrlocals()) { ++ char *s; ++ switch (ldaplookup(addr.s, &s)) { ++ case 1: /* valid */ ++ break; ++ case 0: /* invalid */ ++ err_554msg(s); ++ if (errdisconnect) err_quit(); ++ return; ++ case -1: ++ default: /* other error, treat as soft 4xx */ ++ if (ldapsoftok) ++ break; ++ err_ldapsoft(); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } else { ++ /* not in addrlocals, ldap lookup is useless */ ++ /* normal mode: let through, it's just an external mail coming in */ ++ /* loose mode: see if sender is in rcpthosts, if no reject here */ ++ if (sendercheck == 2 && !addrallowed()) { ++ err_554msg("refused mailfrom because valid " ++ "local sender address required"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ /* strict mode: we require validated sender so reject here right out */ ++ if (sendercheck == 3) { ++ err_554msg("refused mailfrom because valid " ++ "local sender address required"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } ++ } ++ } ++ + seenmail = 1; + if (!stralloc_copys(&rcptto,"")) die_nomem(); + if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); + if (!stralloc_0(&mailfrom)) die_nomem(); ++ rcptcount = 0; ++ if (loglevel == 2) ++ logline2(2,"mail from: ",mailfrom.s); + out("250 ok\r\n"); + } +-void smtp_rcpt(arg) char *arg; { +- if (!seenmail) { err_wantmail(); return; } +- if (!addrparse(arg)) { err_syntax(); return; } +- if (flagbarf) { err_bmf(); return; } ++ ++void smtp_rcpt(char *arg) ++{ ++ if (!seenmail) ++ { ++ err_wantmail(); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* syntax check */ ++ if (!addrparse(arg)) ++ { ++ err_syntax(); ++ logline2(3,"syntax error in 'rcpt to': ",arg); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ logline2(3,"rcpt to: ",addr.s); ++ ++ /* block stupid and bogus sendwhale bug relay probing */ ++ if (blockrelayprobe) /* don't enable this if you use percenthack */ ++ { ++ if (relayprobe()) ++ { ++ err_relay(); ++ logline(3,"'rcpt to' denied, looks like bogus sendwhale bug relay probe"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } ++ ++ /* do we block this recipient */ ++ if (rcptdenied()) ++ { ++ err_badrcptto(); ++ logline2(3,"'rcpt to' denied: ",arg); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* is sender ip allowed to relay */ + if (relayclient) { + --addr.len; + if (!stralloc_cats(&addr,relayclient)) die_nomem(); + if (!stralloc_0(&addr)) die_nomem(); ++ } else { ++ if (!addrallowed()) ++ { ++ err_nogateway(); ++ logline2(3,"no mail relay for 'rcpt to': ",arg); ++ if (errdisconnect) err_quit(); ++ return; ++ } + } +- else +- if (!addrallowed()) { err_nogateway(); return; } ++ ++rcptcount; ++ ++ /* maximum recipient limit reached */ ++ if (maxrcptcount && rcptcount > maxrcptcount) ++ { ++ err_maxrcpt(); ++ logline(3,"message denied because of more 'RCPT TO' than " ++ "allowed by MAXRCPTCOUNT"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* only one recipient for bounce messages */ ++ if (rcptcount > 1 && (!mailfrom.s[0] || !str_diff("#@[]", mailfrom.s))) ++ { ++ err_badbounce(); ++ logline(3,"bounce message denied because it has more than one recipient"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ ++ /* check if recipient exists in ldap */ ++ if (rcptcheck) { ++ if (!goodmailaddr()) { ++ logline(4,"recipient verify, recipient not in goodmailaddr"); ++ if (addrlocals()) { ++ char *s; ++ logline(4,"recipient verify, recipient is local"); ++ switch (ldaplookup(addr.s, &s)) { ++ case 1: /* valid */ ++ logline(4,"recipient verify OK"); ++ break; ++ case 0: /* invalid */ ++ logline(3,"message denied because of recipient verify"); ++ err_554msg(s); ++ if (errdisconnect) err_quit(); ++ return; ++ case -1: ++ default: /* other error, treat as soft 4xx */ ++ if (ldapsoftok) ++ break; ++ logline(3,"recipient verify soft error"); ++ err_ldapsoft(); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ } /* else this is relaying, don't do anything */ ++ } ++ } ++ ++ if (loglevel == 2) ++ logline2(2,"rcpt to: ",addr.s); + if (!stralloc_cats(&rcptto,"T")) die_nomem(); + if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_0(&rcptto)) die_nomem(); ++ if (tarpitcount && tarpitdelay && rcptcount >= tarpitcount) ++ { ++ logline(4,"tarpitting"); ++ while (sleep(tarpitdelay)); ++ } + out("250 ok\r\n"); + } + ++#ifdef DATA_COMPRESS ++z_stream stream; ++char zbuf[4096]; ++int wantcomp = 0; ++int compdata = 0; ++ ++int compression_init(void) ++{ ++ compdata = 1; ++ stream.zalloc = Z_NULL; ++ stream.zfree = Z_NULL; ++ stream.opaque = Z_NULL; ++ stream.avail_in = 0; ++ stream.next_in = zbuf; ++ if (inflateInit(&stream) != Z_OK) { ++ out("451 Initalizing data compression failed: "); ++ out(stream.msg); out(" #(4.3.0)\r\n"); flush(); ++ return -1; ++ } ++ return 0; ++} ++int compression_done(void) ++{ ++ char num[FMT_ULONG + 1]; ++ int r; ++ ++ compdata = 0; ++ if (stream.avail_out != sizeof(zbuf)) { ++ /* there is some left data, ignore */ ++ } ++ if (inflateEnd(&stream) != Z_OK) { ++ out("451 Finishing data compression failed: "); ++ out(stream.msg); out(" #(4.3.0)\r\n"); flush(); ++ return -1; ++ } ++ r = 100 - (int)(100.0*stream.total_in/stream.total_out); ++ if (r < 0) { ++ num[0] = '-'; ++ r *= -1; ++ } else ++ num[0] = ' '; ++ num[fmt_uint(num+1,r)+1] = 0; ++ logpid(3); ++ logstring(3,"DDC saved "); ++ logstring(3,num); ++ logstring(3," percent"); ++ logflush(3); ++ return 0; ++} ++#endif + +-int saferead(fd,buf,len) int fd; char *buf; int len; ++int saferead(int fd,void *buf,int len) + { + int r; + flush(); ++#ifdef DATA_COMPRESS ++ if (compdata) { ++ stream.avail_out = len; ++ stream.next_out = buf; ++ do { ++ if (stream.avail_in == 0) { ++#ifdef TLS_SMTPD ++ if (ssl) ++ r = ssl_timeoutread(timeout,fd,zbuf,sizeof(zbuf)); ++ else ++#endif ++ r = timeoutread(timeout,fd,zbuf,sizeof(zbuf)); ++ if (r == -1) if (errno == error_timeout) die_alarm(); ++ if (r <= 0) die_read(); ++ stream.avail_in = r; ++ stream.next_in = zbuf; ++ } ++ r = inflate(&stream, 0); ++ switch (r) { ++ case Z_OK: ++ if (stream.avail_out == 0) ++ return len; ++ break; ++ case Z_STREAM_END: ++ compdata = 0; ++ return len - stream.avail_out; ++ default: ++ out("451 Receiving compressed data failed: "); ++ out(stream.msg); out(" #(4.3.0)\r\n"); ++ logline2(1, "compressed data read failed: ", stream.msg); ++ flush(); ++ die_read(); ++ } ++ if (stream.avail_out == len) continue; ++ return len - stream.avail_out; ++ } while (1); ++ } ++#endif ++#ifdef TLS_SMTPD ++ if (ssl) ++ r = ssl_timeoutread(timeout,fd,buf,len); ++ else ++#endif + r = timeoutread(timeout,fd,buf,len); + if (r == -1) if (errno == error_timeout) die_alarm(); + if (r <= 0) die_read(); +@@ -278,25 +1259,27 @@ int saferead(fd,buf,len) int fd; char *b + char ssinbuf[1024]; + substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); + +-struct qmail qqt; +-unsigned int bytestooverflow = 0; ++unsigned long bytestooverflow = 0; ++unsigned long bytesreceived = 0; + +-void put(ch) +-char *ch; ++void put(const char *ch) + { ++#ifdef SMTPEXECCHECK ++ execcheck_put(&qqt, ch); ++#endif + if (bytestooverflow) + if (!--bytestooverflow) + qmail_fail(&qqt); + qmail_put(&qqt,ch,1); ++ ++bytesreceived; + } + +-void blast(hops) +-int *hops; ++void blast(unsigned int *hops) + { + char ch; + int state; + int flaginheader; +- int pos; /* number of bytes since most recent \n, if fih */ ++ unsigned int pos; /* number of bytes since most recent \n, if fih */ + int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ + int flagmaybey; /* 1 if this line might match \r\n, if fih */ + int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ +@@ -318,6 +1301,7 @@ int *hops; + if (flagmaybey) if (pos == 1) flaginheader = 0; + } + ++pos; ++ if (pos > MAXLINELEN) oversizedline(); + if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } + } + switch(state) { +@@ -351,49 +1335,331 @@ int *hops; + } + } + +-char accept_buf[FMT_ULONG]; +-void acceptmessage(qp) unsigned long qp; ++void acceptmessage(unsigned long qp) + { ++ static char buf[FMT_ULONG]; ++ + datetime_sec when; + when = now(); + out("250 ok "); +- accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0; +- out(accept_buf); ++ buf[fmt_ulong(buf,(unsigned long) when)] = 0; ++ out(buf); ++ logpid(2); logstring(2,"message queued: "); logstring(2,buf); + out(" qp "); +- accept_buf[fmt_ulong(accept_buf,qp)] = 0; +- out(accept_buf); ++ buf[fmt_ulong(buf,qp)] = 0; ++ out(buf); ++ out(" by "); ++ out(me.s); + out("\r\n"); ++ logstring(2," qp "); logstring(2,buf); ++ buf[fmt_ulong(buf, bytesreceived)] = 0; ++ logstring(2, " size "); ++ logstring(2, buf); ++ logstring(2, " bytes"); ++ logflush(2); + } + +-void smtp_data() { +- int hops; ++#ifdef TLS_SMTPD ++stralloc protocolinfo = {0}; ++#endif ++ ++void smtp_data(char *arg) { ++ unsigned int hops; + unsigned long qp; +- char *qqx; +- +- if (!seenmail) { err_wantmail(); return; } +- if (!rcptto.len) { err_wantrcpt(); return; } ++ const char *qqx; ++ ++ ldaplookupdone(); ++ if (!seenmail) { ++ err_wantmail(); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ if (!rcptto.len) { ++ err_wantrcpt(); ++ if (errdisconnect) err_quit(); ++ return; ++ } + seenmail = 0; + if (databytes) bytestooverflow = databytes + 1; +- if (qmail_open(&qqt) == -1) { err_qqt(); return; } ++#ifdef SMTPEXECCHECK ++ execcheck_start(); ++#endif ++ if (qmail_open(&qqt) == -1) { ++ err_qqt(); ++ logline(1,"failed to start qmail-queue"); ++ return; ++ } + qp = qmail_qp(&qqt); +- out("354 go ahead\r\n"); +- +- received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo); ++ out("354 go ahead punk, make my day\r\n"); logline(4,"go ahead"); ++ rblheader(&qqt); ++ ++#ifdef TLS_SMTPD ++ if(ssl){ ++ if (!stralloc_copys(&protocolinfo, ++ SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)))) die_nomem(); ++#ifdef DATA_COMPRESS ++ if (wantcomp) { ++ if (!stralloc_cats(&protocolinfo, " encrypted compressed SMTP")) ++ die_nomem(); ++ } else ++#endif ++ if (!stralloc_cats(&protocolinfo, " encrypted SMTP")) die_nomem(); ++ } else { ++#ifdef DATA_COMPRESS ++ if (wantcomp) { ++ if (!stralloc_copys(&protocolinfo,"compressed SMTP")) die_nomem(); ++ } else ++#endif ++ if (!stralloc_copys(&protocolinfo,"SMTP")) die_nomem(); ++ } ++ if (!stralloc_0(&protocolinfo)) die_nomem(); ++ received(&qqt,protocolinfo.s,local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]); ++#else ++#ifdef DATA_COMPRESS ++ if (wantcomp) ++ received(&qqt,"compressed SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]); ++ else ++#endif ++ received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]); ++#endif ++ ++#ifdef DATA_COMPRESS ++ if (wantcomp) { if (compression_init() != 0) return; } ++#endif + blast(&hops); ++#ifdef DATA_COMPRESS ++ if (wantcomp) { if (compression_done() != 0) return; } ++#endif ++ + hops = (hops >= MAXHOPS); +- if (hops) qmail_fail(&qqt); ++ if (hops) ++ qmail_fail(&qqt); + qmail_from(&qqt,mailfrom.s); + qmail_put(&qqt,rcptto.s,rcptto.len); + + 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 (*qqx == 'D') out("554 "); else out("451 "); ++ if (hops) { ++ out("554 too many hops, this message is looping (#5.4.6)\r\n"); ++ logline(3,"too many hops, message is looping"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++ if (databytes) if (!bytestooverflow) { ++ out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); ++ logline(3,"datasize limit exceeded"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++#ifdef SMTPEXECCHECK ++ if (execcheck_flag()) { ++ out("552 we don't accept email with this MIME content (#5.3.4)\r\n"); ++ logline(3,"bad MIME attachement detected"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++#endif ++ ++ logpid(1); ++ if (*qqx == 'D') { ++ out("554 "); logstring(1,"message permanently not accepted because: "); ++ } else { ++ out("451 "); logstring(1,"message temporarly not accepted because: "); ++ } + out(qqx + 1); ++ logstring(1,qqx + 1); logflush(1); + out("\r\n"); + } + ++#ifdef DATA_COMPRESS ++void smtp_dataz(char *arg) ++{ ++ wantcomp = 1; ++ smtp_data((char *)0); ++} ++#endif ++ ++stralloc line = {0}; ++ ++void smtp_auth(char *arg) ++{ ++ struct call cct; ++ char *type; ++ const char *status; ++ ++ if (!flagauth) { ++ err_unimpl("AUTH without STARTTLS"); ++ return; ++ } ++ if (flagauthok) { ++ out("503 you are already authenticated\r\n"); ++ logline(3,"reauthentication attempt rejected"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++#ifdef TLS_SMTPD ++ if (needssl && !ssl) { ++ out("538 Encryption required for requested authentication mechanism"); ++ logline(3,"TLS encryption required for authentication"); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++#endif ++ type = arg; ++ while (*arg != '\0' && *arg != ' ') ++arg; ++ if (*arg) { ++ *arg++ = '\0'; ++ while (*arg == ' ') ++arg; ++ } ++ ++ if (case_diffs(type, "login") == 0) { ++ logline(4,"auth login"); ++ if (call_open(&cct, "bin/auth_smtp", 30, 1) == -1) goto fail; ++ call_puts(&cct, "login"); call_put(&cct, "", 1); ++ if (*arg) { ++ call_puts(&cct, arg); call_put(&cct, "", 1); ++ } else { ++ out("334 VXNlcm5hbWU6\r\n"); flush(); /* base64 for 'Username:' */ ++ if (call_getln(&ssin, &line) == -1) die_read(); ++ call_puts(&cct, line.s); call_put(&cct, "", 1); ++ } ++ out("334 UGFzc3dvcmQ6\r\n"); flush(); /* base64 for 'Password:' */ ++ if (call_getln(&ssin, &line) == -1) die_read(); ++ call_puts(&cct, line.s); call_putflush(&cct, "", 1); ++ } else if (case_diffs(type, "plain") == 0) { ++ logline(4,"auth plain"); ++ if (call_open(&cct, "bin/auth_smtp", 30, 1) == -1) goto fail; ++ call_puts(&cct, "plain"); call_put(&cct, "", 1); ++ if (*arg) { ++ call_puts(&cct, arg); call_putflush(&cct, "", 1); ++ } else { ++ out("334 \r\n"); flush(); ++ if (call_getln(&ssin, &line) == -1) die_read(); ++ call_puts(&cct, line.s); call_putflush(&cct, "", 1); ++ } ++ } else { ++ out("504 authentication type not supported\r\n"); ++ logstring(3,"authentication type "); ++ logstring(3,type); ++ logstring(3,": not supported"); ++ logflush(3); ++ if (errdisconnect) err_quit(); ++ return; ++ } ++fail: ++ status = auth_close(&cct, &line, authprepend); ++ switch (*status) { ++ case '2': ++ flagauthok = 1; ++ remoteinfo = line.s; ++ out(status); ++ logline2(2,"authentication success, user ", remoteinfo); ++ break; ++ case '4': ++ case '5': ++ sleep(1); ++ out(status); flush(); ++ logline2(3, "authentication failed: ", status + 4); ++ sleep(4); ++ if (errdisconnect) err_quit(); ++ break; ++ } ++} ++ ++#ifdef TLS_SMTPD ++RSA *tmp_rsa_cb(SSL *s,int export,int keylength) ++{ ++ RSA* rsa; ++ BIO* in; ++ ++ if (!export || keylength == 512) ++ if ((in=BIO_new(BIO_s_file_internal()))) ++ if (BIO_read_filename(in,"control/rsa512.pem") > 0) ++ if ((rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL,NULL))) ++ return rsa; ++ return (RSA_generate_key(export?keylength:512,RSA_F4,NULL,NULL)); ++} ++ ++void smtp_tls(char *arg) ++{ ++ SSL_CTX *ctx; ++ ++ if (sslcert.s == 0 || *sslcert.s == '\0') { ++ err_unimpl("STARTTLS"); ++ return; ++ } ++ ++ if (*arg) ++ { ++ out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n"); ++ logline(3,"aborting TLS negotiations, no parameters to starttls allowed"); ++ return; ++ } ++ ++ SSLeay_add_ssl_algorithms(); ++ if(!(ctx=SSL_CTX_new(SSLv23_server_method()))) ++ { ++ out("454 TLS not available: unable to initialize ctx (#4.3.0)\r\n"); ++ logline(3,"aborting TLS negotiations, " ++ "unable to initialize local SSL context"); ++ return; ++ } ++ if(!SSL_CTX_use_RSAPrivateKey_file(ctx, sslcert.s, SSL_FILETYPE_PEM)) ++ { ++ out("454 TLS not available: missing RSA private key (#4.3.0)\r\n"); ++ logline2(3,"aborting TLS negotiations, " ++ "RSA private key invalid or unable to read ", sslcert.s); ++ return; ++ } ++ if(!SSL_CTX_use_certificate_file(ctx, sslcert.s, SSL_FILETYPE_PEM)) ++ { ++ out("454 TLS not available: missing certificate (#4.3.0)\r\n"); ++ logline2(3,"aborting TLS negotiations, " ++ "local cert invalid or unable to read ", sslcert.s); ++ return; ++ } ++ SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb); ++ ++ out("220 ready for tls\r\n"); flush(); ++ ++ if(!(ssl=SSL_new(ctx))) ++ { ++ logline(3,"aborting TLS connection, unable to set up SSL session"); ++ die_read(); ++ } ++ SSL_set_rfd(ssl,substdio_fileno(&ssin)); ++ SSL_set_wfd(ssl,substdio_fileno(&ssout)); ++ if(SSL_accept(ssl)<=0) ++ { ++ logline(3,"aborting TLS connection, unable to finish SSL accept"); ++ die_read(); ++ } ++ //substdio_fdbuf(&ssout,SSL_write,ssl,ssoutbuf,sizeof(ssoutbuf)); ++ ++ remotehost = env_get("TCPREMOTEHOST"); ++ if (!remotehost) remotehost = "unknown"; ++ dohelo(remotehost); ++} ++#endif ++ ++void cleanup(void) ++{ ++ ldaplookupdone(); ++} ++ ++void err_503or421(char *arg) ++{ ++ if (greeting421) ++ out("421 Service temporarily not available (#4.3.2)\r\n"); ++ else ++ out("503 bad sequence of commands (#5.5.1)\r\n"); ++ if (errdisconnect) err_quit(); ++} ++void err_badcommand(char *arg) ++{ ++ out("503 bad sequence of commands (#5.5.1)\r\n"); ++} ++ + struct commands smtpcommands[] = { + { "rcpt", smtp_rcpt, 0 } + , { "mail", smtp_mail, 0 } +@@ -403,19 +1669,54 @@ struct commands smtpcommands[] = { + , { "ehlo", smtp_ehlo, flush } + , { "rset", smtp_rset, 0 } + , { "help", smtp_help, flush } ++#ifdef TLS_SMTPD ++, { "starttls", smtp_tls, flush } ++#endif ++#ifdef DATA_COMPRESS ++, { "dataz", smtp_dataz, flush } ++#endif ++, { "auth", smtp_auth, flush } + , { "noop", err_noop, flush } + , { "vrfy", err_vrfy, flush } + , { 0, err_unimpl, flush } + } ; + +-void main() ++struct commands smtprestricted[] = { ++ { "quit", smtp_quit, flush } ++, { "helo", err_503or421, flush } ++, { "ehlo", err_503or421, flush } ++, { 0, err_badcommand, flush } ++}; ++ ++int main(int argc, char **argv) + { ++#ifdef TLS_SMTPD ++ sig_alarmcatch(sigalrm); ++#endif + sig_pipeignore(); + if (chdir(auto_qmail) == -1) die_control(); + setup(); + if (ipme_init() != 1) die_ipme(); ++ if (greeting550 || greeting421) { ++ if (!stralloc_copys(&greeting,greeting550 ? greeting550 : greeting421)) ++ die_nomem(); ++ timeout = 20; /* reduce timeout so the abuser is kicked out faster */ ++ if (greeting.len == 0 && greeting550) ++ stralloc_copys(&greeting, ++ "Sorry, your mail was administratively denied. (#5.7.1)"); ++ else if (greeting.len == 0 && greeting421) ++ stralloc_copys(&greeting, ++ "Service temporarily not available (#4.3.2)"); ++ ++ smtp_line(greeting550 ? "554 " : "421 "); ++ if (errdisconnect) err_quit(); ++ if (commands(&ssin,smtprestricted) == 0) die_read(); ++ die_nomem(); ++ } + smtp_greet("220 "); +- out(" ESMTP\r\n"); +- if (commands(&ssin,&smtpcommands) == 0) die_read(); ++ if (commands(&ssin,smtpcommands) == 0) die_read(); + die_nomem(); ++ /* NOTREACHED */ ++ return 1; + } ++ +diff -upN qmail-1.03/qmail-smtpd.rules qmail-ldap/qmail-smtpd.rules +--- qmail-1.03/qmail-smtpd.rules Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-smtpd.rules Tue Apr 6 15:12:00 2004 +@@ -0,0 +1,29 @@ ++# ++# SMTP server rules. ++# Default rule is to accept mails but not to relay. Do not even think of setting ++# RELAYCLIENT on the default rule. ++# Other useful stuff: ++# AUTHPREPEND: String that is prepended to the login in the received line ++# AUTHREQUIRED: Allow sending of messages only to authenticated senders. ++# BLOCKRELAYPROBE: reject recipients with and "!", "%" or double-"@" ++# LDAPSOFTOK: Ignore ldap soft errors in RCPTCHECK and SENDERCHECK ++# LOGLEVEL: Level of log verbosity ++# MAXRCPTCOUNT: maximum number of RCPT TOs you accept ++# NOBOUNCE: Rejects null sender bounces, use only in extreme cases ++# NOPBS: Disable pop-befor-smtp feature (pbscheck). ++# QMAILQUEUE: alternate mail queueing program ++# RBL: If set turns on rbl checking. ++# RBLONLYHEADER: only tag messages filtered by rbl checking. ++# RCPTCHECK: Check if the recipient of a message really exists. ++# REJECTEXEC: Reject DOS/Windows executables in mail attachements. ++# RETURNMXCHECK: Rejects senders if they don't have a valid return MX. ++# SANITYCHECK: Rejects senders without an @, no . or too long/short TLD ++# SENDERCHECK: Check if the sender of a message really exists. ++# SMTPAUTH: Enables SMTP-AUTH for remote clients. ++# 550GREETING: Rejects a connection right away with an 550 error ++# SMTP550DISCONNECT: Disconnect the SMTP session if a 5xx error happens ++# TARPITCOUNT: number of RCPT TOs you accept before you start tarpitting. ++# TARPITDELAY: number of seconds of delay to introduce while tarpitting ++# ++#192.168.0.:allow,RELAYCLIENT="" ++:allow +diff -upN qmail-1.03/qmail-smtpd.sh qmail-ldap/qmail-smtpd.sh +--- qmail-1.03/qmail-smtpd.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-smtpd.sh Wed Aug 18 11:27:12 2004 +@@ -0,0 +1,35 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# SMTP service ++# ++QMAIL="%QMAIL%" ++ME="`head -1 $QMAIL/control/me`" ++CONCURRENCY=${CONCURRENCY:=50} ++QUSER="qmaild" ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# source the environemt in ./env ++eval `env - PATH=$PATH envdir ./env awk '\ ++ BEGIN { for (i in ENVIRON) \ ++ if (i != "PATH") { \ ++ printf "export %s=\"%s\"\\n", i, ENVIRON[i] \ ++ } \ ++ }'` ++ ++# enforce some sane defaults ++QUSER=${QUSER:="qmaild"} ++PBSTOOL=${PBSTOOL:="$QMAIL/bin/pbscheck"} ++ ++if [ X${NOPBS+"true"} = X"true" ]; then ++ unset PBSTOOL ++fi ++ ++exec \ ++ envuidgid $QUSER \ ++ tcpserver -v -URl $ME -x$QMAIL/control/qmail-smtpd.cdb \ ++ ${CONCURRENCY:+"-c$CONCURRENCY"} ${BACKLOG:+"-b$BACKLOG"} 0 smtp \ ++ $PBSTOOL \ ++ $QMAIL/bin/qmail-smtpd ++ +diff -upN qmail-1.03/qmail-start.c qmail-ldap/qmail-start.c +--- qmail-1.03/qmail-start.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-start.c Tue Oct 28 18:21:32 2003 +@@ -1,13 +1,19 @@ ++#include ++#include ++#include + #include "fd.h" + #include "prot.h" + #include "exit.h" + #include "fork.h" + #include "auto_uids.h" + +-char *(qsargs[]) = { "qmail-send", 0 }; +-char *(qcargs[]) = { "qmail-clean", 0 }; +-char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 }; +-char *(qrargs[]) = { "qmail-rspawn", 0 }; ++const char *(qsargs[]) = { "qmail-send", 0 }; ++const char *(qcargs[]) = { "qmail-clean", 0 }; ++const char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 }; ++const char *(qrargs[]) = { "qmail-rspawn", 0 }; ++#ifdef EXTERNAL_TODO ++const char *(qtargs[]) = { "qmail-todo", 0}; ++#endif + + void die() { _exit(111); } + +@@ -18,16 +24,31 @@ int pi3[2]; + int pi4[2]; + int pi5[2]; + int pi6[2]; +- +-void close23456() { close(2); close(3); close(4); close(5); close(6); } ++#ifdef EXTERNAL_TODO ++int pi7[2]; ++int pi8[2]; ++int pi9[2]; ++int pi10[2]; ++#endif ++ ++void close23456() { ++ close(2); close(3); close(4); close(5); close(6); ++#ifdef EXTERNAL_TODO ++ close(7); close(8); ++#endif ++} + + void closepipes() { + close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]); + close(pi3[0]); close(pi3[1]); close(pi4[0]); close(pi4[1]); + close(pi5[0]); close(pi5[1]); close(pi6[0]); close(pi6[1]); ++#ifdef EXTERNAL_TODO ++ close(pi7[0]); close(pi7[1]); close(pi8[0]); close(pi8[1]); ++ close(pi9[0]); close(pi9[1]); close(pi10[0]); close(pi10[1]); ++#endif + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -40,6 +61,10 @@ char **argv; + if (fd_copy(4,0) == -1) die(); + if (fd_copy(5,0) == -1) die(); + if (fd_copy(6,0) == -1) die(); ++#ifdef EXTERNAL_TODO ++ if (fd_copy(7,0) == -1) die(); ++ if (fd_copy(8,0) == -1) die(); ++#endif + + if (argv[1]) { + qlargs[1] = argv[1]; +@@ -70,6 +95,12 @@ char **argv; + if (pipe(pi4) == -1) die(); + if (pipe(pi5) == -1) die(); + if (pipe(pi6) == -1) die(); ++#ifdef EXTERNAL_TODO ++ if (pipe(pi7) == -1) die(); ++ if (pipe(pi8) == -1) die(); ++ if (pipe(pi9) == -1) die(); ++ if (pipe(pi10) == -1) die(); ++#endif + + switch(fork()) { + case -1: die(); +@@ -78,7 +109,7 @@ char **argv; + if (fd_copy(1,pi2[1]) == -1) die(); + close23456(); + closepipes(); +- execvp(*qlargs,qlargs); ++ execvp(*qlargs,(char **)qlargs); + die(); + } + +@@ -90,7 +121,7 @@ char **argv; + if (fd_copy(1,pi4[1]) == -1) die(); + close23456(); + closepipes(); +- execvp(*qrargs,qrargs); ++ execvp(*qrargs,(char **)qrargs); + die(); + } + +@@ -102,9 +133,37 @@ char **argv; + if (fd_copy(1,pi6[1]) == -1) die(); + close23456(); + closepipes(); +- execvp(*qcargs,qcargs); ++ execvp(*qcargs,(char **)qcargs); ++ die(); ++ } ++ ++#ifdef EXTERNAL_TODO ++ switch(fork()) { ++ case -1: die(); ++ case 0: ++ if (prot_uid(auto_uids) == -1) die(); ++ if (fd_copy(0,pi7[0]) == -1) die(); ++ if (fd_copy(1,pi8[1]) == -1) die(); ++ close23456(); ++ if (fd_copy(2,pi9[1]) == -1) die(); ++ if (fd_copy(3,pi10[0]) == -1) die(); ++ closepipes(); ++ execvp(*qtargs,(char **)qtargs); ++ die(); ++ } ++ ++ switch(fork()) { ++ case -1: die(); ++ case 0: ++ if (prot_uid(auto_uidq) == -1) die(); ++ if (fd_copy(0,pi9[0]) == -1) die(); ++ if (fd_copy(1,pi10[1]) == -1) die(); ++ close23456(); ++ closepipes(); ++ execvp(*qcargs,(char **)qcargs); + die(); + } ++#endif + + if (prot_uid(auto_uids) == -1) die(); + if (fd_copy(0,1) == -1) die(); +@@ -114,7 +173,11 @@ char **argv; + if (fd_copy(4,pi4[0]) == -1) die(); + if (fd_copy(5,pi5[1]) == -1) die(); + if (fd_copy(6,pi6[0]) == -1) die(); ++#ifdef EXTERNAL_TODO ++ if (fd_copy(7,pi7[1]) == -1) die(); ++ if (fd_copy(8,pi8[0]) == -1) die(); ++#endif + closepipes(); +- execvp(*qsargs,qsargs); +- die(); ++ execvp(*qsargs,(char **)qsargs); ++ return 111; + } +diff -upN qmail-1.03/qmail-tcpok.c qmail-ldap/qmail-tcpok.c +--- qmail-1.03/qmail-tcpok.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-tcpok.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "strerr.h" + #include "substdio.h" + #include "lock.h" +@@ -11,10 +12,10 @@ + char buf[1024]; /* XXX: must match size in tcpto_clean.c, tcpto.c */ + substdio ss; + +-void main() ++int main() + { + int fd; +- int i; ++ unsigned int i; + + if (chdir(auto_qmail) == -1) + strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); +@@ -27,9 +28,9 @@ void main() + if (lock_ex(fd) == -1) + strerr_die4sys(111,FATAL,"unable to lock ",auto_qmail,"/queue/lock/tcpto: "); + +- substdio_fdbuf(&ss,write,fd,buf,sizeof buf); ++ substdio_fdbuf(&ss,subwrite,fd,buf,sizeof buf); + for (i = 0;i < sizeof buf;++i) substdio_put(&ss,"",1); + if (substdio_flush(&ss) == -1) + strerr_die4sys(111,FATAL,"unable to clear ",auto_qmail,"/queue/lock/tcpto: "); +- _exit(0); ++ return 0; + } +diff -upN qmail-1.03/qmail-tcpto.c qmail-ldap/qmail-tcpto.c +--- qmail-1.03/qmail-tcpto.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail-tcpto.c Tue Oct 28 18:21:32 2003 +@@ -1,5 +1,6 @@ + /* XXX: this program knows quite a bit about tcpto's internals */ + ++#include + #include "substdio.h" + #include "subfd.h" + #include "auto_qmail.h" +@@ -10,12 +11,15 @@ + #include "exit.h" + #include "datetime.h" + #include "now.h" ++#include "open.h" ++#include "readwrite.h" ++#include "byte.h" + + void die(n) int n; { substdio_flush(subfdout); _exit(n); } + +-void warn(s) char *s; ++void warn(s) const char *s; + { +- char *x; ++ const char *x; + x = error_str(errno); + substdio_puts(subfdout,s); + substdio_puts(subfdout,": "); +@@ -32,7 +36,7 @@ char tcpto_buf[1024]; + + char tmp[FMT_ULONG + IPFMT]; + +-void main() ++int main() + { + int fdlock; + int fd; +@@ -82,4 +86,6 @@ void main() + } + + die(0); ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/qmail-todo.c qmail-ldap/qmail-todo.c +--- qmail-1.03/qmail-todo.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-todo.c Thu Jul 1 16:28:31 2004 +@@ -0,0 +1,813 @@ ++/* ++ * Copyright (c) 2002-2004 Andre Oppermann, Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "alloc.h" ++#include "auto_qmail.h" ++#include "byte.h" ++#include "case.h" ++#include "cdb.h" ++#include "constmap.h" ++#include "control.h" ++#include "direntry.h" ++#include "error.h" ++#include "exit.h" ++#include "fmt.h" ++#include "fmtqfn.h" ++#include "getln.h" ++#include "open.h" ++#include "ndelay.h" ++#include "now.h" ++#include "readsubdir.h" ++#include "readwrite.h" ++#include "scan.h" ++#include "select.h" ++#include "sig.h" ++#include "str.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "trigger.h" ++ ++/* critical timing feature #1: if not triggered, do not busy-loop */ ++/* critical timing feature #2: if triggered, respond within fixed time */ ++/* important timing feature: when triggered, respond instantly */ ++#define SLEEP_TODO 1500 /* check todo/ every 25 minutes in any case */ ++#define SLEEP_FUZZ 1 /* slop a bit on sleeps to avoid zeno effect */ ++#define SLEEP_FOREVER 86400 /* absolute maximum time spent in select() */ ++#define SLEEP_SYSFAIL 123 ++ ++stralloc percenthack = {0}; ++struct constmap mappercenthack; ++stralloc locals = {0}; ++struct constmap maplocals; ++stralloc vdoms = {0}; ++struct constmap mapvdoms; ++stralloc envnoathost = {0}; ++ ++char strnum[FMT_ULONG]; ++ ++/* XXX not good, if qmail-send.c changes this has to be updated */ ++#define CHANNELS 2 ++const char *chanaddr[CHANNELS] = { "local/", "remote/" }; ++ ++datetime_sec recent; ++ ++void log1(const char *); ++void log3(const char *, const char *, const char *); ++ ++int flagstopasap = 0; ++void sigterm(void) ++{ ++ if (flagstopasap == 0) ++ log1("status: qmail-todo stop processing asap\n"); ++ flagstopasap = 1; ++} ++ ++int flagreadasap = 0; void sighup(void) { flagreadasap = 1; } ++int flagsendalive = 1; void senddied(void) { flagsendalive = 0; } ++ ++void nomem(void) { log1("alert: out of memory, sleeping...\n"); sleep(10); } ++void pausedir(const char *dir) ++{ log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); } ++ ++void cleandied(void) ++{ ++ log1("alert: qmail-todo: oh no! lost qmail-clean connection! dying...\n"); ++ flagstopasap = 1; ++} ++ ++ ++/* this file is not so long ------------------------------------- FILENAMES */ ++ ++stralloc fn = {0}; ++ ++void fnmake_init(void) ++{ ++ while (!stralloc_ready(&fn,FMTQFN)) nomem(); ++} ++ ++void fnmake_info(unsigned long id) { fn.len = fmtqfn(fn.s,"info/",id,1); } ++#ifndef BIGTODO ++void fnmake_todo(unsigned long id) { fn.len = fmtqfn(fn.s,"todo/",id,0); } ++#else ++void fnmake_todo(unsigned long id) { fn.len = fmtqfn(fn.s,"todo/",id,1); } ++#endif ++void fnmake_mess(unsigned long id) { fn.len = fmtqfn(fn.s,"mess/",id,1); } ++void fnmake_chanaddr(unsigned long id, int c) ++{ fn.len = fmtqfn(fn.s,chanaddr[c],id,1); } ++ ++ ++/* this file is not so long ------------------------------------- REWRITING */ ++ ++stralloc localscdb = {0}; ++stralloc rwline = {0}; ++struct cdb cdb; ++ ++/* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */ ++/* may trash recip. must set up rwline, between a T and a \0. */ ++int rewrite(char *recip) ++{ ++ unsigned int i; ++ unsigned int j; ++ const char *x; ++ static stralloc addr = {0}; ++ int at; ++ ++ if (!stralloc_copys(&rwline,"T")) return 0; ++ if (!stralloc_copys(&addr,recip)) return 0; ++ ++ i = byte_rchr(addr.s,addr.len,'@'); ++ if (i == addr.len) { ++ if (!stralloc_cats(&addr,"@")) return 0; ++ if (!stralloc_cat(&addr,&envnoathost)) return 0; ++ } ++ ++ while (constmap(&mappercenthack,addr.s + i + 1,addr.len - i - 1)) { ++ j = byte_rchr(addr.s,i,'%'); ++ if (j == i) break; ++ addr.len = i; ++ i = j; ++ addr.s[i] = '@'; ++ } ++ ++ at = byte_rchr(addr.s,addr.len,'@'); ++ ++ if (localscdb.s && localscdb.len > 1) { ++ static stralloc lowaddr = {0}; ++ int fd, r; ++ uint32 dlen; ++ ++ if (!stralloc_copyb(&lowaddr,addr.s + at + 1,addr.len - at - 1)) return 0; ++ case_lowerb(lowaddr.s, lowaddr.len); ++ fd = open_read(localscdb.s); ++ if (fd == -1) return 0; ++ cdb_init(&cdb, fd); ++ r = cdb_seek(&cdb, lowaddr.s,lowaddr.len, &dlen); ++ cdb_free(&cdb); ++ close(fd); ++ if (r == -1) return 0; ++ if (r == 1) { ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 1; ++ } ++ } else ++ if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) { ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 1; ++ } ++ ++ for (i = 0;i <= addr.len;++i) ++ if (!i || (i == at + 1) || (i == addr.len) || ((i > at) && (addr.s[i] == '.'))) ++ if ((x = constmap(&mapvdoms,addr.s + i,addr.len - i))) { ++ if (!*x) break; ++ if (!stralloc_cats(&rwline,x)) return 0; ++ if (!stralloc_cats(&rwline,"-")) return 0; ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 1; ++ } ++ ++ if (!stralloc_cat(&rwline,&addr)) return 0; ++ if (!stralloc_0(&rwline)) return 0; ++ return 2; ++} ++ ++/* this file is not so long --------------------------------- COMMUNICATION */ ++ ++substdio sstoqc; char sstoqcbuf[1024]; ++substdio ssfromqc; char ssfromqcbuf[1024]; ++stralloc comm_buf = {0}; ++int comm_pos; ++int fdout = -1; ++int fdin = -1; ++ ++void comm_init(void) ++{ ++ substdio_fdbuf(&sstoqc,subwrite,2,sstoqcbuf,sizeof(sstoqcbuf)); ++ substdio_fdbuf(&ssfromqc,subread,3,ssfromqcbuf,sizeof(ssfromqcbuf)); ++ ++ fdout = 1; /* stdout */ ++ fdin = 0; /* stdin */ ++ if (ndelay_on(fdout) == -1) ++ /* this is so stupid: NDELAY semantics should be default on write */ ++ senddied(); /* drastic, but better than risking deadlock */ ++ ++ while (!stralloc_ready(&comm_buf,1024)) nomem(); ++} ++ ++int comm_canwrite(void) ++{ ++ /* XXX: could allow a bigger buffer; say 10 recipients */ ++ /* XXX: returns true if there is something in the buffer */ ++ if (!flagsendalive) return 0; ++ if (comm_buf.s && comm_buf.len) return 1; ++ return 0; ++} ++ ++void log1(const char* x) ++{ ++ unsigned int pos; ++ ++ pos = comm_buf.len; ++ if (!stralloc_cats(&comm_buf,"L")) goto fail; ++ if (!stralloc_cats(&comm_buf,x)) goto fail; ++ if (!stralloc_0(&comm_buf)) goto fail; ++ return; ++ ++fail: ++ /* either all or nothing */ ++ comm_buf.len = pos; ++} ++ ++void log3(const char *x, const char *y, const char *z) ++{ ++ unsigned int pos; ++ ++ pos = comm_buf.len; ++ if (!stralloc_cats(&comm_buf,"L")) goto fail; ++ if (!stralloc_cats(&comm_buf,x)) goto fail; ++ if (!stralloc_cats(&comm_buf,y)) goto fail; ++ if (!stralloc_cats(&comm_buf,z)) goto fail; ++ if (!stralloc_0(&comm_buf)) goto fail; ++ return; ++ ++fail: ++ /* either all or nothing */ ++ comm_buf.len = pos; ++} ++ ++void comm_write(unsigned long id, int local, int remote) ++{ ++ unsigned int pos; ++ const char *s; ++ ++ if (local && remote) s="B"; ++ else if (local) s="L"; ++ else if (remote) s="R"; ++ else s="X"; ++ ++ pos = comm_buf.len; ++ strnum[fmt_ulong(strnum,id)] = 0; ++ if (!stralloc_cats(&comm_buf,"D")) goto fail; ++ if (!stralloc_cats(&comm_buf,s)) goto fail; ++ if (!stralloc_cats(&comm_buf,strnum)) goto fail; ++ if (!stralloc_0(&comm_buf)) goto fail; ++ return; ++ ++fail: ++ /* either all or nothing */ ++ comm_buf.len = pos; ++} ++ ++static int issafe(char ch) ++{ ++ if (ch == '%') return 0; /* general principle: allman's code is crap */ ++ if (ch < 33) return 0; ++ if (ch > 126) return 0; ++ return 1; ++} ++ ++void comm_info(unsigned long id, unsigned long size, char* from, unsigned long pid, unsigned long uid) ++{ ++ unsigned int pos; ++ unsigned int i; ++ ++ pos = comm_buf.len; ++ if (!stralloc_cats(&comm_buf,"Linfo msg ")) goto fail; ++ strnum[fmt_ulong(strnum,id)] = 0; ++ if (!stralloc_cats(&comm_buf,strnum)) goto fail; ++ if (!stralloc_cats(&comm_buf,": bytes ")) goto fail; ++ strnum[fmt_ulong(strnum,size)] = 0; ++ if (!stralloc_cats(&comm_buf,strnum)) goto fail; ++ if (!stralloc_cats(&comm_buf," from <")) goto fail; ++ i = comm_buf.len; ++ if (!stralloc_cats(&comm_buf,from)) goto fail; ++ for (;i < comm_buf.len;++i) ++ if (comm_buf.s[i] == '\n') ++ comm_buf.s[i] = '/'; ++ else ++ if (!issafe(comm_buf.s[i])) ++ comm_buf.s[i] = '_'; ++ if (!stralloc_cats(&comm_buf,"> qp ")) goto fail; ++ strnum[fmt_ulong(strnum,pid)] = 0; ++ if (!stralloc_cats(&comm_buf,strnum)) goto fail; ++ if (!stralloc_cats(&comm_buf," uid ")) goto fail; ++ strnum[fmt_ulong(strnum,uid)] = 0; ++ if (!stralloc_cats(&comm_buf,strnum)) goto fail; ++ if (!stralloc_cats(&comm_buf,"\n")) goto fail; ++ if (!stralloc_0(&comm_buf)) goto fail; ++ return; ++ ++fail: ++ /* either all or nothing */ ++ comm_buf.len = pos; ++} ++ ++void comm_exit(void) ++{ ++ /* if it fails exit, we have already stoped */ ++ if (!stralloc_cats(&comm_buf,"X")) _exit(1); ++ if (!stralloc_0(&comm_buf)) _exit(1); ++} ++ ++void comm_selprep(int *nfds, fd_set *wfds, fd_set *rfds) ++{ ++ if (flagsendalive) { ++ if (flagstopasap && comm_canwrite() == 0) ++ comm_exit(); ++ if (comm_canwrite()) { ++ FD_SET(fdout,wfds); ++ if (*nfds <= fdout) ++ *nfds = fdout + 1; ++ } ++ FD_SET(fdin,rfds); ++ if (*nfds <= fdin) ++ *nfds = fdin + 1; ++ } ++} ++ ++void comm_do(fd_set *wfds, fd_set *rfds) ++{ ++ /* first write then read */ ++ if (flagsendalive) ++ if (comm_canwrite()) ++ if (FD_ISSET(fdout,wfds)) { ++ int w; ++ unsigned int len; ++ len = comm_buf.len; ++ w = write(fdout,comm_buf.s + comm_pos,len - comm_pos); ++ if (w <= 0) { ++ if ((w == -1) && (errno == error_pipe)) ++ senddied(); ++ } else { ++ comm_pos += w; ++ if (comm_pos == len) { ++ comm_buf.len = 0; ++ comm_pos = 0; ++ } ++ } ++ } ++ if (flagsendalive) ++ if (FD_ISSET(fdin,rfds)) { ++ /* there are only two messages 'H' and 'X' */ ++ char c; ++ int r; ++ r = read(fdin, &c, 1); ++ if (r <= 0) { ++ if (r != -1 || errno != error_intr) ++ senddied(); ++ } else { ++ switch(c) { ++ case 'H': ++ sighup(); ++ break; ++ case 'X': ++ sigterm(); ++ break; ++ default: ++ log1("warning: qmail-todo: qmail-send speaks an obscure dialect\n"); ++ break; ++ } ++ } ++ } ++} ++ ++/* this file is not so long ------------------------------------------ TODO */ ++ ++datetime_sec nexttodorun; ++#ifndef BIGTODO ++DIR *tododir; /* if 0, have to opendir again */ ++#else ++int flagtododir = 0; /* if 0, have to readsubdir_init again */ ++readsubdir todosubdir; ++#endif ++stralloc todoline = {0}; ++char todobuf[SUBSTDIO_INSIZE]; ++char todobufinfo[512]; ++char todobufchan[CHANNELS][1024]; ++ ++void todo_init(void) ++{ ++#ifndef BIGTODO ++ tododir = 0; ++#else ++ flagtododir = 0; ++#endif ++ nexttodorun = now(); ++ trigger_set(); ++} ++ ++void todo_selprep(int *nfds, fd_set *rfds, datetime_sec *wakeup) ++{ ++ if (flagstopasap) return; ++ trigger_selprep(nfds,rfds); ++#ifndef BIGTODO ++ if (tododir) *wakeup = 0; ++#else ++ if (flagtododir) *wakeup = 0; ++#endif ++ if (*wakeup > nexttodorun) *wakeup = nexttodorun; ++} ++ ++void todo_do(fd_set *rfds) ++{ ++ struct stat st; ++ substdio ss; int fd; ++ substdio ssinfo; int fdinfo; ++ substdio sschan[CHANNELS]; ++ int fdchan[CHANNELS]; ++ int flagchan[CHANNELS]; ++ char ch; ++ int match; ++ unsigned long id; ++#ifndef BIGTODO ++ unsigned int len; ++ direntry *d; ++#endif ++ int c; ++ unsigned long uid; ++ unsigned long pid; ++ ++ fd = -1; ++ fdinfo = -1; ++ for (c = 0;c < CHANNELS;++c) fdchan[c] = -1; ++ ++ if (flagstopasap) return; ++ ++#ifndef BIGTODO ++ if (!tododir) ++#else ++ if (!flagtododir) ++#endif ++ { ++ if (!trigger_pulled(rfds)) ++ if (recent < nexttodorun) ++ return; ++ trigger_set(); ++#ifndef BIGTODO ++ tododir = opendir("todo"); ++ if (!tododir) ++ { ++ pausedir("todo"); ++ return; ++ } ++#else ++ readsubdir_init(&todosubdir, "todo", pausedir); ++ flagtododir = 1; ++#endif ++ nexttodorun = recent + SLEEP_TODO; ++ } ++ ++#ifndef BIGTODO ++ d = readdir(tododir); ++ if (!d) ++ { ++ closedir(tododir); ++ tododir = 0; ++ return; ++ } ++ if (str_equal(d->d_name,".")) return; ++ if (str_equal(d->d_name,"..")) return; ++ len = scan_ulong(d->d_name,&id); ++ if (!len || d->d_name[len]) return; ++#else ++ switch(readsubdir_next(&todosubdir, &id)) ++ { ++ case 1: break; ++ case 0: flagtododir = 0; ++ default: return; ++ } ++#endif ++ ++ fnmake_todo(id); ++ ++ fd = open_read(fn.s); ++ if (fd == -1) { log3("warning: qmail-todo: unable to open ",fn.s,"\n"); return; } ++ ++ fnmake_mess(id); ++ /* just for the statistics */ ++ if (stat(fn.s,&st) == -1) ++ { log3("warning: qmail-todo: unable to stat ",fn.s,"\n"); goto fail; } ++ ++ for (c = 0;c < CHANNELS;++c) ++ { ++ fnmake_chanaddr(id,c); ++ if (unlink(fn.s) == -1) if (errno != error_noent) ++ { log3("warning: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; } ++ } ++ ++ fnmake_info(id); ++ if (unlink(fn.s) == -1) if (errno != error_noent) ++ { log3("warning: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; } ++ ++ fdinfo = open_excl(fn.s); ++ if (fdinfo == -1) ++ { log3("warning: qmail-todo: unable to create ",fn.s,"\n"); goto fail; } ++ ++ strnum[fmt_ulong(strnum,id)] = 0; ++ log3("new msg ",strnum,"\n"); ++ ++ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0; ++ ++ substdio_fdbuf(&ss,subread,fd,todobuf,sizeof(todobuf)); ++ substdio_fdbuf(&ssinfo,subwrite,fdinfo,todobufinfo,sizeof(todobufinfo)); ++ ++ uid = 0; ++ pid = 0; ++ ++ for (;;) ++ { ++ if (getln(&ss,&todoline,&match,'\0') == -1) ++ { ++ /* perhaps we're out of memory, perhaps an I/O error */ ++ fnmake_todo(id); ++ log3("warning: qmail-todo: trouble reading ",fn.s,"\n"); goto fail; ++ } ++ if (!match) break; ++ ++ switch(todoline.s[0]) ++ { ++ case 'u': ++ scan_ulong(todoline.s + 1,&uid); ++ break; ++ case 'p': ++ scan_ulong(todoline.s + 1,&pid); ++ break; ++ case 'F': ++ if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1) ++ { ++ fnmake_info(id); ++ log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; ++ } ++ comm_info(id, (unsigned long) st.st_size, todoline.s + 1, pid, uid); ++ break; ++ case 'T': ++ switch(rewrite(todoline.s + 1)) ++ { ++ case 0: nomem(); goto fail; ++ case 2: c = 1; break; ++ default: c = 0; break; ++ } ++ if (fdchan[c] == -1) ++ { ++ fnmake_chanaddr(id,c); ++ fdchan[c] = open_excl(fn.s); ++ if (fdchan[c] == -1) ++ { log3("warning: qmail-todo: unable to create ",fn.s,"\n"); goto fail; } ++ substdio_fdbuf(&sschan[c], ++ subwrite,fdchan[c],todobufchan[c],sizeof(todobufchan[c])); ++ flagchan[c] = 1; ++ } ++ if (substdio_bput(&sschan[c],rwline.s,rwline.len) == -1) ++ { ++ fnmake_chanaddr(id,c); ++ log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; ++ } ++ break; ++ default: ++ fnmake_todo(id); ++ log3("warning: qmail-todo: unknown record type in ",fn.s,"\n"); goto fail; ++ } ++ } ++ ++ close(fd); fd = -1; ++ ++ fnmake_info(id); ++ if (substdio_flush(&ssinfo) == -1) ++ { log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; } ++ if (fsync(fdinfo) == -1) ++ { log3("warning: qmail-todo: trouble fsyncing ",fn.s,"\n"); goto fail; } ++ close(fdinfo); fdinfo = -1; ++ ++ for (c = 0;c < CHANNELS;++c) ++ if (fdchan[c] != -1) ++ { ++ fnmake_chanaddr(id,c); ++ if (substdio_flush(&sschan[c]) == -1) ++ { log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; } ++ if (fsync(fdchan[c]) == -1) ++ { log3("warning: qmail-todo: trouble fsyncing ",fn.s,"\n"); goto fail; } ++ close(fdchan[c]); fdchan[c] = -1; ++ } ++ ++ fnmake_todo(id); ++ if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; } ++ if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; } ++ if (ch != '+') ++ { ++ log3("warning: qmail-clean unable to clean up ",fn.s,"\n"); ++ return; ++ } ++ ++ comm_write(id, flagchan[0], flagchan[1]); ++ ++ return; ++ ++ fail: ++ if (fd != -1) close(fd); ++ if (fdinfo != -1) close(fdinfo); ++ for (c = 0;c < CHANNELS;++c) ++ if (fdchan[c] != -1) close(fdchan[c]); ++} ++ ++/* this file is too long ---------------------------------------------- MAIN */ ++ ++int getcontrols(void) ++{ ++ struct stat st; ++ ++ if (control_init() == -1) return 0; ++ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0; ++ ++ if (stat("control/locals.cdb", &st) == 0) { ++ if (!stralloc_copys(&localscdb, auto_qmail)) return 0; ++ if (!stralloc_cats(&localscdb, "/control/locals.cdb")) return 0; ++ if (!stralloc_0(&localscdb)) return 0; ++ if (!constmap_init(&maplocals,"",0,1)) return 0; ++ } else { ++ if (control_readfile(&locals,"control/locals",1) != 1) return 0; ++ if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0; ++ } ++ ++ switch(control_readfile(&percenthack,"control/percenthack",0)) ++ { ++ case -1: return 0; ++ case 0: if (!constmap_init(&mappercenthack,"",0,0)) return 0; break; ++ case 1: if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) return 0; break; ++ } ++ switch(control_readfile(&vdoms,"control/virtualdomains",0)) ++ { ++ case -1: return 0; ++ case 0: if (!constmap_init(&mapvdoms,"",0,1)) return 0; break; ++ case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) return 0; break; ++ } ++ return 1; ++} ++ ++stralloc newlocals = {0}; ++stralloc newvdoms = {0}; ++ ++void regetcontrols(void) ++{ ++ struct stat st; ++ int r; ++ ++ if (stat("control/locals.cdb", &st) == 0) { ++ while (!stralloc_copys(&localscdb, auto_qmail)) nomem(); ++ while (!stralloc_cats(&localscdb, "/control/locals.cdb")) nomem(); ++ while (!stralloc_0(&localscdb)) nomem(); ++ ++ constmap_free(&maplocals); ++ while (!constmap_init(&maplocals,"",0,1)) nomem(); ++ } else { ++ if (control_readfile(&newlocals,"control/locals",1) != 1) ++ { log1("alert: qmail-todo: unable to reread control/locals\n"); return; } ++ ++ while (!stralloc_copys(&localscdb, "")) nomem(); ++ ++ constmap_free(&maplocals); ++ while (!stralloc_copy(&locals,&newlocals)) nomem(); ++ while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem(); ++ } ++ ++ r = control_readfile(&newvdoms,"control/virtualdomains",0); ++ if (r == -1) ++ { log1("alert: qmail-todo: unable to reread control/virtualdomains\n"); return; } ++ ++ constmap_free(&mapvdoms); ++ ++ if (r) ++ { ++ while (!stralloc_copy(&vdoms,&newvdoms)) nomem(); ++ while (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) nomem(); ++ } ++ else ++ while (!constmap_init(&mapvdoms,"",0,1)) nomem(); ++} ++ ++void reread(void) ++{ ++ if (chdir(auto_qmail) == -1) ++ { ++ log1("alert: qmail-todo: unable to reread controls: unable to switch to home directory\n"); ++ return; ++ } ++ regetcontrols(); ++ while (chdir("queue") == -1) ++ { ++ log1("alert: qmail-todo: unable to switch back to queue directory; HELP! sleeping...\n"); ++ sleep(10); ++ } ++} ++ ++int main() ++{ ++ datetime_sec wakeup; ++ fd_set rfds; ++ fd_set wfds; ++ int nfds; ++ struct timeval tv; ++ int r; ++ char c; ++ ++ if (chdir(auto_qmail) == -1) ++ { log1("alert: qmail-todo: cannot start: unable to switch to home directory\n"); _exit(111); } ++ if (!getcontrols()) ++ { log1("alert: qmail-todo: cannot start: unable to read controls\n"); _exit(111); } ++ if (chdir("queue") == -1) ++ { log1("alert: qmail-todo: cannot start: unable to switch to queue directory\n"); _exit(111); } ++ sig_pipeignore(); ++ umask(077); ++ ++ fnmake_init(); ++ ++ todo_init(); ++ comm_init(); ++ ++ do { ++ r = read(fdin, &c, 1); ++ if ((r == -1) && (errno != error_intr)) ++ _exit(100); /* read failed probably qmail-send died */ ++ if (r == 0) /* Uh-oh, qmail-send died. */ ++ _exit(100); ++ } while (r != 1); /* we assume it is a 'S' */ ++ ++ for (;;) ++ { ++ recent = now(); ++ ++ if (flagreadasap) { flagreadasap = 0; reread(); } ++ if (!flagsendalive) { ++ /* qmail-send finaly exited, so do the same. */ ++ if (flagstopasap) _exit(0); ++ /* ++ * qmail-send died. ++ * We can not log and we can not work therefor _exit(1). ++ */ ++ _exit(1); ++ } ++ ++ wakeup = recent + SLEEP_FOREVER; ++ FD_ZERO(&rfds); ++ FD_ZERO(&wfds); ++ nfds = 1; ++ ++ todo_selprep(&nfds,&rfds,&wakeup); ++ comm_selprep(&nfds,&wfds,&rfds); ++ ++ if (wakeup <= recent) tv.tv_sec = 0; ++ else tv.tv_sec = wakeup - recent + SLEEP_FUZZ; ++ tv.tv_usec = 0; ++ ++ if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) == -1) ++ if (errno == error_intr) ++ ; ++ else ++ log1("warning: qmail-todo: trouble in select\n"); ++ else ++ { ++ recent = now(); ++ ++ todo_do(&rfds); ++ comm_do(&wfds, &rfds); ++ } ++ } ++ /* NOTREACHED */ ++ return 1; ++} ++ +diff -upN qmail-1.03/qmail-verify.c qmail-ldap/qmail-verify.c +--- qmail-1.03/qmail-verify.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail-verify.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,257 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include "error.h" ++#include "getln.h" ++#include "qldap.h" ++#include "qldap-errno.h" ++#include "qmail-ldap.h" ++#include "read-ctrl.h" ++#include "stralloc.h" ++#include "subfd.h" ++#include "substdio.h" ++#include "timeoutread.h" ++ ++struct qldap *q; ++ ++void cleanup(void); ++void ++die_read(void) ++{ ++ cleanup(); ++ _exit(1); ++} ++void ++die_write(void) ++{ ++ cleanup(); ++ _exit(1); ++} ++void ++die_nomem(void) ++{ ++ cleanup(); ++ _exit(111); ++} ++void ++die_timeout(void) ++{ ++ cleanup(); ++ _exit(111); ++} ++void ++die_temp(void) ++{ ++ cleanup(); ++ _exit(111); ++} ++void ++die_control(void) ++{ ++ _exit(100); ++} ++void ++temp_fail(void) ++{ ++ if (substdio_putflush(subfdout, "Z", 2) == -1) ++ die_write(); ++ qldap_free_results(q); ++} ++ ++void lookup(stralloc *mail); ++ ++ ++int timeout = 3; ++int ++saferead(int fd, void *buf, int len) ++{ ++ return timeoutread(timeout,fd,buf,len); ++} ++ ++char ssinbuf[512]; ++substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); ++ ++stralloc line = {0}; ++ctrlfunc ctrls[] = { ++ qldap_ctrl_trylogin, ++ qldap_ctrl_generic, ++ 0 }; ++ ++int ++main(int argc, char **argv) ++{ ++ int match; ++ ++ if (read_controls(ctrls) == -1) ++ die_control(); ++ ++ q = 0; ++ do { ++ if (getln(&ssin, &line, &match, '\0') != 0) { ++ if (errno != error_timeout) ++ die_read(); ++ cleanup(); ++ continue; ++ } ++ if (!match) { ++ cleanup(); /* other side closed pipe */ ++ break; ++ } ++ lookup(&line); ++ } while (1); ++ return 0; ++} ++ ++void ++lookup(stralloc *mail) ++{ ++ const char *attrs[] = { LDAP_ISACTIVE, 0 }; ++ char *f; ++ int done; ++ int status; ++ int rv; ++ ++ /* TODO more debug output is needed */ ++ if (q == 0) { ++ q = qldap_new(); ++ if (q == 0) ++ die_nomem(); ++ ++ rv = qldap_open(q); ++ if (rv != OK) die_temp(); ++ rv = qldap_bind(q, 0, 0); ++ if (rv != OK) die_temp(); ++ } ++ ++ /* ++ * this handles the "catch all" and "-default" extension ++ * but also the normal eMail address. ++ * Code handels also mail addresses with multiple '@' safely. ++ * at = index to last @ sign in mail address ++ * escaped = ldap escaped mailaddress ++ * len = length of escaped mailaddress ++ * i = position of current '-' or '@' ++ */ ++ done = 0; ++ do { ++ f = filter_mail(mail->s, &done); ++ if (f == (char *)0) die_nomem(); ++ ++ //logit(16, "ldapfilter: '%s'\n", f); ++ ++ /* do the search for the email address */ ++ rv = qldap_lookup(q, f, attrs); ++ switch (rv) { ++ case OK: ++ break; /* something found */ ++ case TIMEOUT: ++ /* temporary error but give up so that the ++ * ldap server can recover */ ++ die_timeout(); ++ case TOOMANY: ++#ifdef DUPEALIAS ++ if (substdio_putflush(subfdout, "K", 1) == -1) ++ die_write(); ++ qldap_free_results(q); ++#else ++ /* admin error, also temporary */ ++ temp_fail(); ++#endif ++ return; ++ case FAILED: ++ /* ... again temporary */ ++ temp_fail(); ++ return; ++ case NOSUCH: ++ break; ++ } ++ } while (rv != OK && !done); ++ /* reset filter_mail */ ++ filter_mail(0, 0); ++ ++ /* nothing found, try a local lookup or a alias delivery */ ++ if (rv == NOSUCH) { ++ /* Sorry, no mailbox here by that name. (#5.1.1) */ ++ if (substdio_puts(subfdout, ++ "DSorry, no mailbox here by that name. " ++ "(#5.1.1)") == -1) ++ die_write(); ++ if (substdio_putflush(subfdout, "", 1) == -1) ++ die_write(); ++ qldap_free_results(q); ++ return; ++ } ++ ++ /* check if the ldap entry is active */ ++ rv = qldap_get_status(q, &status); ++ if (rv != OK) { ++ temp_fail(); ++ return; ++ } ++ if (status == STATUS_BOUNCE) { ++ /* Mailaddress is administratively disabled. (#5.2.1) */ ++ if (substdio_puts(subfdout, ++ "DMailaddress is administratively disabled. " ++ "(#5.2.1)") == -1) ++ die_write(); ++ if (substdio_putflush(subfdout, "", 1) == -1) ++ die_write(); ++ qldap_free_results(q); ++ return; ++ } else if (status == STATUS_DELETE) { ++ /* Sorry, no mailbox here by that name. (#5.1.1) */ ++ if (substdio_puts(subfdout, ++ "DSorry, no mailbox here by that name. " ++ "(#5.1.1)") == -1) ++ die_write(); ++ if (substdio_putflush(subfdout, "", 1) == -1) ++ die_write(); ++ qldap_free_results(q); ++ return; ++ } ++ ++ /* OK */ ++ if (substdio_putflush(subfdout, "K", 1) == -1) ++ die_write(); ++ qldap_free_results(q); ++} ++ ++void ++cleanup(void) ++{ ++ if (q != 0) ++ qldap_free(q); ++ q = 0; ++} ++ +diff -upN qmail-1.03/qmail.c qmail-ldap/qmail.c +--- qmail-1.03/qmail.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "substdio.h" + #include "readwrite.h" + #include "wait.h" +@@ -7,7 +8,24 @@ + #include "qmail.h" + #include "auto_qmail.h" + ++#ifdef ALTQUEUE ++#include "env.h" ++ ++static char *binqqargs[2] = { 0, 0 } ; ++ ++static void ++setup_qqargs(void) ++{ ++ if(!binqqargs[0]) ++ binqqargs[0] = (char *)env_get("QMAILQUEUE"); ++ if(!binqqargs[0]) ++ binqqargs[0] = (char *)"bin/qmail-queue"; ++} ++ ++#else + static char *binqqargs[2] = { "bin/qmail-queue", 0 } ; ++#endif ++ + + int qmail_open(qq) + struct qmail *qq; +@@ -15,6 +33,10 @@ struct qmail *qq; + int pim[2]; + int pie[2]; + ++#ifdef ALTQUEUE ++ setup_qqargs(); ++#endif ++ + if (pipe(pim) == -1) return -1; + if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } + +@@ -35,7 +57,44 @@ struct qmail *qq; + + qq->fdm = pim[1]; close(pim[0]); + qq->fde = pie[1]; close(pie[0]); +- substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf)); ++ substdio_fdbuf(&qq->ss,subwrite,qq->fdm,qq->buf,sizeof(qq->buf)); ++ qq->flagerr = 0; ++ return 0; ++} ++ ++int qmail_remote(qq, host) ++struct qmail *qq; ++char *host; ++{ ++ int pim[2]; ++ int pie[2]; ++ char *(args[3]); ++ ++ args[0] = (char *)"bin/qmail-qmqpc"; ++ args[1] = host; ++ args[2] = 0; ++ ++ if (pipe(pim) == -1) return -1; ++ if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } ++ ++ switch(qq->pid = vfork()) { ++ case -1: ++ close(pim[0]); close(pim[1]); ++ close(pie[0]); close(pie[1]); ++ return -1; ++ case 0: ++ close(pim[1]); ++ close(pie[1]); ++ if (fd_move(0,pim[0]) == -1) _exit(120); ++ if (fd_move(1,pie[0]) == -1) _exit(120); ++ if (chdir(auto_qmail) == -1) _exit(61); ++ execv(*args,args); ++ _exit(120); ++ } ++ ++ qq->fdm = pim[1]; close(pim[0]); ++ qq->fde = pie[1]; close(pie[0]); ++ substdio_fdbuf(&qq->ss,subwrite,qq->fdm,qq->buf,sizeof(qq->buf)); + qq->flagerr = 0; + return 0; + } +@@ -50,34 +109,34 @@ void qmail_fail(qq) struct qmail *qq; + qq->flagerr = 1; + } + +-void qmail_put(qq,s,len) struct qmail *qq; char *s; int len; ++void qmail_put(qq,s,len) struct qmail *qq; const char *s; int len; + { + if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1; + } + +-void qmail_puts(qq,s) struct qmail *qq; char *s; ++void qmail_puts(qq,s) struct qmail *qq; const char *s; + { + if (!qq->flagerr) if (substdio_puts(&qq->ss,s) == -1) qq->flagerr = 1; + } + +-void qmail_from(qq,s) struct qmail *qq; char *s; ++void qmail_from(qq,s) struct qmail *qq; const char *s; + { + if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; + close(qq->fdm); +- substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf)); ++ substdio_fdbuf(&qq->ss,subwrite,qq->fde,qq->buf,sizeof(qq->buf)); + qmail_put(qq,"F",1); + qmail_puts(qq,s); + qmail_put(qq,"",1); + } + +-void qmail_to(qq,s) struct qmail *qq; char *s; ++void qmail_to(qq,s) struct qmail *qq; const char *s; + { + qmail_put(qq,"T",1); + qmail_puts(qq,s); + qmail_put(qq,"",1); + } + +-char *qmail_close(qq) ++const char *qmail_close(qq) + struct qmail *qq; + { + int wstat; +diff -upN qmail-1.03/qmail.h qmail-ldap/qmail.h +--- qmail-1.03/qmail.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qmail.h Tue Oct 28 18:21:32 2003 +@@ -12,13 +12,14 @@ struct qmail { + char buf[1024]; + } ; + +-extern int qmail_open(); +-extern void qmail_put(); +-extern void qmail_puts(); +-extern void qmail_from(); +-extern void qmail_to(); +-extern void qmail_fail(); +-extern char *qmail_close(); +-extern unsigned long qmail_qp(); ++extern int qmail_open(struct qmail *); ++extern int qmail_remote(struct qmail *, char *); ++extern void qmail_put(struct qmail *, const char *, int); ++extern void qmail_puts(struct qmail *, const char *); ++extern void qmail_from(struct qmail *, const char *); ++extern void qmail_to(struct qmail *, const char *); ++extern void qmail_fail(struct qmail *); ++extern const char *qmail_close(struct qmail *); ++extern unsigned long qmail_qp(struct qmail *); + + #endif +diff -upN qmail-1.03/qmail.schema qmail-ldap/qmail.schema +--- qmail-1.03/qmail.schema Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail.schema Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,279 @@ ++# ++# qmail-ldap (20030901) ldapv3 directory schema ++# ++# The offical qmail-ldap OID assigned by IANA is 7914 ++# ++# Created by: David E. Storey ++# Modified and included into qmail-ldap by Andre Oppermann ++# Schema fixes by Mike Jackson ++# Schema fixes by Christian Zoffoli (XMerlin) ++# ++# ++# This schema depends on: ++# - core.schema ++# - cosine.schema ++# - nis.schema ++# ++ ++# Attribute Type Definitions ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.1 NAME 'qmailUID' ++ DESC 'UID of the user on the mailsystem' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.2 NAME 'qmailGID' ++ DESC 'GID of the user on the mailsystem' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.3 NAME 'mailMessageStore' ++ DESC 'Path to the maildir/mbox on the mail system' ++ EQUALITY caseExactIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.4 NAME 'mailAlternateAddress' ++ DESC 'Secondary (alias) mailaddresses for the same user' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++# ++# mailQuota format is no longer supported from qmail-ldap 20030901 on, ++# user mailQuotaSize and mailQuotaCount instead. ++# ++#attributetype ( 1.3.6.1.4.1.7914.1.2.1.5 NAME 'mailQuota' ++# DESC 'The amount of space the user can use until all further messages get bounced.' ++# SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 SINGLE-VALUE ) ++# ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.6 NAME 'mailHost' ++ DESC 'On which qmail server the messagestore of this user is located.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.7 NAME 'mailForwardingAddress' ++ DESC 'Address(es) to forward all incoming messages to.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.8 NAME 'deliveryProgramPath' ++ DESC 'Program to execute for all incoming mails.' ++ EQUALITY caseExactIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.9 NAME 'qmailDotMode' ++ DESC 'Interpretation of .qmail files: both, dotonly, ldaponly, ldapwithprog' ++ EQUALITY caseIgnoreIA5Match ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.10 NAME 'deliveryMode' ++ DESC 'multi field entries of: nolocal, noforward, noprogram, reply' ++ EQUALITY caseIgnoreIA5Match ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.11 NAME 'mailReplyText' ++ DESC 'A reply text for every incoming message' ++ EQUALITY caseIgnoreMatch ++ SUBSTR caseIgnoreSubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.12 NAME 'accountStatus' ++ DESC 'The status of a user account: active, noaccess, disabled, deleted' ++ EQUALITY caseIgnoreIA5Match ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.14 NAME 'qmailAccountPurge' ++ DESC 'The earliest date when a mailMessageStore will be purged' ++ EQUALITY numericStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.15 NAME 'mailQuotaSize' ++ DESC 'The size of space the user can have until further messages get bounced.' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.16 NAME 'mailQuotaCount' ++ DESC 'The number of messages the user can have until further messages get bounced.' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.2.1.17 NAME 'mailSizeMax' ++ DESC 'The maximum size of a single messages the user accepts.' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++# ++# qmailGroup attributes ++# ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.1 NAME 'dnmember' ++ DESC 'Group member specified as distinguished name.' ++ EQUALITY distinguishedNameMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.2 NAME 'rfc822member' ++ DESC 'Group member specified as normal rf822 email address.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.3 NAME 'filtermember' ++ DESC 'Group member specified as ldap search filter.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.4 NAME 'senderconfirm' ++ DESC 'Sender to Group has to answer confirmation email.' ++ EQUALITY booleanMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.5 NAME 'membersonly' ++ DESC 'Sender to Group must be group member itself.' ++ EQUALITY booleanMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.6 NAME 'confirmtext' ++ DESC 'Text that will be sent with sender confirmation email.' ++ EQUALITY caseIgnoreMatch ++ SUBSTR caseIgnoreSubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.7 NAME 'dnmoderator' ++ DESC 'Group moderator specified as Distinguished name.' ++ EQUALITY distinguishedNameMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.8 NAME 'rfc822moderator' ++ DESC 'Group moderator specified as normal rfc822 email address.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.9 NAME 'moderatortext' ++ DESC 'Text that will be sent with request for moderation email.' ++ EQUALITY caseIgnoreMatch ++ SUBSTR caseIgnoreSubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.10 NAME 'dnsender' ++ DESC 'Allowed sender specified as distinguished name.' ++ EQUALITY distinguishedNameMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.11 NAME 'rfc822sender' ++ DESC 'Allowed sender specified as normal rf822 email address.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.12 NAME 'filtersender' ++ DESC 'Allowed sender specified as ldap search filter.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.3.1.13 NAME 'bounceadmin' ++ DESC 'rfc822 email address where bounces should be sent to.' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++ ++# ++# qldapAdmin Attributes ++# ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.1 NAME 'qladnmanager' ++ DESC '' ++ EQUALITY distinguishedNameMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.2 NAME 'qlaDomainList' ++ DESC '' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.3 NAME 'qlaUidPrefix' ++ DESC '' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.4 NAME 'qlaQmailUid' ++ DESC '' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.5 NAME 'qlaQmailGid' ++ DESC '' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.6 NAME 'qlaMailMStorePrefix' ++ DESC '' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.7 NAME 'qlaMailQuotaSize' ++ DESC '' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.8 NAME 'qlaMailQuotaCount' ++ DESC '' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.9 NAME 'qlaMailSizeMax' ++ DESC '' ++ EQUALITY integerMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) ++ ++attributetype ( 1.3.6.1.4.1.7914.1.4.1.10 NAME 'qlaMailHostList' ++ DESC '' ++ EQUALITY caseIgnoreIA5Match ++ SUBSTR caseIgnoreIA5SubstringsMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) ++ ++ ++# Object Class Definitions ++ ++objectclass ( 1.3.6.1.4.1.7914.1.2.2.1 NAME 'qmailUser' ++ DESC 'QMail-LDAP User' ++ SUP top ++ AUXILIARY ++ MUST ( mail ) ++ MAY ( uid $ mailMessageStore $ homeDirectory $ userPassword $ ++ mailAlternateAddress $ qmailUID $ qmailGID $ ++ mailHost $ mailForwardingAddress $ deliveryProgramPath $ ++ qmailDotMode $ deliveryMode $ mailReplyText $ ++ accountStatus $ qmailAccountPurge $ ++ mailQuotaSize $ mailQuotaCount $ mailSizeMax ) ) ++ ++objectclass ( 1.3.6.1.4.1.7914.1.3.2.1 NAME 'qmailGroup' ++ DESC 'QMail-LDAP Group' ++ SUP top ++ AUXILIARY ++ MUST ( mail $ mailAlternateAddress $ mailMessageStore ) ++ MAY ( dnmember $ rfc822member $ filtermember $ senderconfirm $ ++ membersonly $ confirmtext $ dnmoderator $ rfc822moderator $ ++ moderatortext $ dnsender $ rfc822sender $ filtersender $ ++ bounceadmin) ) ++ ++objectclass ( 1.3.6.1.4.1.7914.1.4.2.1 NAME 'qldapAdmin' ++ DESC 'QMail-LDAP Subtree Admin' ++ SUP top ++ AUXILIARY ++ MUST ( qlaDnManager $ qlaDomainList $ qlaMailMStorePrefix $ ++ qlaMailHostList ) ++ MAY ( qlaUidPrefix $ qlaQmailUid $ qlaQmailGid $ qlaMailQuotaSize $ ++ qlaMailQuotaCount $ qlaMailSizeMax ) ) ++ +diff -upN qmail-1.03/qmail.sh qmail-ldap/qmail.sh +--- qmail-1.03/qmail.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmail.sh Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,20 @@ ++#!/bin/sh ++exec 2>&1 ++# ++# qmail-send and friends ++# ++QMAIL="%QMAIL%" ++if [ -e $QMAIL/control/defaultdelivery ]; then ++ ALIASEMPTY=`cat $QMAIL/control/defaultdelivery 2> /dev/null` ++else ++ ALIASEMPTY=`cat $QMAIL/control/aliasempty 2> /dev/null` ++fi ++ALIASEMPTY=${ALIASEMPTY:="./Maildir/"} ++ ++PATH="$QMAIL/bin:$PATH" ++ ++# limit to prevent memory hogs ++ulimit -c 204800 ++ ++exec envdir ./env qmail-start "$ALIASEMPTY" ++ +diff -upN qmail-1.03/qmailAccountPurge.sh qmail-ldap/qmailAccountPurge.sh +--- qmail-1.03/qmailAccountPurge.sh Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/qmailAccountPurge.sh Fri Apr 20 23:35:56 2001 +@@ -0,0 +1,22 @@ ++#!/bin/sh ++ ++case "$1" in ++ ++show) ++ ++ /usr/local/bin/ldapsearch \ ++ -u -F "=" \ ++ -h "`cat /var/qmail/control/ldapserver`" \ ++ -b "`cat /var/qmail/control/ldapbasedn`" \ ++ -S "mail" \ ++ "(&(accountStatus=deleted)(qmailAccountPurge=<`/var/qmail/bin/gettimeofday`))" \ ++ mail mailAlternateAddress uid mailMessageStore mailHost ++ ++ ;; ++ ++purge) ++ ++ ;; ++ ++esac ++ +diff -upN qmail-1.03/qreceipt.c qmail-ldap/qreceipt.c +--- qmail-1.03/qreceipt.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qreceipt.c Tue Oct 28 18:21:32 2003 +@@ -60,7 +60,7 @@ stralloc quoted = {0}; + + void finishheader() + { +- char *qqx; ++ const char *qqx; + + if (!flagreceipt) die_noreceipt(); + if (str_equal(returnpath,"")) die_noreceipt(); +@@ -92,9 +92,10 @@ following address: "); + qmail_to(&qqt,returnpath); + qqx = qmail_close(&qqt); + +- if (*qqx) ++ if (*qqx) { + if (*qqx == 'D') die_qqperm(); + else die_qqtemp(); ++ } + } + + stralloc hfbuf = {0}; +@@ -119,7 +120,7 @@ stralloc *h; + + void dobody(h) stralloc *h; { ; } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -128,4 +129,6 @@ char **argv; + if (!(returnpath = env_get("SENDER"))) die_usage(); + if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read(); + die_noreceipt(); ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/qsmhook.c qmail-ldap/qsmhook.c +--- qmail-1.03/qsmhook.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qsmhook.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "fd.h" + #include "stralloc.h" + #include "readwrite.h" +@@ -35,7 +36,7 @@ char outbuf[SUBSTDIO_OUTSIZE]; + substdio ssin; + char inbuf[SUBSTDIO_INSIZE]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -45,7 +46,7 @@ char **argv; + int opt; + char **arg; + char *x; +- int i; ++ unsigned int i; + int flagesc; + + sig_pipeignore(); +@@ -78,7 +79,7 @@ char **argv; + + if (!*argv) die_usage(); + +- for (arg = argv;x = *arg;++arg) ++ for (arg = argv;(x = *arg);++arg) + { + if (!stralloc_copys(&newarg,"")) die_temp(); + flagesc = 0; +@@ -122,8 +123,8 @@ char **argv; + } + close(pi[0]); + +- substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf)); +- substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); ++ substdio_fdbuf(&ssout,subwrite,pi[1],outbuf,sizeof(outbuf)); ++ substdio_fdbuf(&ssin,subread,0,inbuf,sizeof(inbuf)); + if (flagufline) substdio_bputs(&ssout,ufline); + if (flagrpline) substdio_bputs(&ssout,rpline); + if (flagdtline) substdio_bputs(&ssout,dtline); +@@ -133,5 +134,5 @@ char **argv; + + if (wait_pid(&wstat,pid) == -1) die_temp(); + if (wait_crashed(wstat)) die_temp(); +- _exit(wait_exitcode(wstat)); ++ return wait_exitcode(wstat); + } +diff -upN qmail-1.03/qsutil.c qmail-ldap/qsutil.c +--- qmail-1.03/qsutil.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qsutil.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "stralloc.h" + #include "readwrite.h" + #include "substdio.h" +@@ -6,22 +7,22 @@ + static stralloc foo = {0}; + + static char errbuf[1]; +-static struct substdio sserr = SUBSTDIO_FDBUF(write,0,errbuf,1); ++static struct substdio sserr = SUBSTDIO_FDBUF(subwrite,0,errbuf,1); + + void logsa(sa) stralloc *sa; { + substdio_putflush(&sserr,sa->s,sa->len); } +-void log1(s1) char *s1; { ++void log1(s1) const char *s1; { + substdio_putsflush(&sserr,s1); } +-void log2(s1,s2) char *s1; char *s2; { ++void log2(s1,s2) const char *s1; const char *s2; { + substdio_putsflush(&sserr,s1); + substdio_putsflush(&sserr,s2); } +-void log3(s1,s2,s3) char *s1; char *s2; char *s3; { ++void log3(s1,s2,s3) const char *s1; const char *s2; const char *s3; { + substdio_putsflush(&sserr,s1); + substdio_putsflush(&sserr,s2); + substdio_putsflush(&sserr,s3); } +-void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); } ++void nomem(void) { log1("alert: out of memory, sleeping...\n"); sleep(10); } + +-void pausedir(dir) char *dir; ++void pausedir(dir) const char *dir; + { log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); } + + static int issafe(ch) char ch; +@@ -32,7 +33,7 @@ static int issafe(ch) char ch; + return 1; + } + +-void logsafe(s) char *s; ++void logsafe(s) const char *s; + { + int i; + while (!stralloc_copys(&foo,s)) nomem(); +diff -upN qmail-1.03/qsutil.h qmail-ldap/qsutil.h +--- qmail-1.03/qsutil.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/qsutil.h Tue Oct 28 18:21:32 2003 +@@ -1,12 +1,12 @@ + #ifndef QSUTIL_H + #define QSUTIL_H + +-extern void log1(); +-extern void log2(); +-extern void log3(); +-extern void logsa(); +-extern void nomem(); +-extern void pausedir(); +-extern void logsafe(); ++extern void log1(const char *); ++extern void log2(const char *, const char *); ++extern void log3(const char *, const char *, const char *); ++extern void logsa(stralloc *); ++extern void nomem(void); ++extern void pausedir(const char *); ++extern void logsafe(const char *); + + #endif +diff -upN qmail-1.03/quote.c qmail-ldap/quote.c +--- qmail-1.03/quote.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/quote.c Thu Jan 29 16:48:14 2004 +@@ -9,7 +9,7 @@ no, 821 and 822 don't have the same enco + no special encoding here for bytes above 127. + */ + +-static char ok[128] = { ++static const char ok[128] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ,0,7,0,7,7,7,7,7,0,0,7,7,0,7,7,7 ,7,7,7,7,7,7,7,7,7,7,0,0,0,7,0,7 + ,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 ,7,7,7,7,7,7,7,7,7,7,7,0,0,0,7,7 +@@ -21,8 +21,8 @@ stralloc *saout; + stralloc *sain; + { + char ch; +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + + if (!stralloc_ready(saout,sain->len * 2 + 2)) return 0; + j = 0; +@@ -40,11 +40,11 @@ stralloc *sain; + } + + int quote_need(s,n) +-char *s; ++const char *s; + unsigned int n; + { + unsigned char uch; +- int i; ++ unsigned int i; + if (!n) return 1; + for (i = 0;i < n;++i) + { +@@ -70,9 +70,9 @@ static stralloc foo = {0}; + + int quote2(sa,s) + stralloc *sa; +-char *s; ++const char *s; + { +- int j; ++ unsigned int j; + if (!*s) return stralloc_copys(sa,s); + j = str_rchr(s,'@'); + if (!stralloc_copys(&foo,s)) return 0; +diff -upN qmail-1.03/quote.h qmail-ldap/quote.h +--- qmail-1.03/quote.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/quote.h Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,10 @@ + #ifndef QUOTE_H + #define QUOTE_H + +-extern int quote_need(); +-extern int quote(); +-extern int quote2(); ++#include "stralloc.h" ++ ++extern int quote_need(const char *, unsigned int); ++extern int quote(stralloc *, stralloc *); ++extern int quote2(stralloc *, const char *); + + #endif +diff -upN qmail-1.03/rbl.c qmail-ldap/rbl.c +--- qmail-1.03/rbl.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/rbl.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,253 @@ ++/* ++ * Copyright (c) 2002-2004 Andre Oppermann, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include "alloc.h" ++#include "control.h" ++#include "dns.h" ++#include "env.h" ++#include "ipalloc.h" ++#include "qmail.h" ++#include "str.h" ++#include "stralloc.h" ++ ++#include "rbl.h" ++ ++static stralloc rblmessage = {0}; ++int rblprintheader = 0; ++ ++/* functions borrowed from qmail-smtpd.c */ ++extern void safeput(); ++extern void die_nomem(); ++ ++extern void logpid(); ++extern void logline(); ++extern void logstring(); ++extern void logflush(); ++ ++void rblheader(struct qmail *qqt) ++{ ++ if (!rblprintheader) return; ++ /* rblmessage is safe because it does not contain any remote info */ ++ if (rblmessage.s) qmail_put(qqt,rblmessage.s,rblmessage.len); ++} ++ ++struct rbl { ++ char *baseaddr; ++ char *action; ++ char *matchon; ++ char *message; ++} *rbl; ++ ++unsigned int numrbl; ++ ++static stralloc ip_reverse = {0}; ++static stralloc rbl_tmp = {0}; ++ ++static int rbl_start(const char *remoteip) ++{ ++ unsigned int i; ++ unsigned int j; ++ const char *ip_env; ++ ++ ip_env = remoteip; ++ if (!ip_env) ip_env = ""; ++ ++ if (!stralloc_copys(&ip_reverse,"")) die_nomem(); ++ ++ i = str_len(ip_env); ++ while (i) { ++ for (j = i;j > 0;--j) { ++ if (ip_env[j - 1] == '.') break; ++ if (ip_env[j - 1] == ':') return 0; /* no IPv6 */ ++ } ++ if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) die_nomem(); ++ if (!stralloc_cats(&ip_reverse,".")) die_nomem(); ++ if (!j) break; ++ i = j - 1; ++ } ++ return 1; ++} ++ ++static char ipstr[IPFMT]; ++ ++static int rbl_lookup(char *base, char *matchon) ++{ ++ ipalloc rblsa = {0}; ++ unsigned int i; ++ ++ if (!*base) return 2; ++ ++ if (!stralloc_copy(&rbl_tmp,&ip_reverse)) die_nomem(); ++ if (!stralloc_cats(&rbl_tmp,base)) die_nomem(); ++ ++ switch (dns_ip(&rblsa,&rbl_tmp)) { ++ case DNS_MEM: ++ case DNS_SOFT: ++ return 2; /* soft error */ ++ case DNS_HARD: ++ return 0; /* found no match */ ++ default: /* found match */ ++ if (!str_diff("any", matchon)) ++ return 1; ++ for (i = 0;i < rblsa.len;++i) ++ { ++ ipstr[ip_fmt(ipstr,&rblsa.ix[i].ip)]=0; ++ if (!str_diff(ipstr, matchon)) return 1; ++ } ++ return 0; /* found match but ignored */ ++ } ++ return 1; /* should never get here */ ++} ++ ++void rbladdheader(char *base, char *matchon, char *message) ++{ ++ /* all of base, matchon and message can be trusted because these ++ are under our control */ ++ rblprintheader = 1; ++ if(!stralloc_cats(&rblmessage, "X-RBL: (")) die_nomem(); ++ if(!stralloc_cats(&rblmessage, base)) die_nomem(); ++ if(!stralloc_cats(&rblmessage, ") ")) die_nomem(); ++ if (str_diff("any", matchon)) { ++ if(!stralloc_cats(&rblmessage, "matches with ")) die_nomem(); ++ if(!stralloc_cats(&rblmessage, matchon)) die_nomem(); ++ if(!stralloc_cats(&rblmessage, " and ")) die_nomem(); ++ } ++ if(!stralloc_cats(&rblmessage, "tells us ")) die_nomem(); ++ if(!stralloc_cats(&rblmessage, message)) die_nomem(); ++ if(!stralloc_cats(&rblmessage, "\n")) die_nomem(); ++} ++ ++int rblcheck(const char *remoteip, char** rblname, int rbloh) ++{ ++ int r = 1; ++ unsigned int i; ++ ++ if(!stralloc_copys(&rblmessage, "")) die_nomem(); ++ if(!rbl_start(remoteip)) return 0; ++ ++ for (i=0; i < numrbl; i++) { ++ logpid(2); logstring(2,"RBL check with '"); ++ logstring(2,rbl[i].baseaddr); logstring(2,"': "); ++ ++ r = rbl_lookup(rbl[i].baseaddr, rbl[i].matchon); ++ if (r == 2) { ++ logstring(2,"temporary DNS error, ignored"); logflush(2); ++ } else if (r == 1) { ++ logstring(2,"found match, "); ++ *rblname = rbl[i].message; ++ if (rbloh) { ++ logstring(2,"tag header"); logflush(2); ++ rbladdheader(rbl[i].baseaddr, rbl[i].matchon, rbl[i].message); ++ continue; ++ } ++ if (!str_diff("addheader", rbl[i].action)) { ++ logstring(2,"tag header"); logflush(2); ++ rbladdheader(rbl[i].baseaddr, rbl[i].matchon, rbl[i].message); ++ continue; ++ } else { ++ /* default reject */ ++ logstring(2,"reject sender"); logflush(2); ++ rblprintheader = 0; ++ return 1; ++ } ++ } ++ /* continue */ ++ logstring(2,"no match found, continue."); logflush(2); ++ } ++ return 0; /* either tagged, soft error or allowed */ ++} ++ ++stralloc rbldata = {0}; ++ ++int rblinit(void) ++{ ++ char** x; ++ int on; ++ unsigned int i; ++ unsigned int j; ++ unsigned int k; ++ unsigned int n; ++ ++ on = control_readfile(&rbldata,"control/rbllist",0); ++ if (on == -1) return on; ++ if (!on) return on; ++ ++ for(i=0, numrbl=0; i < rbldata.len; ++i) ++ if (rbldata.s[i] == '\0') ++ ++numrbl; ++ ++ rbl = (struct rbl*)alloc(numrbl*sizeof(struct rbl)); ++ if (!rbl) return -1; ++ ++ /* line format is "basedomain action matchon message" ++ message may have spaces */ ++ x = (char **)&rbl[0]; ++ for (i=0, j=0, k=0, n=0; i < rbldata.len; ++i) { ++ while (1) { ++ /* hop over spaces */ ++ if (rbldata.s[i] != ' ' && rbldata.s[i] != '\t') break; ++ if (rbldata.s[i] == '\0') { ++ logline(1, "parse error in rbllist, unexpected end of line"); ++ return -1; ++ } ++ i++; ++ } ++ j = i; ++ if (n == 3) { ++ /* message */ ++ x[n] = rbldata.s + j; ++ n = 0; ++ x = (char **)&rbl[++k]; ++ while (rbldata.s[i] != '\0') i++; ++ } else { ++ while (1) { ++ /* hop over argument */ ++ if (rbldata.s[i] == ' ' || rbldata.s[i] == '\t') break; ++ if (rbldata.s[i] == '\0') { ++ logline(1, "parse error in rbllist, unexpected end of line"); ++ return -1; ++ } ++ i++; ++ } ++ rbldata.s[i] = '\0'; ++ x[n++] = rbldata.s + j; ++ } ++ } ++ if (k != numrbl) { ++ logline(1,"parse error in rbllist, unexpected end of file"); ++ return -1; ++ } ++ ++ return 1; /* everything fine */ ++} ++ +diff -upN qmail-1.03/rbl.h qmail-ldap/rbl.h +--- qmail-1.03/rbl.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/rbl.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2002-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef RBL_H ++#define RBL_H ++ ++#include "qmail.h" ++ ++extern void rblheader(struct qmail *); ++extern int rblcheck(const char *, char **, int); ++extern int rblinit(void); ++ ++#endif +diff -upN qmail-1.03/rcpthosts.c qmail-ldap/rcpthosts.c +--- qmail-1.03/rcpthosts.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/rcpthosts.c Wed May 5 17:42:12 2004 +@@ -1,5 +1,6 @@ + #include "cdb.h" + #include "byte.h" ++#include "case.h" + #include "open.h" + #include "error.h" + #include "control.h" +@@ -7,54 +8,126 @@ + #include "stralloc.h" + #include "rcpthosts.h" + +-static int flagrh = 0; ++static int flagrh = -1; + static stralloc rh = {0}; + static struct constmap maprh; ++static int fdlo; ++static int fdrh; + static int fdmrh; ++static struct cdb cdblo; ++static struct cdb cdbrh; ++static struct cdb cdbmrh; ++static stralloc locals = {0}; ++static struct constmap maplocals; + +-int rcpthosts_init() ++int rcpthosts_init(void) + { +- flagrh = control_readfile(&rh,"control/rcpthosts",0); +- if (flagrh != 1) return flagrh; +- if (!constmap_init(&maprh,rh.s,rh.len,0)) return flagrh = -1; +- fdmrh = open_read("control/morercpthosts.cdb"); +- if (fdmrh == -1) if (errno != error_noent) return flagrh = -1; +- return 0; ++ fdlo = open_read("control/locals.cdb"); ++ if (fdlo == -1) { ++ if (errno != error_noent) ++ return -1; ++ if (control_readfile(&locals,"control/locals",1) != 1) ++ return -1; ++ if (!constmap_init(&maplocals,locals.s,locals.len,0)) ++ return -1; ++ } else ++ cdb_init(&cdblo, fdlo); ++ ++ fdrh = open_read("control/rcpthosts.cdb"); ++ if (fdrh == -1) { ++ if (errno != error_noent) return -1; ++ ++ if (control_readfile(&rh,"control/rcpthosts",0) == -1) ++ return -1; ++ if (!constmap_init(&maprh,rh.s,rh.len,0)) ++ return -1; ++ fdmrh = open_read("control/morercpthosts.cdb"); ++ if (fdmrh == -1) { ++ if (errno != error_noent) ++ return -1; ++ } else ++ cdb_init(&cdbmrh, fdmrh); ++ } else ++ cdb_init(&cdbrh, fdrh); ++ ++ flagrh = 1; ++ return 0; + } + + static stralloc host = {0}; + +-int rcpthosts(buf,len) +-char *buf; +-int len; ++int localhosts(char *buf, unsigned int len) + { +- int j; +- +- if (flagrh != 1) return 1; +- +- j = byte_rchr(buf,len,'@'); +- if (j >= len) return 1; /* presumably envnoathost is acceptable */ +- +- ++j; buf += j; len -= j; ++ unsigned int j; ++ uint32 dlen; + +- if (!stralloc_copyb(&host,buf,len)) return -1; +- buf = host.s; +- case_lowerb(buf,len); ++ if (flagrh < 0) return 0; + +- for (j = 0;j < len;++j) +- if (!j || (buf[j] == '.')) +- if (constmap(&maprh,buf + j,len - j)) return 1; +- +- if (fdmrh != -1) { +- uint32 dlen; +- int r; ++ j = byte_rchr(buf,len,'@'); ++ if (j >= len) return 0; /* envnoathost is not acceptable */ ++ ++j; buf += j; len -= j; ++ ++ if (!stralloc_copyb(&host,buf,len)) return -1; ++ buf = host.s; ++ case_lowerb(buf,len); ++ ++ /* if local.cdb available use this as source */ ++ if (fdlo != -1) ++ return cdb_seek(&cdblo, buf, len, &dlen); ++ else ++ if (constmap(&maplocals, buf, len)) return 1; ++ return 0; ++} + +- for (j = 0;j < len;++j) +- if (!j || (buf[j] == '.')) { +- r = cdb_seek(fdmrh,buf + j,len - j,&dlen); +- if (r) return r; +- } +- } ++int rcpthosts(char *buf, unsigned int len) ++{ ++ unsigned int j; ++ int r; ++ uint32 dlen; ++ ++ if (flagrh < 0) return 0; /* uh-oh init failed so fail too, ++ * never be a open relay! ++ */ ++ ++ j = byte_rchr(buf,len,'@'); ++ if (j >= len) return 1; /* presumably envnoathost is acceptable */ ++ ++ ++j; buf += j; len -= j; ++ ++ if (!stralloc_copyb(&host,buf,len)) return -1; ++ buf = host.s; ++ case_lowerb(buf,len); ++ ++ /* first locals */ ++ /* if local.cdb available use this as source */ ++ if (fdlo != -1) { ++ r = cdb_seek(&cdblo, buf, len, &dlen); ++ if (r) return r; ++ } else ++ if (constmap(&maplocals,buf,len)) return 1; ++ ++ /* then rcpthosts */ ++ for (j = 0;j < len;++j) ++ if (!j || (buf[j] == '.')) { ++ /* if rcpthosts.cdb available use this as source */ ++ if (fdrh != -1) { ++ r = cdb_seek(&cdbrh, buf + j, len - j, &dlen); ++ if (r) ++ return r; ++ } else ++ if (constmap(&maprh,buf + j,len - j)) ++ return 1; ++ } ++ /* finaly morercpthosts.cdb but only if not rcpthosts.cdb avail */ ++ if (fdmrh != -1 && fdrh == -1) { ++ for (j = 0;j < len;++j) ++ if (!j || (buf[j] == '.')) { ++ r = cdb_seek(&cdbmrh,buf + j,len - j,&dlen); ++ if (r) ++ return r; ++ } ++ } + +- return 0; ++ return 0; + } ++ +diff -upN qmail-1.03/rcpthosts.h qmail-ldap/rcpthosts.h +--- qmail-1.03/rcpthosts.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/rcpthosts.h Thu Jan 29 16:48:14 2004 +@@ -1,7 +1,8 @@ + #ifndef RCPTHOSTS_H + #define RCPTHOSTS_H + +-extern int rcpthosts_init(); +-extern int rcpthosts(); ++extern int rcpthosts_init(void); ++extern int rcpthosts(char *, unsigned int); ++extern int localhosts(char *, unsigned int); + + #endif +diff -upN qmail-1.03/read-ctrl.c qmail-ldap/read-ctrl.c +--- qmail-1.03/read-ctrl.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/read-ctrl.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++ ++#include "auto_qmail.h" ++#include "control.h" ++#include "error.h" ++#include "open.h" ++ ++#include "read-ctrl.h" ++ ++/* TODO logging */ ++int ++read_controls(ctrlfunc *f) ++{ ++ int i, fddir; ++ ++ fddir = open_read("."); ++ if (fddir == -1) ++ return -1; ++ if (chdir(auto_qmail) == -1) ++ return -1; ++ ++ if (control_init() == -1) ++ goto fail; ++ for (i = 0; f[i] != 0; i++) { ++ if (f[i]() == -1) ++ goto fail; ++ } ++ ++ if (fchdir(fddir) == -1) ++ return -1; ++ close(fddir); ++ return 0; ++ ++fail: ++ i = errno; ++ if (fchdir(fddir) == -1) ++ return -1; ++ close(fddir); ++ errno = i; ++ return -1; ++} ++ +diff -upN qmail-1.03/read-ctrl.h qmail-ldap/read-ctrl.h +--- qmail-1.03/read-ctrl.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/read-ctrl.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __READ_CTRL_H__ ++#define __READ_CTRL_H__ ++ ++typedef int (*ctrlfunc)(void); ++ ++int read_controls(ctrlfunc *); ++ ++#endif +diff -upN qmail-1.03/readsubdir.c qmail-ldap/readsubdir.c +--- qmail-1.03/readsubdir.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/readsubdir.c Thu Jan 29 16:48:14 2004 +@@ -6,7 +6,7 @@ + + void readsubdir_init(rs,name,pause) + readsubdir *rs; +-char *name; ++const char *name; + void (*pause)(); + { + rs->name = name; +@@ -31,7 +31,7 @@ unsigned long *id; + len = 0; + len += fmt_str(namepos + len,rs->name); + namepos[len++] = '/'; +- len += fmt_ulong(namepos + len,(unsigned long) rs->pos); ++ len += fmt_uint(namepos + len, rs->pos); + namepos[len] = 0; + while (!(rs->dir = opendir(namepos))) rs->pause(namepos); + rs->pos++; +diff -upN qmail-1.03/readsubdir.h qmail-ldap/readsubdir.h +--- qmail-1.03/readsubdir.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/readsubdir.h Thu Jan 29 16:48:14 2004 +@@ -6,14 +6,14 @@ + typedef struct readsubdir + { + DIR *dir; +- int pos; +- char *name; ++ unsigned int pos; ++ const char *name; + void (*pause)(); + } + readsubdir; + +-extern void readsubdir_init(); +-extern int readsubdir_next(); ++extern void readsubdir_init(readsubdir *, const char *, void (*)()); ++extern int readsubdir_next(readsubdir *, unsigned long *); + + #define READSUBDIR_NAMELEN 10 + +diff -upN qmail-1.03/readwrite.c qmail-ldap/readwrite.c +--- qmail-1.03/readwrite.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/readwrite.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include ++ ++#include "readwrite.h" ++ ++int ++subread(int fd, void *buf, int size) ++{ ++ return (int)read(fd, buf, size); ++} ++ ++int ++subwrite(int fd, void *buf, int size) ++{ ++ return (int)write(fd, buf, size); ++} ++ +diff -upN qmail-1.03/readwrite.h qmail-ldap/readwrite.h +--- qmail-1.03/readwrite.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/readwrite.h Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #ifndef READWRITE_H + #define READWRITE_H + +-extern int read(); +-extern int write(); ++int subread(int, void *, int); ++int subwrite(int, void *, int); + + #endif +diff -upN qmail-1.03/received.c qmail-ldap/received.c +--- qmail-1.03/received.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/received.c Tue Oct 28 18:21:32 2003 +@@ -15,6 +15,10 @@ static int issafe(ch) char ch; + if (ch == '=') return 1; + if (ch == ':') return 1; + if (ch == '-') return 1; ++ if (ch == '_') return 1; ++ if (ch == '#') return 1; ++ if (ch == ']') return 1; ++ if (ch == '[') return 1; + if ((ch >= 'a') && (ch <= 'z')) return 1; + if ((ch >= 'A') && (ch <= 'Z')) return 1; + if ((ch >= '0') && (ch <= '9')) return 1; +@@ -26,7 +30,7 @@ struct qmail *qqt; + char *s; + { + char ch; +- while (ch = *s++) { ++ while ((ch = *s++)) { + if (!issafe(ch)) ch = '?'; + qmail_put(qqt,&ch,1); + } +@@ -37,14 +41,17 @@ static char buf[DATE822FMT]; + /* "Received: from relay1.uu.net (HELO uunet.uu.net) (7@192.48.96.5)\n" */ + /* " by silverton.berkeley.edu with SMTP; 26 Sep 1995 04:46:54 -0000\n" */ + +-void received(qqt,protocol,local,remoteip,remotehost,remoteinfo,helo) ++void ++received(qqt,protocol,local,remoteip,remotehost,remoteinfo,helo,mailfrom,rcptto) + struct qmail *qqt; +-char *protocol; +-char *local; +-char *remoteip; +-char *remotehost; +-char *remoteinfo; +-char *helo; ++const char *protocol; ++const char *local; ++const char *remoteip; ++const char *remotehost; ++const char *remoteinfo; ++const char *helo; ++const char *mailfrom; ++const char *rcptto; + { + struct datetime dt; + +@@ -60,12 +67,29 @@ char *helo; + safeput(qqt,remoteinfo); + qmail_puts(qqt,"@"); + } ++ qmail_puts(qqt,"["); + safeput(qqt,remoteip); +- qmail_puts(qqt,")\n by "); ++ qmail_puts(qqt,"])"); ++ ++ if (mailfrom) { ++ qmail_puts(qqt,"\n (envelope-sender <"); ++ safeput(qqt,mailfrom); ++ qmail_puts(qqt,">)"); ++ } ++ qmail_puts(qqt,"\n by "); ++ + safeput(qqt,local); +- qmail_puts(qqt," with "); ++ qmail_puts(qqt," (qmail-ldap-1.03) with "); + qmail_puts(qqt,protocol); ++ ++ if (rcptto) { ++ qmail_puts(qqt,"\n for <"); ++ safeput(qqt,rcptto); ++ qmail_puts(qqt,">"); ++ } + qmail_puts(qqt,"; "); ++ + datetime_tai(&dt,now()); + qmail_put(qqt,buf,date822fmt(buf,&dt)); + } ++ +diff -upN qmail-1.03/received.h qmail-ldap/received.h +--- qmail-1.03/received.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/received.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,9 @@ + #ifndef RECEIVED_H + #define RECEIVED_H + +-extern void received(); ++#include "qmail.h" ++ ++extern void received(struct qmail *, const char *, const char *, const char *, ++ const char *, const char *, const char *, const char *, const char *); + + #endif +diff -upN qmail-1.03/remoteinfo.c qmail-ldap/remoteinfo.c +--- qmail-1.03/remoteinfo.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/remoteinfo.c Tue Oct 28 18:21:32 2003 +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include "byte.h" + #include "substdio.h" + #include "ip.h" +@@ -32,7 +33,6 @@ int timeout; + { + char *x; + int s; +- struct sockaddr_in sin; + substdio ss; + char buf[32]; + unsigned int len; +@@ -44,12 +44,7 @@ int timeout; + s = socket(AF_INET,SOCK_STREAM,0); + if (s == -1) return 0; + +- 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 (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 -upN qmail-1.03/remoteinfo.h qmail-ldap/remoteinfo.h +--- qmail-1.03/remoteinfo.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/remoteinfo.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,9 @@ + #ifndef REMOTEINFO_H + #define REMOTEINFO_H + +-extern char *remoteinfo_get(); ++struct ip_address; ++ ++extern char *remoteinfo_get(struct ip_address *, unsigned long, ++ struct ip_address *, unsigned long, int); + + #endif +diff -upN qmail-1.03/scan.h qmail-ldap/scan.h +--- qmail-1.03/scan.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/scan.h Tue Oct 28 18:21:32 2003 +@@ -1,16 +1,22 @@ + #ifndef SCAN_H + #define SCAN_H + ++/* XXX not available in qmail-1.03 + extern unsigned int scan_uint(); + extern unsigned int scan_xint(); + extern unsigned int scan_nbbint(); + extern unsigned int scan_ushort(); + extern unsigned int scan_xshort(); + extern unsigned int scan_nbbshort(); +-extern unsigned int scan_ulong(); ++*/ ++extern unsigned int scan_ulong(const char *, unsigned long *); ++/* XXX not available in qmail-1.03 + extern unsigned int scan_xlong(); + extern unsigned int scan_nbblong(); ++*/ ++extern unsigned int scan_8long(const char *, unsigned long *); + ++/* XXX not available in qmail-1.03 + extern unsigned int scan_plusminus(); + extern unsigned int scan_0x(); + +@@ -23,5 +29,6 @@ extern unsigned int scan_strncmp(); + extern unsigned int scan_memcmp(); + + extern unsigned int scan_long(); ++*/ + + #endif +diff -upN qmail-1.03/scan_8long.c qmail-ldap/scan_8long.c +--- qmail-1.03/scan_8long.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/scan_8long.c Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,6 @@ + #include "scan.h" + +-unsigned int scan_8long(s,u) register char *s; register unsigned long *u; ++unsigned int scan_8long(s,u) register const char *s; register unsigned long *u; + { + register unsigned int pos; register unsigned long result; + register unsigned long c; +diff -upN qmail-1.03/scan_ulong.c qmail-ldap/scan_ulong.c +--- qmail-1.03/scan_ulong.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/scan_ulong.c Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,6 @@ + #include "scan.h" + +-unsigned int scan_ulong(s,u) register char *s; register unsigned long *u; ++unsigned int scan_ulong(s,u) register const char *s; register unsigned long *u; + { + register unsigned int pos; register unsigned long result; + register unsigned long c; +diff -upN qmail-1.03/seek.h qmail-ldap/seek.h +--- qmail-1.03/seek.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/seek.h Tue Oct 28 18:21:32 2003 +@@ -3,12 +3,12 @@ + + typedef unsigned long seek_pos; + +-extern seek_pos seek_cur(); ++extern seek_pos seek_cur(int fd); + +-extern int seek_set(); +-extern int seek_end(); ++extern int seek_set(int fd, seek_pos); ++extern int seek_end(int fd); + +-extern int seek_trunc(); ++extern int seek_trunc(int fd, seek_pos); + + #define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) + +diff -upN qmail-1.03/seek_cur.c qmail-ldap/seek_cur.c +--- qmail-1.03/seek_cur.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/seek_cur.c Wed Oct 29 22:27:25 2003 +@@ -1,4 +1,5 @@ + #include ++#include + #include "seek.h" + + #define CUR 1 /* sigh */ +diff -upN qmail-1.03/seek_end.c qmail-ldap/seek_end.c +--- qmail-1.03/seek_end.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/seek_end.c Wed Oct 29 22:27:25 2003 +@@ -1,4 +1,5 @@ + #include ++#include + #include "seek.h" + + #define END 2 /* sigh */ +diff -upN qmail-1.03/seek_set.c qmail-ldap/seek_set.c +--- qmail-1.03/seek_set.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/seek_set.c Wed Oct 29 22:27:25 2003 +@@ -1,4 +1,5 @@ + #include ++#include + #include "seek.h" + + #define SET 0 /* sigh */ +diff -upN qmail-1.03/seek_trunc.c qmail-ldap/seek_trunc.c +--- qmail-1.03/seek_trunc.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/seek_trunc.c Wed Oct 29 22:27:25 2003 +@@ -1,4 +1,5 @@ + #include ++#include + #include "seek.h" + + int seek_trunc(fd,pos) int fd; seek_pos pos; +diff -upN qmail-1.03/select.h2 qmail-ldap/select.h2 +--- qmail-1.03/select.h2 Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/select.h2 Mon Aug 25 17:12:50 2003 +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include /* OpenBSD needs this for FD_ZERO */ + extern int select(); + + #endif +diff -upN qmail-1.03/sendmail.c qmail-ldap/sendmail.c +--- qmail-1.03/sendmail.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sendmail.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "sgetopt.h" + #include "substdio.h" + #include "subfd.h" +@@ -19,7 +20,7 @@ void die_usage() + _exit(100); + } + +-char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; ++const char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; + void smtpd() + { + if (!env_get("PROTO")) { +@@ -32,29 +33,61 @@ void smtpd() + if (!env_put("TCPREMOTEHOST=localhost")) nomem(); + if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem(); + } +- execv(*smtpdarg,smtpdarg); ++ execv(*smtpdarg,(char **)smtpdarg); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n"); + _exit(111); + } + +-char *qreadarg[] = { "bin/qmail-qread", 0 }; ++const char *qreadarg[] = { "bin/qmail-qread", 0 }; + void mailq() + { +- execv(*qreadarg,qreadarg); ++ execv(*qreadarg,(char **)qreadarg); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n"); + _exit(111); + } + ++void do_sender(s) ++const char *s; ++{ ++ char *x; ++ unsigned int n; ++ unsigned int a; ++ unsigned 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 = 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; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { + int opt; +- char **qiargv; +- char **arg; ++ const char **qiargv; ++ const char **arg; + int i; + + if (chdir(auto_qmail) == -1) { +@@ -109,7 +142,7 @@ char **argv; + _exit(100); + } + +- qiargv = (char **) alloc((argc + 10) * sizeof(char *)); ++ qiargv = (const char **) alloc((argc + 10) * sizeof(char *)); + if (!qiargv) nomem(); + + arg = qiargv; +@@ -118,12 +151,13 @@ char **argv; + if (sender) { + *arg++ = "-f"; + *arg++ = sender; ++ do_sender(sender); + } + *arg++ = "--"; + for (i = 0;i < argc;++i) *arg++ = argv[i]; + *arg = 0; + +- execv(*qiargv,qiargv); ++ execv(*qiargv,(char **)qiargv); + substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n"); +- _exit(111); ++ return 111; + } +diff -upN qmail-1.03/sgetopt.c qmail-ldap/sgetopt.c +--- qmail-1.03/sgetopt.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sgetopt.c Tue Oct 28 18:21:32 2003 +@@ -23,15 +23,15 @@ Documentation in sgetopt.3. + #define optprogname sgetoptprogname + + int opterr = 1; +-char *optprogname = 0; ++const char *optprogname = 0; + + int getopt(argc,argv,opts) + int argc; + char **argv; +-char *opts; ++const char *opts; + { + int c; +- char *s; ++ const char *s; + + if (!optprogname) { + optprogname = *argv; +diff -upN qmail-1.03/sgetopt.h qmail-ldap/sgetopt.h +--- qmail-1.03/sgetopt.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sgetopt.h Tue Oct 28 18:21:32 2003 +@@ -14,8 +14,8 @@ + + #include "subgetopt.h" + +-extern int sgetoptmine(); ++extern int sgetoptmine(int, char **, const char *); + extern int sgetopterr; +-extern char *sgetoptprogname; ++extern const char *sgetoptprogname; + + #endif +diff -upN qmail-1.03/sig.h qmail-ldap/sig.h +--- qmail-1.03/sig.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig.h Tue Oct 28 18:21:32 2003 +@@ -1,43 +1,45 @@ + #ifndef SIG_H + #define SIG_H + +-extern void sig_catch(); +-extern void sig_block(); +-extern void sig_unblock(); +-extern void sig_blocknone(); +-extern void sig_pause(); ++extern void sig_catch(int, void (*)()); ++extern void sig_block(int); ++extern void sig_unblock(int); ++extern void sig_blocknone(void); ++extern void sig_pause(void); + + extern void sig_dfl(); + +-extern void sig_miscignore(); +-extern void sig_bugcatch(); ++extern void sig_miscignore(void); ++extern void sig_bugcatch(void (*)()); + +-extern void sig_pipeignore(); +-extern void sig_pipedefault(); ++extern void sig_pipeignore(void); ++extern void sig_pipedefault(void); + ++/* XXX not available in qmail-1.03 + extern void sig_contblock(); + extern void sig_contunblock(); + extern void sig_contcatch(); + extern void sig_contdefault(); ++*/ + +-extern void sig_termblock(); +-extern void sig_termunblock(); +-extern void sig_termcatch(); +-extern void sig_termdefault(); +- +-extern void sig_alarmblock(); +-extern void sig_alarmunblock(); +-extern void sig_alarmcatch(); +-extern void sig_alarmdefault(); +- +-extern void sig_childblock(); +-extern void sig_childunblock(); +-extern void sig_childcatch(); +-extern void sig_childdefault(); +- +-extern void sig_hangupblock(); +-extern void sig_hangupunblock(); +-extern void sig_hangupcatch(); +-extern void sig_hangupdefault(); ++extern void sig_termblock(void); ++extern void sig_termunblock(void); ++extern void sig_termcatch(void (*)()); ++extern void sig_termdefault(void); ++ ++extern void sig_alarmblock(void); ++extern void sig_alarmunblock(void); ++extern void sig_alarmcatch(void (*)()); ++extern void sig_alarmdefault(void); ++ ++extern void sig_childblock(void); ++extern void sig_childunblock(void); ++extern void sig_childcatch(void (*)()); ++extern void sig_childdefault(void); ++ ++extern void sig_hangupblock(void); ++extern void sig_hangupunblock(void); ++extern void sig_hangupcatch(void (*)()); ++extern void sig_hangupdefault(void); + + #endif +diff -upN qmail-1.03/sig_alarm.c qmail-ldap/sig_alarm.c +--- qmail-1.03/sig_alarm.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_alarm.c Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #include + #include "sig.h" + +-void sig_alarmblock() { sig_block(SIGALRM); } +-void sig_alarmunblock() { sig_unblock(SIGALRM); } ++void sig_alarmblock(void) { sig_block(SIGALRM); } ++void sig_alarmunblock(void) { sig_unblock(SIGALRM); } + void sig_alarmcatch(f) void (*f)(); { sig_catch(SIGALRM,f); } +-void sig_alarmdefault() { sig_catch(SIGALRM,SIG_DFL); } ++void sig_alarmdefault(void) { sig_catch(SIGALRM,SIG_DFL); } +diff -upN qmail-1.03/sig_block.c qmail-ldap/sig_block.c +--- qmail-1.03/sig_block.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_block.c Tue Oct 28 18:21:32 2003 +@@ -28,7 +28,7 @@ int sig; + #endif + } + +-void sig_blocknone() ++void sig_blocknone(void) + { + #ifdef HASSIGPROCMASK + sigset_t ss; +diff -upN qmail-1.03/sig_child.c qmail-ldap/sig_child.c +--- qmail-1.03/sig_child.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_child.c Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #include + #include "sig.h" + +-void sig_childblock() { sig_block(SIGCHLD); } +-void sig_childunblock() { sig_unblock(SIGCHLD); } ++void sig_childblock(void) { sig_block(SIGCHLD); } ++void sig_childunblock(void) { sig_unblock(SIGCHLD); } + void sig_childcatch(f) void (*f)(); { sig_catch(SIGCHLD,f); } +-void sig_childdefault() { sig_catch(SIGCHLD,SIG_DFL); } ++void sig_childdefault(void) { sig_catch(SIGCHLD,SIG_DFL); } +diff -upN qmail-1.03/sig_hup.c qmail-ldap/sig_hup.c +--- qmail-1.03/sig_hup.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_hup.c Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #include + #include "sig.h" + +-void sig_hangupblock() { sig_block(SIGHUP); } +-void sig_hangupunblock() { sig_unblock(SIGHUP); } ++void sig_hangupblock(void) { sig_block(SIGHUP); } ++void sig_hangupunblock(void) { sig_unblock(SIGHUP); } + void sig_hangupcatch(f) void (*f)(); { sig_catch(SIGHUP,f); } +-void sig_hangupdefault() { sig_catch(SIGHUP,SIG_DFL); } ++void sig_hangupdefault(void) { sig_catch(SIGHUP,SIG_DFL); } +diff -upN qmail-1.03/sig_misc.c qmail-ldap/sig_misc.c +--- qmail-1.03/sig_misc.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_misc.c Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #include + #include "sig.h" + +-void sig_miscignore() ++void sig_miscignore(void) + { + sig_catch(SIGVTALRM,SIG_IGN); + sig_catch(SIGPROF,SIG_IGN); +diff -upN qmail-1.03/sig_pause.c qmail-ldap/sig_pause.c +--- qmail-1.03/sig_pause.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_pause.c Tue Oct 28 18:21:32 2003 +@@ -2,7 +2,7 @@ + #include "sig.h" + #include "hassgprm.h" + +-void sig_pause() ++void sig_pause(void) + { + #ifdef HASSIGPROCMASK + sigset_t ss; +diff -upN qmail-1.03/sig_pipe.c qmail-ldap/sig_pipe.c +--- qmail-1.03/sig_pipe.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_pipe.c Tue Oct 28 18:21:32 2003 +@@ -1,5 +1,5 @@ + #include + #include "sig.h" + +-void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } +-void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } ++void sig_pipeignore(void) { sig_catch(SIGPIPE,SIG_IGN); } ++void sig_pipedefault(void) { sig_catch(SIGPIPE,SIG_DFL); } +diff -upN qmail-1.03/sig_term.c qmail-ldap/sig_term.c +--- qmail-1.03/sig_term.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/sig_term.c Tue Oct 28 18:21:32 2003 +@@ -1,7 +1,7 @@ + #include + #include "sig.h" + +-void sig_termblock() { sig_block(SIGTERM); } +-void sig_termunblock() { sig_unblock(SIGTERM); } ++void sig_termblock(void) { sig_block(SIGTERM); } ++void sig_termunblock(void) { sig_unblock(SIGTERM); } + void sig_termcatch(f) void (*f)(); { sig_catch(SIGTERM,f); } +-void sig_termdefault() { sig_catch(SIGTERM,SIG_DFL); } ++void sig_termdefault(void) { sig_catch(SIGTERM,SIG_DFL); } +diff -upN qmail-1.03/signatures qmail-ldap/signatures +--- qmail-1.03/signatures Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/signatures Mon Dec 6 13:55:26 2004 +@@ -0,0 +1,66 @@ ++# Windows executables seen in active virii ++TVqQAAMAA ++TVpQAAIAA ++TVoAAAEAA ++TVoAACQAA ++TVqQAAMAA ++TVoAAD8AA ++# Additional windows executable signatures not yet seen in virii ++TVpAALQAc ++TVpyAXkAX ++TVrmAU4AA ++TVrhARwAk ++TVoFAQUAA ++TVoAAAQAA ++TVoIARMAA ++TVouARsAA ++TVrQAT8AA ++# .GIF file found in the current fake Microsoft patch virus making the rounds. ++R0lGODlhaAA7APcAAP///+rp6puSp6GZrDUjUUc6Zn53mFJMdbGvvVtXh2xre8bF1x8cU4yLprOy ++ ++# .ZIPfile signature seen in SoBig.E: ++# This signature is to generic and blocks valid zip files so disable it. ++#UEsDBBQAA ++ ++# .ZIPfile signature of MyDoom: ++# nota bene * is a anymatch. ++UEsDBAoAAAAAA*****DKJx+eAFgAAABYAA**AAAA ++# .ZIPfile signatures of Beagle and friends: ++UEsDBAoAAQAAA*****Cf4kJRDDAAAAAwAAA*AAAA ++UEsDBAoAAQAAAi****Bcl5T9DzAAAAMwAAA*AAAA ++UEsDBAoAAAAAA*****CxG9oCAH4AAAB+AA**AAAA ++UEsDBAoAAAAAA*****BiZMYWCWMAAAljAAA*AAAA ++UEsDBAoAAAAAA******jiB3egHMAAIBzAAB*AAAA ++UEsDBAoAAQAAA******D+JTDGqkIAA6pCAA*AAAA ++UEsDBAoAAAAAA*****B+cADhaG0AAGhtAAB*AAAA ++UEsDBAoAAAAAA*****BdbrAiAFYAAABWAAA*AAAA ++UEsDBAoAAAAAA******FWheeAPQBAAD0AQ**AAAA ++UEsDBAoAAAAAA*****GpXle1AOABAADgAQA*AAAA ++UEsDBAoAAAAAA*****AnDhYmfXMAAH1zAABwAAAA ++UEsDBAoAAQAIA*****AZRqEfZFEAACROAAAMAAAA ++UEsDBAoAAQAIA*****DJkv0Bq1QAAAxRAAANAAAA ++UEsDBAoAAQAAA*****AZ45yiDFMAAABTAAAKAAAA ++UEsDBAoAAQAAA*****AOGOjBMVMAACVTAAANAAAA ++UEsDBAoAAAAAAAFYrj******/cEAAP3BAAAfAAAA ++UEsDBAoAAAAAA*****C93UuYwHAAAMBwAADXAAAA ++UEsDBAoAAQAAA*****DUdqQ1v1QAALNUAAAKAAAA ++UEsDBAoAAQAAA*****EsQ5lqlnsEAIp7BAAMAAAA ++UEsDBAoAAQAAA*****Epm2uEYuoAAFbqAAAJAAAA ++UEsDBAoAAQAAA*****HelFoJ1eUBAMnlAQAKAAAA ++UEsDBAoAAAAAA*****AjTTDoAIAAAACAAACjAAAA ++UEsDBAoAAAAAA*****BCNPQYAPwBAAD8AQAHAAAA ++UEsDBAoAAAAAA*****FZUaXpAHwAAAB8AABUAAAA ++UEsDBAoAAAAAA*****FxKYToA34AAAN+AABXAAAA ++UEsDBAoAAAAAA*****EAAAAAAAAAAAAAAAAFAAAA ++UEsDBBQAAAAIA*****FhTJoyVgAAAG8AAAAIAAAA ++UEsDBAoAAAAAA*****CHcNZsANAAAADQAAC*AAAA ++UEsDBAoAAAAAA*****H7vMVGA38AAAN/AABUAAAA ++UEsDBAoAAAAAA*****FbiToH6N0AAOjdAABPAAAA ++UEsDBAoAAAAAA***VzFZUaXpAHwAAAB8AAB*AAAA ++UEsDBAoAAAAAA****TFUnOUjAHoAAAB6AAA*AAAA ++ ++# strange .hta virus I got ++PEhUTUw+DQo8SEVBRD4NCjxUSVRMRT5XaW5kb3dz ++# ... and a .vbs virus ++ZGltIGZpbGVzeXMsIGZpbGV0eHQsIGdldG5hbWUs ++ +diff -upN qmail-1.03/slurpclose.c qmail-ldap/slurpclose.c +--- qmail-1.03/slurpclose.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/slurpclose.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "stralloc.h" + #include "readwrite.h" + #include "slurpclose.h" +@@ -6,7 +7,7 @@ + int slurpclose(fd,sa,bufsize) + int fd; + stralloc *sa; +-int bufsize; ++unsigned int bufsize; + { + int r; + for (;;) { +diff -upN qmail-1.03/slurpclose.h qmail-ldap/slurpclose.h +--- qmail-1.03/slurpclose.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/slurpclose.h Thu Jan 29 16:48:14 2004 +@@ -1,6 +1,8 @@ + #ifndef SLURPCLOSE_H + #define SLURPCLOSE_H + +-extern int slurpclose(); ++#include "stralloc.h" ++ ++extern int slurpclose(int, stralloc *, unsigned int); + + #endif +diff -upN qmail-1.03/smtpcall.c qmail-ldap/smtpcall.c +--- qmail-1.03/smtpcall.c Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/smtpcall.c Wed May 5 17:42:12 2004 +@@ -0,0 +1,274 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#include ++#include "auto_qmail.h" ++#include "coe.h" ++#include "fd.h" ++#include "substdio.h" ++#include "str.h" ++#include "stralloc.h" ++#include "timeoutread.h" ++#include "timeoutwrite.h" ++#include "wait.h" ++ ++#include "smtpcall.h" ++ ++int call_getln(substdio *ss, stralloc *l) ++{ ++ int i; ++ if (!stralloc_copys(l, "")) return -1; ++ for (;;) { ++ if (!stralloc_readyplus(l,1)) return -1; ++ i = substdio_get(ss, l->s + l->len, 1); ++ if (i != 1) return i; ++ if (l->s[l->len] == '\n') break; ++ ++l->len; ++ } ++ if (l->len > 0) if (l->s[l->len-1] == '\r') --l->len; ++ l->s[l->len] = 0; ++ return l->len; ++} ++ ++int ++call_getc(struct call *cc, char *c) ++{ ++ int r; ++ if (cc->flagerr || cc->flagabort) return -1; ++ r = substdio_get(&cc->ssfrom, c, 1); ++ if (r == -1) { ++ cc->flagerr = 1; ++ return -1; ++ } ++ return r; ++} ++ ++int ++call_put(struct call *cc, const char *s, unsigned int len) ++{ ++ if (cc->flagerr || cc->flagabort) return -1; ++ if (cc->flagstar && str_diffn(s, "*", len) == 0) { ++ cc->flagabort = 1; ++ return -1; ++ } ++ if (substdio_put(&cc->ssto, s, len) == -1) { ++ cc->flagerr = 1; ++ return -1; ++ } ++ return 0; ++} ++ ++int ++call_puts(struct call *cc, const char *s) ++{ ++ if (cc->flagerr || cc->flagabort) return -1; ++ if (cc->flagstar && str_diff(s, "*") == 0) { ++ cc->flagabort = 1; ++ return -1; ++ } ++ if (substdio_puts(&cc->ssto, s) == -1) { ++ cc->flagerr = 1; ++ return -1; ++ } ++ return 0; ++} ++ ++int ++call_flush(struct call *cc) ++{ ++ if (cc->flagerr || cc->flagabort) return -1; ++ if (substdio_flush(&cc->ssto) == -1) { ++ cc->flagerr = 1; ++ return -1; ++ } ++ return 0; ++ ++} ++ ++int ++call_putflush(struct call *cc, const char *s, unsigned int len) ++{ ++ if (call_put(cc, s, len) == -1) return -1; ++ if (call_flush(cc) == -1) return -1; ++ return 0; ++} ++ ++int ++call_putsflush(struct call *cc, const char *s) ++{ ++ if (call_puts(cc, s) == -1) return -1; ++ if (call_flush(cc) == -1) return -1; ++ return 0; ++} ++ ++static int mytimeout = 10; ++ ++static int ++mywrite(int fd, void *buf, int len) ++{ ++ return timeoutwrite(mytimeout,fd,buf,len); ++} ++ ++static int ++myread(int fd, void *buf, int len) ++{ ++ return timeoutread(mytimeout,fd,buf,len); ++} ++ ++int ++call_open(struct call *cc, const char *prog, int timeout, int flagstar) ++{ ++ int pit[2]; ++ int pif[2]; ++ const char *(args[2]); ++ ++ args[0] = prog; ++ args[1] = 0; ++ ++ if (pipe(pit) == -1) return -1; ++ if (pipe(pif) == -1) { close(pit[0]); close(pit[1]); return -1; } ++ ++ switch(cc->pid = vfork()) { ++ case -1: ++ close(pit[0]); close(pit[1]); ++ close(pif[0]); close(pif[1]); ++ return -1; ++ case 0: ++ close(pit[1]); ++ close(pif[0]); ++ if (fd_move(0,pit[0]) == -1) _exit(120); ++ if (fd_move(1,pif[1]) == -1) _exit(120); ++ if (chdir(auto_qmail) == -1) _exit(61); ++ execv(*args,(char **)args); ++ _exit(120); ++ } ++ ++ if (timeout != 0) mytimeout = timeout; ++ cc->flagerr = 0; ++ cc->flagabort = 0; ++ cc->flagstar = flagstar; ++ cc->tofd = pit[1]; close(pit[0]); ++ cc->fromfd = pif[0]; close(pif[1]); ++ coe(cc->tofd); coe(cc->fromfd); ++ substdio_fdbuf(&cc->ssto, mywrite, cc->tofd, ++ cc->tobuf, sizeof(cc->tobuf)); ++ substdio_fdbuf(&cc->ssfrom, myread, cc->fromfd, ++ cc->frombuf, sizeof(cc->frombuf)); ++ return 0; ++} ++ ++void ++call_close(struct call *cc) ++{ ++ int wstat; ++ int r; ++ char ch; ++ ++ if (cc->pid == -1) return; /* nothing running */ ++ call_flush(cc); ++ close(cc->tofd); ++ while ((r = call_getc(cc, &ch)) == 1) ; ++ if (r == -1) ; /* bad thing happend but who cares */ ++ close(cc->fromfd); ++ ++ wait_pid(&wstat,cc->pid); /* just kill the zombie */ ++} ++ ++const char * ++auth_close(struct call *cc, stralloc *user, const char *pre) ++{ ++ const char *s; ++ int wstat; ++ int exitcode; ++ char c; ++ ++ s = 0; c = 0; ++ if (cc->pid == -1) ++ return "454 unable to start authentication process. " ++ "(#4.3.0)\r\n"; ++ ++ if (cc->flagabort) ++ s = "501 authentication exchange aborted. (#4.3.0)\r\n"; ++ if (cc->flagerr) ++ s = "454 authentication process write failure. (#4.3.0)\r\n"; ++ ++ if (!cc->flagerr && !cc->flagabort) { ++ if (call_getc(cc, &c) == -1) { ++ s = "454 authentication process read failure. " ++ "(#4.3.0)\r\n"; ++ } else ++ switch (c) { ++ case 'K': ++ if (!stralloc_copys(user, pre!=0?pre:"")) { ++ s = "421 out of memory (#4.3.0)\r\n"; ++ break; ++ } ++ while (call_getc(cc, &c) == 1) { ++ if (!stralloc_append(user, &c)) { ++ s = "421 out of memory (#4.3.0)\r\n"; ++ break; ++ } ++ } ++ if (cc->flagerr) ++ s = "454 authentication process read " ++ "failure. (#4.3.0)\r\n"; ++ else ++ s = "235 nice to meet you\r\n"; ++ break; ++ case 'D': ++ s = "535 authentication failure\r\n"; ++ break; ++ case 'Z': ++ s = "501 authentication exchange failed\r\n"; ++ break; ++ default: ++ s = "454 authentication process failure. (#4.3.0)\r\n"; ++ break; ++ } ++ } ++ close(cc->tofd); ++ close(cc->fromfd); ++ ++ if (wait_pid(&wstat,cc->pid) != cc->pid) ++ return "454 authentication waitpid surprise (#4.3.0)\r\n"; ++ if (wait_crashed(wstat)) ++ return "454 authentication process crashed (#4.3.0)\r\n"; ++ exitcode = wait_exitcode(wstat); ++ switch (exitcode) { ++ case 0: ++ return s; ++ default: ++ return "454 temporary authentication failure (#4.3.0)\r\n"; ++ } ++} ++ +diff -upN qmail-1.03/smtpcall.h qmail-ldap/smtpcall.h +--- qmail-1.03/smtpcall.h Thu Jan 1 01:00:00 1970 ++++ qmail-ldap/smtpcall.h Wed May 5 17:42:12 2004 +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (c) 2003-2004 Claudio Jeker, ++ * Internet Business Solutions AG, CH-8005 Zürich, Switzerland ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Internet Business ++ * Solutions AG and its contributors. ++ * 4. Neither the name of the author nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++#ifndef __SMTPCALL_H__ ++#define __SMTPCALL_H__ ++ ++#include "stralloc.h" ++#include "substdio.h" ++ ++struct call { ++ int flagerr; ++ int flagabort; ++ int flagstar; ++ unsigned long pid; ++ int tofd; ++ int fromfd; ++ substdio ssto; ++ substdio ssfrom; ++ char tobuf[256]; ++ char frombuf[128]; ++} ; ++ ++int call_getln(substdio *, stralloc *); ++int call_getc(struct call *, char *); ++int call_put(struct call *, const char *, unsigned int); ++int call_puts(struct call *, const char *); ++int call_flush(struct call *); ++int call_putflush(struct call *, const char *, unsigned int); ++int call_putsflush(struct call *, const char *); ++int call_open(struct call *, const char *, int, int); ++void call_close(struct call *); ++ ++const char *auth_close(struct call *, stralloc *, const char *); ++ ++#endif +diff -upN qmail-1.03/spawn.c qmail-ldap/spawn.c +--- qmail-1.03/spawn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/spawn.c Thu Jul 1 16:28:31 2004 +@@ -1,5 +1,8 @@ + #include + #include ++#include ++#include "readwrite.h" ++#include "alloc.h" + #include "sig.h" + #include "wait.h" + #include "substdio.h" +@@ -15,11 +18,13 @@ + #include "auto_uids.h" + #include "auto_spawn.h" + +-extern int truncreport; ++extern unsigned int truncreport; + extern int spawn(); + extern void report(); + extern void initialize(); + ++int flagreinit = 0; ++ + struct delivery + { + int used; +@@ -28,6 +33,9 @@ struct delivery + int wstat; /* if !pid: status of child */ + int fdout; /* pipe output, -1 if !pid; delays eof until after death */ + stralloc output; ++#ifdef DEBUG ++ stralloc log; ++#endif + } + ; + +@@ -37,7 +45,7 @@ void sigchld() + { + int wstat; + int pid; +- int i; ++ unsigned int i; + while ((pid = wait_nohang(&wstat)) > 0) + for (i = 0;i < auto_spawn;++i) if (d[i].used) + if (d[i].pid == pid) +@@ -63,30 +71,44 @@ int okwrite(fd,buf,n) int fd; char *buf; + int flagreading = 1; + char outbuf[1024]; substdio ssout; + +-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */ ++int stage = 0; /* reading 0:delnum 1:delnum2 2:messid 3:sender 4:recip */ + int flagabort = 0; /* if 1, everything except delnum is garbage */ +-int delnum; ++unsigned int delnum; + stralloc messid = {0}; + stralloc sender = {0}; + stralloc recip = {0}; + + void err(s) char *s; + { +- char ch; ch = delnum; substdio_put(&ssout,&ch,1); ++ unsigned char ch; ++ ch = delnum; substdio_put(&ssout,&ch,1); ++ ch = delnum >> 8; substdio_put(&ssout,&ch,1); + substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1); + } + + void docmd() + { + int f; +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + int fdmess; + int pi[2]; + struct stat st; + ++ /* SIGHUP HANDLING */ ++ if (delnum == 0xbeef) ++ if (*messid.s == '\0' && *sender.s == '\0' && *recip.s == '\0') { ++#if 0 ++ err("HHUP received\n"); ++#endif ++ flagreinit = 1; ++ return; ++ } ++ + if (flagabort) { err("Zqmail-spawn out of memory. (#4.3.0)\n"); return; } ++#if 0 /* no longer possible, delnum is unsigned */ + if (delnum < 0) { err("ZInternal error: delnum negative. (#4.3.5)\n"); return; } ++#endif + if (delnum >= auto_spawn) { err("ZInternal error: delnum too big. (#4.3.5)\n"); return; } + if (d[delnum].used) { err("ZInternal error: delnum in use. (#4.3.5)\n"); return; } + for (i = 0;i < messid.len;++i) +@@ -136,7 +158,7 @@ void getcmd() + { + int i; + int r; +- char ch; ++ unsigned char ch; + + r = read(0,cmdbuf,sizeof(cmdbuf)); + if (r == 0) +@@ -154,17 +176,20 @@ void getcmd() + switch(stage) + { + case 0: +- delnum = (unsigned int) (unsigned char) ch; +- messid.len = 0; stage = 1; break; ++ delnum = ch; ++ stage = 1; break; + case 1: ++ delnum += (unsigned int)ch << 8; ++ messid.len = 0; stage = 2; break; ++ case 2: + if (!stralloc_append(&messid,&ch)) flagabort = 1; + if (ch) break; +- sender.len = 0; stage = 2; break; +- case 2: ++ sender.len = 0; stage = 3; break; ++ case 3: + if (!stralloc_append(&sender,&ch)) flagabort = 1; + if (ch) break; +- recip.len = 0; stage = 3; break; +- case 3: ++ recip.len = 0; stage = 4; break; ++ case 4: + if (!stralloc_append(&recip,&ch)) flagabort = 1; + if (ch) break; + docmd(); +@@ -175,12 +200,12 @@ void getcmd() + + char inbuf[128]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +- char ch; +- int i; ++ unsigned char ch; ++ unsigned int i; + int r; + fd_set rfds; + int nfds; +@@ -201,12 +226,23 @@ char **argv; + + initialize(argc,argv); + +- ch = auto_spawn; substdio_putflush(&ssout,&ch,1); ++ ch = auto_spawn; substdio_put(&ssout,&ch,1); ++ ch = auto_spawn >> 8; substdio_putflush(&ssout,&ch,1); + +- for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; } ++ for (i = 0;i < auto_spawn;++i) { ++ d[i].used = 0; ++ d[i].output.s = 0; ++#ifdef DEBUG ++ d[i].log.s = 0; ++#endif ++ } + + for (;;) + { ++ if (flagreinit) { ++ initialize(argc,argv); ++ flagreinit = 0; ++ } + if (!flagreading) + { + for (i = 0;i < auto_spawn;++i) if (d[i].used) break; +@@ -236,24 +272,92 @@ char **argv; + continue; /* read error on a readable pipe? be serious */ + if (r == 0) + { +- ch = i; substdio_put(&ssout,&ch,1); ++ unsigned char c; c = i; substdio_put(&ssout,&c,1); ++ c = i >> 8; substdio_put(&ssout,&c,1); + report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len); + substdio_put(&ssout,"",1); + substdio_flush(&ssout); + close(d[i].fdin); d[i].used = 0; + continue; + } ++#ifdef DEBUG ++# define IS_LOG(x) ( d[(x)].used & 0x8 ) ++# define LOGON(x) ( d[(x)].used |= 0x8 ) ++# define LOGOFF(x) ( d[(x)].used = 1 ) ++ { ++ unsigned int j; ++ unsigned int b; ++ int t; ++ for (j=0, b=0; j 100) ++ if (d[i].log.len > truncreport) ++ { ++ const char *truncmess = "\nError report too long, sorry.\n"; ++ d[i].log.len = truncreport - str_len(truncmess) - 3; ++ stralloc_cats(&d[i].log,truncmess); ++ } ++ ch = i; substdio_put(&ssout,&ch,1); ++ ch = i >> 8; substdio_put(&ssout,&ch,1); ++ ch = 'L'; substdio_put(&ssout,&ch,1); ++ for (t = 0;t < d[i].log.len; ++t) if (!d[i].log.s[t]) break; ++ substdio_put(&ssout,d[i].log.s,t); ++ substdio_put(&ssout,"",1); ++ substdio_flush(&ssout); ++ d[i].log.len = 0; ++ } ++ } ++ if (b == r) continue; ++ if ( IS_LOG(i) ) ++ { ++ while (!stralloc_readyplus(&d[i].log,r-b)) sleep(10); /*XXX*/ ++ byte_copy(d[i].log.s + d[i].log.len,r-b,inbuf+b); ++ d[i].log.len += r-b; ++ } ++ else ++ { ++ while (!stralloc_readyplus(&d[i].output,r-b)) sleep(10); /*XXX*/ ++ byte_copy(d[i].output.s + d[i].output.len,r-b,inbuf+b); ++ d[i].output.len += r-b; ++ if (truncreport > 100) ++ if (d[i].output.len > truncreport) ++ { ++ const char *truncmess = "\nError report too long, sorry.\n"; ++ d[i].output.len = truncreport - str_len(truncmess) - 3; ++ stralloc_cats(&d[i].output,truncmess); ++ } ++ } ++ } ++#else + while (!stralloc_readyplus(&d[i].output,r)) sleep(10); /*XXX*/ + byte_copy(d[i].output.s + d[i].output.len,r,inbuf); + d[i].output.len += r; + if (truncreport > 100) + if (d[i].output.len > truncreport) + { +- char *truncmess = "\nError report too long, sorry.\n"; ++ const char *truncmess = "\nError report too long, sorry.\n"; + d[i].output.len = truncreport - str_len(truncmess) - 3; + stralloc_cats(&d[i].output,truncmess); + } ++#endif + } + } + } ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/splogger.c qmail-ldap/splogger.c +--- qmail-1.03/splogger.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/splogger.c Thu Jan 29 16:48:14 2004 +@@ -10,7 +10,7 @@ + #include "fmt.h" + + char buf[800]; /* syslog truncates long lines (or crashes); GPACIC */ +-int bufpos = 0; /* 0 <= bufpos < sizeof(buf) */ ++unsigned int bufpos = 0; /* 0 <= bufpos < sizeof(buf) */ + int flagcont = 0; + int priority; /* defined if flagcont */ + char stamp[FMT_ULONG + FMT_ULONG + 3]; /* defined if flagcont */ +@@ -45,7 +45,7 @@ void flush() + bufpos = 0; + } + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char **argv; + { +@@ -69,4 +69,6 @@ char **argv; + if ((ch < 32) || (ch > 126)) ch = '?'; /* logger truncates at 0; GPACIC */ + buf[bufpos++] = ch; + } ++ /* NOTREACHED */ ++ return 0; + } +diff -upN qmail-1.03/str.h qmail-ldap/str.h +--- qmail-1.03/str.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str.h Tue Oct 28 18:21:32 2003 +@@ -1,13 +1,13 @@ + #ifndef STR_H + #define STR_H + +-extern unsigned int str_copy(); +-extern int str_diff(); +-extern int str_diffn(); +-extern unsigned int str_len(); +-extern unsigned int str_chr(); +-extern unsigned int str_rchr(); +-extern int str_start(); ++extern unsigned int str_copy(char *, const char *); ++extern int str_diff(const char *, const char *); ++extern int str_diffn(const char *, const char *, unsigned int); ++extern unsigned int str_len(const char *); ++extern unsigned int str_chr(const char *, int); ++extern unsigned int str_rchr(const char *, int); ++extern int str_start(const char *, const char *); + + #define str_equal(s,t) (!str_diff((s),(t))) + +diff -upN qmail-1.03/str_chr.c qmail-ldap/str_chr.c +--- qmail-1.03/str_chr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_chr.c Tue Oct 28 18:21:32 2003 +@@ -1,11 +1,11 @@ + #include "str.h" + + unsigned int str_chr(s,c) +-register char *s; ++register const char *s; + int c; + { + register char ch; +- register char *t; ++ register const char *t; + + ch = c; + t = s; +diff -upN qmail-1.03/str_cpy.c qmail-ldap/str_cpy.c +--- qmail-1.03/str_cpy.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_cpy.c Thu Jan 29 16:48:14 2004 +@@ -2,9 +2,9 @@ + + unsigned int str_copy(s,t) + register char *s; +-register char *t; ++register const char *t; + { +- register int len; ++ register unsigned int len; + + len = 0; + for (;;) { +diff -upN qmail-1.03/str_diff.c qmail-ldap/str_diff.c +--- qmail-1.03/str_diff.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_diff.c Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,8 @@ + #include "str.h" + + int str_diff(s,t) +-register char *s; +-register char *t; ++register const char *s; ++register const char *t; + { + register char x; + +diff -upN qmail-1.03/str_diffn.c qmail-ldap/str_diffn.c +--- qmail-1.03/str_diffn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_diffn.c Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,8 @@ + #include "str.h" + + int str_diffn(s,t,len) +-register char *s; +-register char *t; ++register const char *s; ++register const char *t; + unsigned int len; + { + register char x; +diff -upN qmail-1.03/str_len.c qmail-ldap/str_len.c +--- qmail-1.03/str_len.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_len.c Tue Oct 28 18:21:32 2003 +@@ -1,9 +1,9 @@ + #include "str.h" + + unsigned int str_len(s) +-register char *s; ++register const char *s; + { +- register char *t; ++ register const char *t; + + t = s; + for (;;) { +diff -upN qmail-1.03/str_rchr.c qmail-ldap/str_rchr.c +--- qmail-1.03/str_rchr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_rchr.c Tue Oct 28 18:21:32 2003 +@@ -1,12 +1,12 @@ + #include "str.h" + + unsigned int str_rchr(s,c) +-register char *s; ++register const char *s; + int c; + { + register char ch; +- register char *t; +- register char *u; ++ register const char *t; ++ register const char *u; + + ch = c; + t = s; +diff -upN qmail-1.03/str_start.c qmail-ldap/str_start.c +--- qmail-1.03/str_start.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/str_start.c Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,8 @@ + #include "str.h" + + int str_start(s,t) +-register char *s; +-register char *t; ++register const char *s; ++register const char *t; + { + register char x; + +diff -upN qmail-1.03/stralloc.h qmail-ldap/stralloc.h +--- qmail-1.03/stralloc.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc.h Tue Oct 28 18:21:32 2003 +@@ -5,16 +5,16 @@ + + GEN_ALLOC_typedef(stralloc,char,s,len,a) + +-extern int stralloc_ready(); +-extern int stralloc_readyplus(); +-extern int stralloc_copy(); +-extern int stralloc_cat(); +-extern int stralloc_copys(); +-extern int stralloc_cats(); +-extern int stralloc_copyb(); +-extern int stralloc_catb(); +-extern int stralloc_append(); /* beware: this takes a pointer to 1 char */ +-extern int stralloc_starts(); ++extern int stralloc_ready(stralloc *, unsigned int); ++extern int stralloc_readyplus(stralloc *, unsigned int); ++extern int stralloc_copy(stralloc *, stralloc *); ++extern int stralloc_cat(stralloc *, stralloc *); ++extern int stralloc_copys(stralloc *, const char *); ++extern int stralloc_cats(stralloc *, const char *); ++extern int stralloc_copyb(stralloc *, const char *, unsigned int); ++extern int stralloc_catb(stralloc *, const char *, unsigned int); ++extern int stralloc_append(stralloc *, const char *); /* beware: this takes a pointer to 1 char */ ++extern int stralloc_starts(stralloc *, const char *); + + #define stralloc_0(sa) stralloc_append(sa,"") + +diff -upN qmail-1.03/stralloc_arts.c qmail-ldap/stralloc_arts.c +--- qmail-1.03/stralloc_arts.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_arts.c Thu Jan 29 16:48:14 2004 +@@ -4,9 +4,9 @@ + + int stralloc_starts(sa,s) + stralloc *sa; +-char *s; ++const char *s; + { +- int len; ++ unsigned int len; + len = str_len(s); + return (sa->len >= len) && byte_equal(s,len,sa->s); + } +diff -upN qmail-1.03/stralloc_catb.c qmail-ldap/stralloc_catb.c +--- qmail-1.03/stralloc_catb.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_catb.c Tue Oct 28 18:21:32 2003 +@@ -3,7 +3,7 @@ + + int stralloc_catb(sa,s,n) + stralloc *sa; +-char *s; ++const char *s; + unsigned int n; + { + if (!sa->s) return stralloc_copyb(sa,s,n); +diff -upN qmail-1.03/stralloc_cats.c qmail-ldap/stralloc_cats.c +--- qmail-1.03/stralloc_cats.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_cats.c Tue Oct 28 18:21:32 2003 +@@ -4,7 +4,7 @@ + + int stralloc_cats(sa,s) + stralloc *sa; +-char *s; ++const char *s; + { + return stralloc_catb(sa,s,str_len(s)); + } +diff -upN qmail-1.03/stralloc_opyb.c qmail-ldap/stralloc_opyb.c +--- qmail-1.03/stralloc_opyb.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_opyb.c Tue Oct 28 18:21:32 2003 +@@ -3,7 +3,7 @@ + + int stralloc_copyb(sa,s,n) + stralloc *sa; +-char *s; ++const char *s; + unsigned int n; + { + if (!stralloc_ready(sa,n + 1)) return 0; +diff -upN qmail-1.03/stralloc_opys.c qmail-ldap/stralloc_opys.c +--- qmail-1.03/stralloc_opys.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_opys.c Tue Oct 28 18:21:32 2003 +@@ -4,7 +4,7 @@ + + int stralloc_copys(sa,s) + stralloc *sa; +-char *s; ++const char *s; + { + return stralloc_copyb(sa,s,str_len(s)); + } +diff -upN qmail-1.03/stralloc_pend.c qmail-ldap/stralloc_pend.c +--- qmail-1.03/stralloc_pend.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/stralloc_pend.c Tue Oct 28 18:21:32 2003 +@@ -2,4 +2,4 @@ + #include "stralloc.h" + #include "gen_allocdefs.h" + +-GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) ++GEN_ALLOC_append(stralloc,const char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) +diff -upN qmail-1.03/strerr.h qmail-ldap/strerr.h +--- qmail-1.03/strerr.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/strerr.h Tue Oct 28 18:21:32 2003 +@@ -4,18 +4,22 @@ + struct strerr + { + struct strerr *who; +- char *x; +- char *y; +- char *z; ++ const char *x; ++ const char *y; ++ const char *z; + } + ; + + extern struct strerr strerr_sys; +-extern void strerr_sysinit(); ++extern void strerr_sysinit(void); + ++/* XXX not available in qmail-1.03 + extern char *strerr(); +-extern void strerr_warn(); +-extern void strerr_die(); ++*/ ++extern void strerr_warn(const char *, const char *, const char *, ++ const char *, const char *, const char *, struct strerr *); ++extern void strerr_die(int, const char *, const char *, const char *, ++ const char *, const char *, const char *, struct strerr *); + + #define STRERR(r,se,a) \ + { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } +diff -upN qmail-1.03/strerr_die.c qmail-ldap/strerr_die.c +--- qmail-1.03/strerr_die.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/strerr_die.c Tue Oct 28 18:21:32 2003 +@@ -4,7 +4,8 @@ + #include "strerr.h" + + void strerr_warn(x1,x2,x3,x4,x5,x6,se) +-char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; ++const char *x1; const char *x2; const char *x3; ++const char *x4; const char *x5; const char *x6; + struct strerr *se; + { + strerr_sysinit(); +@@ -29,7 +30,8 @@ struct strerr *se; + + void strerr_die(e,x1,x2,x3,x4,x5,x6,se) + int e; +-char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; ++const char *x1; const char *x2; const char *x3; ++const char *x4; const char *x5; const char *x6; + struct strerr *se; + { + strerr_warn(x1,x2,x3,x4,x5,x6,se); +diff -upN qmail-1.03/strerr_sys.c qmail-ldap/strerr_sys.c +--- qmail-1.03/strerr_sys.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/strerr_sys.c Tue Oct 28 18:21:32 2003 +@@ -3,7 +3,7 @@ + + struct strerr strerr_sys; + +-void strerr_sysinit() ++void strerr_sysinit(void) + { + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); +diff -upN qmail-1.03/subfd.h qmail-ldap/subfd.h +--- qmail-1.03/subfd.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfd.h Wed Oct 29 22:27:25 2003 +@@ -9,7 +9,7 @@ extern substdio *subfdout; + extern substdio *subfdoutsmall; + extern substdio *subfderr; + +-extern int subfd_read(); +-extern int subfd_readsmall(); ++extern int subfd_read(int, void *, int); ++extern int subfd_readsmall(int, void *, int); + + #endif +diff -upN qmail-1.03/subfderr.c qmail-ldap/subfderr.c +--- qmail-1.03/subfderr.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfderr.c Tue Oct 28 18:21:32 2003 +@@ -3,5 +3,5 @@ + #include "subfd.h" + + char subfd_errbuf[256]; +-static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256); ++static substdio it = SUBSTDIO_FDBUF(subwrite,2,subfd_errbuf,256); + substdio *subfderr = ⁢ +diff -upN qmail-1.03/subfdin.c qmail-ldap/subfdin.c +--- qmail-1.03/subfdin.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfdin.c Wed Oct 29 22:27:25 2003 +@@ -2,10 +2,10 @@ + #include "substdio.h" + #include "subfd.h" + +-int subfd_read(fd,buf,len) int fd; char *buf; int len; ++int subfd_read(fd,buf,len) int fd; void *buf; int len; + { + if (substdio_flush(subfdout) == -1) return -1; +- return read(fd,buf,len); ++ return subread(fd,buf,len); + } + + char subfd_inbuf[SUBSTDIO_INSIZE]; +diff -upN qmail-1.03/subfdins.c qmail-ldap/subfdins.c +--- qmail-1.03/subfdins.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfdins.c Wed Oct 29 22:27:25 2003 +@@ -2,10 +2,10 @@ + #include "substdio.h" + #include "subfd.h" + +-int subfd_readsmall(fd,buf,len) int fd; char *buf; int len; ++int subfd_readsmall(fd,buf,len) int fd; void *buf; int len; + { + if (substdio_flush(subfdoutsmall) == -1) return -1; +- return read(fd,buf,len); ++ return subread(fd,buf,len); + } + + char subfd_inbufsmall[256]; +diff -upN qmail-1.03/subfdout.c qmail-ldap/subfdout.c +--- qmail-1.03/subfdout.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfdout.c Tue Oct 28 18:21:32 2003 +@@ -3,5 +3,5 @@ + #include "subfd.h" + + char subfd_outbuf[SUBSTDIO_OUTSIZE]; +-static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbuf,SUBSTDIO_OUTSIZE); ++static substdio it = SUBSTDIO_FDBUF(subwrite,1,subfd_outbuf,SUBSTDIO_OUTSIZE); + substdio *subfdout = ⁢ +diff -upN qmail-1.03/subfdouts.c qmail-ldap/subfdouts.c +--- qmail-1.03/subfdouts.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subfdouts.c Tue Oct 28 18:21:32 2003 +@@ -3,5 +3,5 @@ + #include "subfd.h" + + char subfd_outbufsmall[256]; +-static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbufsmall,256); ++static substdio it = SUBSTDIO_FDBUF(subwrite,1,subfd_outbufsmall,256); + substdio *subfdoutsmall = ⁢ +diff -upN qmail-1.03/subgetopt.c qmail-ldap/subgetopt.c +--- qmail-1.03/subgetopt.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subgetopt.c Tue Oct 28 18:21:32 2003 +@@ -28,10 +28,10 @@ int optdone = SUBGETOPTDONE; + int sgopt(argc,argv,opts) + int argc; + char **argv; +-char *opts; ++const char *opts; + { + int c; +- char *s; ++ const char *s; + + optarg = 0; + if (!argv || (optind >= argc) || !argv[optind]) return optdone; +diff -upN qmail-1.03/subgetopt.h qmail-ldap/subgetopt.h +--- qmail-1.03/subgetopt.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/subgetopt.h Tue Oct 28 18:21:32 2003 +@@ -13,7 +13,7 @@ + + #define SUBGETOPTDONE -1 + +-extern int subgetopt(); ++extern int subgetopt(int, char **, const char *); + extern char *subgetoptarg; + extern int subgetoptind; + extern int subgetoptpos; +diff -upN qmail-1.03/substdi.c qmail-ldap/substdi.c +--- qmail-1.03/substdi.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/substdi.c Tue Feb 17 15:31:30 2004 +@@ -6,7 +6,7 @@ static int oneread(op,fd,buf,len) + register int (*op)(); + register int fd; + register char *buf; +-register int len; ++register unsigned int len; + { + register int r; + +@@ -20,9 +20,9 @@ register int len; + static int getthis(s,buf,len) + register substdio *s; + register char *buf; +-register int len; ++register unsigned int len; + { +- register int r; ++ register unsigned int r; + register int q; + + r = s->p; +@@ -53,7 +53,7 @@ register substdio *s; + int substdio_bget(s,buf,len) + register substdio *s; + register char *buf; +-register int len; ++register unsigned int len; + { + register int r; + +@@ -66,7 +66,7 @@ register int len; + int substdio_get(s,buf,len) + register substdio *s; + register char *buf; +-register int len; ++register unsigned int len; + { + register int r; + +@@ -84,7 +84,7 @@ register substdio *s; + + void substdio_seek(s,len) + register substdio *s; +-register int len; ++register unsigned int len; + { + s->n += len; + s->p -= len; +diff -upN qmail-1.03/substdio.c qmail-ldap/substdio.c +--- qmail-1.03/substdio.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/substdio.c Thu Jan 29 16:48:14 2004 +@@ -5,7 +5,7 @@ register substdio *s; + register int (*op)(); + register int fd; + register char *buf; +-register int len; ++register unsigned int len; + { + s->x = buf; + s->fd = fd; +diff -upN qmail-1.03/substdio.h qmail-ldap/substdio.h +--- qmail-1.03/substdio.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/substdio.h Thu Jan 29 16:48:14 2004 +@@ -3,30 +3,30 @@ + + typedef struct substdio { + char *x; +- int p; +- int n; ++ unsigned int p; ++ unsigned int n; + int fd; +- int (*op)(); ++ int (*op)(int, void *, int); + } substdio; + + #define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } + +-extern void substdio_fdbuf(); ++extern void substdio_fdbuf(substdio *, int (*)(int, void *, int), int, char *, unsigned int); + +-extern int substdio_flush(); +-extern int substdio_put(); +-extern int substdio_bput(); +-extern int substdio_putflush(); +-extern int substdio_puts(); +-extern int substdio_bputs(); +-extern int substdio_putsflush(); +- +-extern int substdio_get(); +-extern int substdio_bget(); +-extern int substdio_feed(); ++extern int substdio_flush(substdio *); ++extern int substdio_put(substdio *, const char *, unsigned int); ++extern int substdio_bput(substdio *, const char *, unsigned int); ++extern int substdio_putflush(substdio *, const char *, unsigned int); ++extern int substdio_puts(substdio *, const char *); ++extern int substdio_bputs(substdio *, const char *); ++extern int substdio_putsflush(substdio *, const char *); ++ ++extern int substdio_get(substdio *, char *, unsigned int); ++extern int substdio_bget(substdio *, char *, unsigned int); ++extern int substdio_feed(substdio *); + +-extern char *substdio_peek(); +-extern void substdio_seek(); ++extern char *substdio_peek(substdio *); ++extern void substdio_seek(substdio *, unsigned int); + + #define substdio_fileno(s) ((s)->fd) + +@@ -42,6 +42,6 @@ extern void substdio_seek(); + : substdio_bput((s),&(c),1) \ + ) + +-extern int substdio_copy(); ++extern int substdio_copy(substdio *, substdio *); + + #endif +diff -upN qmail-1.03/substdo.c qmail-ldap/substdo.c +--- qmail-1.03/substdo.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/substdo.c Thu Jan 29 16:48:14 2004 +@@ -6,8 +6,8 @@ + static int allwrite(op,fd,buf,len) + register int (*op)(); + register int fd; +-register char *buf; +-register int len; ++register const char *buf; ++register unsigned int len; + { + register int w; + +@@ -27,7 +27,7 @@ register int len; + int substdio_flush(s) + register substdio *s; + { +- register int p; ++ register unsigned int p; + + p = s->p; + if (!p) return 0; +@@ -37,10 +37,10 @@ register substdio *s; + + int substdio_bput(s,buf,len) + register substdio *s; +-register char *buf; +-register int len; ++register const char *buf; ++register unsigned int len; + { +- register int n; ++ register unsigned int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; +@@ -54,10 +54,10 @@ register int len; + + int substdio_put(s,buf,len) + register substdio *s; +-register char *buf; +-register int len; ++register const char *buf; ++register unsigned int len; + { +- register int n; ++ register unsigned int n; + + n = s->n; + if (len > n - s->p) { +@@ -79,8 +79,8 @@ register int len; + + int substdio_putflush(s,buf,len) + register substdio *s; +-register char *buf; +-register int len; ++register const char *buf; ++register unsigned int len; + { + if (substdio_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +@@ -88,21 +88,21 @@ register int len; + + int substdio_bputs(s,buf) + register substdio *s; +-register char *buf; ++register const char *buf; + { + return substdio_bput(s,buf,str_len(buf)); + } + + int substdio_puts(s,buf) + register substdio *s; +-register char *buf; ++register const char *buf; + { + return substdio_put(s,buf,str_len(buf)); + } + + int substdio_putsflush(s,buf) + register substdio *s; +-register char *buf; ++register const char *buf; + { + return substdio_putflush(s,buf,str_len(buf)); + } +diff -upN qmail-1.03/tcp-env.c qmail-ldap/tcp-env.c +--- qmail-1.03/tcp-env.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/tcp-env.c Tue Oct 28 18:21:32 2003 +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include "sig.h" + #include "stralloc.h" + #include "str.h" +@@ -30,7 +31,7 @@ stralloc remotename = {0}; + + char temp[IPFMT + FMT_ULONG]; + +-void main(argc,argv) ++int main(argc,argv) + int argc; + char *argv[]; + { +@@ -125,5 +126,5 @@ char *argv[]; + + sig_pipedefault(); + execvp(*argv,argv); +- die(); ++ return 111; + } +diff -upN qmail-1.03/tcpto.c qmail-ldap/tcpto.c +--- qmail-1.03/tcpto.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/tcpto.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "tcpto.h" + #include "open.h" + #include "lock.h" +@@ -77,6 +78,7 @@ void tcpto_err(ip,flagerr) struct ip_add + int firstpos; + datetime_sec lastwhen; + ++ firstwhen = 0; + if (!flagerr) + if (!flagwasthere) + return; /* could have been added, but not worth the effort to check */ +diff -upN qmail-1.03/tcpto.h qmail-ldap/tcpto.h +--- qmail-1.03/tcpto.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/tcpto.h Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,10 @@ + #ifndef TCPTO_H + #define TCPTO_H + +-extern int tcpto(); +-extern void tcpto_err(); +-extern void tcpto_clean(); ++struct ip_address; ++ ++extern int tcpto(struct ip_address *); ++extern void tcpto_err(struct ip_address *, int); ++extern void tcpto_clean(void); + + #endif +diff -upN qmail-1.03/tcpto_clean.c qmail-ldap/tcpto_clean.c +--- qmail-1.03/tcpto_clean.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/tcpto_clean.c Thu Jan 29 16:48:14 2004 +@@ -1,3 +1,4 @@ ++#include + #include "tcpto.h" + #include "open.h" + #include "substdio.h" +@@ -5,15 +6,15 @@ + + char tcpto_cleanbuf[1024]; + +-void tcpto_clean() /* running from queue/mess */ ++void tcpto_clean(void) /* running from queue/mess */ + { + int fd; +- int i; ++ unsigned int i; + substdio ss; + + fd = open_write("../lock/tcpto"); + if (fd == -1) return; +- substdio_fdbuf(&ss,write,fd,tcpto_cleanbuf,sizeof(tcpto_cleanbuf)); ++ substdio_fdbuf(&ss,subwrite,fd,tcpto_cleanbuf,sizeof(tcpto_cleanbuf)); + for (i = 0;i < sizeof(tcpto_cleanbuf);++i) substdio_put(&ss,"",1); + substdio_flush(&ss); /* if it fails, bummer */ + close(fd); +diff -upN qmail-1.03/timeoutconn.c qmail-ldap/timeoutconn.c +--- qmail-1.03/timeoutconn.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutconn.c Thu Jan 29 16:48:14 2004 +@@ -10,29 +10,32 @@ + #include "byte.h" + #include "timeoutconn.h" + +-int timeoutconn(s,ip,port,timeout) +-int s; +-struct ip_address *ip; +-unsigned int port; +-int timeout; ++int timeoutconn(int s, struct ip_address *ip, struct ip_address *outip, ++ unsigned int port, int timeout) + { + char ch; +- struct sockaddr_in sin; ++ struct sockaddr_in s_in; + char *x; + fd_set wfds; + struct timeval tv; + +- byte_zero(&sin,sizeof(sin)); +- byte_copy(&sin.sin_addr,4,ip); +- x = (char *) &sin.sin_port; +- x[1] = port; port >>= 8; x[0] = port; +- sin.sin_family = AF_INET; + + if (ndelay_on(s) == -1) return -1; + +- /* XXX: could bind s */ ++ /* bind() an outgoing ipaddr */ ++ byte_zero(&s_in,sizeof(s_in)); ++ byte_copy(&s_in.sin_addr.s_addr,4,outip); ++ s_in.sin_family = AF_INET; ++ ++ if (bind(s,(struct sockaddr *) &s_in,sizeof(s_in)) == -1) return -1; ++ ++ byte_zero(&s_in,sizeof(s_in)); ++ byte_copy(&s_in.sin_addr,4,ip); ++ x = (char *) &s_in.sin_port; ++ x[1] = port; port >>= 8; x[0] = port; ++ s_in.sin_family = AF_INET; + +- if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) { ++ if (connect(s,(struct sockaddr *) &s_in,sizeof(s_in)) == 0) { + ndelay_off(s); + return 0; + } +@@ -45,9 +48,9 @@ int timeout; + if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; + if (FD_ISSET(s,&wfds)) { + int dummy; +- dummy = sizeof(sin); +- if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) { +- read(s,&ch,1); ++ dummy = sizeof(s_in); ++ if (getpeername(s,(struct sockaddr *) &s_in,&dummy) == -1) { ++ subread(s,&ch,1); + return -1; + } + ndelay_off(s); +diff -upN qmail-1.03/timeoutconn.h qmail-ldap/timeoutconn.h +--- qmail-1.03/timeoutconn.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutconn.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,9 @@ + #ifndef TIMEOUTCONN_H + #define TIMEOUTCONN_H + +-extern int timeoutconn(); ++struct ip_address; ++ ++extern int timeoutconn(int, struct ip_address *, ++ struct ip_address *, unsigned int, int); + + #endif +diff -upN qmail-1.03/timeoutread.c qmail-ldap/timeoutread.c +--- qmail-1.03/timeoutread.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutread.c Tue Oct 28 18:21:32 2003 +@@ -15,7 +15,7 @@ int timeoutread(t,fd,buf,len) int t; int + FD_SET(fd,&rfds); + + if (select(fd + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tv) == -1) return -1; +- if (FD_ISSET(fd,&rfds)) return read(fd,buf,len); ++ if (FD_ISSET(fd,&rfds)) return subread(fd,buf,len); + + errno = error_timeout; + return -1; +diff -upN qmail-1.03/timeoutread.h qmail-ldap/timeoutread.h +--- qmail-1.03/timeoutread.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutread.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,6 @@ + #ifndef TIMEOUTREAD_H + #define TIMEOUTREAD_H + +-extern int timeoutread(); ++extern int timeoutread(int, int, char *, int); + + #endif +diff -upN qmail-1.03/timeoutwrite.c qmail-ldap/timeoutwrite.c +--- qmail-1.03/timeoutwrite.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutwrite.c Thu Jan 29 16:48:15 2004 +@@ -3,7 +3,7 @@ + #include "error.h" + #include "readwrite.h" + +-int timeoutwrite(t,fd,buf,len) int t; int fd; char *buf; int len; ++int timeoutwrite(t,fd,buf,len) int t; int fd; const void *buf; int len; + { + fd_set wfds; + struct timeval tv; +@@ -15,7 +15,7 @@ int timeoutwrite(t,fd,buf,len) int t; in + FD_SET(fd,&wfds); + + if (select(fd + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; +- if (FD_ISSET(fd,&wfds)) return write(fd,buf,len); ++ if (FD_ISSET(fd,&wfds)) return subwrite(fd,(void *)buf,len); + + errno = error_timeout; + return -1; +diff -upN qmail-1.03/timeoutwrite.h qmail-ldap/timeoutwrite.h +--- qmail-1.03/timeoutwrite.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/timeoutwrite.h Thu Jan 29 16:48:15 2004 +@@ -1,6 +1,6 @@ + #ifndef TIMEOUTWRITE_H + #define TIMEOUTWRITE_H + +-extern int timeoutwrite(); ++extern int timeoutwrite(int, int, const void *, int); + + #endif +diff -upN qmail-1.03/token822.c qmail-ldap/token822.c +--- qmail-1.03/token822.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/token822.c Tue Feb 17 15:31:30 2004 +@@ -9,10 +9,11 @@ static struct token822 comma = { TOKEN82 + void token822_reverse(ta) + token822_alloc *ta; + { +- int i; +- int n; ++ unsigned int i; ++ unsigned int n; + struct token822 temp; + ++ if (ta->len == 0) return; + n = ta->len - 1; + for (i = 0;i + i < n;++i) + { +@@ -65,7 +66,7 @@ char ch; + static void atomcheck(t) + struct token822 *t; + { +- int i; ++ unsigned int i; + char ch; + for (i = 0;i < t->slen;++i) + { +@@ -84,10 +85,10 @@ token822_alloc *ta; + unsigned int linelen; + { + struct token822 *t; +- int len; ++ unsigned int len; + int ch; +- int i; +- int j; ++ unsigned int i; ++ unsigned int j; + int lasttype; + int newtype; + char *s; +@@ -184,9 +185,9 @@ stralloc *sa; + token822_alloc *ta; + { + struct token822 *t; +- int len; +- int i; +- int j; ++ unsigned int len; ++ unsigned int i; ++ unsigned int j; + char *s; + + len = 0; +@@ -240,12 +241,12 @@ token822_alloc *ta; + stralloc *sa; + stralloc *buf; + { +- int i; +- int salen; +- int level; ++ unsigned int i; ++ unsigned int salen; ++ unsigned int level; + struct token822 *t; +- int numtoks; +- int numchars; ++ unsigned int numtoks; ++ unsigned int numchars; + char *cbuf; + + salen = sa->len; +@@ -403,7 +404,7 @@ token822_alloc *taout; + token822_alloc *taaddr; + int (*callback)(); + { +- int i; ++ unsigned int i; + + if (callback(taaddr) != 1) + return 0; +diff -upN qmail-1.03/token822.h qmail-ldap/token822.h +--- qmail-1.03/token822.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/token822.h Tue Oct 28 18:21:32 2003 +@@ -4,23 +4,28 @@ + struct token822 + { + int type; +- char *s; ++ const char *s; + int slen; + } + ; + + #include "gen_alloc.h" ++#include "stralloc.h" ++ + GEN_ALLOC_typedef(token822_alloc,struct token822,t,len,a) + +-extern int token822_parse(); +-extern int token822_addrlist(); +-extern int token822_unquote(); +-extern int token822_unparse(); ++extern int token822_parse(token822_alloc *, stralloc *, stralloc *); ++extern int token822_addrlist(token822_alloc *, token822_alloc *, ++ token822_alloc *, int (*)()); ++extern int token822_unquote(stralloc *, token822_alloc *); ++extern int token822_unparse(stralloc *, token822_alloc *, unsigned int); ++/* XXX not available in qmail-1.03 + extern void token822_free(); +-extern void token822_reverse(); +-extern int token822_ready(); +-extern int token822_readyplus(); +-extern int token822_append(); ++*/ ++extern void token822_reverse(token822_alloc *); ++extern int token822_ready(token822_alloc *, unsigned int); ++extern int token822_readyplus(token822_alloc *, unsigned int); ++extern int token822_append(token822_alloc *, struct token822 *); + + #define TOKEN822_ATOM 1 + #define TOKEN822_QUOTE 2 +diff -upN qmail-1.03/trigger.c qmail-ldap/trigger.c +--- qmail-1.03/trigger.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/trigger.c Tue Oct 28 18:21:32 2003 +@@ -1,3 +1,4 @@ ++#include + #include "select.h" + #include "open.h" + #include "trigger.h" +@@ -8,7 +9,7 @@ static int fd = -1; + static int fdw = -1; + #endif + +-void trigger_set() ++void trigger_set(void) + { + if (fd != -1) + close(fd); +diff -upN qmail-1.03/trigger.h qmail-ldap/trigger.h +--- qmail-1.03/trigger.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/trigger.h Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,10 @@ + #ifndef TRIGGER_H + #define TRIGGER_H + +-extern void trigger_set(); +-extern void trigger_selprep(); +-extern int trigger_pulled(); ++#include "select.h" ++ ++extern void trigger_set(void); ++extern void trigger_selprep(int *, fd_set *); ++extern int trigger_pulled(fd_set *); + + #endif +diff -upN qmail-1.03/triggerpull.c qmail-ldap/triggerpull.c +--- qmail-1.03/triggerpull.c Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/triggerpull.c Tue Oct 28 18:21:32 2003 +@@ -1,8 +1,10 @@ ++#include ++#include "readwrite.h" + #include "ndelay.h" + #include "open.h" + #include "triggerpull.h" + +-void triggerpull() ++void triggerpull(void) + { + int fd; + +diff -upN qmail-1.03/triggerpull.h qmail-ldap/triggerpull.h +--- qmail-1.03/triggerpull.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/triggerpull.h Tue Oct 28 18:21:32 2003 +@@ -1,6 +1,6 @@ + #ifndef TRIGGERPULL_H + #define TRIGGERPULL_H + +-extern void triggerpull(); ++extern void triggerpull(void); + + #endif +diff -upN qmail-1.03/wait.h qmail-ldap/wait.h +--- qmail-1.03/wait.h Mon Jun 15 12:53:16 1998 ++++ qmail-ldap/wait.h Tue Oct 28 18:21:32 2003 +@@ -1,11 +1,12 @@ + #ifndef WAIT_H + #define WAIT_H + +-extern int wait_pid(); +-extern int wait_nohang(); ++extern int wait_pid(int *, int); ++extern int wait_nohang(int *); ++/* XXX not available in qmail-1.03 + extern int wait_stop(); + extern int wait_stopnohang(); +- ++*/ + #define wait_crashed(w) ((w) & 127) + #define wait_exitcode(w) ((w) >> 8) + #define wait_stopsig(w) ((w) >> 8) --- qmail-1.03.orig/qregex.c +++ qmail-1.03/qregex.c @@ -0,0 +1,57 @@ +/* + * qregex (v2) + * $Id: qregex.c,v 2.1 2001/12/28 07:05:21 evan Exp $ + * + * Author : Evan Borgstrom (evan at unixpimps dot org) + * Created : 2001/12/14 23:08:16 + * Modified: $Date: 2001/12/28 07:05:21 $ + * Revision: $Revision: 2.1 $ + * + * Do POSIX regex matching on addresses for anti-relay / spam control. + * It logs to the maillog + * See the qregex-readme file included with this tarball. + * If you didn't get this file in a tarball please see the following URL: + * http://www.unixpimps.org/software/qregex + * + * qregex.c is released under a BSD style copyright. + * See http://www.unixpimps.org/software/qregex/copyright.html + * + * Note: this revision follows the coding guidelines set forth by the rest of + * the qmail code and that described at the following URL. + * http://cr.yp.to/qmail/guarantee.html + * + */ + +#include +#include +#include "qregex.h" + +#define REGCOMP(X,Y) regcomp(&X, Y, REG_EXTENDED|REG_ICASE) +#define REGEXEC(X,Y) regexec(&X, Y, (size_t)0, (regmatch_t *)0, (int)0) + +int matchregex(char *text, char *regex) { + regex_t qreg; + int retval = 0; + + + /* build the regex */ + if ((retval = REGCOMP(qreg, regex)) != 0) { + regfree(&qreg); + return(-retval); + } + + /* execute the regex */ + if ((retval = REGEXEC(qreg, text)) != 0) { + /* did we just not match anything? */ + if (retval == REG_NOMATCH) { + regfree(&qreg); + return(0); + } + regfree(&qreg); + return(-retval); + } + + /* signal the match */ + regfree(&qreg); + return(1); +} --- qmail-1.03.orig/binm1.sh +++ qmail-1.03/binm1.sh @@ -4,7 +4,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start \ '|preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/qregex.h +++ qmail-1.03/qregex.h @@ -0,0 +1,5 @@ +/* simple header file for the matchregex prototype */ +#ifndef _QREGEX_H_ +#define _QREGEX_H_ +int matchregex(char *text, char *regex); +#endif --- qmail-1.03.orig/binm3.sh +++ qmail-1.03/binm3.sh @@ -4,7 +4,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using V7 binmail interface: /bin/mail -f -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start \ '|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/home+df.sh +++ qmail-1.03/home+df.sh @@ -4,6 +4,6 @@ # Using dot-forward to support sendmail-style ~/.forward files. # Using qmail-local to deliver messages to ~/Mailbox by default. -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|dot-forward .forward ./Mailbox' splogger qmail --- qmail-1.03.orig/README.qregex +++ qmail-1.03/README.qregex @@ -0,0 +1,196 @@ +QREGEX (v2) 20040725 - README July 25, 2004 +A Regular Expression matching patch for qmail 1.03 and netqmail + + +OVERVIEW: + +qregex adds the ability to match address evelopes via Regular Expressions (REs) +in the qmail-smtpd process. It has the abiltiy to match `helo/ehlo` (host name), +`mail from` (envelope sender), and `rcpt to` (envelope recipient) commands. +It follows all the base rules that are set out with qmail (ie using control +files) so it makes for easy integretion into an existing setup (see the +install instructions for more info). The v2 is specified because qregex was +re-written to better conform to the security guarantee set forth by the author +of qmail. The original version used stdio.h and stdlib.h for reading the +control files whereas v2 now uses all stralloc functions which are much more +regulated against buffer overruns and the like. +See: http://cr.yp.to/qmail/guarantee.html + + +FEATURES: + +Features of qregex include: + +1. Performs pattern matching on envelope senders and envelope + recipients against REs in the badmailfrom and badmailto control + files. Two additional control files, badmailfromnorelay and + badmailtonorelay, are used for pattern matching when the + RELAYCLIENT environment variable is not set. + +2. Performs pattern matching on the helo/ehlo host name. Setting the + NOBADHELO environment variable prevents the host name from being + compared to the patterns in the badhelo control file. + +3. Matches to patterns are logged + +4. Matching is case insensitive. + +5. qregex ignores empty envelope senders. An empty envelope sender is not + compared to the patterns in the badmailfrom and badmailfromnorelay + control files and is always accepted. + + +PLATFORMS: + +qregex has been built and tested on the following platforms. I'm sure it won't +have any problems on any platform that qmail will run on (providing they have +a regex interface) but if you run into problems let me know. + + - OpenBSD 3.x + - FreeBSD 4.x + - Mandrake Linux 9.x + - SuSE Linux 8.x + + + +INSTALLATION INSTRUCTIONS: + +Installation is very simple, there is only one requirement. You need to use the +GNU version of the patch utility (http://www.gnu.org/software/patch/patch.html). +(For Solaris 8 users it is installed as 'gpatch') + +- If this is a new setup. +Unpack the qmail archive, cd into the qmail-1.03 directory and run +"patch < /path/to/qregex-.patch". Follow the instructions as per the +included qmail INSTALL file. Once you are done come back to this file and read +the section on the control files. + +If you are using netqmail, then unpack the netqmail archive. Run the collate.sh +script and cd into the resulting netqmail- directory. From there, run +"patch < /path/to/qregex-.patch". Complete the netqmail installation +normally. Once you are done, come back to this file and read the section on the +control files. + +- If this is an existing setup. +FIRST: create your control files (see below). +cd into your existing qmail or netqmail source directory. Run +"patch < /path/to/qregex-.patch" then "make qmail-smtpd". Now run +./qmail-smtpd and test your new rules to make sure they work as expected. + +Install the new binary by cd'ing to /var/qmail/bin and as root (in one command) +copy the existing binary to 'qmail-smtpd.old' and copy the new binary from the +source directory to 'qmail-smtpd'. +(ex. cp qmail-smtpd qmail-smtpd.old && cp ~/qmail-1.03/qmail-smtpd qmail-smtpd) + +You can also optionally just run "make setup check" as it will install the +updated documentation and man pages provided with this patch. Stopping qmail +before doing the "make setup check" is always a good idea. + + +LOGGING: + +qregex will log matches to the patterns in the various control files. Log +messages will take these three forms depending on which control file was +matched: + +badhelo +qmail-smtpd: badhelo: at + +badmailfrom and badmailfromnorelay +qmail-smtpd: badmailfrom: at + +badmailto and badmailtonorelay +qmail-smtpd: badmailto: at + + +CONTROL FILES: + +qregex provides you with five control files. None of these control files +is mandatory and you can use them in any combination you choose in your setup. + +The "control/badmailfrom" and "control/badmailto" files contain your REs for +matching against the 'mail from' (envelope sender) and 'rcpt to' (envelope +recipient) smtp commands respectively. +The "control/badmailfromnorelay" and "control/badmailtonorelay" match against +the same commands but are read only when the RELAYCLIENT environment variable +is not set. +The "control/badhelo" file matches against the 'helo/ehlo' smtp command. + +If you prefer you can symlink the badmailfrom and badmailto control files +(ln -s badmailfrom badmailto) and maintain fewer sets of rules. Beware +this might cause problems in certain setups. + + Here's an example "badhelo" file. + ----------------------------------- + # block host strings with no dot (not a FQDN) + !\. + ----------------------------------- + + An example "badmailfrom" file. + ----------------------------------- + # this will drop everything containing the string + # bad.domain.com or Bad.Domain.Com or BAD.domain.COM + bad\.domain\.com + # force users to fully qualify themselves + # (i.e. deny "user", accept "user@domain") + !@ + ----------------------------------- + + And "badmailto" (a little more interesting) + ----------------------------------- + # must not contain invalid characters, brakets or multiple @'s + [!%#:*^(){}] + @.*@ + ----------------------------------- + +You can use the non-RE character '!' to start an RE as a signal to qregex to +negate the action. As used above in the badmailfrom file, by negating the '@' +symbol qregex will signal qmail-smtpd to deny the 'mail from' command whenever +the address doesn't contain an @ symbol. When used inside a bracket expression, +the '!' character looses this special meaning. This is shown in the badmailto +example. + +The norelay control files follow the same rules as the other control files but +are intended to address two specific scenarios. +The badmailfromnorelay file can be used to block mail trying to spoof a domain +hosted on your mail server. It prevents a mail client that is not allowed to +relay email through your server from using one of your hosted domains as its +envelope sender. +The badmailtonorelay file can be used to create email addresses that cannot +receive mail from any source not allowed to relay email through your server. +This is handy for creating email addresses for use only within your own +domain(s) that can't receive spam from the world at large. + + +INTERNALS: + +qregex (or regexmatch as the function is called) will be called during the +`helo/ehlo`, `rcpt to` and `mail from` handling routines in "qmail-smtpd.c". +When called, it will read the proper control file then one by one compile and +execute the regex on the string passed into qmail-smtpd. If the regex matches +it returns TRUE (1) and the qmail-smtpd process will deny the user the ability +to continue. If you change anything and think it betters this patch please +send me a new diff file so I can take a peek. + + +CONTACT: +qregex is maintained by: + Andrew St. Jean + andrew@arda.homeunix.net + www.arda.homeunix.net/store/qmail/ + +Contributers to qregex: + Jeremy Kitchen + kitchen at scriptkitchen dot com + http://www.scriptkitchen.com/qmail + + Alex Pleiner + alex@zeitform.de + zeitform Internet Dienste + http://www.zeitform.de/ + + Thanos Massias + +Original qregex patch written by: + Evan Borgstrom + evan at unixpimps dot org --- qmail-1.03.orig/qmail-smtpd.c +++ qmail-1.03/qmail-smtpd.c @@ -23,6 +23,15 @@ #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" +#include "qregex.h" +#include "strerr.h" + +#define BMCHECK_BMF 0 +#define BMCHECK_BMFNR 1 +#define BMCHECK_BMT 2 +#define BMCHECK_BMTNR 3 +#define BMCHECK_BHELO 4 + #define MAXHOPS 100 unsigned int databytes = 0; @@ -49,14 +58,16 @@ 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 err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } +void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); } +void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); } +void err_bhelo() { out("553 sorry, your HELO host name has been denied (#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() { out("502 unimplemented (#5.5.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() { out("250 ok\r\n"); } -void err_vrfy() { out("252 send some mail, i'll try my best\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"); } @@ -67,11 +78,11 @@ substdio_puts(&ssout,code); substdio_put(&ssout,greeting.s,greeting.len); } -void smtp_help() +void smtp_help(arg) char *arg; { out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); } -void smtp_quit() +void smtp_quit(arg) char *arg; { smtp_greet("221 "); out("\r\n"); flush(); _exit(0); } @@ -93,9 +104,21 @@ int liphostok = 0; stralloc liphost = {0}; + int bmfok = 0; stralloc bmf = {0}; -struct constmap mapbmf; + +int bmfnrok = 0; +stralloc bmfnr = {0}; + +int bmtok = 0; +stralloc bmt = {0}; + +int bmtnrok = 0; +stralloc bmtnr = {0}; + +int bhelook = 0; +stralloc bhelo = {0}; void setup() { @@ -114,8 +137,19 @@ bmfok = control_readfile(&bmf,"control/badmailfrom",0); if (bmfok == -1) die_control(); - if (bmfok) - if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + + bmfnrok = control_readfile(&bmfnr,"control/badmailfromnorelay",0); + if (bmfnrok == -1) die_control(); + + bmtok = control_readfile(&bmt,"control/badmailto",0); + if (bmtok == -1) die_control(); + + bmtnrok = control_readfile(&bmtnr,"control/badmailtonorelay",0); + if (bmtnrok == -1) die_control(); + + bhelook = control_readfile(&bhelo, "control/badhelo",0); + if (bhelook == -1) die_control(); + if (env_get("NOBADHELO")) bhelook = 0; if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); @@ -197,14 +231,48 @@ return 1; } -int bmfcheck() +int bmcheck(which) int which; { - int j; - if (!bmfok) return 0; - if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1; - j = byte_rchr(addr.s,addr.len,'@'); - if (j < addr.len) - if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1; + int i = 0; + int j = 0; + int x = 0; + int negate = 0; + static stralloc bmb = {0}; + static stralloc curregex = {0}; + + if (which == BMCHECK_BMF) { + if (!stralloc_copy(&bmb,&bmf)) die_nomem(); + } else if (which == BMCHECK_BMFNR) { + if (!stralloc_copy(&bmb,&bmfnr)) die_nomem(); + } else if (which == BMCHECK_BMT) { + if (!stralloc_copy(&bmb,&bmt)) die_nomem(); + } else if (which == BMCHECK_BMTNR) { + if (!stralloc_copy(&bmb,&bmtnr)) die_nomem(); + } else if (which == BMCHECK_BHELO) { + if (!stralloc_copy(&bmb,&bhelo)) die_nomem(); + } else { + die_control(); + } + + while (j < bmb.len) { + i = j; + while ((bmb.s[i] != '\0') && (i < bmb.len)) i++; + if (bmb.s[j] == '!') { + negate = 1; + j++; + } + if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem(); + if (!stralloc_0(&curregex)) die_nomem(); + if (which == BMCHECK_BHELO) { + x = matchregex(helohost.s, curregex.s); + } else { + x = matchregex(addr.s, curregex.s); + } + if ((negate) && (x == 0)) return 1; + if (!(negate) && (x > 0)) return 1; + j = i + 1; + negate = 0; + } return 0; } @@ -218,7 +286,9 @@ int seenmail = 0; -int flagbarf; /* defined if seenmail */ +int flagbarfbmf; /* defined if seenmail */ +int flagbarfbmt; +int flagbarfbhelo; stralloc mailfrom = {0}; stralloc rcptto = {0}; @@ -226,13 +296,15 @@ { smtp_greet("250 "); out("\r\n"); seenmail = 0; dohelo(arg); + if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO); } void smtp_ehlo(arg) char *arg; { smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); seenmail = 0; dohelo(arg); + if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO); } -void smtp_rset() +void smtp_rset(arg) char *arg; { seenmail = 0; out("250 flushed\r\n"); @@ -240,7 +312,11 @@ void smtp_mail(arg) char *arg; { if (!addrparse(arg)) { err_syntax(); return; } - flagbarf = bmfcheck(); + flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */ + if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF); + if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) { + flagbarfbmf = bmcheck(BMCHECK_BMFNR); + } seenmail = 1; if (!stralloc_copys(&rcptto,"")) die_nomem(); if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); @@ -250,7 +326,25 @@ void smtp_rcpt(arg) char *arg; { if (!seenmail) { err_wantmail(); return; } if (!addrparse(arg)) { err_syntax(); return; } - if (flagbarf) { err_bmf(); return; } + if (flagbarfbhelo) { + strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0); + err_bhelo(); + return; + } + if (flagbarfbmf) { + strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0); + err_bmf(); + return; + } + if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT); + if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) { + flagbarfbmt = bmcheck(BMCHECK_BMTNR); + } + if (flagbarfbmt) { + strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0); + err_bmt(); + return; + } if (relayclient) { --addr.len; if (!stralloc_cats(&addr,relayclient)) die_nomem(); @@ -296,7 +390,7 @@ char ch; int state; int flaginheader; - int pos; /* number of bytes since most recent \n, if fih */ + unsigned int pos; /* number of bytes since most recent \n, if fih */ int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ int flagmaybey; /* 1 if this line might match \r\n, if fih */ int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ @@ -316,8 +410,8 @@ if (flagmaybex) if (pos == 7) ++*hops; if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; if (flagmaybey) if (pos == 1) flaginheader = 0; + ++pos; } - ++pos; if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } } switch(state) { @@ -365,7 +459,7 @@ out("\r\n"); } -void smtp_data() { +void smtp_data(arg) char *arg; { int hops; unsigned long qp; char *qqx; --- qmail-1.03.orig/conf-groups +++ qmail-1.03/conf-groups @@ -1,5 +1,5 @@ qmail -nofiles +nogroup These are the qmail groups. The second group should not have access to any files, but it must be usable for processes; this requirement --- qmail-1.03.orig/cdb_seek.c +++ qmail-1.03/cdb_seek.c @@ -1,6 +1,5 @@ #include #include -extern int errno; #include "cdb.h" #ifndef SEEK_SET --- qmail-1.03.orig/date822fmt.c +++ qmail-1.03/date822fmt.c @@ -1,3 +1,4 @@ +#include #include "datetime.h" #include "fmt.h" #include "date822fmt.h" @@ -12,18 +13,51 @@ { unsigned int i; unsigned int len; + time_t now; + datetime_sec utc; + datetime_sec local; + struct tm *tm; + struct datetime new_dt; + int minutes; + + utc = datetime_untai(dt); + now = (time_t)utc; + tm = localtime(&now); + new_dt.year = tm->tm_year; + new_dt.mon = tm->tm_mon; + new_dt.mday = tm->tm_mday; + new_dt.hour = tm->tm_hour; + new_dt.min = tm->tm_min; + new_dt.sec = tm->tm_sec; + local = datetime_untai(&new_dt); + len = 0; - i = fmt_uint(s,dt->mday); len += i; if (s) s += i; + i = fmt_uint(s,new_dt.mday); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; - i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i; + i = fmt_str(s,montab[new_dt.mon]); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; - i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i; + i = fmt_uint(s,new_dt.year + 1900); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; - i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i; + i = fmt_uint0(s,new_dt.hour,2); len += i; if (s) s += i; i = fmt_str(s,":"); len += i; if (s) s += i; - i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i; + i = fmt_uint0(s,new_dt.min,2); len += i; if (s) s += i; i = fmt_str(s,":"); len += i; if (s) s += i; - i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i; - i = fmt_str(s," -0000\n"); len += i; if (s) s += i; + i = fmt_uint0(s,new_dt.sec,2); len += i; if (s) s += i; + + if (local < utc) { + minutes = (utc - local + 30) / 60; + i = fmt_str(s," -"); len += i; if (s) s += i; + i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i; + i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i; + } + else { + minutes = (local - utc + 30) / 60; + i = fmt_str(s," +"); len += i; if (s) s += i; + i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i; + i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i; + } + + i = fmt_str(s,"\n"); len += i; if (s) s += i; + return len; } --- qmail-1.03.orig/Makefile +++ qmail-1.03/Makefile @@ -263,7 +263,7 @@ cdbmake_add.o cdbmake_add.o: \ -compile cdbmake_add.c cdbmake.h uint32.h +compile cdbmake_add.c cdbmake.h alloc.h uint32.h ./compile cdbmake_add.c cdbmake_hash.o: \ @@ -1483,12 +1483,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 @@ -1532,16 +1532,16 @@ ./compile qmail-showctl.c qmail-smtpd: \ -load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ +load qmail-smtpd.o rcpthosts.o qregex.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 alloc.a strerr.a substdio.a error.a str.a \ fs.a auto_qmail.o socket.lib - ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ + ./load qmail-smtpd qregex.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 `cat \ + alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ socket.lib` qmail-smtpd.0: \ @@ -1681,6 +1681,10 @@ constmap.h stralloc.h gen_alloc.h rcpthosts.h ./compile rcpthosts.c +qregex.o: \ +compile qregex.c qregex.h + ./compile qregex.c + readsubdir.o: \ compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \ auto_split.h @@ -1892,7 +1896,7 @@ spawn.o: \ compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ -stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \ +stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \ auto_qmail.h auto_uids.h auto_spawn.h ./chkspawn ./compile spawn.c --- qmail-1.03.orig/dns.c +++ qmail-1.03/dns.c @@ -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 u_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; } --- qmail-1.03.orig/config.sh +++ qmail-1.03/config.sh @@ -6,18 +6,18 @@ if read fqdn then echo Your host\'s fully qualified name in DNS is "$fqdn". - echo Putting "$fqdn" into control/me... + echo Putting "$fqdn" into QMAIL/control/me ... echo "$fqdn" > QMAIL/control/me chmod 644 QMAIL/control/me ( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | ( read ddom - echo Putting "$ddom" into control/defaultdomain... + echo Putting "$ddom" into QMAIL/control/defaultdomain ... echo "$ddom" > QMAIL/control/defaultdomain chmod 644 QMAIL/control/defaultdomain ) ) ( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | ( read pdom - echo Putting "$pdom" into control/plusdomain... + echo Putting "$pdom" into QMAIL/control/plusdomain ... echo "$pdom" > QMAIL/control/plusdomain chmod 644 QMAIL/control/plusdomain ) ) @@ -34,7 +34,7 @@ ./dnsptr "$localip" 2>/dev/null | ( if read local then - echo Adding "$local" to control/locals... + echo Adding "$local" to QMAIL/control/locals... echo "$local" >> QMAIL/control/locals else echo PTR lookup failed. I assume this address has no DNS name. @@ -54,11 +54,11 @@ echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!' else echo Sorry, I couldn\'t find your host\'s canonical name in DNS. - echo You will have to set up control/me yourself. + echo You will have to set up QMAIL/control/me yourself. fi ) else echo Sorry, I couldn\'t find your hostname. - echo You will have to set up control/me yourself. + echo You will have to set up QMAIL/control/me yourself. fi ) --- qmail-1.03.orig/spawn.c +++ qmail-1.03/spawn.c @@ -5,6 +5,7 @@ #include "substdio.h" #include "byte.h" #include "str.h" +#include "alloc.h" #include "stralloc.h" #include "select.h" #include "exit.h" --- qmail-1.03.orig/home.sh +++ qmail-1.03/home.sh @@ -3,5 +3,5 @@ # Using splogger to send the log through syslog. # Using qmail-local to deliver messages to ~/Mailbox by default. -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start ./Mailbox splogger qmail --- qmail-1.03.orig/elq.sh +++ qmail-1.03/elq.sh @@ -1 +1 @@ -QMAIL/bin/maildir2mbox && exec elm ${1+"$@"} +/usr/bin/maildir2mbox && exec elm ${1+"$@"} --- qmail-1.03.orig/mailsubj.sh +++ qmail-1.03/mailsubj.sh @@ -4,4 +4,4 @@ echo To: ${1+"$@"} echo '' cat -) | QMAIL/bin/qmail-inject +) | /usr/sbin/qmail-inject --- qmail-1.03.orig/qmail-showctl.c +++ qmail-1.03/qmail-showctl.c @@ -214,7 +214,11 @@ _exit(111); } - do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM."); + do_lst("badhelo","Any HELO host name is allowed.",""," HELO host name denied if it matches this pattern."); + do_lst("badmailfrom","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern."); + do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set."); + do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern."); + do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set."); do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); do_str("bouncehost",1,"bouncehost","Bounce host name is "); do_int("concurrencylocal","10","Local concurrency is ",""); @@ -267,7 +271,11 @@ if (str_equal(d->d_name,"..")) continue; if (str_equal(d->d_name,"bouncefrom")) continue; if (str_equal(d->d_name,"bouncehost")) continue; + if (str_equal(d->d_name,"badhelo")) continue; if (str_equal(d->d_name,"badmailfrom")) continue; + if (str_equal(d->d_name,"badmailfromnorelay")) continue; + if (str_equal(d->d_name,"badmailto")) continue; + if (str_equal(d->d_name,"badmailtonorelay")) continue; if (str_equal(d->d_name,"bouncefrom")) continue; if (str_equal(d->d_name,"bouncehost")) continue; if (str_equal(d->d_name,"concurrencylocal")) continue; --- qmail-1.03.orig/binm2+df.sh +++ qmail-1.03/binm2+df.sh @@ -5,7 +5,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using SVR4 binmail interface: /bin/mail -r -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|dot-forward .forward |preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/qmail.c +++ qmail-1.03/qmail.c @@ -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; } --- qmail-1.03.orig/TARGETS +++ qmail-1.03/TARGETS @@ -252,6 +252,7 @@ qmail-qmtpd qmail-smtpd.o qmail-smtpd +qregex.o sendmail.o sendmail tcp-env.o --- qmail-1.03.orig/binm3+df.sh +++ qmail-1.03/binm3+df.sh @@ -5,7 +5,7 @@ # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using V7 binmail interface: /bin/mail -f -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|dot-forward .forward |preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail --- qmail-1.03.orig/install.c +++ qmail-1.03/install.c @@ -33,7 +33,9 @@ int gid; int mode; { - if (chdir(home) == -1) + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); + if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (mkdir(subdir,0700) == -1) if (errno != error_exist) @@ -51,6 +53,8 @@ int gid; int mode; { + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (fifo_make(fifo,0700) == -1) @@ -127,6 +131,8 @@ { int fdout; + if (fchdir(fdsourcedir) == -1) + strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); --- qmail-1.03.orig/sendmail.c +++ qmail-1.03/sendmail.c @@ -19,7 +19,7 @@ _exit(100); } -char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; +char *smtpdarg[] = { "/usr/sbin/qmail-smtpd", 0 }; void smtpd() { if (!env_get("PROTO")) { @@ -37,7 +37,7 @@ _exit(111); } -char *qreadarg[] = { "bin/qmail-qread", 0 }; +char *qreadarg[] = { "/usr/sbin/qmail-qread", 0 }; void mailq() { execv(*qreadarg,qreadarg); @@ -113,7 +113,7 @@ if (!qiargv) nomem(); arg = qiargv; - *arg++ = "bin/qmail-inject"; + *arg++ = "/usr/sbin/qmail-inject"; *arg++ = (flagh ? "-H" : "-a"); if (sender) { *arg++ = "-f"; --- qmail-1.03.orig/config-fast.sh +++ qmail-1.03/config-fast.sh @@ -1,29 +1,29 @@ fqdn="$1" echo Your fully qualified host name is "$fqdn". -echo Putting "$fqdn" into control/me... +echo Putting "$fqdn" into QMAIL/control/me... echo "$fqdn" > QMAIL/control/me chmod 644 QMAIL/control/me ( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | ( read ddom - echo Putting "$ddom" into control/defaultdomain... + echo Putting "$ddom" into QMAIL/control/defaultdomain... echo "$ddom" > QMAIL/control/defaultdomain chmod 644 QMAIL/control/defaultdomain ) ) ( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | ( read pdom - echo Putting "$pdom" into control/plusdomain... + echo Putting "$pdom" into QMAIL/control/plusdomain... echo "$pdom" > QMAIL/control/plusdomain chmod 644 QMAIL/control/plusdomain ) ) -echo Putting "$fqdn" into control/locals... +echo Putting "$fqdn" into QMAIL/control/locals... echo "$fqdn" >> QMAIL/control/locals chmod 644 QMAIL/control/locals -echo Putting "$fqdn" into control/rcpthosts... +echo Putting "$fqdn" into QMAIL/control/rcpthosts... echo "$fqdn" >> QMAIL/control/rcpthosts chmod 644 QMAIL/control/rcpthosts echo "Now qmail will refuse to accept SMTP messages except to $fqdn." --- qmail-1.03.orig/cdbmake_add.c +++ qmail-1.03/cdbmake_add.c @@ -1,3 +1,4 @@ +#include "alloc.h" #include "cdbmake.h" void cdbmake_init(cdbm) --- qmail-1.03.orig/debian/preinst +++ qmail-1.03/debian/preinst @@ -0,0 +1,268 @@ +#!/usr/bin/perl + +require 5.002; +use strict 'subs'; +use English; +use Debconf::Client::ConfModule ':all'; + +# do not print anything to STDOUT, as debconf will interpret it as a command. +# This is not an issue with preinst/postinst scripts written in shell, +# because their confmodule reshuffles their fds for them. The perl binding +# does not, so we have to refrain from using stdout ourselves. The same thing +# holds for any child commands we spawn: stderr is ok, but stdout is not. + +sub debug ($) { + my($msg) = @_; + print STDERR $msg; +} + +sub check_uid($$$$$$) { + my ($name, $uid, $gid, $gecos, $home, $shell) = @_; + my $ok = 1; + + debug("Checking user $name (uid $uid, gid $gid, homedir $home)... "); + @name_entry = getpwnam("$name"); + if ( @name_entry == () ) { + my @uid_entry = getpwuid($uid); + if ( @uid_entry == () ) { + system("adduser --system --no-create-home --quiet --home $home --gid $gid --uid $uid --gecos \'$gecos\' $name >/dev/null 2>&1"); + if ( $? != 0 ) { + debug("\n Error while adding user $name!\n"); + $ok = 0; + } + else { + debug("added.\n"); + } + system("chsh -s $shell $name >/dev/null"); + } + else { + debug("error!\n Uid $uid is being used by user $uid_entry[0]\n"); + $ok = 0; + } + } + else { + if ( $name_entry[3] != $gid ) { + debug("error!\n") if $ok; + debug(" User $name has primary group $name_entry[3] instead of $gid\n"); + $ok = 0; + } + if ( $name_entry[2] != $uid ) { + debug("error!\n") if $ok; + debug(" User $name has uid $name_entry[2] instead of $uid\n"); + $ok = 0; + } + if ( $name_entry[7] ne $home ) { + debug("error!\n") if $ok; + debug(" User $name has home directory $name_entry[7] instead of $home\n"); + $ok = 0; + } + if ( $ok ) { + debug("ok.\n"); + } + } + return $ok; +} + +sub check_gid($$@) { + my ($name, $gid, @members) = @_; + my $ok = 1; + + debug("Checking group $name (gid $gid)... "); + @name_entry = getgrnam($name); + if ( @name_entry == () ) { + my @gid_entry = getgrgid($gid); + if ( @gid_entry == () ) { + system("addgroup --quiet --gid $gid $name >/dev/null"); + if ( $? != 0 ) { + debug("\n Error while adding group $name\n"); + $ok = 0; + } + else { + debug("added.\n"); + } + } + else { + debug("error!\n Gid $gid is being used by group $gid_entry[0]\n"); + $ok = 0; + } + } + else { + if ( $name_entry[2] != $gid ) { + debug("error!\n Group $name has gid $name_entry[2] instead of $gid\n"); + $ok = 0; + } + if ( $ok ) { + debug("ok.\n"); + } + } + return $ok; +} + +sub is_qmail_installed { + my $qmail_installed = 0; + + debug("Checking if qmail is already installed on this computer... "); + + $qmail_home = ''; + if ( -d '/var/qmail' ) { + debug("\n Found /var/qmail directory"); + $qmail_home = '/var/qmail'; + $qmail_installed = 1; + } + else { + $qmail_home = `qmail-home`; + if ( $qmail_home ne '') { + debug("\n Found qmail home directory at $qmail_home (using qmail-home program)"); + $qmail_installed = 1; + } + } + + if ( -d '/var/spool/qmail' ) { + debug("\n Found qmail spool directory at /var/spool/qmail"); + $qmail_installed = 1; + } + if ( -d '/etc/qmail' ) { + debug("\n Found qmail control directory at /etc/qmail"); + $qmail_installed = 1; + } + + if ( (-r '/etc/inetd.conf') and `fgrep -q qmail-smtpd /etc/inetd.conf` ) { + debug("\n Found reference to qmail-smtpd in /etc/inetd.conf"); + $qmail_installed = 1; + } + if ( (-r '/etc/xinetd.conf') and `fgrep -q qmail-smtpd /etc/xinetd.conf` ) { + debug("\n Found reference to qmail-smtpd in /etc/xinetd.conf"); + $qmail_installed = 1; + } + + if ( -x '/etc/init.d/qmail' ) { + debug("\n Found /etc/init.d/qmail script"); + $qmail_installed = 1; + } + elsif ( `fgrep -q qmail-start /etc/init.d/*` ) { + debug("\n Found reference to qmail-start in /etc/init.d directory"); + $qmail_installed = 1; + } + if ( -x '/etc/rc.local' and `fgrep -q qmail-start /etc/rc.local` ) { + debug("\n Found reference to qmail-start in /etc/rc.local"); + $qmail_installed = 1; + } + + if ( `killall -0 qmail-send >/dev/null 2>&1` ) { + debug("\n Found qmail-send process running"); + $qmail_installed = 1; + } + + if ( $qmail_installed == 1) { + debug("yes.\nPre-existing qmail installation detected. Override? [yN] "); + $answer = ; + chop $answer; + + if ($answer =~ /[yY]/ ) { + debug("Overriding. Qmail is not installed.\n"); + $qmail_installed = 0; + } else { + debug("Not overriding. Qmail is installed.\n"); + $qmail_installed = 1; + } + + } else { + debug("no."); + } + + debug("\n"); + return $qmail_installed; +} + + +$| = 1; + +$action = shift; +debug("Performing $action\n"); + +if ( $action eq 'install' ) { + $old_version = shift; + if ( ! defined $old_version || $old_version eq '' ) { + debug("First installation of the Debian qmail package...\n"); + # Check if a non-Debian qmail is installed... + if ( is_qmail_installed() ) { + debug("Please remove your copy of qmail before installing the qmail Debian package.\n\n"); + exit 1; + } + # Check for qmail uids and gids + my $errors; + + $errors++ unless check_gid('qmail', 64010, ()); + #$errors++ unless check_gid('nogroup', 65534, ()); + + $errors++ unless check_uid('alias', 64010, 65534, 'qmail alias', '/var/qmail/alias', '/bin/sh'); + $errors++ unless check_uid('qmaild', 64011, 65534, 'qmail daemon', '/var/qmail', '/bin/sh'); + $errors++ unless check_uid('qmails', 64012, 64010, 'qmail send', '/var/qmail', '/bin/sh'); + $errors++ unless check_uid('qmailr', 64013, 64010, 'qmail remote', '/var/qmail', '/bin/sh'); + $errors++ unless check_uid('qmailq', 64014, 64010, 'qmail queue', '/var/qmail', '/bin/sh'); + $errors++ unless check_uid('qmaill', 64015, 65534, 'qmail log', '/var/qmail', '/bin/sh'); + $errors++ unless check_uid('qmailp', 64016, 65534, 'qmail pw', '/var/qmail', '/bin/sh'); + #$errors++ unless check_uid('nobody', 65534, 65534, 'nobody', '/tmp', '/bin/sh'); + + if ( $errors ) { + debug("\n$errors entries have errors. Please correct these errors and reinstall qmail.\n"); + exit 2; + } + } + + # Make sure there are no smtp entries in /etc/inetd.conf + # Kludge around smail buggy /etc/inetd.conf handling. (Grr.) + my $fixed_smail = 0; + my $found_commented = 0; + my $found_uncommented = 0; + my $new_inetd = "/etc/inetd.conf.qmail-preinst.$$"; + open I, '$new_inetd" or die "Could not create $new_inetd\n"; + while () { + if ( m|^\# *smtp\s+.*/usr/sbin/in.smtpd.*\(will be restored by smail postinst\)\s*$| ) { + $fixed_smail = 1; + next; + } elsif ( m/^\# *smtp\s+/ ) { + $found_commented= 1; + } elsif ( m/^smtp\s+/ ) { + $found_uncommented= 1; + } + print N or die "Cannot write to $new_inetd\n"; + } + close N or die "Could not close $new_inetd\n"; + close I or die "Could not close /etc/inetd.conf\n"; + if ( $found_commented or $found_uncommented ) { + debug("Your /etc/inetd.conf already containts entries for the SMTP service.\n"); + debug("Please remove all SMTP entries from /etc/inetd.conf (even those commented out)\n"); + debug("and reinstall the qmail package.\n\n"); + exit 1; + } + if ( $fixed_smail ) { + debug("Removing commented smtp entry left by buggy version of smail postinst... "); + rename "$new_inetd", '/etc/inetd.conf' or die "failed!\n"; + debug("done.\n"); + } +} elsif ($action eq 'upgrade') { + $old_version = shift; + if ($old_version =~ /1.03/ ) { + debug("You are upgrading from version 1.03 \n"); + debug("Checking control files ... \n"); + if (-l "/var/qmail/control") { + debug("Control files installed in /etc/qmail\n"); + } else { + debug("Control files installed in /var/qmail/control \n"); + debug("Moving control files from /var/qmail/control to /etc/qmail \n"); + `tar -cSpf - -C /var/qmail/control . | tar -xvSpf - -C /etc/qmail && rm -rf /var/qmail/control`; + } + debug("Checking alias files location ... \n"); + if (-d "/usr/lib/qmail/alias") { + debug("Alias files found in /usr/lib/qmail ... moving ...\n"); + debug("Copying /usr/lib/qmail/alias to /var/lib/qmail/alias \n"); + `tar -cSpf - -C /usr/lib/qmail/alias/ . | tar -xvSpf - -C /var/lib/qmail/alias`; + debug("I have left the files in /usr/lib/qmail/alias.\n"); + debug("You can remove them to free up space.\n"); + } + } +} + +exit 0; --- qmail-1.03.orig/debian/substvars +++ qmail-1.03/debian/substvars @@ -0,0 +1 @@ +shlibs:Depends=libc6 (>= 2.3.4-1) --- qmail-1.03.orig/debian/qmail-procmail +++ qmail-1.03/debian/qmail-procmail @@ -0,0 +1,10 @@ +#!/bin/sh + +/usr/bin/preline /usr/bin/procmail "$@" && exit 0 + +# check if procmail returned EX_TEMPFAIL (75) +[ $? = 75 ] && exit 111 + +# otherwise return a permanent error +exit 100 + --- qmail-1.03.orig/debian/prerm +++ qmail-1.03/debian/prerm @@ -0,0 +1,57 @@ +#!/usr/bin/perl + +$hassmtpininetd = 0; +if ( -e "/etc/inetd.conf" ) { + system('grep "^ *[^#].*\" /etc/inetd.conf'); + if ( ! $? ) { + $hassmtpininetd = 1; + } +} + +require DebianNet if ( $hassmtpininetd ); + +$| = 1; + +$action = shift; + +if ( $action eq 'failed-upgrade' ) { + exit 1; +} + +if ( $action eq 'upgrade' or $action eq 'deconfigure' ) { + system("/etc/init.d/qmail stop"); + exit $? if $?; + DebianNet::disable_service('smtp') if ( $hassmtpininetd ); + exit 0; +} + +if ( $action eq 'remove' ) { + # Ask for confirmation if there are still messages in qmail's queue. + $mesg_inqueue = `find /var/qmail/queue/mess -type f -print | wc -l`; + $mesg_inqueue =~ s/\s//g; + $mesg_unprocessed = `find /var/qmail/queue/todo -type f -print | wc -l`; + $mesg_unprocessed =~ s/\s//g; + + if ( $mesg_inqueue != 0 || $mesg_unprocessed != 0 ) { + print STDERR <; + exit 1 unless $answer =~ /^\s*[yY]/; + } + + # Remove qmail-smtpd from inetd.conf + DebianNet::remove_service('smtp\s+stream\s+tcp\s+nowait\s+qmaild.*/usr/sbin/qmail-smtpd') if ( $hassmtpininetd );; + + # Stop qmail process. + system("/etc/init.d/qmail stop"); + exit $? if $?; +} + +exit 0; --- qmail-1.03.orig/debian/src.prerm +++ qmail-1.03/debian/src.prerm @@ -0,0 +1,7 @@ +#!/bin/sh -e +# Automatically added by dh_installdocs +if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/qmail-src ]; then + rm -f /usr/doc/qmail-src +fi +# End automatically added section + --- qmail-1.03.orig/debian/logcheck +++ qmail-1.03/debian/logcheck @@ -0,0 +1,6 @@ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ status: local [0-9]+\/[0-9]+ remote [0-9]+\/[0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ (new|end) msg [0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ info msg [0-9]+: bytes [0-9]+ from .* qp [0-9]+ uid [0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ starting delivery [0-9]+: msg [0-9]+ to local [^[:space:]]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ starting delivery [0-9]+: msg [0-9]+ to remote [^[:space:]]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ qmail: [0-9\.]+ delivery [0-9]+: success: --- qmail-1.03.orig/debian/assign +++ qmail-1.03/debian/assign @@ -0,0 +1,16 @@ +=root:alias:64010:65534:/var/qmail/alias:-:postmaster: +=abuse:alias:64010:65534:/var/qmail/alias:-:postmaster: +=operator:alias:64010:65534:/var/qmail/alias:-:postmaster: +=uucp:alias:64010:65534:/var/qmail/alias:-:postmaster: +=anonymous:alias:64010:65534:/var/qmail/alias:-:postmaster: +=backup-reports:alias:64010:65534:/var/qmail/alias:-:postmaster: +=bbsadmin:alias:64010:65534:/var/qmail/alias:-:postmaster: +=dumper:alias:64010:65534:/var/qmail/alias:-:postmaster: +=hostmaster:alias:64010:65534:/var/qmail/alias:-:postmaster: +=listmaster:alias:64010:65534:/var/qmail/alias:-:postmaster: +=mailer-daemon:alias:64010:65534:/var/qmail/alias:-:postmaster: +=manager:alias:64010:65534:/var/qmail/alias:-:postmaster: +=orphanage:alias:64010:65534:/var/qmail/alias:-:postmaster: +=warnings:alias:64010:65534:/var/qmail/alias:-:postmaster: +=webmaster:alias:64010:65534:/var/qmail/alias:-:postmaster: +. --- qmail-1.03.orig/debian/conffiles +++ qmail-1.03/debian/conffiles @@ -0,0 +1,4 @@ +/etc/init.d/qmail +/etc/qmail/users/assign +/etc/tcp.smtp +/etc/qmail/rcpthosts --- qmail-1.03.orig/debian/rules-ok +++ qmail-1.03/debian/rules-ok @@ -0,0 +1,111 @@ +#!/usr/bin/make -f +# + +PKG_VER = `perl -e 'print <> =~ /\((.*)\)/' debian/changelog` +PKG_UPVER = `perl -e 'print <> =~ /\((.*)-[^-]*\)/' debian/changelog` + +build: + $(checkdir) + if fgrep QMAIL/bin *.sh >/dev/null; then \ + echo >&2 "You must run debian/debianize-source-tree first!"; \ + exit 1; \ + fi + $(MAKE) man + $(MAKE) + touch build + +clean: + $(checkdir) + -rm -f build + -$(MAKE) clean + -rm `find . -name "*~"` + -rm -rf debian/files + -rm -rf `find debian/* -type d -prune` + +binary-indep: checkroot build + $(checkdir) + +binary-arch: checkroot build + $(checkdir) + -rm -rf debian/files debian/substvars debian/tmp + -rm -rf `find debian/* -type d -prune` +# Make the directory tree and copy qmail files. + install -d debian/tmp/etc/init.d \ + debian/tmp/usr/doc \ + debian/tmp/var/qmail \ + debian/tmp/var/qmail/users \ + debian/tmp/var/spool \ + debian/tmp/usr/bin \ + debian/tmp/usr/sbin \ + debian/tmp/usr/lib \ + debian/tmp/usr/lib/qmail \ + debian/qmail-src/usr/bin \ + debian/qmail-src/usr/src/qmail-src \ + debian/qmail-src/usr/doc/qmail-src + ./qmail-hier | ./install debian/tmp/var/qmail + mv debian/tmp/var/qmail/queue debian/tmp/var/spool/qmail + mv debian/tmp/var/qmail/control debian/tmp/etc/qmail + (cd debian/tmp/var/qmail && ln -s /var/spool/qmail queue) + (cd debian/tmp/var/qmail && ln -s /etc/qmail control) + (cd debian/tmp/var/qmail && ln -s /usr/doc/qmail doc) + mv debian/tmp/var/qmail/man debian/tmp/usr/man && \ + rm -r debian/tmp/usr/man/cat? +# Move /var/qmail/bin programs to either /usr/bin or /usr/sbin + bash debian/debianize-binary-tree +# Create /usr/lib/sendmail symlink for backward compatibility. + ln -s ../sbin/sendmail debian/tmp/usr/lib/sendmail +# Copy qmailconfig and its helper programs... + install -o root -g root -m 755 dnsfq debian/tmp/usr/lib/qmail/qmailconfig-dnsfq + install -o root -g root -m 755 dnsip debian/tmp/usr/lib/qmail/qmailconfig-dnsip + install -o root -g root -m 755 ipmeprint debian/tmp/usr/lib/qmail/qmailconfig-ipmeprint + install -o root -g root -m 755 dnsptr debian/tmp/usr/lib/qmail/qmailconfig-dnsptr +# install qmail-procmail script + install -o root -g root -m 755 debian/qmail-procmail debian/tmp/usr/sbin/qmail-procmail +# install newaliases script + install -o root -g root -m 755 debian/newaliases debian/tmp/usr/bin/newaliases +# install eliminate-dups script + install -o root -g root -m 755 debian/eliminate-dups debian/tmp/usr/lib/qmail/eliminate-dups +# install default users/assign + install -o root -g root -m 644 debian/users-assign debian/tmp/var/qmail/users/assign +# (This one is a bit of a kludge...) + sed -e 's|./hostname|hostname|g' \ + -e 's|\./dnsptr|/usr/lib/qmail/qmailconfig-dnsptr|g' \ + -e 's|\./dnsip|/usr/lib/qmail/qmailconfig-dnsip|g' \ + -e 's|\./dnsfq|/usr/lib/qmail/qmailconfig-dnsfq|g' \ + -e 's|\./ipmeprint|/usr/lib/qmail/qmailconfig-ipmeprint|g' \ + qmail-config >debian/tmp/usr/lib/qmail/qmailconfig + chmod 755 debian/tmp/usr/lib/qmail/qmailconfig +# Install /etc/init.d/qmail + install -o root -g root -m 755 debian/qmail debian/tmp/etc/init.d/qmail +# Copy /usr/doc/qmail files. + install -o root -g root -m 644 debian/changelog debian/tmp/usr/doc/qmail/changelog.Debian +# do the stuff for qmail-src + cp ../qmail_$(PKG_UPVER).orig.tar.gz ../qmail_$(PKG_VER).diff.gz \ + ../qmail_$(PKG_VER).dsc debian/qmail-src/usr/src/qmail-src + install -m 755 debian/build-qmail debian/qmail-src/usr/bin + install debian/copyright debian/qmail-src/usr/doc/qmail-src + install debian/qmail-src.README debian/qmail-src/usr/doc/qmail-src/README + debstd -m CHANGES BLURB* FAQ INTERNALS README RFC* \ + SECURITY INSTALL.* SYSDEPS THANKS THOUGHTS TODO +# Correct permissions of binaries and manpages... + chmod go+rx debian/tmp/usr/*bin/* + chown -R root.root debian/tmp/usr/man + + dpkg-gencontrol -pqmail +# And finally, build the Debian package! + dpkg --build debian/tmp .. + +define checkdir + test -f qmail-send.c -a -f debian/rules +endef + +binary: binary-indep + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +checkroot: + $(checkdir) + test "`whoami`" = root + +.PHONY: binary binary-arch binary-indep clean checkroot --- qmail-1.03.orig/debian/rules +++ qmail-1.03/debian/rules @@ -0,0 +1,213 @@ +#!/usr/bin/make -f +# +# Copyright (C) 1998 Software in the Public Interest + +PACKAGE = $(shell perl -e 'print <> =~ /(\S*)\s/' debian/changelog) +PKG_VER = $(shell perl -e 'print <> =~ /\((.*)\)/' debian/changelog) +PKG_UPVER = $(shell perl -e 'print <> =~ /\((.*)-[^-]*\)/' debian/changelog) +INSTALL = '/usr/bin/install' + +build: binary-src + touch build + +buildbinary: checkdir + if fgrep QMAIL/bin *.sh >/dev/null; then \ + echo >&2 "You must run debian/debianize-source-tree first!"; \ + exit 1; \ + fi + $(MAKE) -C contrib/checkpassword-0.90/ + $(MAKE) man + $(MAKE) + # check that the local user ID's match the standard ones + # This has been removed. This is because I have been forced to + # change the qmail uid's & gid's + #@diff -u debian/debian-default_uids.c auto_uids.c || ( echo -e "\nError:\n Your system has user/group ids that differ from the debian default.\n Please rectify this. The easiest way to do this is normally to cut&paste\n the qmail sections from /etc/passwd.dpkg-dist and /etc/group.dpkg-dist,\n into /etc/passwd and /etc/group respectively (relpacing the old values).\n" ; exit 1 ) + touch buildbinary + +clean: checkdir + -rm -f build + -$(MAKE) clean + -$(MAKE) clean -C contrib/checkpassword-0.90/ + -rm `find . -name "*~"` + -rm -rf debian/files* + -rm -rf `find debian/* -type d -prune` + find . \( -name '#*#' -o -name '*~' -o -name DEADJOE -o -name '*.orig' -o -name '*.rej' -o -name '*.bak' -o -name '.*.orig' -o -name '.*.rej' -o -name .SUMS -o -name TAGS -o -name core \) -exec rm -f {} \; + +binary-indep: checkroot build + #nothing to be done + +binary-arch: checkroot buildbinary + -rm -rf debian/substvars debian/tmp +# Make the directory tree and copy qmail files. + $(INSTALL) -d debian/tmp/DEBIAN \ + debian/tmp/etc/init.d \ + debian/tmp/usr/share/doc/qmail \ + debian/tmp/usr/share/doc/qmail/examples \ + debian/tmp/var/qmail \ + debian/tmp/etc/qmail \ + debian/tmp/var/spool \ + debian/tmp/var/lib \ + debian/tmp/var/lib/qmail \ + debian/tmp/usr/bin \ + debian/tmp/usr/sbin \ + debian/tmp/usr/lib \ + debian/tmp/usr/lib/qmail + #./qmail-hier | ./install debian/tmp/var/qmail + ./auto-str auto_qmail debian/tmp/var/qmail > auto_qmail.c + rm -f install + $(MAKE) install + ./install + mv debian/tmp/var/qmail/queue debian/tmp/var/spool/qmail + #mv debian/tmp/var/qmail/control/* debian/tmp/etc/qmail + mv debian/tmp/var/qmail/alias debian/tmp/var/lib/qmail + mv debian/tmp/var/qmail/users debian/tmp/etc/qmail + echo localhost > debian/tmp/etc/qmail/rcpthosts + mv debian/tmp/var/qmail/doc/* debian/tmp/usr/share/doc/qmail + mv debian/tmp/var/qmail/boot debian/tmp/usr/share/doc/qmail/examples + rmdir debian/tmp/var/qmail/doc + rmdir debian/tmp/var/qmail/control + (cd debian/tmp/var/qmail && ln -s /var/spool/qmail queue) + (cd debian/tmp/var/qmail && ln -s /etc/qmail control) + (cd debian/tmp/var/qmail && ln -s /usr/share/doc/qmail doc) + (cd debian/tmp/var/qmail && ln -s /usr/share/doc/qmail/examples/boot boot) + (cd debian/tmp/var/qmail && ln -s /var/lib/qmail/alias alias) + (cd debian/tmp/var/qmail && ln -s /etc/qmail/users users) + mv debian/tmp/var/qmail/man debian/tmp/usr/man && \ + rm -r debian/tmp/usr/man/cat? +# Move /var/qmail/bin programs to either /usr/bin or /usr/sbin + bash debian/debianize-binary-tree +# Install checkpassword in /usr/bin + $(INSTALL) -o root -g root -m 755 contrib/checkpassword-0.90/checkpassword debian/tmp/usr/bin +# Install checkpassword manpage + $(INSTALL) -o root -g root -m 644 contrib/checkpassword-0.90/checkpassword.8 debian/tmp/usr/man/man8 +# Install mbox2maildir in /usr/bin + $(INSTALL) -o root -g root -m 755 contrib/mbox2maildir/mbox2maildir debian/tmp/usr/bin +# Create /usr/lib/sendmail symlink for backward compatibility. + ln -s ../sbin/sendmail debian/tmp/usr/lib/sendmail +# Copy qmailconfig and its helper programs... + $(INSTALL) -o root -g root -m 755 dnsfq debian/tmp/usr/lib/qmail/qmailconfig-dnsfq + $(INSTALL) -o root -g root -m 755 dnsip debian/tmp/usr/lib/qmail/qmailconfig-dnsip + $(INSTALL) -o root -g root -m 755 ipmeprint debian/tmp/usr/lib/qmail/qmailconfig-ipmeprint + $(INSTALL) -o root -g root -m 755 dnsptr debian/tmp/usr/lib/qmail/qmailconfig-dnsptr +# install qmail-procmail script + $(INSTALL) -o root -g root -m 755 debian/qmail-procmail debian/tmp/usr/sbin/qmail-procmail +# install newaliases script + $(INSTALL) -o root -g root -m 755 debian/newaliases debian/tmp/usr/bin/newaliases +# install eliminate-dups script + $(INSTALL) -o root -g root -m 755 debian/eliminate-dups debian/tmp/usr/lib/qmail/eliminate-dups +# install default users/assign + $(INSTALL) -o root -g root -m 644 debian/assign debian/tmp/etc/qmail/users +# (This one is a bit of a kludge...) + sed -e 's|./hostname|hostname|g' \ + -e 's|\./dnsptr|/usr/lib/qmail/qmailconfig-dnsptr|g' \ + -e 's|\./dnsip|/usr/lib/qmail/qmailconfig-dnsip|g' \ + -e 's|\./dnsfq|/usr/lib/qmail/qmailconfig-dnsfq|g' \ + -e 's|\./ipmeprint|/usr/lib/qmail/qmailconfig-ipmeprint|g' \ + config >debian/tmp/usr/lib/qmail/qmailconfig + chmod 755 debian/tmp/usr/lib/qmail/qmailconfig +# Install /etc/init.d/qmail + $(INSTALL) -o root -g root -m 755 debian/init.d debian/tmp/etc/init.d/qmail +# install tcpserver conf file + $(INSTALL) -o root -g root -m 644 debian/tcp.smtp debian/tmp/etc + +# Copy /usr/share/doc/qmail files. + $(INSTALL) -o root -g root -m 644 debian/changelog debian/tmp/usr/share/doc/qmail/changelog.Debian + $(INSTALL) -m 644 -p BLURB* FAQ INTERNALS README* PIC.* \ + SECURITY SENDMAIL SYSDEPS THANKS THOUGHTS TODO UPGRADE \ + BIN* REMOVE* TEST* VERSION CHANGES \ + debian/tmp/usr/share/doc/qmail/ + $(INSTALL) -m 644 -p debian/README.debian debian/tmp/usr/share/doc/qmail/README.Debian + $(INSTALL) -m 644 -p debian/TODO debian/tmp/usr/share/doc/qmail/TODO.Debian + + $(INSTALL) -m 644 -p debian/ip-up.d debian/tmp/usr/share/doc/qmail/examples/ip-up.d + $(INSTALL) -m 644 -p debian/logcheck debian/tmp/usr/share/doc/qmail/examples/logcheck.ignore + + $(INSTALL) -p -m644 debian/changelog debian/tmp/usr/share/doc/qmail/changelog.Debian + $(INSTALL) -p -m644 CHANGES debian/tmp/usr/share/doc/qmail/changelog + -strip --remove-section=comment --remove-section=note \ + debian/tmp/usr/bin/* debian/tmp/usr/sbin/* \ + debian/tmp/usr/lib/* 2>/dev/null + -gzip -fr debian/tmp/usr/share/doc/ debian/tmp/usr/man/ + $(INSTALL) -m 644 -p debian/copyright debian/tmp/usr/share/doc/qmail/copyright +# Correct permissions of binaries and manpages... + chmod go+rx debian/tmp/usr/*bin/* + chown -R root.root debian/tmp/usr/man + $(INSTALL) -p -m755 debian/postinst debian/preinst \ + debian/prerm debian/postrm debian/tmp/DEBIAN + $(INSTALL) -o root -g root -m 644 -p debian/conffiles debian/tmp/DEBIAN/conffiles + + # Install debconf stuff + cp debian/qmail.config debian/tmp/DEBIAN/config + cp debian/qmail.templates debian/tmp/DEBIAN/templates + chmod 755 debian/tmp/DEBIAN/config debian/tmp/DEBIAN/templates + chmod u+x debian/*config + + ## Install logcheck files + #$(INSTALL) -o root -g root -d debian/tmp/etc/logcheck/ignore.d.server + #$(INSTALL) -m 600 debian/logcheck debian/tmp/etc/logcheck/ignore.d.server/qmail + + (cd debian/tmp/var/qmail && ln -s /usr/sbin bin) + dpkg-shlibdeps -Tdebian/substvars debian/tmp/usr/lib/qmail/* debian/tmp/usr/sbin/* debian/tmp/usr/bin/* + dpkg-gencontrol -isp -pqmail -cdebian/control.real +# And finally, build the Debian package! + dpkg --build debian/tmp .. + +# -- here are the bits for the -src package +TMPSRC = debian/tmp-src + +binary-src: checkdir debian/control \ +../$(PACKAGE)_$(PKG_UPVER).orig.tar.gz \ +../$(PACKAGE)_$(PKG_VER).dsc ../$(PACKAGE)_$(PKG_VER).diff.gz + -rm -rf $(TMPSRC) debian/files + + $(INSTALL) -d $(TMPSRC)/DEBIAN \ + $(TMPSRC)/usr/bin \ + $(TMPSRC)/usr/src/$(PACKAGE)-src \ + $(TMPSRC)/usr/share/doc/$(PACKAGE)-src + $(INSTALL) -m 755 debian/build-PACKAGE $(TMPSRC)/usr/bin/build-$(PACKAGE) + $(INSTALL) -m 0644 ../$(PACKAGE)_$(PKG_UPVER).orig.tar.gz \ + ../$(PACKAGE)_$(PKG_VER).dsc \ + ../$(PACKAGE)_$(PKG_VER).diff.gz \ + $(TMPSRC)/usr/src/$(PACKAGE)-src/ + sed -e "s/#PACKAGE#/$(PACKAGE)/" debian/src.postinst > $(TMPSRC)/DEBIAN/postinst + chmod 755 $(TMPSRC)/DEBIAN/postinst + sed -e "s/#PACKAGE#/$(PACKAGE)/" debian/src.prerm > $(TMPSRC)/DEBIAN/prerm + chmod 755 $(TMPSRC)/DEBIAN/prerm + cp debian/src.postrm $(TMPSRC)/DEBIAN/postrm + chmod 755 $(TMPSRC)/DEBIAN/postrm + + sed -e "s/#PACKAGE#/$(PACKAGE)/" debian/README-src > $(TMPSRC)/usr/share/doc/$(PACKAGE)-src/README.Debian + $(INSTALL) -m 0644 debian/changelog $(TMPSRC)/usr/share/doc/$(PACKAGE)-src/changelog.Debian + chmod 644 $(TMPSRC)/usr/share/doc/$(PACKAGE)-src/changelog.Debian + gzip -9fr $(TMPSRC)/usr/share/doc/ + $(INSTALL) -m 0644 debian/copyright $(TMPSRC)/usr/share/doc/$(PACKAGE)-src/ + # Install debconf files + #cp debian/qmail-src.config $(TMPSRC)/DEBIAN/config + #cp debian/qmail-src.templates $(TMPSRC)/DEBIAN/templates + + dpkg-gencontrol -isp -p$(PACKAGE)-src -P$(TMPSRC) + fakeroot chown -R root.root $(TMPSRC) + dpkg --build $(TMPSRC) .. + +debian/control: debian/control.real + test -f debian/control.real && sed -e "/^Package: $(PACKAGE)-src$$/b" -e "/^Package: /,/^$$/d" debian/control.real > debian/control + +../$(PACKAGE)_$(PKG_UPVER).orig.tar.gz: + @{ echo "Error: $@ missing"; exit 1; } + +../$(PACKAGE)_$(PKG_VER).dsc ../$(PACKAGE)_$(PKG_VER).diff.gz: debian/rules + debian/rules clean + cd ..; dpkg-source -b $(PACKAGE)-$(PKG_UPVER) + +binary: binary-src + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +checkdir: + @test -f qmail.c -a -f debian/rules + +checkroot: checkdir + test "`whoami`" = root + +.PHONY: binary binary-arch binary-indep clean checkroot --- qmail-1.03.orig/debian/debianize-binary-tree +++ qmail-1.03/debian/debianize-binary-tree @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e + +function startofpath() { + if [ -f usr/man/man8/`basename $1`.8 ]; then + echo usr/sbin + elif [ -f usr/man/man1/`basename $1`.1 ]; then + echo usr/bin + else + case `basename $1` in + elq|pinq|qail|qlist2) echo usr/bin;; + datemail|predate|qmail-home|qsmhook|sendmail) echo usr/sbin;; + *) echo 1>&2 Cannot determine if $1 belongs in sbin or bin;exit 2;; + esac + fi +} + +test -d debian/tmp || (echo "Could not find debian/tmp directory.";exit 1) + +cd debian/tmp + +for f in var/qmail/bin/*; do + mv $f `startofpath $f` +done + +rmdir var/qmail/bin || ( echo "Could not remove qmail/bin directory!"; exit 3) --- qmail-1.03.orig/debian/build-PACKAGE +++ qmail-1.03/debian/build-PACKAGE @@ -0,0 +1,217 @@ +#!/bin/bash -e +# +# build- +# +# $Id: build-PACKAGE,v 1.5 1998/05/01 08:35:36 phil Exp $ +# +# Written by Philip Hands +# Copyright (C) 1998 Free Software Foundation, Inc. +# Copying: GPL + +# ask_user --- function prompts the user with y/n style prompt +# +# It's behaviour is controlled via the parameters: +# 1 - the initial prompt +# 2 - default return value (set to 0, 1 or "none") +# 3 - the patern match for acceptable Yes responses +# 4 - the patern match for acceptable No responses +# 5 - the error prompt, displayed when the user fails to provide valid input +# +# e.g. ask_user "Foo, or Bar [fb] " none '[fF]*' '[bB]*' "try again" + +ask_user() { + P=${1:-'Should I do this ? [yN] '} + D=${2:-1} + Y=${3:-'[yY]*'} + N=${4:-'[nN]*'} + E=${5:-'\nPlease enter either y)es or n)o, followed by \n'} + + while true ; do + echo -ne "$P" + read response + case "$response" in + ${Y} ) return 0 ;; + ${N} ) return 1 ;; + "" ) [ "$D" = 0 -o "$D" = 1 ] && return $D ;; + esac + echo -e $E + done +} + +package=${0##*build-} +NEWDIR=/tmp/$package + +cat </dev/null && HAVE_FAKEROOT=fakeroot || HAVE_FAKEROOT="" + hash sudo 2>/dev/null && HAVE_SUDO=sudo || HAVE_SUDO="" + if [ -n "$HAVE_FAKEROOT" -a -n "$HAVE_SUDO" ] + then + echo "" + if ask_user "Should I use sudo or fakeroot to build the package ? [sF] " 1 '[sS]*' '[fF]*' "\nPlease enter either s)udo or f)akeroot, followed by \n" + then + BUILDROOT=sudo + else + BUILDROOT=fakeroot + fi + elif [ -n "$HAVE_FAKEROOT" -o -n "$HAVE_SUDO" ] + then + BUILDROOT="${HAVE_FAKEROOT:-$HAVE_SUDO}" + else + # sanity check, dependencies should provide one of them + echo "" + echo 'oops! you have not installed fakeroot or sudo!' + echo "" + exit 1 + fi + + if [ -n "$HAVE_SUDO" ] + then + cat< --- qmail-1.03.orig/debian/qmail-checkmail +++ qmail-1.03/debian/qmail-checkmail @@ -0,0 +1,30 @@ +#!/bin/sh + +# Copyright (c) 1998 Software in the Public Interest +# written by Philip Hands (2 April 1998), inspired by a +# script by Timothy L. Mayo , distributed under the GPL + +EMPTY="d41d8cd98f00b204e9800998ecf8427e" +SUM="md5sum" +# if you don't have md5sum, use something like these two lines instead +# EMPTY="00000 0" +# SUM="sum -r" + +MAILSUM="`ls $HOME/Maildir/new | $SUM`" + +# if "new" is empty, remove the debris, and exit +if [ "$MAILSUM" = "$EMPTY" ]; then + test -f $HOME/.prevmail && rm $HOME/.prevmail + exit 2 +fi + +# check if the sums are unchanged +if [ -f $HOME/.prevmail ] && [ "$MAILSUM" = "`cat $HOME/.prevmail`" ]; then + exit 1 +fi + +# otherwise new mail has arrived +echo -n $MAILSUM > $HOME/.prevmail +exit 0 + +# End of Script --- qmail-1.03.orig/debian/tcp.smtp +++ qmail-1.03/debian/tcp.smtp @@ -0,0 +1 @@ +127.0.0.1:allow,RELAYCLIENT="" --- qmail-1.03.orig/debian/newaliases +++ qmail-1.03/debian/newaliases @@ -0,0 +1,14 @@ +#!/bin/sh + +cat < --- qmail-1.03.orig/debian/smtplog +++ qmail-1.03/debian/smtplog @@ -0,0 +1,4 @@ +#!/bin/sh + +env|egrep -e "(BOUNCEMAIL|TCPREMOTEIP)" >&2 +exec "$@" --- qmail-1.03.orig/debian/init.d +++ qmail-1.03/debian/init.d @@ -0,0 +1,132 @@ +#!/bin/bash +# +# /etc/init.d/qmail : start or stop the qmail mail subsystem. +# +# Written by Christian Hudon +# Currently maintained by Jon Marler +# +# Configuration +# + + +# set default delivery method + +alias_empty="|/usr/sbin/qmail-procmail" # procmail delivery to /var/spool/mail +#alias_empty="./Maildir/" # This uses qmail prefered ~/Maildir/ directory + # You may want to maildirmake /etc/skel/Maildir +#alias_empty="./Mailbox" # This uses Mailbox file in users $HOME + +logger="splogger qmail 2" # facility mail == 2 +#logger="|accustamp >>/var/log/qmail.log" # If you have accustamp installed. +#logger=">>/var/log/qmail.log" # Does not give timing info. + +# If you uncommented one of the lines that appends to /var/log/qmail.log, you +# need to uncomment the following two lines. +#touch /var/log/qmail.log +#chown qmaill /var/log/qmail.log + +# If you want to use one or more of the Relay Black Lists, uncomment +# the appropriate lines. + +rblmsg= +rblsmtpd= +#rblmsg=" (with rblsmtpd)" +#rblsmtpd="/usr/bin/rblsmtpd -r list.dsbl.org -r relays.ordb.org" + +# +# End of configuration +# + +test -x /usr/sbin/qmail-start || exit 0 +test -x /usr/sbin/qmail-send || exit 0 + +case "$1" in + start) + echo -n "Starting mail-transfer agent: qmail" $rblmsg + sh -c "start-stop-daemon --start --quiet --user qmails \ + --exec /usr/sbin/qmail-send \ + --startas /usr/sbin/qmail-start -- \"$alias_empty\" $logger &" + # prevent denial-of-service attacks, with ulimit + ulimit -v 16384 + sh -c "start-stop-daemon --start --quiet --user qmaild \ + --pidfile /var/run/tcpserver_smtpd.pid --make-pidfile \ + --exec /usr/bin/tcpserver -- -R -H \ + -u `id -u qmaild` -g `id -g nobody` -x /etc/tcp.smtp.cdb 0 smtp \ + $rblsmtpd /usr/sbin/qmail-smtpd 2>&1 \ + | $logger &" + + # Uncomment the following lines to automatically start the pop3 server + #sh -c "start-stop-daemon --start --quiet --user root \ + # --pidfile /var/run/tcpserver_pop3d.pid --make-pidfile \ + # --exec /usr/bin/tcpserver -- -R -H \ + # 0 pop-3 /usr/sbin/qmail-popup `hostname`.`dnsdomainname` \ + # /usr/bin/checkpassword /usr/sbin/qmail-pop3d Maildir &" + + echo "." + ;; + stop) + echo -n "Stopping mail-transfer agent: qmail" $rblmsg + if [ "`pidof /usr/sbin/qmail-send`" ] ; then + start-stop-daemon --user qmails --stop --quiet --oknodo --exec /usr/sbin/qmail-send + start-stop-daemon --user qmaild --stop --quiet --oknodo --pidfile /var/run/tcpserver_smtpd.pid --exec /usr/bin/tcpserver + # Uncomment the following line if you have enabled the pop3 server + #start-stop-daemon --user root --stop --quiet --oknodo --pidfile /var/run/tcpserver_pop3d.pid --exec /usr/bin/tcpserver + + # Wait until the timeout for qmail processes to die. + count=120 + numdots=0 + while ([ $count != 0 ]) do + let count=$count-1 + if [ "`pidof /usr/sbin/qmail-send`" ] ; then + echo -n . + let numdots=$numdots+1 + sleep 1 + else + count=0 + fi + done + + # If it's not dead yet, kill it. +# if [ "`pidof /usr/sbin/qmail-send`" ] ; then +# echo -n " TIMEOUT!" +# kill -KILL `pidof /usr/sbin/qmail-send` +# else + case $numdots in + 0) echo "." ;; + 1) echo ;; + *) echo " done." ;; + esac +# fi + else + echo " not running."; + fi + + ;; + restart) + $0 stop + $0 start + ;; + cdb) + echo "Rebuilding tcp.smtp.cdb." + cd /etc + tcprules tcp.smtp.cdb tcp.smtp.temp < tcp.smtp + ;; + flush) + /usr/sbin/qmail-tcpok + start-stop-daemon --stop --quiet --oknodo --signal ALRM --exec /usr/sbin/qmail-send + echo "Queue flushed." + ;; + stat) + /usr/sbin/qmail-qread + /usr/sbin/qmail-qstat + ;; + reload|force-reload) + echo "Reloading 'locals' and 'virtualdomains' control files." + start-stop-daemon --stop --quiet --oknodo --signal HUP --exec /usr/sbin/qmail-send + ;; + *) + echo 'Usage: /etc/init.d/qmail {start|stop|stat|cdb|restart|reload}' + exit 1 +esac + +exit 0 --- qmail-1.03.orig/debian/qmail-src.templates.disabled +++ qmail-1.03/debian/qmail-src.templates.disabled @@ -0,0 +1,26 @@ +Template: qmail-src/build +Type: note +Description: To build qmail binary package, you have to run + build-qmail + +Template: qmail-src/warning +Type: note +Description: WARNING! WARNING! WARNING! + The binary packages built by build-qmail are + dependant on the uid and gid's of the system + that the package was built on. + . + If you are building/installing qmail for the + first time, I highly recommend you check your + /etc/passwd, /etc/shadow, & /etc/group files + and remove ANY existing qmail uid or gid's and + re-install qmail-src. If you choose not to, + it may not work! + +Template: qmail-src/ucspitcp +Type: note +Description: ucspi-tcp dependancy warning + QMail depends on the ucspi-tcp binary package before it can be installed. + . + If you have not already installed ucspi-tcp-src and built ucspi-tcp, I suggest + you do that task first before installing the finished qmail package. --- qmail-1.03.orig/debian/README +++ qmail-1.03/debian/README @@ -0,0 +1,7 @@ +Things to do when debianizing a new version of qmail. + Christian Hudon + +* Run debian/debianize-source-tree + +NB Programs are classified as belonging to sbin or bin according to their +manual page section. (section 1: bin; section 8: sbin) --- qmail-1.03.orig/debian/qmailtest +++ qmail-1.03/debian/qmailtest @@ -0,0 +1,114 @@ +#!/usr/bin/perl -- +# Test message script for debian's Qmail distribution. +# Copyright 1994 Ian Jackson. There is NO WARRANTY. +# See /usr/doc/qmail/copyright + +$mayremote=1; +$|=1; + +$_= shift(@ARGV); +if ($_ eq '--allowremote') { $mayremote=1; } +elsif ($_ eq '--localonly') { $mayremote=0; } +else { die "usage: qmailtest --localonly | --allowremote\n"; } + +$halvestrand='linux-counter@uninett.no'; + +$visiblename=''; +if (open(C,"/etc/qmail/defaulthost") || open(C,"/etc/qmail/me")) { + $visiblename = ; + chomp $visiblename ; +} + +if ($mayremote) { + $msg= length($visiblename) + ? +" +Would you like to send a test message now ? Select one of: + + Return or Y Yes, test offsite delivery with a message to Harald Alvestrand's + Linux Counter project - you should then receive an autoreply + to postmaster\@$visiblename. + + Do not use this option until mail routing to your machine has + been properly enabled, please ! + + L Just a local message from root\@$visiblename + to postmaster\@$visiblename. + + N No, thanks. (You can do this later using /usr/sbin/smailtest.) + +Send a test message now ? (y/l/n) " + : +" +Would you like to send a test message now ? Select one of: + + Return or Y Yes, test offsite delivery with a message to Harald Alvestrand's + Linux Counter project - you should then receive an autoreply. + + Do not use this option until mail routing to your machine has + been properly enabled, please ! + + L Just a local message to \`root' from \`postmaster'. + + N No, thanks. (You can do this later using /usr/sbin/smailtest.) + +Send a test message now ? (y/l/n) "; + $accept= 'yln'; +} else { + $msg= +"Would you like to send a test message from `root' to `postmaster' ? +Send a test message now ? (y/n) "; + $accept= 'yn'; +} + +do { + print $msg; + $_= ; + s/\s+$//; s/^\s+//; +} while (!m/^[$accept]?$/i); + +exit 0 if m/^n/i; + +chop($d=`date`); + +if (!$mayremote || m/^l/i) { + $message= +"From: root +To: postmaster +Subject: Qmail system installation test message + +This is the test message you were promised. +It was sent at $d. + +If you want to send a remote test message run \`smailtest' again. +"; +} else { + chop($host=`hostname --fqdn`); + $message= +"From: postmaster +To: $halvestrand +Subject: Linux mail system installation auto-registration/test + +This message was sent at $d +to test this system's mailer and to register its use of +Qmail under a Debian Linux System. + +//echo +//machine +name: $host +distribution: Debian 1.3.1 +mailer: Qmail 1.01 +//end +"; +} + +open(P,"|/usr/sbin/sendmail -oem -odi -t -oi") || die "pipe to smail: $!\n"; +print(P $message) || die "write to qmail: $!\n"; +$!=0; close(P); $? && die "qmail failed $?/$!\n"; + +print " +Test message sent. + +"; + +exit 0; --- qmail-1.03.orig/debian/ip-up.d +++ qmail-1.03/debian/ip-up.d @@ -0,0 +1,3 @@ +#!/bin/sh + +[ -x /usr/sbin/qmail-send ] && killall -ALRM qmail-send --- qmail-1.03.orig/debian/qmail.config +++ qmail-1.03/debian/qmail.config @@ -0,0 +1,5 @@ +#!/bin/sh -e + +# Source debconf library. +. /usr/share/debconf/confmodule + --- qmail-1.03.orig/debian/changelog +++ qmail-1.03/debian/changelog @@ -0,0 +1,438 @@ +qmail (1.03-45ubuntu1) hardy; urgency=low + + * Merge from Debian unstable. Remaining Ubuntu changes: (LP: #185726) + - debian/rules: add missing 'fakeroot' command before 'chown -R root.root'. + - Modify Maintainer value to match Debian-Maintainer-Field Spec + + -- Stefan Ebner Thu, 24 Jan 2008 20:23:09 +0100 + +qmail (1.03-45) unstable; urgency=low + + * Updated prerm to remove dependancy on update-inetd (Closes #439702) + + -- Jon Marler Tue, 11 Dec 2007 15:32:58 -0600 + +qmail (1.03-44ubuntu1) feisty; urgency=low + + * Merge with Debian, Ubuntu changes: + + debian/rules: add missing 'fakeroot' command before 'chown -R root.root'. + + Adhere to DebianMaintainerField. + + -- Lionel Le Folgoc Thu, 22 Mar 2007 17:24:57 +0100 + +qmail (1.03-44) unstable; urgency=low + + * One minor fix in the control file for autobuild compatibility + + -- Jon Marler Fri, 19 Jan 2007 07:53:39 -0600 + +qmail (1.03-43) unstable; urgency=low + + * Updated to Debian Policy Standards-Version 3.7.2 + * Fixed some non-essential errors in the control file + * Removed old 1.02 transition code and usr/doc cleanup (Closes: #406990) + + -- Jon Marler Sun, 31 Dec 2006 02:47:14 -0600 + +qmail (1.03-42) unstable; urgency=low + + * Attempt #2 at fixing autobuild bug (Closes: #402331) + + -- Jon Marler Thu, 21 Dec 2006 16:54:58 -0600 + +qmail (1.03-41) unstable; urgency=low + + * Changed rules file to allow building -src on systems without qmail users + (Closes: #402331) + + -- Jon Marler Sat, 16 Dec 2006 12:30:32 -0600 + +qmail (1.03-40) unstable; urgency=low + + * Disabled all debconf notes per Christian Perrier + Joey Hess , and srivasta@debian.org (Closes: #388952) + + -- Jon Marler Wed, 27 Sep 2006 13:40:16 -0500 + +qmail (1.03-39) unstable; urgency=low + + * Added debconf-2.0 dependancy option + + -- Jon Marler Mon, 26 Sep 2005 13:29:40 -0500 + +qmail (1.03-38) unstable; urgency=high + + * Added ISO C patch taken from netqmil to fix 64-bit crashes (Closes: #309048) + + -- Jon Marler Sun, 15 May 2005 11:22:27 -0500 + +qmail (1.03-37) unstable; urgency=high + + * Updated qregex patch to 20040725 version + * Added Build-Depends line (Closes: #302677) + * Added pidfile settings to init file (Closes: #293484) + * Applied 0.0.0.0 local patch (Closes: #226753) + * Increased default ulimit to 16384 for x86_64 (Closes: #291437) + * Applied localtime patch (Closes: #272072) + * Fixed bug in qmail-procmail to allow arguments (Closes: #262906) + * Updated postrm to remove /etc/qmail/users on purge (Closes: #272806) + + -- Jon Marler Thu, 5 May 2005 11:54:04 -0600 + +qmail (1.03-36) unstable; urgency=high + + * Fixed problem when building with apt-get source -b (Closes: #280677) + + -- Jon Marler Thu, 11 Nov 2004 13:03:39 -0600 + +qmail (1.03-35) unstable; urgency=high + + * Fixed debconf errors (Closes: #272248, #272164, #272797, #272804) + * Added testing to release list + + -- Jon Marler Thu, 28 Oct 2004 11:15:19 -0500 + +qmail (1.03-34) unstable; urgency=low + + * Moved logcheck ignore file to docs directory (Closes: #271118) + * File is already included in logcheck-database which seems more logical + + -- Jon Marler Mon, 13 Sep 2004 06:50:39 -0500 + +qmail (1.03-33) unstable; urgency=low + + * Added -R -H to example POP3 server call (Closes: #269119) + * Added sample logcheck ignore files (Closes: #266143) + * Fixed hang bug in postinst (Closes: #266010) + + -- Jon Marler Tue, 31 Aug 2004 16:36:51 -0500 + +qmail (1.03-32) unstable; urgency=low + + * Initial debconf implementation + - Please file bug reports for questions i missed + * Removed reference to bmtpatch. (Closes: #246574) + * Leaving bmtpatch in -src pacakge as many users still use it + * Applied latest qregex patch (Closes: #246408) + + -- Jon Marler Tue, 13 Jul 2004 10:24:49 -0500 + +qmail (1.03-31) unstable; urgency=low + + * Added dependancy on perl-modules (Closes: #233015) + + -- Jon Marler Tue, 17 Feb 2004 13:03:08 -0600 + +qmail (1.03-30) unstable; urgency=high + + * Added patch from Scott Gifford to correct qmail-smtpd crash + + -- Jon Marler Tue, 20 Jan 2004 11:57:18 -0600 + +qmail (1.03-29) unstable; urgency=low + + * Added patch to resolve new glibc errors (Closes: #218564, #219872) + * Added patch to fix errno declaration errors (Closes: #219872) + * Remove strict barewords from preinst (Closes: #215152) + * Fixed minor type in build-qmail (Closes: #213415) + * Added patch to make qmail-local behave better (Closes: #95353) + + -- Jon Marler Thu, 13 Nov 2003 17:13:33 -0600 + +qmail (1.03-28) unstable; urgency=low + + * Fixed logging in init to handle rblsmtpd (Closes: #192116) + * Added ability to override qmail installation check (Closes: #187452) + * Changed groff dependancy to groff-base (Closes: #181021) + * Removed rm -rf /etc/qmail command in postrm (Closes: #179637) + * Added list of pre-applied patches in build script before binary build + + -- Jon Marler Thu, 25 Sep 2003 16:48:34 -0500 + +qmail (1.03-27) unstable; urgency=low + + * Added stat to usage list (Closes: #179831) + + -- Jon Marler Tue, 4 Feb 2003 16:16:41 -0600 + +qmail (1.03-26) unstable; urgency=low + + * Added -isp flag to dpkg-gencontrol (Closes: #179609) + * Removed emacs settings from changelog + + -- Jon Marler Mon, 3 Feb 2003 09:56:19 -0600 + +qmail (1.03-25) unstable; urgency=low + + * Applied patch from thunder7@xs4all.nl for libc6 (Closes: #174408) + * Fixed typo in postinst (Closes: #134011) + * Added warning in build script regarding tmpfs (Closes: #155024) + * Removed extra -f from postinst (Closes: #155573) + * Updated init.d script (Closes: #128638) + + -- Jon Marler Thu, 20 Jan 2003 02:56:56 -0600 + +qmail (1.03-24) testing unstable; urgency=low + + * Added libc6-dev back into the Depends line + + -- Jon Marler Mon, 18 Mar 2002 21:19:14 -0600 + +qmail (1.03-23) testing unstable; urgency=low + + * Fixed section of -src and binary .deb files (Closes: #125698) + * Updated checkpassword to .90 (Closes: #126686) + + -- Jon Marler Fri, 28 Dec 2001 11:28:34 -0600 + +qmail (1.03-22) testing unstable; urgency=low + + * Somehow the init.d patch didn't make it in. It's in there now. + + -- Jon Marler Sun, 2 Dec 2001 02:56:22 -0600 + +qmail (1.03-21) testing unstable; urgency=low + + * Updated init to stop reverse DNS and ident lookups (Closes: #111934) + * Added QMAIL-QUEUE patch + * Added badmailto patch + * Updated package description to stop apt-get source confusion + * Added extra verbiage to help ucspi-tcp confusion (Closes: #106704) + + -- Jon Marler Sat, 1 Dec 2001 04:19:49 -0600 + +qmail (1.03-20) testing unstable; urgency=low + + * Updated dependancy to include groff. (Closes: #109003) + * Updated conflicts to prevent installing some binary deb packages + * Added patch from Alvaro Martinez Echevarria (Closes: #104504, #102692) + + -- Jon Marler Fri, 24 Aug 2001 10:49:51 -0500 + +qmail (1.03-19) testing unstable; urgency=low + + * Updated standards version + * Changed priority from optional to extra + * Fixed /usr/doc/ /usr/share/doc link + + -- Jon Marler Wed, 27 Jun 2001 18:26:07 -0500 + +qmail (1.03-18) unstable; urgency=low + + * Applied sync patch to make qmail for reiserfs/ext2 friendly + + -- Jon Marler Tue, 26 Jun 2001 13:44:32 -0500 + +qmail (1.03-17) unstable; urgency=high + + * Fixed gzip compression of manpages & docs (closes #76560) + * Fixed /var/qmail/bin symlink (closes #75736) + * Increased ulimit (closes #74956) + + -- Jon Marler Mon, 18 Dec 2000 15:26:26 -0600 + +qmail (1.03-16) unstable; urgency=high + + * Fixed dependancy problems in qmail-src. (Closes #67699) + + -- Jon Marler Tue, 25 Jul 2000 08:57:11 -0500 + +qmail (1.03-15) unstable; urgency=high + + * Moved documentation to /usr/share/doc (Closes #58682) + * Updated debian/rules to install the checkpassword manpage. (Closes #66975) + * Updated debian/rules to call install, rather then relying on the path. (Closes #67461) + * Updated build-qmail script with patch from Jeff Sheinberg that fixes non-absolute build paths (Closes #65190) + + -- Jon Marler Wed, 19 Jul 2000 14:00:00 -0500 + +qmail (1.03-14) frozen unstable; urgency=high + + * Fixed checkpasswd program. Did not work if both shadow and non-shadow passwords are used. + * Installed patch that fixes the Netscape progress bar. + + -- Jon Marler Mon, 15 May 2000 22:28:38 -0500 + +qmail (1.03-13) frozen unstable; urgency=high + + * Fixed init script to work with new uid/gid scheme. + * Fixed pop3 daemon not starting. Conflict with tcpserver/qmail-smtpd + + -- Jon Marler Tue, 9 May 2000 16:02:04 -0500 + +qmail (1.03-12) frozen unstable; urgency=high + + * Added warning about uid/gid potential conflicts between build and install. + + -- Jon Marler Tue, 22 Feb 2000 13:25:00 +0500 + +qmail (1.03-11) frozen unstable; urgency=high + + * Fixed more problems with new uid's. + * Fixed problem with init.d script. + * Fixed ulimit problem in init.d on some Sparc's and PPC's + * Fixed bug in changelog to upload to frozen AND unstable. + + -- Jon Marler Wed, 9 Feb 2000 13:25:00 +0500 + +qmail (1.03-10) frozen; urgency=high + + * Fixed problems with new uid's on new potato installs. (Closes #56588) + + -- Jon Marler Mon, 31 Jan 2000 13:25:00 +0500 + +qmail (1.03-9) frozen; urgency=high + + * Added new UID's & GID's to comply with new base-passwd package. Only new installs are affected. + + -- Jon Marler Sat, 22 Jan 2000 13:25:00 +0500 + +qmail (1.03-8) unstable; urgency=low + + * Fixed even MORE bugs in preinst ... This time I have used code from the New Rider's Debian book (Closes #48720, #45203) + * Added a mail-transfer-agent provides line to work with other buggy packages (Closes #52623) + + -- Jon Marler Thu, 15 Dec 1999 13:25:00 +0500 + +qmail (1.03-7) unstable; urgency=low + + * Fixed yet another bug in preinst. It's a little more carefull about moving files around. (Closes #45203) + * Fixed bug in checkpassword that would only allow retrieval of files owned by users's primary group. (Closes #47424) Patch provided by russell@coker.com.au + * Fixed bug in init.d/qmail script. Forgot to stop the pop-3 daemon. + + -- Jon Marler Thu, 14 Oct 1999 13:25:00 +0500 + +qmail (1.03-6) unstable; urgency=high + + * Fixed bug in preinst. (Closes #41211) + * Added dependancy to perl5. Perl is used in the pre/post scripts. + + -- Jon Marler Tue, 13 Jul 1999 17:13:00 +0500 + +qmail (1.03-5) unstable; urgency=low + + * New ucspi-tcp broke the init.d/qmail script. Had to remove -S (closes: #40723, #40871, #40872) + + -- Jon Marler Tue, 6 Jul 1999 17:13:00 +0500 + +qmail (1.03-4) unstable; urgency=high + + * Fixed bug in debian/rules that on clean install, the control directory was not moved. (closes: #40381) + * Now features "out-of-the-box" pop-3 support. Just un-comment a few lines in /etc/init.d/qmail (Courtesy of Varga Robert ) + * Fixed bug where /var/lib/qmail/alias was not being created. (Thanks again Varga) + + -- Jon Marler Mon, 28 Jun 1999 17:13:00 +0500 + +qmail (1.03-3) unstable; urgency=high + + * Fixed bug in debian/rules that attempted to install into /usr/doc/qmail and /usr/doc/qmail/examples (closes: #39857, #39890) + + -- Jon Marler Mon, 21 Jun 1999 13:00:00 +0100 + +qmail (1.03-2) unstable; urgency=low + + * Changed dependency on gcc to gcc or egcc (closes: #22053) + * Fixed minor typo in documentation regarding where alias was moved. + * Got permission from Ivan Kohler to distribure mbox2maildir script which is not part of qmail (closes: #34375) + * All documentation normally located in /var/qmail/doc has been moved to /usr/doc/qmail. A symlink from /var/qmail/doc to /usr/doc/qmail is in its place. (closes: #39372) + + -- Jon Marler Fri, 18 Jun 1999 12:33:00 +0100 + +qmail (1.03-1) unstable; urgency=low + + * New upstream release (closes: #30378) + * New maintainer + * Updated qmailconfig to show "/etc/qmail/control/me" instead of "control/me" + (closes: #12311) + * Moved /var/qmail/users to /etc/qmail, and /var/qmail/alias to /var/lib/qmail/alias (closes: #11862) + * Added /usr/doc/examples/ip-up.d example ppp script (closes: #19131) + Used example written by Dick Broadway + * Checkpassword is now compiled and installed in /usr/bin (closes: #28394, #9760) + * Modified /etc/init.d/qmail to add --user arguments to start-stop-deamon + when starting and stopping qmail-send and tcpserver. (closes: #25600) + Uses suggestions from Tommi Virtanen + * Modified /etc/init.d/qmail to be a bash script (closes: #31994) + * Applied patch to dns.c to allow e-mail to deliver correctly to systems where + their DNS size is greater > 512. Fixes "CNAME Lookup Failure" error when + delivering mail to aol.com + + -- Jon Marler Sat, 29 May 1999 12:33:00 +0100 + +qmail (1.02-1) unstable; urgency=low + + * New upstream release + * fix ulimit problem in init.d script + + -- Philip Hands Thu, 7 May 1998 08:43:19 +0100 + +qmail (1.01-7) unstable; urgency=low + + * include INSTALL in docs. + * update rules, to use a binary-src target for the -src package + * check that the builder's machine has debian standard [ug]ids for qmail + * fix default cleanup response in build-PACKAGE + + -- Philip Hands Tue, 7 Apr 1998 00:17:47 +0100 + +qmail (1.01-6) non-free; urgency=low + + * tidy up debian/rules (use binary-indep for binary independant bits :-) + + -- Philip Hands Thu, 19 Mar 1998 18:04:15 +0000 + +qmail (1.01-5) non-free; urgency=low + + * make sure it's in non-free. + Don't know how, but I managed to change it to unstable without + noticing :-( + + -- Philip Hands Tue, 24 Feb 1998 09:05:42 +0000 + +qmail (1.01-4) non-free; urgency=low + + * add newaliases (closes: #13759) + * fix permissions on users/assign + + -- Philip Hands Fri, 13 Feb 1998 09:46:47 +0000 + +qmail (1.01-3) non-free; urgency=low + + * add /etc/hosts.allow lines so we can have stderr `twisted' to syslog + * add a checkpassword, for use with qmail-popup + * actually include qmail-procmail script (closes: #17767, #14315) + * include eliminate-dups + * add default /var/qmail/users/assign + + -- Philip Hands Wed, 4 Feb 1998 12:59:39 +0000 + +qmail (1.01-2) non-free; urgency=low + + * new maintainer + * qmail-1.01.orig.tar.gz now really is pristine source ;-) + * revert to unpatched source, and get dot-locking by use of procmail + * add creation of qmail-src + + -- Philip Hands Fri, 31 Oct 1997 21:13:40 +0000 + +qmail (1.01-1) experimental; urgency=low + + * New upstream release. + * Gave in and added /usr/lib/sendmail symlink (fixes bugs 10283 and 11347) + * Compiled with libc6. + * qmail-1.01.orig.tar.gz is now pristine source, thanks to dpkg 1.4.0.19 + + -- Christian Hudon Fri, 8 Aug 1997 22:22:24 -0400 + +qmail (1.00-2) experimental; urgency=low + + * Fixed error in sed expression of qmailconfig (Thanks to Philip Hands) + * Made '/etc/init.d/qmail stop' output look prettier. + + -- Christian Hudon Sun, 13 Apr 1997 19:12:59 -0400 + +qmail (1.00-1) experimental; urgency=low + + * Initial release. + + -- Christian Hudon Wed, 26 Mar 1997 00:24:38 -0500 + --- qmail-1.03.orig/debian/postrm +++ qmail-1.03/debian/postrm @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +use Debconf::Client::ConfModule ':all'; +version('2.0'); + +$| = 1; + +$action = shift @ARGV; + +if ( $action eq 'purge' ) { + system('update-rc.d qmail remove >/dev/null'); + system("rm -rf /var/qmail"); + # Next command removed because it was VERY evil + #system("rm -rf /etc/qmail"); + # This is not -*quite*- so evil ... + system("rm -rf /etc/qmail/users"); + input ("medium","qmail/userpurge"); + my @ret=go(); + if ( $ret[0] eq "" || $answer =~ /^\s*[yY]/ ) { + system('userdel alias >/dev/null'); + system('userdel qmaild >/dev/null'); + system('userdel qmails >/dev/null'); + system('userdel qmailr >/dev/null'); + system('userdel qmailq >/dev/null'); + system('userdel qmaill >/dev/null'); + system('userdel qmailp >/dev/null'); + system('groupdel qmail >/dev/null'); + } + purge(); + + exit $?; +} + +if ( $action eq 'abort-install' ) { + # Put back old inetd.conf (?) + exit 0 +} + --- qmail-1.03.orig/debian/src.postrm +++ qmail-1.03/debian/src.postrm @@ -0,0 +1,8 @@ +#!/bin/sh -e + +if [ "$1" = "purge" -a -e /usr/share/debconf/confmodule ]; then + # Source debconf library. + . /usr/share/debconf/confmodule + # Remove my changes to the db. + db_purge +fi --- qmail-1.03.orig/debian/qmail.templates +++ qmail-1.03/debian/qmail.templates @@ -0,0 +1,69 @@ +Template: qmail/readme +Type: note +Description: README + Before making any changes to your qmail configuration, please read + /usr/share/doc/qmail/README.Debian.gz. This contains a description of the + differences bewtween other mailers on Debian, qmail on Debian, and qmail on + other systems. + . + If you were using sendmail (or smail) previously, you will also want to read + the "qmail-upgrade" manpage, which details user-visible differences between + sendmail and qmail. + . + If you are new to qmail, you will want to at least peruse the qmail FAQ, which + can be found in /usr/doc/qmail + +Template: qmail/start +Type: select +Choices: yes, no +Description: Do you want to start qmail now? + +Template: qmail/reboot +Type: note +Description: Qmail will be started at the next reboot. + Or you can start qmail manually when + you are ready by typing (as root) "/etc/init.d/qmail start" at a shell prompt. + +Template: qmail/userpurge +Type: select +Choices: yes, no +Description: Remove qmail users during a purge? + +Template: qmail/recipientmap +Type: note +Description: WARNING! + recipientmap is gone from qmail-1.03. The virtualdomains mechanism + has been expanded to support virtual users. You will need to fix your setup. + +Template: qmail/qlist +Type: note +Description: WARNING! + qlist has been split into a separate package by Dan Bernstein (the + author of qmail) since qmail-1.02. + . + I was not planning on debianising qlist, because ezmlm does a better job, + so if you still want qlist, you can either get it direct from + http://pobox.com/~djb/qlist.html + . + Please check in /usr/doc/qmail and the man pages for changes since qmail 1.01 + +Template: qmail/inetd +Type: note +Description: inetd.conf changes + inetd does not handle qmail terribly effectively, so I have decided + to make the default instalation use tcpserver from ucspi-tcp instead. + . + For this reason, I have disabled the smtp line in /etc/inetd.conf. + . + This means that you must configure things such as RELAYCLIENT using + /etc/tcp.smtp, rather than hosts allow (see /usr/doc/qmail/README for details) + +Template: qmail/tcpupdate +Type: note +Description: Updating /etc/tcp.smtp database for tcpserver + +Template: qmail/override +Type: select +Choices: yes, no +Description: Pre-existing qmail installation detected. Override? + --- qmail-1.03.orig/debian/suid +++ qmail-1.03/debian/suid @@ -0,0 +1 @@ +off --- qmail-1.03.orig/debian/control.real +++ qmail-1.03/debian/control.real @@ -0,0 +1,79 @@ +Source: qmail +Maintainer: Jon Marler +Section: non-free/mail +Priority: extra +Build-Depends: dpkg-dev (>= 1.4.0.20), patch (>= 2.5-0bo1), gcc, make, fakeroot | sudo, groff-base, adduser +Standards-Version: 3.7.2 + +Package: qmail +Priority: extra +Section: non-free/mail +Architecture: any +Depends: ${shlibs:Depends}, netbase, procmail, ucspi-tcp, perl-modules +Provides: mail-transport-agent, mail-transfer-agent +Conflicts: mail-transport-agent, qmail-run, qmail-uids-gids +Suggests: mutt | mail-reader +Description: Secure, reliable, efficient, simple mail transport system + qmail is a secure, reliable, efficient, simple message transfer agent. It + is meant as a replacement for the entire sendmail-binmail system on typical + Internet-connected UNIX hosts. + . + Reliable: qmail's straight-paper-path philosophy guarantees that a message, + once accepted into the system, will never be lost. qmail also supports + maildir, a new, super-reliable user mailbox format. Maildirs, unlike mbox + files and mh folders, won't be corrupted if the system crashes during + delivery. Even better, not only can a user safely read his mail over NFS, + but any number of NFS clients can deliver mail to him at the same time. + . + Efficient: On a Pentium, qmail can easily sustain 200000 local messages per + day---that's separate messages injected and delivered to mailboxes in a real + test! Although remote deliveries are inherently limited by the slowness of + DNS and SMTP, qmail overlaps 20 simultaneous deliveries by default, so it + zooms quickly through mailing lists. + . + Simple: qmail is vastly smaller than any other Internet MTA. Some reasons why: + (1) Other MTAs have separate forwarding, aliasing, and mailing list + mechanisms. qmail has one simple forwarding mechanism that lets users handle + their own mailing lists. + (2) Other MTAs offer a spectrum of delivery modes, from fast+unsafe to + slow+queued. qmail-send is instantly triggered by new items in the queue, so + the qmail system has just one delivery mode: fast+queued. + (3) Other MTAs include, in effect, a specialized version of inetd that + watches the load average. qmail's design inherently limits the machine load, + so qmail-smtpd can safely run from your system's inetd. + . + Replacement for sendmail: qmail supports host and user masquerading, full + host hiding, virtual domains, null clients, list-owner rewriting, relay + control, double-bounce recording, arbitrary RFC 822 address lists, cross-host + mailing list loop detection, per-recipient checkpointing, downed host + backoffs, independent message retry schedules, etc. In short, it's up to + speed on modern MTA features. qmail also includes a drop-in ``sendmail'' + wrapper so that it will be used transparently by your current UAs. + +Package: qmail-src +Architecture: all +Depends: dpkg-dev (>= 1.4.0.20), patch (>= 2.5-0bo1), gcc, make, fakeroot | sudo, groff-base, adduser +Conflicts: qmail-run, qmail-uids-gids +Section: non-free/mail +Recommends: ucspi-tcp-src, procmail +Description: Source only package for building qmail binary package + qmail is a secure Secure, reliable, efficient, simple mail transport system. + . + Dan Bernstein (qmail's author) only gives permission for qmail to be + distributed in source form, or binary for by approval. This package + has been put together to allow people to easily build a qmail binary + package for themselves, from source. + . + To build a binary deb package, first install the qmail-src package, then + type the command "build-qmail". If you try "apt-get source --build qmail-src" + only the qmail-src package will be built. You will need to install qmail-src + and type the command "build-qmail" to get a usable binary package of qmail. + Also be sure to build and install ucspi-tcp before installing the binary qmail + package. Install the ucspi-tcp-src package to get ucspi-tcp. + . + This package builds a binary .deb that is FHS compliant and conforms to the + Debian standards guidelines. The resulting binary packages are not suitable + for re-distribution. + . + There are pre-compiled binary packages for qmail available, but they do not + conform to the Debian standards, and are not available in the official archive. --- qmail-1.03.orig/debian/debian-default_uids.c +++ qmail-1.03/debian/debian-default_uids.c @@ -0,0 +1,10 @@ +int auto_uida = 64010; +int auto_uidd = 64011; +int auto_uidl = 64015; +int auto_uido = 0; +int auto_uidp = 64016; +int auto_uidq = 64014; +int auto_uidr = 64013; +int auto_uids = 64012; +int auto_gidq = 64010; +int auto_gidn = 65534; --- qmail-1.03.orig/debian/qmail-src.config.disabled +++ qmail-1.03/debian/qmail-src.config.disabled @@ -0,0 +1,14 @@ +#!/bin/sh -e + +# Source debconf library. +. /usr/share/debconf/confmodule + +db_input medium qmail-src/build || true +db_input high qmail-src/warning || true +UCSPITCP=`/usr/bin/dpkg --get-selections ucspi-tcp 2>/dev/null | /usr/bin/awk '{ print $2; }'` + +if [ "$UCSPITCP" != "install" ]; then + db_input high qmail-src/ucspitcp || true +fi + +db_go || true --- qmail-1.03.orig/debian/src.postinst +++ qmail-1.03/debian/src.postinst @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# Source the debconf library +. /usr/share/debconf/confmodule + +# Previous informational message removed in favor of debconf + +# Code snippet courtesy of Wichert Akkerman + +if ! grep -q '^qmaild:' /etc/passwd ; then + echo "No qmail accounts present, creating them now" + addgroup --gid 64010 qmail + adduser --system --no-create-home --uid 64010 --gid 65534 --disabled-password --home /var/qmail/alias --gecos "qmail alias" alias + adduser --system --no-create-home --uid 64011 --gid 65534 --disabled-password --home /var/qmail --gecos "qmail daemon" qmaild + adduser --system --no-create-home --uid 64012 --gid 64010 --disabled-password --home /var/qmail --gecos "qmail send" qmails + adduser --system --no-create-home --uid 64013 --gid 64010 --disabled-password --home /var/qmail --gecos "qmail remote" qmailr + adduser --system --no-create-home --uid 64014 --gid 64010 --disabled-password --home /var/qmail --gecos "qmail queue" qmailq + adduser --system --no-create-home --uid 64015 --gid 65534 --disabled-password --home /var/qmail --gecos "qmail log" qmaill + adduser --system --no-create-home --uid 64016 --gid 65534 --disabled-password --home /var/qmail --gecos "qmail pw" qmailp +fi + +exit 0 --- qmail-1.03.orig/debian/postinst +++ qmail-1.03/debian/postinst @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +use Debconf::Client::ConfModule ':all'; +version('2.0'); + +# do not print anything to STDOUT, as debconf will interpret it as a command +sub debug ($) { + my($msg) = @_; + print STDERR $msg; +} + +$| = 1; + +my $action = shift @ARGV; + +my $hostsallow = "/etc/hosts.allow"; + +if ( $action eq 'configure' or $action eq 'abort-upgrade' or $action eq 'abort-deconfigure' or $action eq 'abort-remove' ) { + my $old_version = shift @ARGV; + + if ( !defined($old_version) || $old_version le "1.01-7" ) { + check_hosts_allow(); + input ("low","qmail/tcpupdate"); + go(); + system("/usr/bin/tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp >/dev/null") ; + + } + + # Add rc?.d links + system('update-rc.d qmail defaults >/dev/null'); + system("/usr/sbin/qmail-newu >/dev/null"); + + if ( ! -r '/var/qmail/control/me' ) { + # send qmailconfig's progress messages to STDERR + system("/usr/lib/qmail/qmailconfig 1>&2"); + if ($? != 0) { + debug("qmailconfig failed\n"); + } + } + + if ( -l '/etc/qmail/qmail' ) { + system("rm /etc/qmail/qmail >/dev/null"); + } + + $checkstart = 0 ; + if ( $old_version le '1.01-7' ) { + if ( -f '/var/qmail/control/recipientmap' ) { + input ("medium","qmail/recipientmap"); + go(); + } + } + + input ("medium","qmail/qlist"); + input ("medium","qmail/start"); + my @ret=go(); + if ( $ret[0] eq "" || $answer =~ /^\s*[yY]/ ) { + debug("Starting qmail . . .\n"); + system("/etc/init.d/qmail start 1>&2"); + } + else { + input ("medium","qmail/reboot"); + go(); + } + +} + +sub check_hosts_allow { + if (open(HOSTSA,"$hostsallow")) { + @hostsa = ; + close(HOSTSA) ; + if (grep(m/smtp:/,@hostsa)) { + input ("medium","qmail/inetd"); + go(); + } + } +} + +exit 0; --- qmail-1.03.orig/debian/TODO +++ qmail-1.03/debian/TODO @@ -0,0 +1,4 @@ +* Write nice qmailconfig script +* Add aliases for postmaster, root and mailer-daemon +* Enable pop3d daemon? +* Edit /etc/login.defs:MAIL_DIR/MAIL_FILE ? --- qmail-1.03.orig/debian/docs +++ qmail-1.03/debian/docs @@ -0,0 +1,42 @@ +BIN.Makefile +BIN.README +BLURB +BLURB2 +BLURB3 +BLURB4 +CHANGES +FAQ +FILES +INSTALL +INSTALL.alias +INSTALL.ctl +INSTALL.ids +INSTALL.maildir +INSTALL.mbox +INSTALL.vsm +INTERNALS +Makefile +PIC.local2alias +PIC.local2ext +PIC.local2local +PIC.local2rem +PIC.local2virt +PIC.nullclient +PIC.relaybad +PIC.relaygood +PIC.rem2local +README +README.qregex +REMOVE.binmail +REMOVE.sendmail +SECURITY +SENDMAIL +SYSDEPS +TARGETS +TEST.deliver +TEST.receive +THANKS +THOUGHTS +TODO +UPGRADE +VERSION --- qmail-1.03.orig/debian/eliminate-dups +++ qmail-1.03/debian/eliminate-dups @@ -0,0 +1,59 @@ +#! /usr/bin/perl +# Call from a .qmail file as follows: +# |/usr/lib/qmail/eliminate-dups Mailbox + +$hashname = shift; + +use MD5; +$md5 = new MD5; + +$loose = 1; # loose matching if set. + +while(<>) { + last if /^$/; + next if $ignore_continue && /^\s/; + $ignore_continue = 0; + if (/^received:/i) { + $ignore_continue = 1; + next; + } + if (!$loose) { + $headers .= $_; + next; + } + if ($keep_continue && /^\s/) { + $headers .= $_; + next; + } + $keep_continue = 0; + if (m/^(from|message-id|date):/i) { + $headers .= $_; + $keep_continue = 1; + next; + } + next; +} + +$md5->add($headers); +$md5->addfile(STDIN); +$hash = $md5->hexdigest; +print "$headersOur hash:$hash\n"; + +open(HASH, "<$hashname.newer"); +flock(HASH, 2); +while() { chomp; exit 99 if $_ eq $hash; } +open(HASH, "<$hashname.older") || die "$0: Cannot open $hashname.older"; +while() { chomp; exit 99 if $_ eq $hash; } + +# roll the files once a week. +if (-M "$hashname.older" > 7) { + rename("$hashname.newer", "$hashname.older") || die "$0: Unable to move newer to older"; +} + +# add the hash to the "received messages" list. +open(HASH, ">>$hashname.newer") || die "$0: Cannot append to $hashname.newer"; +print HASH "$hash\n"; +close(HASH); + +print "Original message"; +exit 0; --- qmail-1.03.orig/debian/control +++ qmail-1.03/debian/control @@ -0,0 +1,35 @@ +Source: qmail +Maintainer: Ubuntu MOTU Developers +XSBC-Original-Maintainer: Jon Marler +Section: non-free/mail +Priority: extra +Build-Depends: dpkg-dev (>= 1.4.0.20), patch (>= 2.5-0bo1), gcc, make, fakeroot | sudo, groff-base, adduser +Standards-Version: 3.7.2 + +Package: qmail-src +Architecture: all +Depends: dpkg-dev (>= 1.4.0.20), patch (>= 2.5-0bo1), gcc, make, fakeroot | sudo, groff-base, adduser +Conflicts: qmail-run, qmail-uids-gids +Section: non-free/mail +Recommends: ucspi-tcp-src, procmail +Description: Source only package for building qmail binary package + qmail is a secure Secure, reliable, efficient, simple mail transport system. + . + Dan Bernstein (qmail's author) only gives permission for qmail to be + distributed in source form, or binary for by approval. This package + has been put together to allow people to easily build a qmail binary + package for themselves, from source. + . + To build a binary deb package, first install the qmail-src package, then + type the command "build-qmail". If you try "apt-get source --build qmail-src" + only the qmail-src package will be built. You will need to install qmail-src + and type the command "build-qmail" to get a usable binary package of qmail. + Also be sure to build and install ucspi-tcp before installing the binary qmail + package. Install the ucspi-tcp-src package to get ucspi-tcp. + . + This package builds a binary .deb that is FHS compliant and conforms to the + Debian standards guidelines. The resulting binary packages are not suitable + for re-distribution. + . + There are pre-compiled binary packages for qmail available, but they do not + conform to the Debian standards, and are not available in the official archive. --- qmail-1.03.orig/debian/debianize-source-tree +++ qmail-1.03/debian/debianize-source-tree @@ -0,0 +1,53 @@ +#!/bin/bash + +set -e + +if [ ! -f qmail-start.c ]; then + echo "This program must be run from the qmail source directory!" + exit 1 +fi + +#if [ ! -f qmail-send.8 ]; then +# make man +#fi + +for f in `fgrep -l QMAIL/bin *.sh`; do + mv $f $f.$$ && sed -e "s,QMAIL/bin/predate,/usr/sbin/predate,g" \ + -e "s,QMAIL/bin/sendmail,/usr/sbin/sendmail,g" \ + -e "s,QMAIL/bin/maildir2mbox,/usr/bin/maildir2mbox,g" \ + -e "s,QMAIL/bin/qmail-inject,/usr/sbin/qmail-inject,g" \ + -e "s,exec env - PATH=\"QMAIL/bin:\$PATH\",exec,g" \ + -e "s,QMAIL/bin/qlist,/usr/bin/qlist,g" $f.$$ >$f && \ + rm $f.$$ +done + +if ls *.$$ >/dev/null 2>&1; then + echo Error during debianization! Some temporary files remain. + exit 1 +fi + +if fgrep QMAIL/bin *.sh; then + echo Error during debianization! Some .sh files still have relative paths. + exit 2 +fi + + +if fgrep -q nofiles conf-groups; then + if sed conf-groups.$$ -e '2s/nofiles/nogroup/' && \ + mv -f conf-groups.$$ conf-groups; then + echo The file conf-groups was auto-edited. + echo Please eyeball it to see if the editing was done correctly. + echo --- begin conf-groups ---- + cat conf-groups + echo --- end conf-groups ---- + echo + else + echo Error during auto-editing of conf-groups! + exit 3 + fi +fi + +if grep '\"bin/' *.c | grep -v 'qmail-\(check\|setup\)' >/dev/null; then + echo Remember to replace the relative paths by full paths in the following files: + grep '\"bin/' *.c | grep -v 'qmail-\(check\|setup\)' +fi --- qmail-1.03.orig/debian/README.debian +++ qmail-1.03/debian/README.debian @@ -0,0 +1,196 @@ +qmail for Debian +------------------------------------- + +Extra patches automagically included with QMail: + +QMAIL-QUEUE environment patch. This allows you to specify a different program +to process mail messages before the real qmail-queue. It is very useful when +implementing virus scanning. I use the Qmail Scanner package available on +SourceForge at http://qmail-scanner.sourceforge.net/ It catches 10-15 e-mail +worms a day for me. QMAIL-QUEUE patch availabe at: +http://www.qmail.org/qmailqueue-patch + +badmailto patch. This is a patch that I wrote that mirrors the badmailfrom +functionality. In other words, it can block messages going TO a particular +address, rather than from. Whenever I have to fill in an e-mail address on a +site or form, I have a .qmail-default file setup so I can add a little tag to +let me know who I gave my address to. For example: The address I use on +SlashDot is jmarler-sd@emarler.com. If that e-mail address ever ends up on a +SPAM list, i simply add it to my badmailto list, and forget about it. The +badmailto stops the server from ever accepting the message. No messy bounce +messages to deal with. 100% effective. + +------ + +The long awaited 1.03 is here! Which means that Dan will probably release +a newer version just to make my life difficult :) + +Many things have changed in this release: + +1) 10 bug fixes. (#9760, #1182, #12311, #19131, #23102, #25600, #28394, #30578, +#31832, #31994) + +2) Most configuration files are now in /etc/qmail. Alias files have been moved +to /var/lib/qmail/alias. There are still symlinks to everything in /var/qmail. +Before you go posting bug reports that /var/qmail shouldn't exist, trust me when +I say there is a method to my madness. The author of qmail, Dan Bernstein, +will only approve a binary install if it works the same as the pre-compiled +versions available at the distribution sites. If I leave the symlinks in, it +still works exactly the way he designed it. Only it has been 'Debianized'. + +3) The checkpassword program is installed automatically in /usr/bin. This makes +it much easier to implement a pop-3 server. + +4) I got permission from Ivan Kohler to distribute his +mbox2maildir script. mbox2maildir is not officialy a part of qmail. + +Please refer to the changelog for a more detailed listing of what changed. + +Jon Marler +jmarler@debian.org + + +WARNING - WARNING - WARNING - WARNING - WARNING - WARNING + + qmail does not support dot-locking internally. + + You are in danger of losing mail if you re-configure + qmail without understanding the implications of this. + +WARNING - WARNING - WARNING - WARNING - WARNING - WARNING + +On Debian the standard location for a users mailbox is + + /var/spool/mail/ + +and when programs write to that file they are expected to lock the +file to prevent another process from accessing it at the same time, and +thus corrupting your mail file. + +For reasons explained in /usr/share/doc/qmail/INSTALL.mbox, qmail does +not do this. + +The default setup uses /usr/sbin/qmail-procmail to perform the final +delivery of mail with appropriate dot-locking to prevent loss of mail. +This is just a script that invokes procmail. + +You should not really need to invoke this as a user, but if you can +think of a reason to do so, a line like this in your .qmail file will +result in normal delivery via procmail: + + |/usr/sbin/qmail-procmail + +If you were to instead put something like: + + /var/spool/mail/phil + +in your .qmail file, it would deliver mail to that file, but would +lock it using flock's rather than dot-lock's. Unless you know +different, that would probably mean that every other program on the +system would consider the file to be unlocked, and would leave you +open to mail loss. + +Personally, I'd recommend moving to Maildir/ format if you can. Read +the files in /usr/share/doc/qmail to find out more. + +--- + +How the Debian setup differs from standard qmail setups: + + The default setup sets aliasempty (i.e. the default delivery method) + to be /usr/sbin/qmail-procmail, which is a wrapper around procmail. + + This results in delivery into /var/spool/mail. + + To change this to one of the more standard qmail setups edit + /etc/init.d/qmail + + The binaries normaly found in /var/qmail/bin have been split between + /usr/bin and /usr/sbin. + + The configuration files have been moved to /etc/qmail and the queue + has been moved to /var/spool/qmail. + + Symbolic links have been placed in /var/qmail to make it look like a + normal qmail setup. + + Debian is still using /etc/init.d/qmail as the place to configure the + startup, rather than playing with files in /var/qmail/rc + +--- + +tcpserver and /etc/tcp.smtp + +The default /etc/tcp.smtp file contains a single line: + + 127.0.0.1:allow,RELAYCLIENT="" + +which permits clients on the local machine to use this as a mail relay. For +more information, look at question 5.5 of the FAQ (/usr/share/doc/qmail/FAQ.gz) + +--- +Postmaster mail: + + You will want to create a ~alias/.qmail-postmaster file, probably containing + your e-mail address with an ampersand (&) in front of it, i.e: + + &myself@mydomain.com + + This will make postmaster mail go to you. I've also created a default + /var/qmail/users/assign file with contents that will ensure that other + non-user mail (root, mailer-daemon etc.) goes to the postmaster. + + These files should really be setup automatically in the postinst. + +--- +Other stuff: + + /usr/lib/qmail/eliminate-dups has been provided, to allow you to discard + incoming duplicate mails + +--------------------------- +/etc/inetd.conf & /etc/hosts.allow qmail-smtpd setup: + +[This approach has been dropped, in favour of tcpserver (see above)] + +Here's the old info, just in case you want to do it that way: + + the line in /etc/inetd.conf expects there to be special line(s) in + /etc/hosts.allow: + +smtp: .MYDOMAIN.COM: setenv RELAYCLIENT:twist { { /usr/bin/tcp-env /usr/sbin/qmail-smtpd 1>&3;} 2>&1|splogger qmail;} 3>&1 +smtp: ALL: twist { { /usr/bin/tcp-env /usr/sbin/qmail-smtpd 1>&3;} 2>&1|splogger qmail;} 3>&1 + + this example allows hosts from MYDOMAIN.COM to relay mail to anywhere, + and allows others to send mail to hosts listed in rcpthosts as usual. + + The `twist' stuff is to allow the log messages to go (via splogger) to + syslog, rather than mucking up the SMTP connection. + +Phil Hands + +============= + +To build qmail binary package, you have to run + build-qmail + +============= + +WARNING! WARNING! WARNING! + The binary packages built by build-qmail are + dependant on the uid and gid's of the system + that the package was built on. + + If you are building/installing qmail for the + first time, I highly recommend you check your + /etc/passwd, /etc/shadow, & /etc/group files + and remove ANY existing qmail uid or gid's and + re-install qmail-src. If you choose not to, + it may not work! + +============= + +QMail depends on the ucspi-tcp binary package before it can be installed. + +If you have not already installed ucspi-tcp-src and built ucspi-tcp, I suggest +you do that task first before installing the finished qmail package. --- qmail-1.03.orig/error.h +++ qmail-1.03/error.h @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; --- qmail-1.03.orig/qmail-popup.c +++ qmail-1.03/qmail-popup.c @@ -64,10 +64,10 @@ void err_syntax() { err("syntax error"); } void err_wantuser() { err("USER first"); } -void err_authoriz() { err("authorization first"); } +void err_authoriz(arg) char *arg; { err("authorization first"); } -void okay() { puts("+OK \r\n"); flush(); } -void pop3_quit() { okay(); die(); } +void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } +void pop3_quit(arg) char *arg; { okay(0); die(); } char unique[FMT_ULONG + FMT_ULONG + 3]; @@ -136,7 +136,7 @@ void pop3_user(arg) char *arg; { if (!*arg) { err_syntax(); return; } - okay(); + okay(0); seenuser = 1; if (!stralloc_copys(&username,arg)) die_nomem(); if (!stralloc_0(&username)) die_nomem(); --- qmail-1.03.orig/msg00151.txt +++ qmail-1.03/msg00151.txt @@ -0,0 +1,209 @@ +--- Makefile Mon Jun 15 06:53:16 1998 ++++ ../qmail-1.03-modified/Makefile Tue Sep 8 15:36:43 1998 +@@ -803,6 +803,7 @@ + predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ + qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ + qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ ++qmail-popbull \ + qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ + dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ + forward preline condredirect bouncesaying except maildirmake \ +@@ -930,6 +931,7 @@ + qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \ + qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \ + qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \ ++qmail-popbull.0 \ + qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \ + preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \ + maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \ +@@ -1286,6 +1288,18 @@ + timeoutwrite.h + ./compile qmail-pop3d.c + ++qmail-popbull: \ ++load qmail-popbull.o now.o substdio.a stralloc.a alloc.a str.a error.a ++ ./load qmail-popbull now.o substdio.a stralloc.a alloc.a fs.a str.a err +or.a ++ ++qmail-popbull.0: \ ++qmail-popbull.8 ++ nroff -man qmail-popbull.8 > qmail-popbull.0 ++ ++qmail-popbull.o: \ ++compile qmail-popbull.c direntry.h substdio.h stralloc.h fmt.h str.h ++ ./compile qmail-popbull.c ++ + qmail-popup: \ + load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \ + case.a fd.a sig.a wait.a stralloc.a alloc.a substdio.a error.a str.a \ + +diff -u -P ./qmail-popbull.8 new/qmail-popbull.8 +--- ./qmail-popbull.8 Wed Dec 31 19:00:00 1969 ++++ new/qmail-popbull.8 Wed Nov 19 08:53:24 1997 +@@ -0,0 +1,50 @@ ++.TH qmail-popbull 8 ++.SH NAME ++qmail-popbull \- insert bulletins ++.SH SYNOPSIS ++.B qmail-popbull ++.I bulletin-directory ++.I pop3d-program ++.I Maildir ++.SH DESCRIPTION ++.B qmail-popbull ++examines a directory of bulletins whenever a user checks their pop3 mail. ++When a new bulletin is seen, it inserts the bulletin into the user's ++.I Maildir . ++ ++It compares the time on the ++.I Maildir 's ++.B cur ++directory and compares it to the time on the bulletin. If the bulletin ++is newer, ++.B qmail-popbull ++inserts a symlink to the bulletin into the user's Maildir/new directory. ++The bulletin should be an ordinary email message. One reasonable use ++of ++.B qmail-popbull ++is to point it to the ++.B new ++directory of a special user's Maildir. When you send that user mail, ++it becomes a bulletin. ++ ++When it is finished, it execs the ++.I pop3d-program ++with the remainder of its arguments as arguments to ++.I pop3d-program . ++ ++.I pop3d-program ++can be any program, but that program's first argument must be the user's ++.I Maildir . ++ ++Suggested invocation: ++.EX ++ qmail-popup YOURHOST /bin/checkpassword /var/qmail/bin/qmail-popbull ++.br ++ /var/spool/bulletins /var/qmail/bin/qmail-pop3d Maildir ++.br ++ (all on one line) ++.EE ++ ++.SH "SEE ALSO" ++qmail-popup(8), ++qmail-pop3d(8) +diff -u -P ./qmail-popbull.c new/qmail-popbull.c +--- ./qmail-popbull.c Wed Dec 31 19:00:00 1969 ++++ new/qmail-popbull.c Wed Nov 19 08:40:07 1997 +@@ -0,0 +1,108 @@ ++#include ++#include ++#include "direntry.h" ++#include "substdio.h" ++#include "stralloc.h" ++#include "subfd.h" ++#include "fmt.h" ++#include "error.h" ++#include "datetime.h" ++#include "now.h" ++#include "str.h" ++ ++void die() { _exit(100); } ++void die_temp() { _exit(111); } ++void die_usage() { ++ substdio_putsflush(subfderr,"qmail-popbull: usage: qmail-popbull bulldir pop3 +d maildir\n"); die_temp(); } ++void die_nobulldir() { ++ substdio_putsflush(subfderr,"qmail-popbull: fatal: unable to read bulldir\n") +; die_temp(); } ++void die_nomaildir() { ++ substdio_putsflush(subfderr,"qmail-popbull: fatal: unable to write to maildir +\n"); die_temp(); } ++void die_nomem() { ++ substdio_putsflush(subfderr,"qmail-popbull: fatal: out of memory\n"); die_tem +p(); } ++ ++stralloc cur_name = {0}; ++stralloc fn = {0}; ++stralloc fn2 = {0}; ++char fntmptph[80 + FMT_ULONG * 2]; ++ ++void fnmake_maildir(dir) ++char *dir; ++{ ++ unsigned long pid; ++ unsigned long time; ++ char host[64]; ++ char *s; ++ int loop; ++ struct stat st; ++ int fd; ++ ++ pid = getpid(); ++ host[0] = 0; ++ gethostname(host,sizeof(host)); ++ for (loop = 0;;++loop) ++ { ++ time = now(); ++ s = fntmptph; ++ s += fmt_str(s,"new/"); ++ s += fmt_ulong(s,time); *s++ = '.'; ++ s += fmt_ulong(s,pid); *s++ = '.'; ++ s += fmt_strn(s,host,sizeof(host)); *s++ = 0; ++ if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; ++ /* really should never get to this point */ ++ if (loop == 2) _exit(1); ++ sleep(2); ++ } ++} ++ ++ ++void main(argc,argv) ++int argc; ++char **argv; ++{ ++ int fd; ++ struct stat st; ++ datetime_sec cur_date; ++ char *bulldirname; ++ char *programname; ++ char *maildirname; ++ DIR *bulldir; ++ direntry *d; ++ char **childargs; ++ ++ if (!(bulldirname = argv[1])) die_usage(); ++ if (!(programname = argv[2])) die_usage(); ++ if (!(maildirname = argv[3])) die_usage(); ++ ++ if (!stralloc_copys(&cur_name, maildirname)) die_nomem(); ++ if (!stralloc_cats(&cur_name, "/cur")) die_nomem(); ++ if (!stralloc_0(&cur_name)) die_nomem(); ++ ++ if (stat(cur_name.s, &st) == -1) die_nomaildir(); ++ cur_date = st.st_atime; ++ ++ bulldir = opendir(bulldirname); ++ if (!bulldir) die_nobulldir(); ++ while(d = readdir(bulldir)) ++ { ++ if (str_equal(d->d_name,".")) continue; ++ if (str_equal(d->d_name,"..")) continue; ++ if (!stralloc_copys(&fn, bulldirname)) die_nomem(); ++ if (!stralloc_cats(&fn, "/")) die_nomem(); ++ if (!stralloc_cats(&fn, d->d_name)) die_nomem(); ++ if (!stralloc_0(&fn)) die_nomem(); ++ if (stat(fn.s, &st) == -1) die(); ++ if (st.st_mtime > cur_date) ++ { ++ fnmake_maildir(); ++ if (!stralloc_copys(&fn2, maildirname)) die_nomem(); ++ if (!stralloc_cats(&fn2, "/")) die_nomem(); ++ if (!stralloc_cats(&fn2, fntmptph)) die_nomem(); ++ if (!stralloc_0(&fn2)) die_nomem(); ++ symlink(fn.s, fn2.s); ++ } ++ } ++ closedir(bulldir); ++ childargs = argv + 2; ++ execvp(*childargs,childargs); ++} --- qmail-1.03.orig/proc.sh +++ qmail-1.03/proc.sh @@ -3,5 +3,5 @@ # Using splogger to send the log through syslog. # Using procmail to deliver messages to /var/spool/mail/$USER by default. -exec env - PATH="QMAIL/bin:$PATH" \ +exec \ qmail-start '|preline procmail' splogger qmail --- qmail-1.03.orig/qail.sh +++ qmail-1.03/qail.sh @@ -1 +1 @@ -QMAIL/bin/maildir2mbox && exec Mail ${1+"$@"} +/usr/bin/maildir2mbox && exec Mail ${1+"$@"} --- qmail-1.03.orig/install-big.c +++ qmail-1.03/install-big.c @@ -76,6 +76,7 @@ c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); + c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);