diff -N /usr/src/qmail/qmail-1.03/hier.c /usr/src/qmail/qmail-1.03-qregex/hier.c
78a79
>   c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
diff -N /usr/src/qmail/qmail-1.03/install-big.c /usr/src/qmail/qmail-1.03-qregex/install-big.c
78a79
>   c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
diff -N /usr/src/qmail/qmail-1.03/Makefile /usr/src/qmail/qmail-1.03-qregex/Makefile
1560c1560
< load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
---
> load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
1563c1563
< datetime.a getln.a open.a sig.a case.a env.a stralloc.a alloc.a substdio.a \
---
> datetime.a getln.a open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a \
1565c1565
< 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
---
> 	./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
1569c1569
< 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \
---
> 	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \
1708a1709,1712
> qregex.o: \
> compile qregex.c qregex.h
> 	./compile qregex.c
> 
diff -N /usr/src/qmail/qmail-1.03/qmail-control.9 /usr/src/qmail/qmail-1.03-qregex/qmail-control.9
22a23
> .IR badhelo ,
23a25,27
> .IR badmailfromnorelay ,
> .IR badmailto ,
> .IR badmailtonorelay ,
42a47
> .I badhelo	\fR(none)	\fRqmail-smtpd
43a49,51
> .I badmailfromnorelay	\fR(none)	\fRqmail-smtpd
> .I badmailto	\fR(none)	\fRqmail-smtpd
> .I badmailtonorelay	\fR(none)	\fRqmail-smtpd
diff -N /usr/src/qmail/qmail-1.03/qmail-showctl.c /usr/src/qmail/qmail-1.03-qregex/qmail-showctl.c
218c218,222
<   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.");
274a279
>     if (str_equal(d->d_name,"badhelo")) continue;
275a281,283
>     if (str_equal(d->d_name,"badmailfromnorelay")) continue;
>     if (str_equal(d->d_name,"badmailto")) continue;
>     if (str_equal(d->d_name,"badmailtonorelay")) continue;
diff -N /usr/src/qmail/qmail-1.03/qmail-smtpd.8 /usr/src/qmail/qmail-1.03-qregex/qmail-smtpd.8
66a67,80
> .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
71c85,86
< 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,
78a94,119
> 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.
diff -N /usr/src/qmail/qmail-1.03/qmail-smtpd.c /usr/src/qmail/qmail-1.03-qregex/qmail-smtpd.c
40a41,49
> #include "qregex.h"
> #include "strerr.h"
>  
> #define BMCHECK_BMF 0
> #define BMCHECK_BMFNR 1
> #define BMCHECK_BMT 2
> #define BMCHECK_BMTNR 3
> #define BMCHECK_BHELO 4 
> 
118c127,130
< void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
---
> void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
> void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
> void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); } 
> 
181a194
> 
184c197,208
< 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};
211,212c235,247
<   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;
320c355
< int bmfcheck()
---
> int bmcheck(which) int which;
322,327c357,396
<   int j;
<   if (!bmfok) return 0;
<   if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
<   j = byte_rchr(addr.s,addr.len,'@');
<   if (j < addr.len)
<     if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
---
>   int i = 0;
>   int j = 0;
>   int x = 0;
>   int negate = 0;
>   static stralloc bmb = {0};
>   static stralloc curregex = {0};
> 
>   if (which == BMCHECK_BMF) {
>     if (!stralloc_copy(&bmb,&bmf)) die_nomem();
>   } else if (which == BMCHECK_BMFNR) {
>     if (!stralloc_copy(&bmb,&bmfnr)) die_nomem();
>   } else if (which == BMCHECK_BMT) {
>     if (!stralloc_copy(&bmb,&bmt)) die_nomem();
>   } else if (which == BMCHECK_BMTNR) {
>     if (!stralloc_copy(&bmb,&bmtnr)) die_nomem();
>   } else if (which == BMCHECK_BHELO) {
>     if (!stralloc_copy(&bmb,&bhelo)) die_nomem();
>   } else {
>     die_control();
>   }
> 
>   while (j < bmb.len) {
>     i = j;
>     while ((bmb.s[i] != '\0') && (i < bmb.len)) i++;
>     if (bmb.s[j] == '!') {
>       negate = 1;
>       j++;
>     }
>     if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem();
>     if (!stralloc_0(&curregex)) die_nomem();
>     if (which == BMCHECK_BHELO) {
>       x = matchregex(helohost.s, curregex.s);
>     } else {
>       x = matchregex(addr.s, curregex.s);
>     }
>     if ((negate) && (x == 0)) return 1;
>     if (!(negate) && (x > 0)) return 1;
>     j = i + 1;
>     negate = 0;
>   }
360c429,431
< int flagbarf; /* defined if seenmail */
---
> int flagbarfbmf; /* defined if seenmail */
> int flagbarfbmt;
> int flagbarfbhelo;  
369a441
>   if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO); 
396a469
>   if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
408c481,485
<   flagbarf = bmfcheck();
---
>   flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */
>   if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF);
>   if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) {
>     flagbarfbmf = bmcheck(BMCHECK_BMFNR);
>   }   
489c566,584
<   if (flagbarf) { err_bmf(); return; }
---
>   if (flagbarfbhelo) {
>     strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0);
>     err_bhelo();
>     return;
>   }
>   if (flagbarfbmf) {
>     strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0);
>     err_bmf();
>     return;
>   }
>   if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT);
>   if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) {
>     flagbarfbmt = bmcheck(BMCHECK_BMTNR);
>   }
>   if (flagbarfbmt) {
>     strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0);
>     err_bmt();
>     return;
>   }  
diff -N /usr/src/qmail/qmail-1.03/qregex.c /usr/src/qmail/qmail-1.03-qregex/qregex.c
0a1,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 -N /usr/src/qmail/qmail-1.03/qregex.h /usr/src/qmail/qmail-1.03-qregex/qregex.h
0a1,5
> /* simple header file for the matchregex prototype */
> #ifndef _QREGEX_H_
> #define _QREGEX_H_
> int matchregex(char *text, char *regex);
> #endif
diff -N /usr/src/qmail/qmail-1.03/README.qregex /usr/src/qmail/qmail-1.03-qregex/README.qregex
0a1,196
> QREGEX (v2) 20040725 - README July 25, 2004
> A Regular Expression matching patch for qmail 1.03 and netqmail
> 
> 
> OVERVIEW:
> 
> qregex adds the ability to match address evelopes via Regular Expressions (REs)
> in the qmail-smtpd process. It has the abiltiy to match `helo/ehlo` (host name),
> `mail from` (envelope sender), and `rcpt to` (envelope recipient) commands.
> It follows all the base rules that are set out with qmail (ie using control
> files) so it makes for easy integretion into an existing setup (see the
> install instructions for more info). The v2 is specified because qregex was
> re-written to better conform to the security guarantee set forth by the author
> of qmail. The original version used stdio.h and stdlib.h for reading the
> control files whereas v2 now uses all stralloc functions which are much more
> regulated against buffer overruns and the like.
> See: http://cr.yp.to/qmail/guarantee.html
> 
> 
> FEATURES:
> 
> Features of qregex include:
> 
> 1. Performs pattern matching on envelope senders and envelope
>    recipients against REs in the badmailfrom and badmailto control
>    files. Two additional control files, badmailfromnorelay and
>    badmailtonorelay, are used for pattern matching when the 
>    RELAYCLIENT environment variable is not set.
> 
> 2. Performs pattern matching on the helo/ehlo host name. Setting the
>    NOBADHELO environment variable prevents the host name from being
>    compared to the patterns in the badhelo control file.
> 
> 3. Matches to patterns are logged
> 
> 4. Matching is case insensitive.
> 
> 5. qregex ignores empty envelope senders. An empty envelope sender is not
>    compared to the patterns in the badmailfrom and badmailfromnorelay
>    control files and is always accepted.
> 
> 
> PLATFORMS:
> 
> qregex has been built and tested on the following platforms. I'm sure it won't
> have any problems on any platform that qmail will run on (providing they have
> a regex interface) but if you run into problems let me know.
> 
> 	- OpenBSD 3.x
> 	- FreeBSD 4.x
> 	- Mandrake Linux 9.x
> 	- SuSE Linux 8.x
> 
> 
> 
> INSTALLATION INSTRUCTIONS:
> 
> Installation is very simple, there is only one requirement. You need to use the
> GNU version of the patch utility (http://www.gnu.org/software/patch/patch.html).
> (For Solaris 8 users it is installed as 'gpatch')
> 
> - If this is a new setup.
> Unpack the qmail archive, cd into the qmail-1.03 directory and run
> "patch < /path/to/qregex-<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>
> 
> 
> 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 -N /usr/src/qmail/qmail-1.03/TARGETS /usr/src/qmail/qmail-1.03-qregex/TARGETS
263a264
> qregex.o

