qregex-20060423-qmail.patch
changeset 1 b375914441b2
equal deleted inserted replaced
0:5766d031ef25 1:b375914441b2
       
     1 Fixed qregex-20060423 (pristine is against netqmail)
       
     2 
       
     3 diff -r 1510847ae5bf Makefile
       
     4 --- a/Makefile	Thu Nov 01 16:23:16 2007 +0100
       
     5 +++ b/Makefile	Thu Nov 01 16:24:02 2007 +0100
       
     6 @@ -1534,16 +1534,16 @@ auto_split.h
       
     7  	./compile qmail-showctl.c
       
     8  
       
     9  qmail-smtpd: \
       
    10 -load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
       
    11 +load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
       
    12  timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
       
    13  date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
       
    14 -open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
       
    15 +open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
       
    16  fs.a auto_qmail.o socket.lib
       
    17 -	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
       
    18 +	./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
       
    19  	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
       
    20  	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
       
    21  	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
       
    22 -	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
       
    23 +	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
       
    24  	socket.lib`
       
    25  
       
    26  qmail-smtpd.0: \
       
    27 @@ -1696,6 +1696,10 @@ compile rcpthosts.c cdb.h uint32.h byte.
       
    28  compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
       
    29  constmap.h stralloc.h gen_alloc.h rcpthosts.h
       
    30  	./compile rcpthosts.c
       
    31 +
       
    32 +qregex.o: \
       
    33 +compile qregex.c qregex.h
       
    34 +	./compile qregex.c
       
    35  
       
    36  readsubdir.o: \
       
    37  compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
       
    38 diff -r 1510847ae5bf README.qregex
       
    39 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
    40 +++ b/README.qregex	Thu Nov 01 16:24:02 2007 +0100
       
    41 @@ -0,0 +1,203 @@
       
    42 +QREGEX (v2) 20060423 - README April 23, 2006
       
    43 +A Regular Expression matching patch for qmail 1.03 and netqmail
       
    44 +
       
    45 +
       
    46 +OVERVIEW:
       
    47 +
       
    48 +qregex adds the ability to match address evelopes via Regular Expressions (REs)
       
    49 +in the qmail-smtpd process. It has the abiltiy to match `helo/ehlo` (host name),
       
    50 +`mail from` (envelope sender), and `rcpt to` (envelope recipient) commands.
       
    51 +It follows all the base rules that are set out with qmail (ie using control
       
    52 +files) so it makes for easy integretion into an existing setup (see the
       
    53 +install instructions for more info). The v2 is specified because qregex was
       
    54 +re-written to better conform to the security guarantee set forth by the author
       
    55 +of qmail. The original version used stdio.h and stdlib.h for reading the
       
    56 +control files whereas v2 now uses all stralloc functions which are much more
       
    57 +regulated against buffer overruns and the like.
       
    58 +See: http://cr.yp.to/qmail/guarantee.html
       
    59 +
       
    60 +
       
    61 +FEATURES:
       
    62 +
       
    63 +Features of qregex include:
       
    64 +
       
    65 +1. Performs pattern matching on envelope senders and envelope
       
    66 +   recipients against REs in the badmailfrom and badmailto control
       
    67 +   files. Two additional control files, badmailfromnorelay and
       
    68 +   badmailtonorelay, are used for pattern matching when the 
       
    69 +   RELAYCLIENT environment variable is not set.
       
    70 +
       
    71 +2. Performs pattern matching on the helo/ehlo host name. Setting the
       
    72 +   NOBADHELO environment variable prevents the host name from being
       
    73 +   compared to the patterns in the badhelo control file.
       
    74 +
       
    75 +3. Matches to patterns are logged. Setting the LOGREGEX environment
       
    76 +   variable causes the matched regex pattern to be included in the log. 
       
    77 +
       
    78 +4. Matching is case insensitive.
       
    79 +
       
    80 +5. qregex ignores empty envelope senders. An empty envelope sender is not
       
    81 +   compared to the patterns in the badmailfrom and badmailfromnorelay
       
    82 +   control files and is always accepted.
       
    83 +
       
    84 +
       
    85 +PLATFORMS:
       
    86 +
       
    87 +qregex has been built and tested on the following platforms. I'm sure it won't
       
    88 +have any problems on any platform that qmail will run on (providing they have
       
    89 +a regex interface) but if you run into problems let me know.
       
    90 +
       
    91 +	- OpenBSD 3.x
       
    92 +	- FreeBSD 4.x, 5.x
       
    93 +	- Mandrake Linux 9.x
       
    94 +	- SuSE Linux 8.x
       
    95 +
       
    96 +
       
    97 +
       
    98 +INSTALLATION INSTRUCTIONS:
       
    99 +
       
   100 +Installation is very simple, there is only one requirement. You need to use the
       
   101 +GNU version of the patch utility (http://www.gnu.org/software/patch/patch.html).
       
   102 +(For Solaris 8 users it is installed as 'gpatch')
       
   103 +
       
   104 +- If this is a new setup.
       
   105 +Unpack the qmail archive, cd into the qmail-1.03 directory and run
       
   106 +"patch < /path/to/qregex-<version>.patch". Follow the instructions as per the
       
   107 +included qmail INSTALL file. Once you are done come back to this file and read
       
   108 +the section on the control files.
       
   109 +
       
   110 +If you are using netqmail, then unpack the netqmail archive. Run the collate.sh
       
   111 +script and cd into the resulting netqmail-<version> directory. From there, run
       
   112 +"patch < /path/to/qregex-<version>.patch". Complete the netqmail installation
       
   113 +normally. Once you are done, come back to this file and read the section on the
       
   114 +control files.
       
   115 +
       
   116 +- If this is an existing setup.
       
   117 +FIRST: create your control files (see below).
       
   118 +cd into your existing qmail or netqmail source directory. Run
       
   119 +"patch < /path/to/qregex-<version>.patch" then "make qmail-smtpd". Now run
       
   120 +./qmail-smtpd and test your new rules to make sure they work as expected.
       
   121 +
       
   122 +Install the new binary by cd'ing to /var/qmail/bin and as root (in one command)
       
   123 +copy the existing binary to 'qmail-smtpd.old' and copy the new binary from the
       
   124 +source directory to 'qmail-smtpd'.
       
   125 +(ex. cp qmail-smtpd qmail-smtpd.old && cp ~/qmail-1.03/qmail-smtpd qmail-smtpd)
       
   126 +
       
   127 +You can also optionally just run "make setup check" as it will install the
       
   128 +updated documentation and man pages provided with this patch. Stopping qmail
       
   129 +before doing the "make setup check" is always a good idea.
       
   130 +
       
   131 +
       
   132 +LOGGING:
       
   133 +
       
   134 +qregex will log matches to the patterns in the various control files. Log
       
   135 +messages will take these three forms depending on which control file was
       
   136 +matched:
       
   137 +
       
   138 +badhelo
       
   139 +qmail-smtpd: badhelo: <host> at <remote IP>
       
   140 +
       
   141 +badmailfrom and badmailfromnorelay
       
   142 +qmail-smtpd: badmailfrom: <sender address> at <remote IP>
       
   143 +
       
   144 +badmailto and badmailtonorelay
       
   145 +qmail-smtpd: badmailto: <rcpt address> at <remote IP>
       
   146 +
       
   147 +When the LOGREGEX environment variable is set, the matched pattern will
       
   148 +be included in the log. Log messages will have the regex pattern appended
       
   149 +to them. For example, a badhelo log message will look like this:
       
   150 +
       
   151 +qmail-smtpd: badhelo: <host> at <remote IP> matches pattern: <regex>
       
   152 +
       
   153 +
       
   154 +CONTROL FILES:
       
   155 +
       
   156 +qregex provides you with five control files. None of these control files
       
   157 +is mandatory and you can use them in any combination you choose in your setup.
       
   158 +
       
   159 +The "control/badmailfrom" and "control/badmailto" files contain your REs for
       
   160 +matching against the 'mail from' (envelope sender) and 'rcpt to' (envelope
       
   161 +recipient) smtp commands respectively.
       
   162 +The "control/badmailfromnorelay" and "control/badmailtonorelay" match against
       
   163 +the same commands but are read only when the RELAYCLIENT environment variable
       
   164 +is not set.
       
   165 +The "control/badhelo" file matches against the 'helo/ehlo' smtp command.
       
   166 +
       
   167 +If you prefer you can symlink the badmailfrom and badmailto control files
       
   168 +(ln -s badmailfrom badmailto) and maintain fewer sets of rules. Beware
       
   169 +this might cause problems in certain setups.
       
   170 +        
       
   171 +	Here's an example "badhelo" file.
       
   172 +	-----------------------------------
       
   173 +	# block host strings with no dot (not a FQDN)
       
   174 +	!\.
       
   175 +	-----------------------------------
       
   176 +	
       
   177 +	An example "badmailfrom" file.
       
   178 +	-----------------------------------
       
   179 +	# this will drop everything containing the string
       
   180 +	# bad.domain.com or Bad.Domain.Com or BAD.domain.COM
       
   181 +	bad\.domain\.com
       
   182 +	# force users to fully qualify themselves
       
   183 +	# (i.e. deny "user", accept "user@domain")
       
   184 +	!@
       
   185 +	-----------------------------------
       
   186 +
       
   187 +	And "badmailto" (a little more interesting)
       
   188 +	-----------------------------------
       
   189 +	# must not contain invalid characters, brakets or multiple @'s
       
   190 +	[!%#:*^(){}]
       
   191 +	@.*@
       
   192 +	-----------------------------------
       
   193 +
       
   194 +You can use the non-RE character '!' to start an RE as a signal to qregex to
       
   195 +negate the action. As used above in the badmailfrom file, by negating the '@'
       
   196 +symbol qregex will signal qmail-smtpd to deny the 'mail from' command whenever
       
   197 +the address doesn't contain an @ symbol. When used inside a bracket expression,
       
   198 +the '!' character looses this special meaning. This is shown in the badmailto
       
   199 +example.
       
   200 +
       
   201 +The norelay control files follow the same rules as the other control files but
       
   202 +are intended to address two specific scenarios.
       
   203 +The badmailfromnorelay file can be used to block mail trying to spoof a domain
       
   204 +hosted on your mail server. It prevents a mail client that is not allowed to
       
   205 +relay email through your server from using one of your hosted domains as its
       
   206 +envelope sender.
       
   207 +The badmailtonorelay file can be used to create email addresses that cannot
       
   208 +receive mail from any source not allowed to relay email through your server.
       
   209 +This is handy for creating email addresses for use only within your own 
       
   210 +domain(s) that can't receive spam from the world at large.
       
   211 +
       
   212 +
       
   213 +INTERNALS:
       
   214 +
       
   215 +qregex (or regexmatch as the function is called) will be called during the
       
   216 +`helo/ehlo`, `rcpt to` and `mail from` handling routines in "qmail-smtpd.c".
       
   217 +When called, it will read the proper control file then one by one compile and
       
   218 +execute the regex on the string passed into qmail-smtpd. If the regex matches
       
   219 +it returns TRUE (1) and the qmail-smtpd process will deny the user the ability
       
   220 +to continue. If you change anything and think it betters this patch please
       
   221 +send me a new diff file so I can take a peek.
       
   222 +
       
   223 +
       
   224 +CONTACT:
       
   225 +qregex is maintained by:
       
   226 +	Andrew St. Jean
       
   227 +	andrew@arda.homeunix.net
       
   228 +	www.arda.homeunix.net/store/qmail/
       
   229 +
       
   230 +Contributers to qregex:
       
   231 +	Jeremy Kitchen	
       
   232 +	kitchen at scriptkitchen dot com
       
   233 +	http://www.scriptkitchen.com/qmail
       
   234 +
       
   235 +	Alex Pleiner
       
   236 +	alex@zeitform.de
       
   237 +	zeitform Internet Dienste
       
   238 +	http://www.zeitform.de/
       
   239 +
       
   240 +	Thanos Massias
       
   241 +
       
   242 +Original qregex patch written by:
       
   243 +	Evan Borgstrom
       
   244 +	evan at unixpimps dot org
       
   245 diff -r 1510847ae5bf TARGETS
       
   246 --- a/TARGETS	Thu Nov 01 16:23:16 2007 +0100
       
   247 +++ b/TARGETS	Thu Nov 01 16:24:02 2007 +0100
       
   248 @@ -252,6 +252,7 @@ qmail-qmtpd
       
   249  qmail-qmtpd
       
   250  qmail-smtpd.o
       
   251  qmail-smtpd
       
   252 +qregex.o
       
   253  sendmail.o
       
   254  sendmail
       
   255  tcp-env.o
       
   256 diff -r 1510847ae5bf hier.c
       
   257 --- a/hier.c	Thu Nov 01 16:23:16 2007 +0100
       
   258 +++ b/hier.c	Thu Nov 01 16:24:02 2007 +0100
       
   259 @@ -76,6 +76,7 @@ void hier()
       
   260    c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
       
   261  
       
   262    c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
       
   263 +  c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
       
   264    c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
       
   265    c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
       
   266    c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
       
   267 diff -r 1510847ae5bf install-big.c
       
   268 --- a/install-big.c	Thu Nov 01 16:23:16 2007 +0100
       
   269 +++ b/install-big.c	Thu Nov 01 16:24:02 2007 +0100
       
   270 @@ -76,6 +76,7 @@ void hier()
       
   271    c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
       
   272  
       
   273    c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
       
   274 +  c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
       
   275    c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
       
   276    c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
       
   277    c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
       
   278 diff -r 1510847ae5bf qmail-control.9
       
   279 --- a/qmail-control.9	Thu Nov 01 16:23:16 2007 +0100
       
   280 +++ b/qmail-control.9	Thu Nov 01 16:24:02 2007 +0100
       
   281 @@ -20,7 +20,11 @@ other hostname-related control files.
       
   282  
       
   283  Comments are allowed
       
   284  in
       
   285 +.IR badhelo ,
       
   286  .IR badmailfrom ,
       
   287 +.IR badmailfromnorelay ,
       
   288 +.IR badmailto ,
       
   289 +.IR badmailtonorelay ,
       
   290  .IR locals ,
       
   291  .IR percenthack ,
       
   292  .IR qmqpservers ,
       
   293 @@ -40,7 +44,11 @@ See the corresponding man pages for furt
       
   294  .ta 5c 10c
       
   295  control	default	used by
       
   296  
       
   297 +.I badhelo	\fR(none)	\fRqmail-smtpd
       
   298  .I badmailfrom	\fR(none)	\fRqmail-smtpd
       
   299 +.I badmailfromnorelay	\fR(none)	\fRqmail-smtpd
       
   300 +.I badmailto	\fR(none)	\fRqmail-smtpd
       
   301 +.I badmailtonorelay	\fR(none)	\fRqmail-smtpd
       
   302  .I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
       
   303  .I bouncehost	\fIme	\fRqmail-send
       
   304  .I concurrencylocal	\fR10	\fRqmail-send
       
   305 diff -r 1510847ae5bf qmail-showctl.c
       
   306 --- a/qmail-showctl.c	Thu Nov 01 16:23:16 2007 +0100
       
   307 +++ b/qmail-showctl.c	Thu Nov 01 16:24:02 2007 +0100
       
   308 @@ -214,7 +214,11 @@ void main()
       
   309      _exit(111);
       
   310    }
       
   311  
       
   312 -  do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM.");
       
   313 +  do_lst("badhelo","Any HELO host name is allowed.",""," HELO host name denied if it matches this pattern.");
       
   314 +  do_lst("badmailfrom","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern.");
       
   315 +  do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set.");
       
   316 +  do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern.");
       
   317 +  do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set.");
       
   318    do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
       
   319    do_str("bouncehost",1,"bouncehost","Bounce host name is ");
       
   320    do_int("concurrencylocal","10","Local concurrency is ","");
       
   321 @@ -267,7 +271,11 @@ void main()
       
   322      if (str_equal(d->d_name,"..")) continue;
       
   323      if (str_equal(d->d_name,"bouncefrom")) continue;
       
   324      if (str_equal(d->d_name,"bouncehost")) continue;
       
   325 +    if (str_equal(d->d_name,"badhelo")) continue;
       
   326      if (str_equal(d->d_name,"badmailfrom")) continue;
       
   327 +    if (str_equal(d->d_name,"badmailfromnorelay")) continue;
       
   328 +    if (str_equal(d->d_name,"badmailto")) continue;
       
   329 +    if (str_equal(d->d_name,"badmailtonorelay")) continue;
       
   330      if (str_equal(d->d_name,"bouncefrom")) continue;
       
   331      if (str_equal(d->d_name,"bouncehost")) continue;
       
   332      if (str_equal(d->d_name,"concurrencylocal")) continue;
       
   333 diff -r 1510847ae5bf qmail-smtpd.8
       
   334 --- a/qmail-smtpd.8	Thu Nov 01 16:23:16 2007 +0100
       
   335 +++ b/qmail-smtpd.8	Thu Nov 01 16:24:02 2007 +0100
       
   336 @@ -37,11 +37,26 @@ even though such messages violate the SM
       
   337  even though such messages violate the SMTP protocol.
       
   338  .SH "CONTROL FILES"
       
   339  .TP 5
       
   340 +.I badhelo
       
   341 +Unacceptable HELO/EHLO host names.
       
   342 +.B qmail-smtpd
       
   343 +will reject every recipient address for a message if
       
   344 +the host name is listed in, 
       
   345 +or matches a POSIX regular expression pattern listed in,
       
   346 +.IR badhelo .
       
   347 +If the 
       
   348 +.B NOBADHELO 
       
   349 +environment variable is set, then the contents of 
       
   350 +.IR badhelo 
       
   351 +will be ignored.
       
   352 +For more information, please have a look at doc/README.qregex.
       
   353 +.TP 5
       
   354  .I badmailfrom
       
   355  Unacceptable envelope sender addresses.
       
   356  .B qmail-smtpd
       
   357  will reject every recipient address for a message
       
   358 -if the envelope sender address is listed in
       
   359 +if the envelope sender address is listed in, or matches a POSIX regular expression
       
   360 +pattern listed in,
       
   361  .IR badmailfrom .
       
   362  A line in
       
   363  .I badmailfrom
       
   364 @@ -49,6 +64,32 @@ may be of the form
       
   365  .BR @\fIhost ,
       
   366  meaning every address at
       
   367  .IR host .
       
   368 +For more information, please have a look at doc/README.qregex.
       
   369 +.TP 5
       
   370 +.I badmailfromnorelay
       
   371 +Functions the same as the
       
   372 +.IR badmailfrom
       
   373 +control file but is read only if the 
       
   374 +.B RELAYCLIENT 
       
   375 +environment variable is not set.
       
   376 +For more information, please have a look at doc/README.qregex.
       
   377 +.TP 5
       
   378 +.I badmailto
       
   379 +Unacceptable envelope recipient addresses.
       
   380 +.B qmail-smtpd
       
   381 +will reject every recipient address for a message if the recipient address
       
   382 +is listed in,
       
   383 +or matches a POSIX regular expression pattern listed in,
       
   384 +.IR badmailto .
       
   385 +For more information, please have a look at doc/README.qregex.
       
   386 +.TP 5
       
   387 +.I badmailtonorelay
       
   388 +Functions the same as the
       
   389 +.IR badmailto
       
   390 +control file but is read only if the
       
   391 +.B RELAYCLIENT
       
   392 +environment variable is not set.
       
   393 +For more information, please have a look at doc/README.qregex.
       
   394  .TP 5
       
   395  .I databytes
       
   396  Maximum number of bytes allowed in a message,
       
   397 diff -r 1510847ae5bf qmail-smtpd.c
       
   398 --- a/qmail-smtpd.c	Thu Nov 01 16:23:16 2007 +0100
       
   399 +++ b/qmail-smtpd.c	Thu Nov 01 16:24:02 2007 +0100
       
   400 @@ -23,6 +23,15 @@
       
   401  #include "timeoutread.h"
       
   402  #include "timeoutwrite.h"
       
   403  #include "commands.h"
       
   404 +#include "qregex.h"
       
   405 +#include "strerr.h"
       
   406 +
       
   407 +#define BMCHECK_BMF 0
       
   408 +#define BMCHECK_BMFNR 1
       
   409 +#define BMCHECK_BMT 2
       
   410 +#define BMCHECK_BMTNR 3
       
   411 +#define BMCHECK_BHELO 4
       
   412 +    
       
   413  
       
   414  #define MAXHOPS 100
       
   415  unsigned int databytes = 0;
       
   416 @@ -49,7 +58,9 @@ void die_ipme() { out("421 unable to fig
       
   417  void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
       
   418  void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
       
   419  
       
   420 -void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
       
   421 +void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
       
   422 +void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
       
   423 +void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); }
       
   424  void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
       
   425  void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
       
   426  void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
       
   427 @@ -93,9 +104,24 @@ void dohelo(arg) char *arg; {
       
   428  
       
   429  int liphostok = 0;
       
   430  stralloc liphost = {0};
       
   431 +
       
   432  int bmfok = 0;
       
   433  stralloc bmf = {0};
       
   434 -struct constmap mapbmf;
       
   435 +
       
   436 +int bmfnrok = 0;
       
   437 +stralloc bmfnr = {0};
       
   438 +
       
   439 +int bmtok = 0;
       
   440 +stralloc bmt = {0};
       
   441 +
       
   442 +int bmtnrok = 0;
       
   443 +stralloc bmtnr = {0};
       
   444 +
       
   445 +int bhelook = 0;
       
   446 +stralloc bhelo = {0};
       
   447 +
       
   448 +int logregex = 0;
       
   449 +stralloc matchedregex = {0};
       
   450  
       
   451  void setup()
       
   452  {
       
   453 @@ -114,8 +140,21 @@ void setup()
       
   454  
       
   455    bmfok = control_readfile(&bmf,"control/badmailfrom",0);
       
   456    if (bmfok == -1) die_control();
       
   457 -  if (bmfok)
       
   458 -    if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
       
   459 +
       
   460 +  bmfnrok = control_readfile(&bmfnr,"control/badmailfromnorelay",0);
       
   461 +  if (bmfnrok == -1) die_control();
       
   462 +
       
   463 +  bmtok = control_readfile(&bmt,"control/badmailto",0);
       
   464 +  if (bmtok == -1) die_control();
       
   465 +
       
   466 +  bmtnrok = control_readfile(&bmtnr,"control/badmailtonorelay",0);
       
   467 +  if (bmtnrok == -1) die_control();
       
   468 +
       
   469 +  bhelook = control_readfile(&bhelo, "control/badhelo",0);
       
   470 +  if (bhelook == -1) die_control();
       
   471 +  if (env_get("NOBADHELO")) bhelook = 0;
       
   472 +
       
   473 +  if (env_get("LOGREGEX")) logregex = 1;
       
   474   
       
   475    if (control_readint(&databytes,"control/databytes") == -1) die_control();
       
   476    x = env_get("DATABYTES");
       
   477 @@ -197,14 +236,56 @@ char *arg;
       
   478    return 1;
       
   479  }
       
   480  
       
   481 -int bmfcheck()
       
   482 -{
       
   483 -  int j;
       
   484 -  if (!bmfok) return 0;
       
   485 -  if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
       
   486 -  j = byte_rchr(addr.s,addr.len,'@');
       
   487 -  if (j < addr.len)
       
   488 -    if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
       
   489 +int bmcheck(which) int which;
       
   490 +{
       
   491 +  int i = 0;
       
   492 +  int j = 0;
       
   493 +  int x = 0;
       
   494 +  int negate = 0;
       
   495 +  static stralloc bmb = {0};
       
   496 +  static stralloc curregex = {0};
       
   497 +
       
   498 +  if (which == BMCHECK_BMF) {
       
   499 +    if (!stralloc_copy(&bmb,&bmf)) die_nomem();
       
   500 +  } else if (which == BMCHECK_BMFNR) {
       
   501 +    if (!stralloc_copy(&bmb,&bmfnr)) die_nomem();
       
   502 +  } else if (which == BMCHECK_BMT) {
       
   503 +    if (!stralloc_copy(&bmb,&bmt)) die_nomem();
       
   504 +  } else if (which == BMCHECK_BMTNR) {
       
   505 +    if (!stralloc_copy(&bmb,&bmtnr)) die_nomem();
       
   506 +  } else if (which == BMCHECK_BHELO) {
       
   507 +    if (!stralloc_copy(&bmb,&bhelo)) die_nomem();
       
   508 +  } else {
       
   509 +    die_control();
       
   510 +  }
       
   511 +
       
   512 +  while (j < bmb.len) {
       
   513 +    i = j;
       
   514 +    while ((bmb.s[i] != '\0') && (i < bmb.len)) i++;
       
   515 +    if (bmb.s[j] == '!') {
       
   516 +      negate = 1;
       
   517 +      j++;
       
   518 +    }
       
   519 +    if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem();
       
   520 +    if (!stralloc_0(&curregex)) die_nomem();
       
   521 +    if (which == BMCHECK_BHELO) {
       
   522 +      x = matchregex(helohost.s, curregex.s);
       
   523 +    } else {
       
   524 +      x = matchregex(addr.s, curregex.s);
       
   525 +    }
       
   526 +    if ((negate) && (x == 0)) {
       
   527 +      if (!stralloc_copyb(&matchedregex,bmb.s + j - 1,(i - j + 1))) die_nomem();
       
   528 +      if (!stralloc_0(&matchedregex)) die_nomem();      
       
   529 +      return 1;
       
   530 +    }
       
   531 +    if (!(negate) && (x > 0)) {
       
   532 +      if (!stralloc_copyb(&matchedregex,bmb.s + j,(i - j))) die_nomem();
       
   533 +      if (!stralloc_0(&matchedregex)) die_nomem();
       
   534 +      return 1;
       
   535 +    }
       
   536 +    j = i + 1;
       
   537 +    negate = 0;
       
   538 +  }
       
   539    return 0;
       
   540  }
       
   541  
       
   542 @@ -218,7 +299,9 @@ int addrallowed()
       
   543  
       
   544  
       
   545  int seenmail = 0;
       
   546 -int flagbarf; /* defined if seenmail */
       
   547 +int flagbarfbmf; /* defined if seenmail */
       
   548 +int flagbarfbmt;
       
   549 +int flagbarfbhelo;
       
   550  stralloc mailfrom = {0};
       
   551  stralloc rcptto = {0};
       
   552  
       
   553 @@ -226,11 +309,13 @@ void smtp_helo(arg) char *arg;
       
   554  {
       
   555    smtp_greet("250 "); out("\r\n");
       
   556    seenmail = 0; dohelo(arg);
       
   557 +  if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
       
   558  }
       
   559  void smtp_ehlo(arg) char *arg;
       
   560  {
       
   561    smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
       
   562    seenmail = 0; dohelo(arg);
       
   563 +  if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
       
   564  }
       
   565  void smtp_rset()
       
   566  {
       
   567 @@ -240,7 +325,11 @@ void smtp_mail(arg) char *arg;
       
   568  void smtp_mail(arg) char *arg;
       
   569  {
       
   570    if (!addrparse(arg)) { err_syntax(); return; }
       
   571 -  flagbarf = bmfcheck();
       
   572 +  flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */
       
   573 +  if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF);
       
   574 +  if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) {
       
   575 +    flagbarfbmf = bmcheck(BMCHECK_BMFNR);
       
   576 +  }
       
   577    seenmail = 1;
       
   578    if (!stralloc_copys(&rcptto,"")) die_nomem();
       
   579    if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
       
   580 @@ -250,7 +339,37 @@ void smtp_rcpt(arg) char *arg; {
       
   581  void smtp_rcpt(arg) char *arg; {
       
   582    if (!seenmail) { err_wantmail(); return; }
       
   583    if (!addrparse(arg)) { err_syntax(); return; }
       
   584 -  if (flagbarf) { err_bmf(); return; }
       
   585 +  if (flagbarfbhelo) {
       
   586 +    if (logregex) {
       
   587 +      strerr_warn6("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
       
   588 +    } else {
       
   589 +      strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0);
       
   590 +    }
       
   591 +    err_bhelo();
       
   592 +    return;
       
   593 +  }
       
   594 +  if (flagbarfbmf) {
       
   595 +    if (logregex) {
       
   596 +      strerr_warn6("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
       
   597 +    } else {
       
   598 +      strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0);
       
   599 +    }
       
   600 +    err_bmf();
       
   601 +    return;
       
   602 +  }
       
   603 +  if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT);
       
   604 +  if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) {
       
   605 +    flagbarfbmt = bmcheck(BMCHECK_BMTNR);
       
   606 +  }
       
   607 +  if (flagbarfbmt) {
       
   608 +    if (logregex) {
       
   609 +      strerr_warn6("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip," matches pattern: ",matchedregex.s,0);
       
   610 +    } else {
       
   611 +      strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0);
       
   612 +    }
       
   613 +    err_bmt();
       
   614 +    return;
       
   615 +  }
       
   616    if (relayclient) {
       
   617      --addr.len;
       
   618      if (!stralloc_cats(&addr,relayclient)) die_nomem();
       
   619 diff -r 1510847ae5bf qregex.c
       
   620 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
   621 +++ b/qregex.c	Thu Nov 01 16:24:02 2007 +0100
       
   622 @@ -0,0 +1,57 @@
       
   623 +/*
       
   624 + * qregex (v2)
       
   625 + * $Id: qregex.c,v 2.1 2001/12/28 07:05:21 evan Exp $
       
   626 + *
       
   627 + * Author  : Evan Borgstrom (evan at unixpimps dot org)
       
   628 + * Created : 2001/12/14 23:08:16
       
   629 + * Modified: $Date: 2001/12/28 07:05:21 $
       
   630 + * Revision: $Revision: 2.1 $
       
   631 + *
       
   632 + * Do POSIX regex matching on addresses for anti-relay / spam control.
       
   633 + * It logs to the maillog
       
   634 + * See the qregex-readme file included with this tarball.
       
   635 + * If you didn't get this file in a tarball please see the following URL:
       
   636 + *  http://www.unixpimps.org/software/qregex
       
   637 + *
       
   638 + * qregex.c is released under a BSD style copyright.
       
   639 + * See http://www.unixpimps.org/software/qregex/copyright.html
       
   640 + *
       
   641 + * Note: this revision follows the coding guidelines set forth by the rest of
       
   642 + *       the qmail code and that described at the following URL.
       
   643 + *       http://cr.yp.to/qmail/guarantee.html
       
   644 + * 
       
   645 + */
       
   646 +
       
   647 +#include <sys/types.h>
       
   648 +#include <regex.h>
       
   649 +#include "qregex.h"
       
   650 +
       
   651 +#define REGCOMP(X,Y)    regcomp(&X, Y, REG_EXTENDED|REG_ICASE)
       
   652 +#define REGEXEC(X,Y)    regexec(&X, Y, (size_t)0, (regmatch_t *)0, (int)0)
       
   653 +
       
   654 +int matchregex(char *text, char *regex) {
       
   655 +  regex_t qreg;
       
   656 +  int retval = 0;
       
   657 +
       
   658 +
       
   659 +  /* build the regex */
       
   660 +  if ((retval = REGCOMP(qreg, regex)) != 0) {
       
   661 +    regfree(&qreg);
       
   662 +    return(-retval);
       
   663 +  }
       
   664 +
       
   665 +  /* execute the regex */
       
   666 +  if ((retval = REGEXEC(qreg, text)) != 0) {
       
   667 +    /* did we just not match anything? */
       
   668 +    if (retval == REG_NOMATCH) {
       
   669 +      regfree(&qreg);
       
   670 +      return(0);
       
   671 +    }
       
   672 +    regfree(&qreg);
       
   673 +    return(-retval);
       
   674 +  }
       
   675 +
       
   676 +  /* signal the match */
       
   677 +  regfree(&qreg);
       
   678 +  return(1);
       
   679 +}
       
   680 diff -r 1510847ae5bf qregex.h
       
   681 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
   682 +++ b/qregex.h	Thu Nov 01 16:24:02 2007 +0100
       
   683 @@ -0,0 +1,5 @@
       
   684 +/* simple header file for the matchregex prototype */
       
   685 +#ifndef _QREGEX_H_
       
   686 +#define _QREGEX_H_
       
   687 +int matchregex(char *text, char *regex);
       
   688 +#endif