Download | Plain Text | No Line Numbers
- qregex-starttls-2way-auth-20060423.patch
-
- This patch is a combination of five patches that together provide the
- following features:
- secure SMTP communication using starttls
- authenticated SMTP for both the server and client side of connections
- SMTP connection filtering by pattern matching of envelope senders and recipients
- logging of canonicalised recipients by qmail-remote
-
- The five patches are:
- netqmail-1.05-tls-20060104 <http://inoa.net/qmail-tls/>
- qmail-smtpd-auth-057 <http://www.fehcom.de/qmail/smtpauth.html>
- qmail-remote_authenticated_smtp <http://www.ornl.gov/lists/mailing-lists/qmail/2002/03/msg00091.html>
- qregex-20060423 <http://www.arda.homeunix.net/store/qmail/>
- canonicalised-recipient-logging <http://romana.now.ie/#rcpt-logging>
-
- The version of qmail-remote_authenticated_smtp patch used here is the one
- modified by Robert Sander. Qmail-remote does the base64 encoding so the
- username and password appear as clear text in control/smtproutes.
-
- The version of qregex used here 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.
-
- I've made the following changes to the patches:
- * The files README.auth, README.remote-auth, and README.starttls are copied to
- the qmail/doc directory when qmail is installed.
- * I've changed the way that the qmail-remote_authenticated_smtp patch logs
- notifications that authentication isn't being used. The way the patch was
- doing it originally could result in lost mail or non-delivery
- notifications not being sent under certain circumstances.
- * I've added two lines to qmail-remote.c to fix another problem with the
- qmail-remote_authenticated_smtp patch. These two lines set the auth_status
- stralloc when remote authentication is used.
- * I've removed two lines from qmail-smtpd.c put there by the qmail-smtpd-auth
- patch. This was necessary to let the patch work with the starttls patch.
- As a consequence, TLS will not be reported in Received headers when
- ESMTPA is used.
-
- This patch applies cleanly to the following:
- netqmail-1.05
-
- To apply the patch, unpack the package, run the collate.sh script, and then cd
- into the netqmail-1.05 source tree.
- Run this command:
-
- patch < /path/to/patchfile
-
- To apply the patch to qmail-1.03 or netqmail-1.04, you need to increase patch's fuzz factor.
- This works for me.
-
- patch -F 3 < /path/to/patchfile
-
- Enjoy!
-
- This combination patch was prepared by:
- Andrew St. Jean <andrew@arda.homeunix.net>
- <http://www.arda.homeunix.net/store/qmail/>
-
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/base64.c ./netqmail-1.05/netqmail-1.05/base64.c
- --- ./netqmail-1.05.orig/netqmail-1.05/base64.c 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/base64.c 2006-05-10 19:28:51.219866097 -0400
- @@ -0,0 +1,122 @@
- +#include "base64.h"
- +#include "stralloc.h"
- +#include "substdio.h"
- +#include "str.h"
- +
- +static char *b64alpha =
- + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- +#define B64PAD '='
- +
- +/* returns 0 ok, 1 illegal, -1 problem */
- +
- +int b64decode(in,l,out)
- +const unsigned char *in;
- +int l;
- +stralloc *out; /* not null terminated */
- +{
- + int p = 0;
- + int n;
- + unsigned int x;
- + int i, j;
- + char *s;
- + unsigned char b[3];
- +
- + if (l == 0)
- + {
- + if (!stralloc_copys(out,"")) return -1;
- + return 0;
- + }
- +
- + while(in[l-1] == B64PAD) {
- + p ++;
- + l--;
- + }
- +
- + n = (l + p) / 4;
- + out->len = (n * 3) - p;
- + if (!stralloc_ready(out,out->len)) return -1;
- + s = out->s;
- +
- + for(i = 0; i < n - 1 ; i++) {
- + x = 0;
- + for(j = 0; j < 4; j++) {
- + if(in[j] >= 'A' && in[j] <= 'Z')
- + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
- + else if(in[j] >= 'a' && in[j] <= 'z')
- + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
- + else if(in[j] >= '0' && in[j] <= '9')
- + x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
- + else if(in[j] == '+')
- + x = (x << 6) + 62;
- + else if(in[j] == '/')
- + x = (x << 6) + 63;
- + else if(in[j] == '=')
- + x = (x << 6);
- + }
- +
- + s[2] = (unsigned char)(x & 255); x >>= 8;
- + s[1] = (unsigned char)(x & 255); x >>= 8;
- + s[0] = (unsigned char)(x & 255); x >>= 8;
- + s += 3; in += 4;
- + }
- +
- + x = 0;
- + for(j = 0; j < 4; j++) {
- + if(in[j] >= 'A' && in[j] <= 'Z')
- + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
- + else if(in[j] >= 'a' && in[j] <= 'z')
- + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
- + else if(in[j] >= '0' && in[j] <= '9')
- + x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
- + else if(in[j] == '+')
- + x = (x << 6) + 62;
- + else if(in[j] == '/')
- + x = (x << 6) + 63;
- + else if(in[j] == '=')
- + x = (x << 6);
- + }
- +
- + b[2] = (unsigned char)(x & 255); x >>= 8;
- + b[1] = (unsigned char)(x & 255); x >>= 8;
- + b[0] = (unsigned char)(x & 255); x >>= 8;
- +
- + for(i = 0; i < 3 - p; i++)
- + s[i] = b[i];
- +
- + return 0;
- +}
- +
- +int b64encode(in,out)
- +stralloc *in;
- +stralloc *out; /* not null terminated */
- +{
- + unsigned char a, b, c;
- + int i;
- + char *s;
- +
- + if (in->len == 0)
- + {
- + if (!stralloc_copys(out,"")) return -1;
- + return 0;
- + }
- +
- + if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
- + s = out->s;
- +
- + for (i = 0;i < in->len;i += 3) {
- + a = in->s[i];
- + b = i + 1 < in->len ? in->s[i + 1] : 0;
- + c = i + 2 < in->len ? in->s[i + 2] : 0;
- +
- + *s++ = b64alpha[a >> 2];
- + *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
- +
- + if (i + 1 >= in->len) *s++ = B64PAD;
- + else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
- +
- + if (i + 2 >= in->len) *s++ = B64PAD;
- + else *s++ = b64alpha[c & 63];
- + }
- + out->len = s - out->s;
- + return 0;
- +}
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/base64.h ./netqmail-1.05/netqmail-1.05/base64.h
- --- ./netqmail-1.05.orig/netqmail-1.05/base64.h 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/base64.h 2006-05-10 19:28:51.219866097 -0400
- @@ -0,0 +1,7 @@
- +#ifndef BASE64_H
- +#define BASE64_H
- +
- +extern int b64decode();
- +extern int b64encode();
- +
- +#endif
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/case_startb.c ./netqmail-1.05/netqmail-1.05/case_startb.c
- --- ./netqmail-1.05.orig/netqmail-1.05/case_startb.c 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/case_startb.c 2006-05-10 19:28:51.219866097 -0400
- @@ -0,0 +1,21 @@
- +#include "case.h"
- +
- +int case_startb(s,len,t)
- +register char *s;
- +unsigned int len;
- +register char *t;
- +{
- + register unsigned char x;
- + register 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 -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/conf-cc ./netqmail-1.05/netqmail-1.05/conf-cc
- --- ./netqmail-1.05.orig/netqmail-1.05/conf-cc 1998-06-15 06:53:16.000000000 -0400
- +++ ./netqmail-1.05/netqmail-1.05/conf-cc 2006-05-10 19:28:51.220865921 -0400
- @@ -1,3 +1,3 @@
- -cc -O2
- +cc -O2 -DTLS=20060104 -I/usr/local/ssl/include
-
- This will be used to compile .c files.
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/dns.c ./netqmail-1.05/netqmail-1.05/dns.c
- --- ./netqmail-1.05.orig/netqmail-1.05/dns.c 2004-06-04 21:51:58.000000000 -0400
- +++ ./netqmail-1.05/netqmail-1.05/dns.c 2006-05-10 19:28:51.220865921 -0400
- @@ -267,12 +267,11 @@
- int pref;
- {
- int r;
- - struct ip_mx ix;
- + struct ip_mx ix = {0};
-
- if (!stralloc_copy(&glue,sa)) return DNS_MEM;
- if (!stralloc_0(&glue)) return DNS_MEM;
- if (glue.s[0]) {
- - ix.pref = 0;
- if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
- {
- if (!ipalloc_append(ia,&ix)) return DNS_MEM;
- @@ -291,9 +290,16 @@
- ix.ip = ip;
- ix.pref = pref;
- if (r == DNS_SOFT) return DNS_SOFT;
- - if (r == 1)
- + if (r == 1) {
- +#ifdef IX_FQDN
- + ix.fqdn = glue.s;
- +#endif
- if (!ipalloc_append(ia,&ix)) return DNS_MEM;
- }
- + }
- +#ifdef IX_FQDN
- + glue.s = 0;
- +#endif
- return 0;
- }
-
- @@ -313,7 +319,7 @@
- {
- int r;
- struct mx { stralloc sa; unsigned short p; } *mx;
- - struct ip_mx ix;
- + struct ip_mx ix = {0};
- int nummx;
- int i;
- int j;
- @@ -325,7 +331,6 @@
- if (!stralloc_copy(&glue,sa)) return DNS_MEM;
- if (!stralloc_0(&glue)) return DNS_MEM;
- if (glue.s[0]) {
- - ix.pref = 0;
- if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
- {
- if (!ipalloc_append(ia,&ix)) return DNS_MEM;
- 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 2006-05-10 20:09:44.858547363 -0400
- @@ -76,6 +76,10 @@
- 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","README.auth",auto_uido,auto_gidq,0644);
- + c(auto_qmail,"doc","README.remote-auth",auto_uido,auto_gidq,0644);
- + c(auto_qmail,"doc","README.starttls",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);
- @@ -143,6 +147,9 @@
- 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);
- +#ifdef TLS
- + c(auto_qmail,"bin","update_tmprsadh",auto_uido,auto_gidq,0755);
- +#endif
-
- 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 -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 2006-05-10 20:10:18.298648290 -0400
- @@ -76,6 +76,10 @@
- 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","README.auth",auto_uido,auto_gidq,0644);
- + c(auto_qmail,"doc","README.remote-auth",auto_uido,auto_gidq,0644);
- + c(auto_qmail,"doc","README.starttls",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/ipalloc.h ./netqmail-1.05/netqmail-1.05/ipalloc.h
- --- ./netqmail-1.05.orig/netqmail-1.05/ipalloc.h 1998-06-15 06:53:16.000000000 -0400
- +++ ./netqmail-1.05/netqmail-1.05/ipalloc.h 2006-05-10 19:28:51.222865569 -0400
- @@ -3,7 +3,15 @@
-
- #include "ip.h"
-
- +#ifdef TLS
- +# define IX_FQDN 1
- +#endif
- +
- +#ifdef IX_FQDN
- +struct ip_mx { struct ip_address ip; int pref; char *fqdn; } ;
- +#else
- struct ip_mx { struct ip_address ip; int pref; } ;
- +#endif
-
- #include "gen_alloc.h"
-
- 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 2006-05-10 20:12:41.649359367 -0400
- @@ -136,6 +136,10 @@
- compile auto_usera.c
- ./compile auto_usera.c
-
- +base64.o: \
- +compile base64.c base64.h stralloc.h substdio.h str.h
- + ./compile base64.c
- +
- binm1: \
- binm1.sh conf-qmail
- cat binm1.sh \
- @@ -808,7 +812,7 @@
- forward preline condredirect bouncesaying except maildirmake \
- maildir2mbox maildirwatch qail elq pinq idedit install-big install \
- instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
- -binm3 binm3+df
- +binm3 binm3+df update_tmprsadh
-
- load: \
- make-load warn-auto.sh systype
- @@ -1441,12 +1445,13 @@
- 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 \
- 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
- +substdio.a error.a str.a fs.a auto_qmail.o base64.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 \
- + tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
- 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`
- + str.a fs.a auto_qmail.o base64.o `cat dns.lib` `cat socket.lib`
-
- qmail-remote.0: \
- qmail-remote.8
- @@ -1532,16 +1537,17 @@
- ./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 \
- -fs.a auto_qmail.o socket.lib
- - ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
- +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 base64.o socket.lib
- + ./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
- timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
- + tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
- 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 base64.o `cat \
- socket.lib`
-
- qmail-smtpd.0: \
- @@ -1553,7 +1559,7 @@
- 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
- +exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h
- ./compile qmail-smtpd.c
-
- qmail-start: \
- @@ -1681,6 +1687,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
- @@ -1827,7 +1837,8 @@
- ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
- ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
- prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
- -maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
- +maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
- +update_tmprsadh
- shar -m `cat FILES` > shar
- chmod 400 shar
-
- @@ -2108,6 +2119,19 @@
- compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
- ./compile timeoutwrite.c
-
- +qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
- +qmail-remote: tls.o ssl_timeoutio.o
- +qmail-smtpd.o: tls.h ssl_timeoutio.h
- +qmail-remote.o: tls.h ssl_timeoutio.h
- +
- +tls.o: \
- +compile tls.c exit.h error.h
- + ./compile tls.c
- +
- +ssl_timeoutio.o: \
- +compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
- + ./compile ssl_timeoutio.c
- +
- token822.o: \
- compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
- gen_alloc.h gen_allocdefs.h
- @@ -2139,3 +2163,26 @@
- wait_pid.o: \
- compile wait_pid.c error.h haswaitp.h
- ./compile wait_pid.c
- +
- +cert cert-req: \
- +Makefile-cert
- + @$(MAKE) -sf $< $@
- +
- +Makefile-cert: \
- +conf-qmail conf-users conf-groups Makefile-cert.mk
- + @cat Makefile-cert.mk \
- + | sed s}QMAIL}"`head -1 conf-qmail`"}g \
- + > $@
- +
- +update_tmprsadh: \
- +conf-qmail conf-users conf-groups update_tmprsadh.sh
- + @cat update_tmprsadh.sh\
- + | sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
- + | sed s}QMAIL}"`head -1 conf-qmail`"}g \
- + > $@
- + chmod 755 update_tmprsadh
- +
- +tmprsadh: \
- +update_tmprsadh
- + echo "Creating new temporary RSA and DH parameters"
- + ./update_tmprsadh
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/Makefile-cert.mk ./netqmail-1.05/netqmail-1.05/Makefile-cert.mk
- --- ./netqmail-1.05.orig/netqmail-1.05/Makefile-cert.mk 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/Makefile-cert.mk 2006-05-10 19:28:51.225865040 -0400
- @@ -0,0 +1,21 @@
- +cert-req: req.pem
- +cert cert-req: QMAIL/control/clientcert.pem
- + @:
- +
- +QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
- + ln -s $< $@
- +
- +QMAIL/control/servercert.pem:
- + PATH=$$PATH:/usr/local/ssl/bin \
- + openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
- + chmod 640 $@
- + chown `head -2 conf-users | tail -1`:`head -1 conf-groups` $@
- +
- +req.pem:
- + PATH=$$PATH:/usr/local/ssl/bin openssl req \
- + -new -nodes -out $@ -keyout QMAIL/control/servercert.pem
- + chmod 640 QMAIL/control/servercert.pem
- + chown `head -2 conf-users | tail -1`:`head -1 conf-groups` QMAIL/control/servercert.pem
- + @echo
- + @echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
- + @echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
- 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 2006-05-10 19:29:13.782888633 -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,14 +44,22 @@
- .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 clientca.pem \fR(none) \fRqmail-smtpd
- +.I clientcert.pem \fR(none) \fRqmail-remote
- .I concurrencylocal \fR10 \fRqmail-send
- .I concurrencyremote \fR20 \fRqmail-send
- .I defaultdomain \fIme \fRqmail-inject
- .I defaulthost \fIme \fRqmail-inject
- .I databytes \fR0 \fRqmail-smtpd
- +.I dh1024.pem \fR(none) \fRqmail-smtpd
- +.I dh512.pem \fR(none) \fRqmail-smtpd
- .I doublebouncehost \fIme \fRqmail-send
- .I doublebounceto \fRpostmaster \fRqmail-send
- .I envnoathost \fIme \fRqmail-send
- @@ -61,11 +73,17 @@
- .I qmqpservers \fR(none) \fRqmail-qmqpc
- .I queuelifetime \fR604800 \fRqmail-send
- .I rcpthosts \fR(none) \fRqmail-smtpd
- +.I rsa512.pem \fR(none) \fRqmail-smtpd
- +.I servercert.pem \fR(none) \fRqmail-smtpd
- .I smtpgreeting \fIme \fRqmail-smtpd
- .I smtproutes \fR(none) \fRqmail-remote
- .I timeoutconnect \fR60 \fRqmail-remote
- .I timeoutremote \fR1200 \fRqmail-remote
- .I timeoutsmtpd \fR1200 \fRqmail-smtpd
- +.I tlsclients \fR(none) \fRqmail-smtpd
- +.I tlsclientciphers \fR(none) \fRqmail-remote
- +.I tlshosts/FQDN.pem \fR(none) \fRqmail-remote
- +.I tlsserverciphers \fR(none) \fRqmail-smtpd
- .I virtualdomains \fR(none) \fRqmail-send
- .fi
- .RE
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-remote.8 ./netqmail-1.05/netqmail-1.05/qmail-remote.8
- --- ./netqmail-1.05.orig/netqmail-1.05/qmail-remote.8 1998-06-15 06:53:16.000000000 -0400
- +++ ./netqmail-1.05/netqmail-1.05/qmail-remote.8 2006-05-10 19:28:51.226864864 -0400
- @@ -114,6 +114,10 @@
- always exits zero.
- .SH "CONTROL FILES"
- .TP 5
- +.I clientcert.pem
- +SSL certificate that is used to authenticate with the remote server
- +during a TLS session.
- +.TP 5
- .I helohost
- Current host name,
- for use solely in saying hello to the remote SMTP server.
- @@ -123,6 +127,16 @@
- otherwise
- .B qmail-remote
- refuses to run.
- +
- +.TP 5
- +.I notlshosts/<FQDN>
- +.B qmail-remote
- +will not try TLS on servers for which this file exists
- +.RB ( <FQDN>
- +is the fully-qualified domain name of the server).
- +.IR (tlshosts/<FQDN>.pem
- +takes precedence over this file however).
- +
- .TP 5
- .I smtproutes
- Artificial SMTP routes.
- @@ -156,6 +170,8 @@
- this tells
- .B qmail-remote
- to look up MX records as usual.
- +.I port
- +value of 465 (deprecated smtps port) causes TLS session to be started.
- .I smtproutes
- may include wildcards:
-
- @@ -195,6 +211,33 @@
- .B qmail-remote
- will wait for each response from the remote SMTP server.
- Default: 1200.
- +
- +.TP 5
- +.I tlsclientciphers
- +A set of OpenSSL client cipher strings. Multiple ciphers
- +contained in a string should be separated by a colon.
- +
- +.TP 5
- +.I tlshosts/<FQDN>.pem
- +.B qmail-remote
- +requires TLS authentication from servers for which this certificate exists
- +.RB ( <FQDN>
- +is the fully-qualified domain name of the server). One of the
- +.I dNSName
- +or the
- +.I CommonName
- +attributes have to match.
- +
- +.B WARNING:
- +this option may cause mail to be delayed, bounced, doublebounced, or lost.
- +
- +.TP 5
- +.I tlshosts/exhaustivelist
- +if this file exists
- +no TLS will be tried on hosts other than those for which a file
- +.B tlshosts/<FQDN>.pem
- +exists.
- +
- .SH "SEE ALSO"
- addresses(5),
- envelopes(5),
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/qmail-remote.c ./netqmail-1.05/netqmail-1.05/qmail-remote.c
- --- ./netqmail-1.05.orig/netqmail-1.05/qmail-remote.c 1998-06-15 06:53:16.000000000 -0400
- +++ ./netqmail-1.05/netqmail-1.05/qmail-remote.c 2006-05-10 19:28:51.227864688 -0400
- @@ -28,6 +28,7 @@
- #include "timeoutconn.h"
- #include "timeoutread.h"
- #include "timeoutwrite.h"
- +#include "base64.h"
-
- #define HUGESMTPTEXT 5000
-
- @@ -43,11 +44,27 @@
- struct constmap maproutes;
- stralloc host = {0};
- stralloc sender = {0};
- +stralloc auth_smtp_user = {0};
- +stralloc auth_smtp_pass = {0};
- +stralloc auth_b64_user = {0};
- +stralloc auth_b64_pass = {0};
- +stralloc auth_status = {0};
-
- saa reciplist = {0};
-
- struct ip_address partner;
-
- +#ifdef TLS
- +# include <sys/stat.h>
- +# include "tls.h"
- +# include "ssl_timeoutio.h"
- +# include <openssl/x509v3.h>
- +# define EHLO 1
- +
- +int tls_init();
- +const char *ssl_err_str = 0;
- +#endif
- +
- 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); }
- @@ -85,6 +102,18 @@
- 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 auth_user_not_set() {
- + if(!stralloc_copys(&auth_status, \
- + "User and password not set, continuing without authentication.\n"))
- + temp_nomem();
- + if(!stralloc_0(&auth_status)) temp_nomem();
- +}
- +void no_supported_auth() {
- + if(!stralloc_copys(&auth_status, \
- + "No supported AUTH method found, continuing without authentication.\n"))
- + temp_nomem();
- + if(!stralloc_0(&auth_status)) temp_nomem();
- +}
-
- void outhost()
- {
- @@ -99,6 +128,9 @@
- outhost();
- out(" but connection died. ");
- if (flagcritical) out("Possible duplicate! ");
- +#ifdef TLS
- + if (ssl_err_str) { out(ssl_err_str); out(" "); }
- +#endif
- out("(#4.4.2)\n");
- zerodie();
- }
- @@ -110,6 +142,12 @@
- int saferead(fd,buf,len) int fd; char *buf; int len;
- {
- int r;
- +#ifdef TLS
- + if (ssl) {
- + r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
- + if (r < 0) ssl_err_str = ssl_error_str();
- + } else
- +#endif
- r = timeoutread(timeout,smtpfd,buf,len);
- if (r <= 0) dropped();
- return r;
- @@ -117,6 +155,12 @@
- int safewrite(fd,buf,len) int fd; char *buf; int len;
- {
- int r;
- +#ifdef TLS
- + if (ssl) {
- + r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
- + if (r < 0) ssl_err_str = ssl_error_str();
- + } else
- +#endif
- r = timeoutwrite(timeout,smtpfd,buf,len);
- if (r <= 0) dropped();
- return r;
- @@ -163,6 +207,65 @@
- return code;
- }
-
- +#ifdef EHLO
- +saa ehlokw = {0}; /* list of EHLO keywords and parameters */
- +int maxehlokwlen = 0;
- +
- +unsigned long ehlo()
- +{
- + stralloc *sa;
- + char *s, *e, *p;
- + unsigned long code;
- +
- + if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
- + ehlokw.len = 0;
- +
- +# ifdef MXPS
- + if (type == 's') return 0;
- +# endif
- +
- + substdio_puts(&smtpto, "EHLO ");
- + substdio_put(&smtpto, helohost.s, helohost.len);
- + substdio_puts(&smtpto, "\r\n");
- + substdio_flush(&smtpto);
- +
- + code = smtpcode();
- + if (code != 250) return code;
- +
- + s = smtptext.s;
- + while (*s++ != '\n') ; /* skip the first line: contains the domain */
- +
- + e = smtptext.s + smtptext.len - 6; /* 250-?\n */
- + while (s <= e)
- + {
- + int wasspace = 0;
- +
- + if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
- + sa = ehlokw.sa + ehlokw.len++;
- + if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
- +
- + /* smtptext is known to end in a '\n' */
- + for (p = (s += 4); ; ++p)
- + if (*p == '\n' || *p == ' ' || *p == '\t') {
- + if (!wasspace)
- + if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
- + if (*p == '\n') break;
- + wasspace = 1;
- + } else if (wasspace == 1) {
- + wasspace = 0;
- + s = p;
- + }
- + s = ++p;
- +
- + /* keyword should consist of alpha-num and '-'
- + * broken AUTH might use '=' instead of space */
- + for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
- + }
- +
- + return 250;
- +}
- +#endif
- +
- void outsmtptext()
- {
- int i;
- @@ -179,6 +282,11 @@
- char *prepend;
- char *append;
- {
- +#ifdef TLS
- + /* shouldn't talk to the client unless in an appropriate state */
- + int state = ssl ? ssl->state : SSL_ST_BEFORE;
- + if (state & SSL_ST_OK || (!smtps && state & SSL_ST_BEFORE))
- +#endif
- substdio_putsflush(&smtpto,"QUIT\r\n");
- /* waiting for remote side is just too ridiculous */
- out(prepend);
- @@ -186,6 +294,30 @@
- out(append);
- out(".\n");
- outsmtptext();
- +
- +#if defined(TLS) && defined(DEBUG)
- + if (ssl) {
- + X509 *peercert;
- +
- + out("STARTTLS proto="); out(SSL_get_version(ssl));
- + out("; cipher="); out(SSL_get_cipher(ssl));
- +
- + /* we want certificate details */
- + if (peercert = SSL_get_peer_certificate(ssl)) {
- + char *str;
- +
- + str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
- + out("; subject="); out(str); OPENSSL_free(str);
- +
- + str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
- + out("; issuer="); out(str); OPENSSL_free(str);
- +
- + X509_free(peercert);
- + }
- + out(";\n");
- + }
- +#endif
- +
- zerodie();
- }
-
- @@ -214,26 +346,297 @@
- substdio_flush(&smtpto);
- }
-
- +#ifdef TLS
- +char *partner_fqdn = 0;
- +
- +# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
- +void tls_quit(const char *s1, const char *s2)
- +{
- + out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
- +}
- +# define tls_quit_error(s) tls_quit(s, ssl_error())
- +
- +int match_partner(const char *s, int len)
- +{
- + if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
- + /* we also match if the name is *.domainname */
- + if (*s == '*') {
- + const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
- + if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
- + }
- + return 0;
- +}
- +
- +/* don't want to fail handshake if certificate can't be verified */
- +int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
- +
- +int tls_init()
- +{
- + int i;
- + SSL *myssl;
- + SSL_CTX *ctx;
- + stralloc saciphers = {0};
- + const char *ciphers, *servercert = 0;
- +
- + if (partner_fqdn) {
- + struct stat st;
- + stralloc tmp = {0};
- + if (!stralloc_copys(&tmp, "control/tlshosts/")
- + || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
- + || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
- + if (stat(tmp.s, &st) == 0)
- + servercert = tmp.s;
- + else {
- + if (!stralloc_copys(&tmp, "control/notlshosts/")
- + || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
- + temp_nomem();
- + if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
- + (stat(tmp.s, &st) == 0)) {
- + alloc_free(tmp.s);
- + return 0;
- + }
- + alloc_free(tmp.s);
- + }
- + }
- +
- + if (!smtps) {
- + stralloc *sa = ehlokw.sa;
- + unsigned int len = ehlokw.len;
- + /* look for STARTTLS among EHLO keywords */
- + for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
- + if (!len) {
- + if (!servercert) return 0;
- + out("ZNo TLS achieved while "); out(servercert);
- + out(" exists"); smtptext.len = 0; TLS_QUIT;
- + }
- + }
- +
- + SSL_library_init();
- + ctx = SSL_CTX_new(SSLv23_client_method());
- + if (!ctx) {
- + if (!smtps && !servercert) return 0;
- + smtptext.len = 0;
- + tls_quit_error("ZTLS error initializing ctx");
- + }
- +
- + if (servercert) {
- + if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
- + SSL_CTX_free(ctx);
- + smtptext.len = 0;
- + out("ZTLS unable to load "); tls_quit_error(servercert);
- + }
- + /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
- + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
- + }
- +
- + /* let the other side complain if it needs a cert and we don't have one */
- +# define CLIENTCERT "control/clientcert.pem"
- + if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
- + SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
- +# undef CLIENTCERT
- +
- + myssl = SSL_new(ctx);
- + SSL_CTX_free(ctx);
- + if (!myssl) {
- + if (!smtps && !servercert) return 0;
- + smtptext.len = 0;
- + tls_quit_error("ZTLS error initializing ssl");
- + }
- +
- + if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
- +
- + /* while the server is preparing a responce, do something else */
- + if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
- + { SSL_free(myssl); temp_control(); }
- + if (saciphers.len) {
- + for (i = 0; i < saciphers.len - 1; ++i)
- + if (!saciphers.s[i]) saciphers.s[i] = ':';
- + ciphers = saciphers.s;
- + }
- + else ciphers = "DEFAULT";
- + SSL_set_cipher_list(myssl, ciphers);
- + alloc_free(saciphers.s);
- +
- + /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
- + SSL_set_fd(myssl, smtpfd);
- +
- + /* read the responce to STARTTLS */
- + if (!smtps) {
- + if (smtpcode() != 220) {
- + SSL_free(myssl);
- + if (!servercert) return 0;
- + out("ZSTARTTLS rejected while ");
- + out(servercert); out(" exists"); TLS_QUIT;
- + }
- + smtptext.len = 0;
- + }
- +
- + ssl = myssl;
- + if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
- + tls_quit("ZTLS connect failed", ssl_error_str());
- +
- + if (servercert) {
- + X509 *peercert;
- + STACK_OF(GENERAL_NAME) *gens;
- +
- + int r = SSL_get_verify_result(ssl);
- + if (r != X509_V_OK) {
- + out("ZTLS unable to verify server with ");
- + tls_quit(servercert, X509_verify_cert_error_string(r));
- + }
- + alloc_free(servercert);
- +
- + peercert = SSL_get_peer_certificate(ssl);
- + if (!peercert) {
- + out("ZTLS unable to verify server ");
- + tls_quit(partner_fqdn, "no certificate provided");
- + }
- +
- + /* RFC 2595 section 2.4: find a matching name
- + * first find a match among alternative names */
- + gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
- + if (gens) {
- + for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
- + {
- + const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
- + if (gn->type == GEN_DNS)
- + if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
- + }
- + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- + }
- +
- + /* no alternative name matched, look up commonName */
- + if (!gens || i >= r) {
- + stralloc peer = {0};
- + X509_NAME *subj = X509_get_subject_name(peercert);
- + i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
- + if (i >= 0) {
- + const ASN1_STRING *s = X509_NAME_get_entry(subj, i)->value;
- + if (s) { peer.len = s->length; peer.s = s->data; }
- + }
- + if (peer.len <= 0) {
- + out("ZTLS unable to verify server ");
- + tls_quit(partner_fqdn, "certificate contains no valid commonName");
- + }
- + if (!match_partner(peer.s, peer.len)) {
- + out("ZTLS unable to verify server "); out(partner_fqdn);
- + out(": received certificate for "); outsafe(&peer); TLS_QUIT;
- + }
- + }
- +
- + X509_free(peercert);
- + }
- +
- + if (smtps) if (smtpcode() != 220)
- + quit("ZTLS Connected to "," but greeting failed");
- +
- + return 1;
- +}
- +#endif
- +
- stralloc recip = {0};
-
- +void mail_without_auth()
- +{
- + substdio_puts(&smtpto,"MAIL FROM:<");
- + substdio_put(&smtpto,sender.s,sender.len);
- + substdio_puts(&smtpto,">\r\n");
- + substdio_flush(&smtpto);
- +}
- +
- void smtp()
- {
- unsigned long code;
- int flagbother;
- - int i;
- + int i, j;
- +
- +#ifndef PORT_SMTP
- + /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
- +# define port smtp_port
- +#endif
- +
- +#ifdef TLS
- +# ifdef MXPS
- + if (type == 'S') smtps = 1;
- + else if (type != 's')
- +# endif
- + if (port == 465) smtps = 1;
- + if (!smtps)
- +#endif
-
- if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
-
- +#ifdef EHLO
- +# ifdef TLS
- + if (!smtps)
- +# endif
- + code = ehlo();
- +
- +# ifdef TLS
- + if (tls_init())
- + /* RFC2487 says we should issue EHLO (even if we might not need
- + * extensions); at the same time, it does not prohibit a server
- + * to reject the EHLO and make us fallback to HELO */
- + code = ehlo();
- +# endif
- +
- + if (code == 250) {
- + /* add EHLO response checks here */
- +
- + /* and if EHLO failed, use HELO */
- + } else {
- +#endif
- +
- substdio_puts(&smtpto,"HELO ");
- substdio_put(&smtpto,helohost.s,helohost.len);
- substdio_puts(&smtpto,"\r\n");
- substdio_flush(&smtpto);
- if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
-
- - substdio_puts(&smtpto,"MAIL FROM:<");
- - substdio_put(&smtpto,sender.s,sender.len);
- - substdio_puts(&smtpto,">\r\n");
- - substdio_flush(&smtpto);
- +#ifdef EHLO
- + }
- +#endif
- + i = 0;
- + if (auth_smtp_user.len && auth_smtp_pass.len) {
- + while((i += str_chr(smtptext.s+i,'\n') + 1) &&
- + (i+8 < smtptext.len) &&
- + str_diffn(smtptext.s+i+4,"AUTH",4));
- + if (((i+9 < smtptext.len) &&
- + (str_diffn(smtptext.s+i+9," ",1) ||
- + str_diffn(smtptext.s+i+9,"=",1))) &&
- + ( i += str_chr(smtptext.s+i,'L') + 1 ) &&
- + str_diffn(smtptext.s+i+1,"OGIN",4)) {
- +
- + if (b64encode(&auth_smtp_user,&auth_b64_user)) quit("ZConnected to "," but unable to base64encode user");
- + if (b64encode(&auth_smtp_pass,&auth_b64_pass)) quit("ZConnected to "," but unable to base64encode pass");
- +
- + substdio_puts(&smtpto,"AUTH LOGIN\r\n");
- + substdio_flush(&smtpto);
- + if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)");
- + substdio_put(&smtpto,auth_b64_user.s,auth_b64_user.len);
- + substdio_puts(&smtpto,"\r\n");
- + substdio_flush(&smtpto);
- + if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)");
- + substdio_put(&smtpto,auth_b64_pass.s,auth_b64_pass.len);
- + substdio_puts(&smtpto,"\r\n");
- + substdio_flush(&smtpto);
- + if (smtpcode() != 235) quit("ZConnected to "," but authentication was rejected (password)");
- + substdio_puts(&smtpto,"MAIL FROM:<");
- + substdio_put(&smtpto,sender.s,sender.len);
- + substdio_puts(&smtpto,"> AUTH=<");
- + substdio_put(&smtpto,sender.s,sender.len);
- + substdio_puts(&smtpto,">\r\n");
- + substdio_flush(&smtpto);
- + if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem();
- + if(!stralloc_0(&auth_status)) temp_nomem();
- + } else {
- + no_supported_auth();
- + mail_without_auth();
- + }
- + } else {
- + auth_user_not_set();
- + mail_without_auth();
- + }
- code = smtpcode();
- if (code >= 500) quit("DConnected to "," but sender was rejected");
- if (code >= 400) quit("ZConnected to "," but sender was rejected");
- @@ -246,15 +649,22 @@
- substdio_flush(&smtpto);
- code = smtpcode();
- if (code >= 500) {
- - out("h"); outhost(); out(" does not like recipient.\n");
- + out("h"); out(auth_status.s); outhost();
- + out(" does not like recipient.\n");
- outsmtptext(); zero();
- }
- else if (code >= 400) {
- - out("s"); outhost(); out(" does not like recipient.\n");
- + out("s"); out(auth_status.s); outhost();
- + out(" does not like recipient.\n");
- outsmtptext(); zero();
- }
- else {
- - out("r"); zero();
- + /*
- + * James Raftery <james@now.ie>
- + * Log _real_ envelope recipient, post canonicalisation.
- + */
- + out("r"); out(auth_status.s);
- + out("<"); outsafe(&reciplist.sa[i]); out("> "); zero();
- flagbother = 1;
- }
- }
- @@ -331,7 +741,7 @@
- char **argv;
- {
- static ipalloc ip = {0};
- - int i;
- + int i,j;
- unsigned long random;
- char **recips;
- unsigned long prefme;
- @@ -347,6 +757,9 @@
-
- if (!stralloc_copys(&host,argv[1])) temp_nomem();
-
- + if (!stralloc_copys(&auth_smtp_user,"")) temp_nomem();
- + if (!stralloc_copys(&auth_smtp_pass,"")) temp_nomem();
- +
- relayhost = 0;
- for (i = 0;i <= host.len;++i)
- if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
- @@ -355,6 +768,16 @@
- if (relayhost && !*relayhost) relayhost = 0;
-
- if (relayhost) {
- + i = str_chr(relayhost,' ');
- + if (relayhost[i]) {
- + j = str_chr(relayhost + i + 1,' ');
- + if (relayhost[j]) {
- + relayhost[i] = 0;
- + relayhost[i + j + 1] = 0;
- + if (!stralloc_copys(&auth_smtp_user,relayhost + i + 1)) temp_nomem();
- + if (!stralloc_copys(&auth_smtp_pass,relayhost + i + j + 2)) temp_nomem();
- + }
- + }
- i = str_chr(relayhost,':');
- if (relayhost[i]) {
- scan_ulong(relayhost + i + 1,&port);
- @@ -417,6 +840,9 @@
- if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
- tcpto_err(&ip.ix[i].ip,0);
- partner = ip.ix[i].ip;
- +#ifdef TLS
- + partner_fqdn = ip.ix[i].fqdn;
- +#endif
- smtp(); /* does not return */
- }
- tcpto_err(&ip.ix[i].ip,errno == error_timeout);
- 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 2006-05-10 19:29:13.783888457 -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 2006-05-10 20:24:02.114316580 -0400
- @@ -14,6 +14,15 @@
- see
- .BR tcp-environ(5) .
-
- +If the environment variable
- +.B SMTPS
- +is non-empty,
- +.B qmail-smtpd
- +starts a TLS session (to support the deprecated SMTPS protocol,
- +normally on port 465). Otherwise,
- +.B qmail-smtpd
- +offers the STARTTLS extension to ESMTP.
- +
- .B qmail-smtpd
- is responsible for counting hops.
- It rejects any message with 100 or more
- @@ -23,7 +32,30 @@
- header fields.
-
- .B qmail-smtpd
- -supports ESMTP, including the 8BITMIME and PIPELINING options.
- +supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
- +.B qmail-smtpd
- +includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
- +.B qmail-smtpd
- +can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes
- +.IR checkprogram ,
- +which reads on file descriptor 3 the username, a 0 byte, the password
- +or CRAM-MD5 digest/response derived from the SMTP client,
- +another 0 byte, a CRAM-MD5 challenge (if applicable to the AUTH type),
- +and a final 0 byte.
- +.I checkprogram
- +invokes
- +.I subprogram
- +upon successful authentication, which should in turn return 0 to
- +.BR qmail-smtpd ,
- +effectively setting the environment variables $RELAYCLIENT and $TCPREMOTEINFO
- +(any supplied value replaced with the authenticated username).
- +.B qmail-smtpd
- +will reject the authentication attempt if it receives a nonzero return
- +value from
- +.I checkprogram
- +or
- +.IR subprogram .
- +
- .SH TRANSPARENCY
- .B qmail-smtpd
- converts the SMTP newline convention into the UNIX newline convention
- @@ -37,11 +69,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 +96,45 @@
- .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 clientca.pem
- +A list of Certifying Authority (CA) certificates that are used to verify
- +the client-presented certificates during a TLS-encrypted session.
- +
- +.TP 5
- +.I clientcrl.pem
- +A list of Certificate Revocation Lists (CRLs). If present it
- +should contain the CRLs of the CAs in
- +.I clientca.pem
- +and client certs will be checked for revocation.
- +
- .TP 5
- .I databytes
- Maximum number of bytes allowed in a message,
- @@ -76,6 +162,18 @@
- .B DATABYTES
- is set, it overrides
- .IR databytes .
- +
- +.TP 5
- +.I dh1024.pem
- +If these 1024 bit DH parameters are provided,
- +.B qmail-smtpd
- +will use them for TLS sessions instead of generating one on-the-fly
- +(which is very timeconsuming).
- +.TP 5
- +.I dh512.pem
- +512 bit counterpart for
- +.B dh1024.pem.
- +
- .TP 5
- .I localiphost
- Replacement host name for local IP addresses.
- @@ -151,6 +249,19 @@
-
- Envelope recipient addresses without @ signs are
- always allowed through.
- +
- +.TP 5
- +.I rsa512.pem
- +If this 512 bit RSA key is provided,
- +.B qmail-smtpd
- +will use it for TLS sessions instead of generating one on-the-fly.
- +
- +.TP 5
- +.I servercert.pem
- +SSL certificate to be presented to clients in TLS-encrypted sessions.
- +Should contain both the certificate and the private key. Certifying Authority
- +(CA) and intermediate certificates can be added at the end of the file.
- +
- .TP 5
- .I smtpgreeting
- SMTP greeting message.
- @@ -169,6 +280,24 @@
- .B qmail-smtpd
- will wait for each new buffer of data from the remote SMTP client.
- Default: 1200.
- +
- +.TP 5
- +.I tlsclients
- +A list of email addresses. When relay rules would reject an incoming message,
- +.B qmail-smtpd
- +can allow it if the client presents a certificate that can be verified against
- +the CA list in
- +.I clientca.pem
- +and the certificate email address is in
- +.IR tlsclients .
- +
- +.TP 5
- +.I tlsserverciphers
- +A set of OpenSSL cipher strings. Multiple ciphers contained in a
- +string should be separated by a colon. If the environment variable
- +.B TLSCIPHERS
- +is set to such a string, it takes precedence.
- +
- .SH "SEE ALSO"
- tcp-env(1),
- tcp-environ(5),
- 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 2006-05-10 20:22:01.244635083 -0400
- @@ -23,14 +23,44 @@
- #include "timeoutread.h"
- #include "timeoutwrite.h"
- #include "commands.h"
- +#include "qregex.h"
- +#include "strerr.h"
- +#include "wait.h"
- +
- +#define CRAM_MD5
- +#define AUTHSLEEP 5
- +
- +#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;
- int timeout = 1200;
-
- +const char *protocol = "SMTP";
- +
- +#ifdef TLS
- +#include <sys/stat.h>
- +#include "tls.h"
- +#include "ssl_timeoutio.h"
- +
- +void tls_init();
- +int tls_verify();
- +void tls_nogateway();
- +int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
- +#endif
- +
- int safewrite(fd,buf,len) int fd; char *buf; int len;
- {
- int r;
- +#ifdef TLS
- + if (ssl && fd == ssl_wfd)
- + r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
- + else
- +#endif
- r = timeoutwrite(timeout,fd,buf,len);
- if (r <= 0) _exit(1);
- return r;
- @@ -49,8 +79,20 @@
- 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_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\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"); }
- +#ifndef TLS
- void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
- +#else
- +void err_nogateway()
- +{
- + out("553 sorry, that domain isn't in my list of allowed rcpthosts");
- + tls_nogateway();
- + out(" (#5.7.1)\r\n");
- +}
- +#endif
- 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"); }
- @@ -59,6 +101,16 @@
- 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"); }
-
- +int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
- +int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
- +int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
- +int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
- +void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
- +void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
- +int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
- +int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
- +int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
- +void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
-
- stralloc greeting = {0};
-
- @@ -93,9 +145,24 @@
-
- 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};
- +
- +int logregex = 0;
- +stralloc matchedregex = {0};
-
- void setup()
- {
- @@ -109,13 +176,25 @@
- if (liphostok == -1) die_control();
- if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
- if (timeout <= 0) timeout = 1;
- -
- 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();
- +
- + 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 (env_get("LOGREGEX")) logregex = 1;
-
- if (control_readint(&databytes,"control/databytes") == -1) die_control();
- x = env_get("DATABYTES");
- @@ -131,6 +210,11 @@
- if (!remotehost) remotehost = "unknown";
- remoteinfo = env_get("TCPREMOTEINFO");
- relayclient = env_get("RELAYCLIENT");
- +
- +#ifdef TLS
- + if (env_get("SMTPS")) { smtps = 1; tls_init(); }
- + else
- +#endif
- dohelo(remotehost);
- }
-
- @@ -197,14 +281,56 @@
- 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)) {
- + if (!stralloc_copyb(&matchedregex,bmb.s + j - 1,(i - j + 1))) die_nomem();
- + if (!stralloc_0(&matchedregex)) die_nomem();
- + return 1;
- + }
- + if (!(negate) && (x > 0)) {
- + if (!stralloc_copyb(&matchedregex,bmb.s + j,(i - j))) die_nomem();
- + if (!stralloc_0(&matchedregex)) die_nomem();
- + return 1;
- + }
- + j = i + 1;
- + negate = 0;
- + }
- return 0;
- }
-
- @@ -213,24 +339,110 @@
- int r;
- r = rcpthosts(addr.s,str_len(addr.s));
- if (r == -1) die_control();
- +#ifdef TLS
- + if (r == 0) if (tls_verify()) r = -2;
- +#endif
- return r;
- }
-
-
- int seenmail = 0;
- -int flagbarf; /* defined if seenmail */
- +int flagbarfbmf; /* defined if seenmail */
- +int flagbarfbmt;
- +int flagbarfbhelo;
- +int flagsize;
- stralloc mailfrom = {0};
- stralloc rcptto = {0};
- +stralloc fuser = {0};
- +stralloc mfparms = {0};
- +
- +int mailfrom_size(arg) char *arg;
- +{
- + long r;
- + unsigned long sizebytes = 0;
- +
- + scan_ulong(arg,&r);
- + sizebytes = r;
- + if (databytes) if (sizebytes > databytes) return 1;
- + return 0;
- +}
- +
- +void mailfrom_auth(arg,len)
- +char *arg;
- +int len;
- +{
- + int j;
- +
- + if (!stralloc_copys(&fuser,"")) die_nomem();
- + if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
- + else
- + while (len) {
- + if (*arg == '+') {
- + if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
- + if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
- + }
- + else
- + if (!stralloc_catb(&fuser,arg,1)) die_nomem();
- + arg++; len--;
- + }
- + if(!stralloc_0(&fuser)) die_nomem();
- + if (!remoteinfo) {
- + remoteinfo = fuser.s;
- + if (!env_unset("TCPREMOTEINFO")) die_read();
- + if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
- + }
- +}
- +
- +void mailfrom_parms(arg) char *arg;
- +{
- + int i;
- + int len;
- +
- + len = str_len(arg);
- + if (!stralloc_copys(&mfparms,"")) die_nomem;
- + i = byte_chr(arg,len,'>');
- + if (i > 4 && i < len) {
- + while (len) {
- + arg++; len--;
- + if (*arg == ' ' || *arg == '\0' ) {
- + if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
- + if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
- + if (!stralloc_copys(&mfparms,"")) die_nomem;
- + }
- + else
- + if (!stralloc_catb(&mfparms,arg,1)) die_nomem;
- + }
- + }
- +}
-
- void smtp_helo(arg) char *arg;
- {
- smtp_greet("250 "); out("\r\n");
- seenmail = 0; dohelo(arg);
- + if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
- }
- +/* ESMTP extensions are published here */
- void smtp_ehlo(arg) char *arg;
- {
- - smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
- +#ifdef TLS
- + struct stat st;
- +#endif
- + char size[FMT_ULONG];
- + size[fmt_ulong(size,(unsigned int) databytes)] = 0;
- + smtp_greet("250-");
- +#ifdef TLS
- + if (!ssl && (stat("control/servercert.pem",&st) == 0))
- + out("\r\n250-STARTTLS");
- +#endif
- + out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
- + out("250-SIZE "); out(size); out("\r\n");
- +#ifdef CRAM_MD5
- + out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
- +#else
- + out("250 AUTH LOGIN PLAIN\r\n");
- +#endif
- seenmail = 0; dohelo(arg);
- + if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
- }
- void smtp_rset(arg) char *arg;
- {
- @@ -240,7 +452,14 @@
- void smtp_mail(arg) char *arg;
- {
- if (!addrparse(arg)) { err_syntax(); return; }
- - flagbarf = bmfcheck();
- + flagsize = 0;
- + mailfrom_parms(arg);
- + if (flagsize) { err_size(); return; }
- + 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 +469,37 @@
- void smtp_rcpt(arg) char *arg; {
- if (!seenmail) { err_wantmail(); return; }
- if (!addrparse(arg)) { err_syntax(); return; }
- - if (flagbarf) { err_bmf(); return; }
- + if (flagbarfbhelo) {
- + if (logregex) {
- + strerr_warn6("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
- + } else {
- + strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0);
- + }
- + err_bhelo();
- + return;
- + }
- + if (flagbarfbmf) {
- + if (logregex) {
- + strerr_warn6("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
- + } else {
- + 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) {
- + if (logregex) {
- + strerr_warn6("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
- + } else {
- + strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0);
- + }
- + err_bmt();
- + return;
- + }
- if (relayclient) {
- --addr.len;
- if (!stralloc_cats(&addr,relayclient)) die_nomem();
- @@ -269,6 +518,11 @@
- {
- int r;
- flush();
- +#ifdef TLS
- + if (ssl && fd == ssl_rfd)
- + r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
- + else
- +#endif
- r = timeoutread(timeout,fd,buf,len);
- if (r == -1) if (errno == error_timeout) die_alarm();
- if (r <= 0) die_read();
- @@ -378,7 +632,7 @@
- qp = qmail_qp(&qqt);
- out("354 go ahead\r\n");
-
- - received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
- + received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
- blast(&hops);
- hops = (hops >= MAXHOPS);
- if (hops) qmail_fail(&qqt);
- @@ -388,28 +642,494 @@
- 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 (databytes) if (!bytestooverflow) { err_size(); return; }
- if (*qqx == 'D') out("554 "); else out("451 ");
- out(qqx + 1);
- out("\r\n");
- }
-
- +/* this file is too long ----------------------------------------- SMTP AUTH */
- +
- +char unique[FMT_ULONG + FMT_ULONG + 3];
- +static stralloc authin = {0}; /* input from SMTP client */
- +static stralloc user = {0}; /* authorization user-id */
- +static stralloc pass = {0}; /* plain passwd or digest */
- +static stralloc resp = {0}; /* b64 response */
- +#ifdef CRAM_MD5
- +static stralloc chal = {0}; /* plain challenge */
- +static stralloc slop = {0}; /* b64 challenge */
- +#endif
- +
- +int flagauth = 0;
- +char **childargs;
- +char ssauthbuf[512];
- +substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
- +
- +int authgetl(void) {
- + int i;
- +
- + if (!stralloc_copys(&authin,"")) die_nomem();
- + for (;;) {
- + if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
- + i = substdio_get(&ssin,authin.s + authin.len,1);
- + if (i != 1) die_read();
- + if (authin.s[authin.len] == '\n') break;
- + ++authin.len;
- + }
- +
- + if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
- + authin.s[authin.len] = 0;
- + if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
- + if (authin.len == 0) { return err_input(); }
- + return authin.len;
- +}
- +
- +int authenticate(void)
- +{
- + int child;
- + int wstat;
- + int pi[2];
- +
- + if (!stralloc_0(&user)) die_nomem();
- + if (!stralloc_0(&pass)) die_nomem();
- +#ifdef CRAM_MD5
- + if (!stralloc_0(&chal)) die_nomem();
- +#endif
- +
- + if (pipe(pi) == -1) return err_pipe();
- + switch(child = fork()) {
- + case -1:
- + return err_fork();
- + case 0:
- + close(pi[1]);
- + if(fd_copy(3,pi[0]) == -1) return err_pipe();
- + sig_pipedefault();
- + execvp(*childargs, childargs);
- + _exit(1);
- + }
- + close(pi[0]);
- +
- + substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
- + if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
- + if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
- +#ifdef CRAM_MD5
- + if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
- +#endif
- + if (substdio_flush(&ssauth) == -1) return err_write();
- +
- + close(pi[1]);
- +#ifdef CRAM_MD5
- + if (!stralloc_copys(&chal,"")) die_nomem();
- + if (!stralloc_copys(&slop,"")) die_nomem();
- +#endif
- + byte_zero(ssauthbuf,sizeof ssauthbuf);
- + if (wait_pid(&wstat,child) == -1) return err_child();
- + if (wait_crashed(wstat)) return err_child();
- + if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
- + return 0; /* yes */
- +}
- +
- +int auth_login(arg) char *arg;
- +{
- + int r;
- +
- + if (*arg) {
- + if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
- + }
- + else {
- + out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
- + if (authgetl() < 0) return -1;
- + if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
- + }
- + if (r == -1) die_nomem();
- +
- + out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
- +
- + if (authgetl() < 0) return -1;
- + if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
- + if (r == -1) die_nomem();
- +
- + if (!user.len || !pass.len) return err_input();
- + return authenticate();
- +}
- +
- +int auth_plain(arg) char *arg;
- +{
- + int r, id = 0;
- +
- + if (*arg) {
- + if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input();
- + }
- + else {
- + out("334 \r\n"); flush();
- + if (authgetl() < 0) return -1;
- + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
- + }
- + if (r == -1 || !stralloc_0(&resp)) die_nomem();
- + while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */
- +
- + if (resp.len > id + 1)
- + if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
- + if (resp.len > id + user.len + 2)
- + if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
- +
- + if (!user.len || !pass.len) return err_input();
- + return authenticate();
- +}
- +
- +#ifdef CRAM_MD5
- +int auth_cram()
- +{
- + int i, r;
- + char *s;
- +
- + s = unique; /* generate challenge */
- + s += fmt_uint(s,getpid());
- + *s++ = '.';
- + s += fmt_ulong(s,(unsigned long) now());
- + *s++ = '@';
- + *s++ = 0;
- + if (!stralloc_copys(&chal,"<")) die_nomem();
- + if (!stralloc_cats(&chal,unique)) die_nomem();
- + if (!stralloc_cats(&chal,local)) die_nomem();
- + if (!stralloc_cats(&chal,">")) die_nomem();
- + if (b64encode(&chal,&slop) < 0) die_nomem();
- + if (!stralloc_0(&slop)) die_nomem();
- +
- + out("334 "); /* "334 base64_challenge \r\n" */
- + out(slop.s);
- + out("\r\n");
- + flush();
- +
- + if (authgetl() < 0) return -1; /* got response */
- + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
- + if (r == -1 || !stralloc_0(&resp)) die_nomem();
- +
- + i = str_chr(resp.s,' ');
- + s = resp.s + i;
- + while (*s == ' ') ++s;
- + resp.s[i] = 0;
- + if (!stralloc_copys(&user,resp.s)) die_nomem(); /* userid */
- + if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */
- +
- + if (!user.len || !pass.len) return err_input();
- + return authenticate();
- +}
- +#endif
- +
- +struct authcmd {
- + char *text;
- + int (*fun)();
- +} authcmds[] = {
- + { "login",auth_login }
- +, { "plain",auth_plain }
- +#ifdef CRAM_MD5
- +, { "cram-md5",auth_cram }
- +#endif
- +, { 0,err_noauth }
- +};
- +
- +void smtp_auth(arg)
- +char *arg;
- +{
- + int i;
- + char *cmd = arg;
- +
- + if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
- + if (flagauth) { err_authd(); return; }
- + if (seenmail) { err_authmail(); return; }
- +
- + if (!stralloc_copys(&user,"")) die_nomem();
- + if (!stralloc_copys(&pass,"")) die_nomem();
- + if (!stralloc_copys(&resp,"")) die_nomem();
- +#ifdef CRAM_MD5
- + if (!stralloc_copys(&chal,"")) die_nomem();
- +#endif
- +
- + i = str_chr(cmd,' ');
- + arg = cmd + i;
- + while (*arg == ' ') ++arg;
- + cmd[i] = 0;
- +
- + for (i = 0;authcmds[i].text;++i)
- + if (case_equals(authcmds[i].text,cmd)) break;
- +
- + switch (authcmds[i].fun(arg)) {
- + case 0:
- + flagauth = 1;
- + protocol = "ESMTPA";
- + relayclient = "";
- + remoteinfo = user.s;
- + if (!env_unset("TCPREMOTEINFO")) die_read();
- + if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
- + if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
- + out("235 ok, go ahead (#2.0.0)\r\n");
- + break;
- + case 1:
- + err_authfail(user.s,authcmds[i].text);
- + }
- +}
- +
- +
- +/* this file is too long --------------------------------------------- GO ON */
- +
- +#ifdef TLS
- +stralloc proto = {0};
- +int ssl_verified = 0;
- +const char *ssl_verify_err = 0;
- +
- +void smtp_tls(char *arg)
- +{
- + if (ssl) err_unimpl();
- + else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
- + else tls_init();
- +}
- +
- +RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
- +{
- + if (!export) keylen = 512;
- + if (keylen == 512) {
- + FILE *in = fopen("control/rsa512.pem", "r");
- + if (in) {
- + RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
- + fclose(in);
- + if (rsa) return rsa;
- + }
- + }
- + return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- +}
- +
- +DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
- +{
- + if (!export) keylen = 1024;
- + if (keylen == 512) {
- + FILE *in = fopen("control/dh512.pem", "r");
- + if (in) {
- + DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
- + fclose(in);
- + if (dh) return dh;
- + }
- + }
- + if (keylen == 1024) {
- + FILE *in = fopen("control/dh1024.pem", "r");
- + if (in) {
- + DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
- + fclose(in);
- + if (dh) return dh;
- + }
- + }
- + return DH_generate_parameters(keylen, DH_GENERATOR_2, NULL, NULL);
- +}
- +
- +/* don't want to fail handshake if cert isn't verifiable */
- +int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
- +
- +void tls_nogateway()
- +{
- + /* there may be cases when relayclient is set */
- + if (!ssl || relayclient) return;
- + out("; no valid cert for gatewaying");
- + if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
- +}
- +void tls_out(const char *s1, const char *s2)
- +{
- + out("454 TLS "); out(s1);
- + if (s2) { out(": "); out(s2); }
- + out(" (#4.3.0)\r\n"); flush();
- +}
- +void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
- +
- +# define CLIENTCA "control/clientca.pem"
- +# define CLIENTCRL "control/clientcrl.pem"
- +# define SERVERCERT "control/servercert.pem"
- +
- +int tls_verify()
- +{
- + stralloc clients = {0};
- + struct constmap mapclients;
- +
- + if (!ssl || relayclient || ssl_verified) return 0;
- + ssl_verified = 1; /* don't do this twice */
- +
- + /* request client cert to see if it can be verified by one of our CAs
- + * and the associated email address matches an entry in tlsclients */
- + switch (control_readfile(&clients, "control/tlsclients", 0))
- + {
- + case 1:
- + if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
- + /* if CLIENTCA contains all the standard root certificates, a
- + * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
- + * it is probably due to 0.9.6b supporting only 8k key exchange
- + * data while the 0.9.6c release increases that limit to 100k */
- + STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
- + if (sk) {
- + SSL_set_client_CA_list(ssl, sk);
- + SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
- + break;
- + }
- + constmap_free(&mapclients);
- + }
- + case 0: alloc_free(clients.s); return 0;
- + case -1: die_control();
- + }
- +
- + if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
- + const char *err = ssl_error_str();
- + tls_out("rehandshake failed", err); die_read();
- + }
- +
- + do { /* one iteration */
- + X509 *peercert;
- + X509_NAME *subj;
- + stralloc email = {0};
- +
- + int n = SSL_get_verify_result(ssl);
- + if (n != X509_V_OK)
- + { ssl_verify_err = X509_verify_cert_error_string(n); break; }
- + peercert = SSL_get_peer_certificate(ssl);
- + if (!peercert) break;
- +
- + subj = X509_get_subject_name(peercert);
- + n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
- + if (n >= 0) {
- + const ASN1_STRING *s = X509_NAME_get_entry(subj, n)->value;
- + if (s) { email.len = s->length; email.s = s->data; }
- + }
- +
- + if (email.len <= 0)
- + ssl_verify_err = "contains no email address";
- + else if (!constmap(&mapclients, email.s, email.len))
- + ssl_verify_err = "email address not in my list of tlsclients";
- + else {
- + /* add the cert email to the proto if it helped allow relaying */
- + --proto.len;
- + if (!stralloc_cats(&proto, "\n (cert ") /* continuation line */
- + || !stralloc_catb(&proto, email.s, email.len)
- + || !stralloc_cats(&proto, ")")
- + || !stralloc_0(&proto)) die_nomem();
- + relayclient = "";
- + protocol = proto.s;
- + }
- +
- + X509_free(peercert);
- + } while (0);
- + constmap_free(&mapclients); alloc_free(clients.s);
- +
- + /* we are not going to need this anymore: free the memory */
- + SSL_set_client_CA_list(ssl, NULL);
- + SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
- +
- + return relayclient ? 1 : 0;
- +}
- +
- +void tls_init()
- +{
- + SSL *myssl;
- + SSL_CTX *ctx;
- + const char *ciphers;
- + stralloc saciphers = {0};
- + X509_STORE *store;
- + X509_LOOKUP *lookup;
- +
- + SSL_library_init();
- +
- + /* a new SSL context with the bare minimum of options */
- + ctx = SSL_CTX_new(SSLv23_server_method());
- + if (!ctx) { tls_err("unable to initialize ctx"); return; }
- +
- + if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
- + { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
- + SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
- +
- +#if OPENSSL_VERSION_NUMBER >= 0x00907000L
- + /* crl checking */
- + store = SSL_CTX_get_cert_store(ctx);
- + if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
- + (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
- + X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
- + X509_V_FLAG_CRL_CHECK_ALL);
- +#endif
- +
- + /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
- + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
- +
- + /* a new SSL object, with the rest added to it directly to avoid copying */
- + myssl = SSL_new(ctx);
- + SSL_CTX_free(ctx);
- + if (!myssl) { tls_err("unable to initialize ssl"); return; }
- +
- + /* this will also check whether public and private keys match */
- + if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
- + { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
- +
- + ciphers = env_get("TLSCIPHERS");
- + if (!ciphers) {
- + if (control_readfile(&saciphers, "control/tlsserverciphers") == -1)
- + { SSL_free(myssl); die_control(); }
- + if (saciphers.len) { /* convert all '\0's except the last one to ':' */
- + int i;
- + for (i = 0; i < saciphers.len - 1; ++i)
- + if (!saciphers.s[i]) saciphers.s[i] = ':';
- + ciphers = saciphers.s;
- + }
- + }
- + if (!ciphers || !*ciphers) ciphers = "DEFAULT";
- + SSL_set_cipher_list(myssl, ciphers);
- + alloc_free(saciphers.s);
- +
- + SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
- + SSL_set_tmp_dh_callback(myssl, tmp_dh_cb);
- + SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
- + SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
- +
- + if (!smtps) { out("220 ready for tls\r\n"); flush(); }
- +
- + if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
- + /* neither cleartext nor any other response here is part of a standard */
- + const char *err = ssl_error_str();
- + ssl_free(myssl); tls_out("connection failed", err); die_read();
- + }
- + ssl = myssl;
- +
- + /* populate the protocol string, used in Received */
- + if (!stralloc_copys(&proto, "(")
- + || !stralloc_cats(&proto, SSL_get_cipher(ssl))
- + || !stralloc_cats(&proto, " encrypted) SMTP")) die_nomem();
- + if (!stralloc_0(&proto)) die_nomem();
- + protocol = proto.s;
- +
- + /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
- + dohelo(remotehost);
- +}
- +
- +# undef SERVERCERT
- +# undef CLIENTCA
- +
- +#endif
- +
- struct commands smtpcommands[] = {
- { "rcpt", smtp_rcpt, 0 }
- , { "mail", smtp_mail, 0 }
- , { "data", smtp_data, flush }
- +, { "auth", smtp_auth, flush }
- , { "quit", smtp_quit, flush }
- , { "helo", smtp_helo, flush }
- , { "ehlo", smtp_ehlo, flush }
- , { "rset", smtp_rset, 0 }
- , { "help", smtp_help, flush }
- +#ifdef TLS
- +, { "starttls", smtp_tls, flush }
- +#endif
- , { "noop", err_noop, flush }
- , { "vrfy", err_vrfy, flush }
- , { 0, err_unimpl, flush }
- } ;
-
- -void main()
- +void main(argc,argv)
- +int argc;
- +char **argv;
- {
- + childargs = argv + 1;
- sig_pipeignore();
- if (chdir(auto_qmail) == -1) die_control();
- setup();
- 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 2006-05-10 19:29:13.789887397 -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 <sys/types.h>
- +#include <regex.h>
- +#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 2006-05-10 19:29:13.789887397 -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.auth ./netqmail-1.05/netqmail-1.05/README.auth
- --- ./netqmail-1.05.orig/netqmail-1.05/README.auth 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/README.auth 2006-05-10 19:28:51.237862925 -0400
- @@ -0,0 +1,66 @@
- +README qmail-smtpd SMTP Authentication
- +======================================
- +
- +
- +History:
- +--------
- +
- +This patch is based on Krzysztof Dabrowski's qmail-smtpd-auth-0.31 patch
- +which itself uses "Mrs. Brisby's" initial code.
- +Version 0.41 of this patch fixes the "CAPS-LOCK" typo announcing
- +'CRAM_MD5' instead of 'CRAM-MD5' (german keyboard) - tx to Mike Garrison.
- +Version 0.42 fixes the '421 unable to read controls (#4.3.0)' problem
- +(can't read control/morercpthosts.cdb) because FD 3 was already closed - tx Richard Lyons.
- +Version 0.43 fixes the ba64decode() failure in case CRAM_MD5 is not enabled - tx Vladimir Zidar.
- +Version 0.51 includes the evaluation of the 'Auth' and the 'Size' parameter in the 'Mail From:' command.
- +Version 0.52 uses DJB functions to copy FDs.
- +Version 0.56 corrects some minor mistakes displaying the 'Auth' userid.
- +Version 0.57 uses keyword "ESMTPA" in Received header in case of authentication to comply with RFC 3848.
- +
- +
- +Scope:
- +------
- +
- +This patch supports RFC 2554 "SMTP Service Extension for Authentication" for qmail-smtpd.
- +Additionally, RFC 1870 is honoured ("SMTP Service Extension for Message Size Declaration").
- +For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html.
- +
- +
- +Installation:
- +-------------
- +
- +* Untar the source in the qmail-1.03 home direcotry.
- +* Run ./install_auth.
- +* Modify the compile time option "#define CRAM_MD5" to your needs.
- +* Re-make qmail.
- +
- +
- +Setup:
- +------
- +
- +In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module'
- +PAM to be called by qmail-smtpd; typically
- +
- + /var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1
- +
- +Since qmail-smtpd does not run as root, checkpassword has to be made sticky.
- +There is no need to include additionally the hostname in the call.
- +In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information.
- +
- +
- +Changes wrt. Krysztof Dabrowski's patch:
- +----------------------------------------
- +
- +* Avoid the 'hostname' in the call of the PAM.
- +* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5.
- +* Doesn't close FD 2; thus not inhibiting logging to STDERR.
- +* Fixed bugs in base64.c.
- +* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'.
- +* Evaluation of the (informational) Mail From: < > Auth=username.
- +* Additional support for the advertised "Size" via 'Mail From: <return-path> SIZE=123456780' (RFC 1870).
- +* RFC 3848 conformance for Received header in case of SMTP Auth.
- +
- +
- +Erwin Hoffmann - Cologne 2005-01-23 (www.fehcom.de)
- +
- +
- 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 2006-05-10 19:29:13.790887220 -0400
- @@ -0,0 +1,203 @@
- +QREGEX (v2) 20060423 - README April 23, 2006
- +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. Setting the LOGREGEX environment
- + variable causes the matched regex pattern to be included in the log.
- +
- +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, 5.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-<version>.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-<version> directory. From there, run
- +"patch < /path/to/qregex-<version>.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-<version>.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: <host> at <remote IP>
- +
- +badmailfrom and badmailfromnorelay
- +qmail-smtpd: badmailfrom: <sender address> at <remote IP>
- +
- +badmailto and badmailtonorelay
- +qmail-smtpd: badmailto: <rcpt address> at <remote IP>
- +
- +When the LOGREGEX environment variable is set, the matched pattern will
- +be included in the log. Log messages will have the regex pattern appended
- +to them. For example, a badhelo log message will look like this:
- +
- +qmail-smtpd: badhelo: <host> at <remote IP> matches pattern: <regex>
- +
- +
- +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/README.remote-auth ./netqmail-1.05/netqmail-1.05/README.remote-auth
- --- ./netqmail-1.05.orig/netqmail-1.05/README.remote-auth 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/README.remote-auth 2006-05-10 19:28:51.237862925 -0400
- @@ -0,0 +1,31 @@
- +Docs for http://www.qmail.org/qmail-remote_authenticated_smtp.patch
- +a patch to convince qmail-remote to use Authenticated SMTP when
- +talking to certain hosts.
- +
- +This version of the patch has been modified by Robert Sanders so that
- +base64 encoding of usernames and passwords is done automatically by
- +qmail-remote.
- +
- +After applying the patch, the username password go into
- +/var/qmail/control/smtproutes like so:
- +
- +domain:relay username password
- +
- +The domain:relay part is identical to a normal smtproutes entry (see
- +the qmail-remote man page). For sites that require authentication, you
- +simply add two space separated fields to the line, where the first
- +field is the username, the second is the password. For example:
- +
- +inside.af.mil:firewall.af.mil:26 johndoe secret
- +
- +would send mail for inside.af.mil to firewall.af.mil, port 26 using
- +username 'johndoe' and password 'secret'
- +
- +Since smtproutes will contain plain text usernames and passwords
- +you might want to make the file owned by qmailr and set its permissions
- +to 0600. Of course, the entries are going to go over the wire in the clear
- +anyway as part of the SMTP transaction.
- +
- +Good luck.
- +
- +j.
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/README.starttls ./netqmail-1.05/netqmail-1.05/README.starttls
- --- ./netqmail-1.05.orig/netqmail-1.05/README.starttls 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/README.starttls 2006-05-10 19:28:51.238862749 -0400
- @@ -0,0 +1,103 @@
- +Frederik Vermeulen <qmail-tls akrul inoa.net> 20060104
- +http://inoa.net/qmail-tls/
- +
- +This patch implements RFC 3207 (was RFC 2487) in qmail.
- +This means you can get SSL or TLS encrypted and
- +authenticated SMTP between the MTAs and from MUA to MTA.
- +The code is considered experimental (but has worked for
- +many since its first release on 1999-03-21).
- +
- +Usage: - install OpenSSL-0.9.8 http://www.openssl.org/
- + (any 0.9.6 to 0.9.8 version is presumed to work)
- + - apply patch to netqmail-1.05 http://qmail.org/netqmail
- + (should work on qmail-1.03 too). The patches to
- + qmail-remote.c and qmail-smtpd.c can be applied separately.
- + - provide a server certificate in /var/qmail/control/servercert.pem.
- + "make cert" makes a self-signed certificate.
- + "make cert-req" makes a certificate request.
- + Note: you can add the CA certificate and intermediate
- + certs to the end of servercert.pem.
- + - replace qmail-smtpd and/or qmail-remote binary
- + - verify operation (header information should show
- + something like
- + "Received [..] with (DHE-RSA-AES256-SHA encrypted) SMTP;")
- + If you don't have a server to test with, you can test
- + by sending mail to tag-ping@tbs-internet.com,
- + which will bounce your mail.
- +
- +Optional: - when DEBUG is defined, some extra TLS info will be logged
- + - qmail-remote will authenticate with the certificate in
- + /var/qmail/control/clientcert.pem. By preference this is
- + the same as servercert.pem, where nsCertType should be
- + == server,client or be a generic certificate (no usage specified).
- + - when a 512 bit RSA key is provided in /var/qmail/control/rsa512.pem,
- + this key will be used instead of (slow) on-the-fly generation by
- + qmail-smtpd. Idem for 512 and 1024 DH params in control/dh512.pem
- + and control/dh1024.pem. `make tmprsadh` does this.
- + Periodical replacement can be done by crontab:
- + 01 01 * * * /var/qmail/bin/update_tmprsadh > /dev/null 2>&1
- + - 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). CommonName has to match.
- + WARNING: this option may cause mail to be delayed, bounced,
- + doublebounced, and lost.
- + If /var/qmail/control/tlshosts/exhaustivelist is present,
- + the lists of hosts in /var/qmail/control/tlshosts is
- + an exhaustive list of hosts TLS is tried on.
- + If /var/qmail/control/notlshosts/host.dom.ain is present,
- + no TLS is tried on this host.
- + - 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. CRLs can be provided through
- + /var/qmail/control/clientcrl.pem.
- + - cipher selection:
- + qmail-remote:
- + openssl cipher string (`man ciphers`) read from
- + /var/qmail/control/tlsclientciphers
- + qmail-smtpd:
- + openssl cipher string read from TLSCIPHERS environment variable
- + (can vary based on client IP address e.g.)
- + or if that is not available /var/qmail/control/tlsserverciphers
- + - smtps (deprecated SMTP over TLS via port 465):
- + qmail-remote: when connecting to port 465
- + qmail-smtpd: when SMTPS environment variable is not empty
- +
- +Caveats: - do a `make clean` after patching
- + - binaries dynamically linked with current openssl versions need
- + recompilation when the shared openssl libs are upgraded.
- + - this patch could conflict with other patches (notably those
- + replacing \n with \r\n, which is a bad idea on encrypted links).
- + - some broken servers have a problem with TLSv1 compatibility.
- + Uncomment the line where we set the SSL_OP_NO_TLSv1 option.
- + - needs working /dev/urandom (or EGD for openssl versions >0.9.7)
- + for seeding random number generator.
- + - packagers should make sure that installing without a valid
- + servercert is impossible
- + - when applied in combination with AUTH patch, AUTH patch
- + should be applied first and first part of this patch
- + will fail. This error can be ignored. Packagers should
- + cut the first 12 lines of this patch to make a happy
- + patch
- + - `make tmprsadh` is recommended (or should I say required),
- + otherwise DH generation can be unpredictably slow
- + - some need "-I/usr/kerberos/include" to be added in conf-cc
- +
- +Copyright: GPL
- + Links with OpenSSL
- + Inspiration and code from examples in SSLeay (E. Young
- + <eay@cryptsoft.com> and T. Hudson <tjh@cryptsoft.com>),
- + stunnel (M. Trojnara <mtrojnar@ddc.daewoo.com.pl>),
- + Postfix/TLS (L. Jaenicke <Lutz.Jaenicke@aet.tu-cottbus.de>),
- + modssl (R. Engelschall <rse@engelschall.com>),
- + openssl examples of E. Rescorla <ekr@rtfm.com>.
- +
- +Bug reports: mailto:<qmail-tls akrul inoa.net>
- +
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/ssl_timeoutio.c ./netqmail-1.05/netqmail-1.05/ssl_timeoutio.c
- --- ./netqmail-1.05.orig/netqmail-1.05/ssl_timeoutio.c 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/ssl_timeoutio.c 2006-05-10 19:28:51.238862749 -0400
- @@ -0,0 +1,94 @@
- +#include "select.h"
- +#include "error.h"
- +#include "ndelay.h"
- +#include "ssl_timeoutio.h"
- +
- +int ssl_timeoutio(int (*fun)(),
- + long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
- +{
- + int n;
- + const long end = t + time(NULL);
- +
- + do {
- + fd_set fds;
- + struct timeval tv;
- +
- + const int r = buf ? fun(ssl, buf, len) : fun(ssl);
- + if (r > 0) return r;
- +
- + t = end - time(NULL);
- + if (t < 0) break;
- + tv.tv_sec = t; tv.tv_usec = 0;
- +
- + FD_ZERO(&fds);
- + switch (SSL_get_error(ssl, r))
- + {
- + default: return r; /* some other error */
- + case SSL_ERROR_WANT_READ:
- + FD_SET(rfd, &fds); n = select(rfd + 1, &fds, NULL, NULL, &tv);
- + break;
- + case SSL_ERROR_WANT_WRITE:
- + FD_SET(wfd, &fds); n = select(wfd + 1, NULL, &fds, NULL, &tv);
- + break;
- + }
- +
- + /* n is the number of descriptors that changed status */
- + } while (n > 0);
- +
- + if (n != -1) errno = error_timeout;
- + return -1;
- +}
- +
- +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl)
- +{
- + int r;
- +
- + /* if connection is established, keep NDELAY */
- + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
- + r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
- +
- + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
- + else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
- +
- + return r;
- +}
- +
- +int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl)
- +{
- + int r;
- +
- + /* if connection is established, keep NDELAY */
- + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
- + r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0);
- +
- + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
- + else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
- +
- + return r;
- +}
- +
- +int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl)
- +{
- + int r;
- +
- + SSL_renegotiate(ssl);
- + r = ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
- + if (r <= 0 || ssl->type == SSL_ST_CONNECT) return r;
- +
- + /* this is for the server only */
- + ssl->state = SSL_ST_ACCEPT;
- + return ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
- +}
- +
- +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
- +{
- + if (!buf) return 0;
- + if (SSL_pending(ssl)) return SSL_read(ssl, buf, len);
- + return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
- +}
- +
- +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
- +{
- + if (!buf) return 0;
- + return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
- +}
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/ssl_timeoutio.h ./netqmail-1.05/netqmail-1.05/ssl_timeoutio.h
- --- ./netqmail-1.05.orig/netqmail-1.05/ssl_timeoutio.h 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/ssl_timeoutio.h 2006-05-10 19:28:51.239862573 -0400
- @@ -0,0 +1,21 @@
- +#ifndef SSL_TIMEOUTIO_H
- +#define SSL_TIMEOUTIO_H
- +
- +#include <openssl/ssl.h>
- +
- +/* the version is like this: 0xMNNFFPPS: major minor fix patch status */
- +#if OPENSSL_VERSION_NUMBER < 0x00906000L
- +# error "Need OpenSSL version at least 0.9.6"
- +#endif
- +
- +int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl);
- +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl);
- +int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl);
- +
- +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
- +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
- +
- +int ssl_timeoutio(
- + int (*fun)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
- +
- +#endif
- 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 2006-05-10 19:29:13.791887044 -0400
- @@ -10,6 +10,7 @@
- qmail.o
- quote.o
- now.o
- +base64.o
- gfrom.o
- myctime.o
- slurpclose.o
- @@ -168,6 +169,8 @@
- constmap.o
- timeoutread.o
- timeoutwrite.o
- +tls.o
- +ssl_timeoutio.o
- timeoutconn.o
- tcpto.o
- dns.o
- @@ -252,6 +255,7 @@
- qmail-qmtpd
- qmail-smtpd.o
- qmail-smtpd
- +qregex.o
- sendmail.o
- sendmail
- tcp-env.o
- @@ -320,6 +324,7 @@
- binm2+df
- binm3
- binm3+df
- +Makefile-cert
- it
- qmail-local.0
- qmail-lspawn.0
- @@ -385,3 +390,4 @@
- man
- setup
- check
- +update_tmprsadh
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/tls.c ./netqmail-1.05/netqmail-1.05/tls.c
- --- ./netqmail-1.05.orig/netqmail-1.05/tls.c 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/tls.c 2006-05-10 19:28:51.240862397 -0400
- @@ -0,0 +1,25 @@
- +#include "exit.h"
- +#include "error.h"
- +#include <openssl/ssl.h>
- +#include <openssl/err.h>
- +
- +int smtps = 0;
- +SSL *ssl = NULL;
- +
- +void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
- +void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
- +
- +const char *ssl_error()
- +{
- + int r = ERR_get_error();
- + if (!r) return NULL;
- + SSL_load_error_strings();
- + return ERR_error_string(r, NULL);
- +}
- +const char *ssl_error_str()
- +{
- + const char *err = ssl_error();
- + if (err) return err;
- + if (!errno) return 0;
- + return (errno == error_timeout) ? "timed out" : error_str(errno);
- +}
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/tls.h ./netqmail-1.05/netqmail-1.05/tls.h
- --- ./netqmail-1.05.orig/netqmail-1.05/tls.h 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/tls.h 2006-05-10 19:28:51.240862397 -0400
- @@ -0,0 +1,16 @@
- +#ifndef TLS_H
- +#define TLS_H
- +
- +#include <openssl/ssl.h>
- +
- +extern int smtps;
- +extern SSL *ssl;
- +
- +void ssl_free(SSL *myssl);
- +void ssl_exit(int status);
- +# define _exit ssl_exit
- +
- +const char *ssl_error();
- +const char *ssl_error_str();
- +
- +#endif
- diff -u --unidirectional-new-file ./netqmail-1.05.orig/netqmail-1.05/update_tmprsadh.sh ./netqmail-1.05/netqmail-1.05/update_tmprsadh.sh
- --- ./netqmail-1.05.orig/netqmail-1.05/update_tmprsadh.sh 1969-12-31 19:00:00.000000000 -0500
- +++ ./netqmail-1.05/netqmail-1.05/update_tmprsadh.sh 2006-05-10 19:28:51.240862397 -0400
- @@ -0,0 +1,25 @@
- +#!/bin/sh
- +
- +# Update temporary RSA and DH keys
- +# Frederik Vermeulen 2004-05-31 GPL
- +
- +umask 0077 || exit 0
- +
- +export PATH="$PATH:/usr/local/bin/ssl:/usr/sbin"
- +
- +openssl genrsa -out QMAIL/control/rsa512.new 512 &&
- +chmod 600 QMAIL/control/rsa512.new &&
- +chown UGQMAILD QMAIL/control/rsa512.new &&
- +mv -f QMAIL/control/rsa512.new QMAIL/control/rsa512.pem
- +echo
- +
- +openssl dhparam -2 -out QMAIL/control/dh512.new 512 &&
- +chmod 600 QMAIL/control/dh512.new &&
- +chown UGQMAILD QMAIL/control/dh512.new &&
- +mv -f QMAIL/control/dh512.new QMAIL/control/dh512.pem
- +echo
- +
- +openssl dhparam -2 -out QMAIL/control/dh1024.new 1024 &&
- +chmod 600 QMAIL/control/dh1024.new &&
- +chown UGQMAILD QMAIL/control/dh1024.new &&
- +mv -f QMAIL/control/dh1024.new QMAIL/control/dh1024.pem
-