From 4ac59229622fa0621d10931708b88fee03f0bb35 Mon Sep 17 00:00:00 2001 From: Roberto Puzzanghera <73385325+sagredo-dev@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:28:07 +0100 Subject: [PATCH] DKIM patch upgraded to v. 1.47 - fixed a bug which was preventing filterargs' wildcards to work properly on sender domain --- CHANGELOG.md | 4 + Makefile | 24 +- README.md | 2 +- TARGETS | 5 +- MakeArgs.c => makeargs.c | 5 +- makeargs.h | 17 + qmail-dkim.c | 31 +- report.c | 119 +++++++ report.h | 25 ++ spawn-filter.9 | 190 +++++++---- spawn-filter.c | 718 +++++++++++++++++++++++++-------------- str.h | 1 + wildmat.c | 2 +- 13 files changed, 790 insertions(+), 353 deletions(-) rename MakeArgs.c => makeargs.c (97%) create mode 100644 makeargs.h create mode 100644 report.c create mode 100644 report.h diff --git a/CHANGELOG.md b/CHANGELOG.md index ef6eef6..5ab365e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +- Feb 6, 2023 + - DKIM patch upgraded to v. 1.47 + - fixed a bug which was preventing filterargs' wildcards to work properly on sender domain + - Jan 20, 2024 [diff](https://github.com/sagredo-dev/qmail/pull/2/commits/3caabe095eae6ab74508b3d56a0398f64a4a5c73) - liberal-lf: bare LF no longer allowed due to smuggling vulnerability ([CVE-2023-51765](https://nvd.nist.gov/vuln/detail/CVE-2023-51765)). Enable bare LF by defining ALLOW_BARELF in tcprules or in run file. diff --git a/Makefile b/Makefile index cf3c6ce..d80a293 100644 --- a/Makefile +++ b/Makefile @@ -1213,13 +1213,13 @@ qmail-control.9 conf-break conf-spawn qmail-dkim: \ load qmail-dkim.o triggerpull.o fmtqfn.o now.o date822fmt.o \ -subgetopt.o MakeArgs.o datetime.a seek.a ndelay.a \ +subgetopt.o makeargs.o datetime.a seek.a ndelay.a \ dns_text.o open.a sig.a alloc.a substdio.a error.a \ wildmat.o str.a case.a fs.a auto_qmail.o auto_split.o \ parse_env.o auto_uids.o fd.a wait.a getDomainToken.o \ env.a getln.a control.o stralloc.a dns.lib libdkim.a g++ -o qmail-dkim qmail-dkim.o triggerpull.o fmtqfn.o now.o \ - subgetopt.o MakeArgs.o date822fmt.o datetime.a seek.a ndelay.a \ + subgetopt.o makeargs.o date822fmt.o datetime.a seek.a ndelay.a \ dns_text.o open.a sig.a substdio.a error.a auto_qmail.o \ wildmat.o auto_split.o auto_uids.o fd.a wait.a \ getDomainToken.o parse_env.o \ @@ -2398,28 +2398,29 @@ compile wait_nohang.c haswaitp.h wait_pid.o: \ compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c -MakeArgs.o: compile MakeArgs.c alloc.h str.h alloc.h stralloc.h - ./compile MakeArgs.c +makeargs.o: compile makeargs.c alloc.h str.h alloc.h stralloc.h + ./compile makeargs.c spawn-filter: \ load spawn-filter.o auto_qmail.o getDomainToken.o \ parse_env.o fmt_ulong.o scan_ulong.o control.o \ -open_read.o wildmat.o qregex.o MakeArgs.o \ +open_read.o wildmat.o qregex.o makeargs.o report.o \ case_lowerb.o constmap.o byte_chr.o byte_cr.o case_diffb.o \ error.a env.a stralloc.a wait.a strerr.a str.a \ getln.a substdio.a alloc.a ./load spawn-filter getDomainToken.o parse_env.o \ fmt_ulong.o scan_ulong.o control.o open_read.o \ - wildmat.o qregex.o MakeArgs.o case_lowerb.o \ + wildmat.o qregex.o makeargs.o case_lowerb.o \ constmap.o byte_chr.o byte_cr.o case_diffb.o \ - auto_qmail.o \ + auto_qmail.o report.o \ error.a env.a stralloc.a wait.a strerr.a str.a \ getln.a substdio.a alloc.a spawn-filter.o: \ compile spawn-filter.c fmt.h str.h strerr.h env.h \ -substdio.h stralloc.h error.h \ -wait.h qregex.h +substdio.h stralloc.h error.h wait.h qregex.h \ +getDomainToken.h makeargs.h scan.h control.h \ +report.h qregex.h auto_qmail.h ./compile spawn-filter.c qregex.o: \ @@ -2439,6 +2440,11 @@ wildmat.o: \ compile wildmat.c ./compile wildmat.c +report.o: \ +compile report.c substdio.h subfd.h strerr.h report.h \ +getDomainToken.h + ./compile report.c + spawn-filter.0: \ spawn-filter.8 nroff -man spawn-filter.8 > spawn-filter.0 diff --git a/README.md b/README.md index 82b3396..f886b94 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ This distribution of qmail puts together netqmail-1.06 with the following patche adds a user-definable delay after SMTP clients have initiated SMTP sessions, prior to qmail-smtpd responding with "220 ESMTP". It can reject connections from clients which tried to send commands before greeting. https://notes.sagredo.eu/files/qmail/patches/qmail-greetdelay.patch -* Manvendra Bhangui's DKIM and SURBL filter v.1.46 patch +* Manvendra Bhangui's DKIM and SURBL filter v.1.47 patch adds DKIM signing & verification and SURBL filtering support to qmail. qmail-dk is based on Russ Nelson's patch: http//:www.qmail.org/qmail-1.03-dk-0.54.patch qmail-dkim uses hacked libdkim libraries from libdkim project at http://libdkim.sourceforge.net/ diff --git a/TARGETS b/TARGETS index 050d25a..3c04adb 100644 --- a/TARGETS +++ b/TARGETS @@ -436,8 +436,9 @@ qmail-dkim.8 qmail-dkim.0 str_cpyb.o dkimfuncs.o -MakeArgs.o -spawn-filter spawn-filter.o qregex.o wildmat.o +makeargs.o +report.o +spawn-filter spawn-filter.o qregex.o wildmat.o wildmat spawn-filter.8 spawn-filter.0 case_startb.o diff --git a/MakeArgs.c b/makeargs.c similarity index 97% rename from MakeArgs.c rename to makeargs.c index 60ef625..fea0402 100644 --- a/MakeArgs.c +++ b/makeargs.c @@ -36,6 +36,7 @@ #include "stralloc.h" #include "env.h" #include +#include "makeargs.h" #define isEscape(ch) ((ch) == '"' || (ch) == '\'') @@ -48,7 +49,7 @@ * */ char ** -MakeArgs(char *cmmd) +makeargs(char *cmmd) { char *ptr, *marker; char **argv; @@ -128,7 +129,7 @@ MakeArgs(char *cmmd) } void -FreeMakeArgs(char **argv) +free_makeargs(char **argv) { alloc_free(argv); return; diff --git a/makeargs.h b/makeargs.h new file mode 100644 index 0000000..2b55f76 --- /dev/null +++ b/makeargs.h @@ -0,0 +1,17 @@ +/* + * $Log: makeargs.h,v $ + * Revision 1.1 2021-06-09 21:27:06+05:30 Cprogrammer + * Initial revision + * + */ +#ifndef MAKEARGS_H +#define MAKEARGS_H + +#ifndef lint +static char sccsidmakeargsh[] = "$Id: makeargs.h,v 1.1 2021-06-09 21:27:06+05:30 Cprogrammer Exp mbhangui $"; +#endif + +char **makeargs(char *); +void free_makeargs(char **); + +#endif diff --git a/qmail-dkim.c b/qmail-dkim.c index 8e3f9e4..4b1e86e 100644 --- a/qmail-dkim.c +++ b/qmail-dkim.c @@ -1,5 +1,5 @@ /* - * $Id: qmail-dkim.c,v 1.71 2023-01-30 10:42:16+05:30 Cprogrammer Exp mbhangui $ + * $Id: qmail-dkim.c,v 1.76 2024-01-10 23:01:23+05:30 Cprogrammer Exp mbhangui $ */ #include #include @@ -26,6 +26,7 @@ #include "control.h" #include "error.h" #include "getDomainToken.h" +#include "makeargs.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -63,9 +64,6 @@ static char *controldir; static stralloc fntmp = {0}; static stralloc bouncehost = {0}; -char **MakeArgs(char *); -void FreeMakeArgs(char **); - void die(int e, int what) { @@ -332,7 +330,7 @@ dkim_setoptions(DKIMSignOptions *opts, char *signOptions) !stralloc_cats(&dkimopts, signOptions) || !stralloc_0(&dkimopts)) die(51, 0); - if (!(argv = MakeArgs(dkimopts.s))) + if (!(argv = makeargs(dkimopts.s))) die(51, 0); for (argc = 0;argv[argc];argc++); while ((ch = sgopt(argc, argv, "b:c:li:qthx:z:")) != sgoptdone) { @@ -356,7 +354,7 @@ dkim_setoptions(DKIMSignOptions *opts, char *signOptions) opts->nCanon = DKIM_SIGN_SIMPLE_RELAXED; break; default: - FreeMakeArgs(argv); + free_makeargs(argv); return (1); } break; @@ -404,16 +402,16 @@ dkim_setoptions(DKIMSignOptions *opts, char *signOptions) break; #endif default: - FreeMakeArgs(argv); + free_makeargs(argv); return (1); } break; default: - FreeMakeArgs(argv); + free_makeargs(argv); return (1); } /*- switch (ch) */ } /*- while (1) */ - FreeMakeArgs(argv); + free_makeargs(argv); return (0); } @@ -1358,7 +1356,7 @@ main(int argc, char *argv[]) void getversion_qmail_dkim_c() { - static char *x = "$Id: qmail-dkim.c,v 1.72 2023-02-01 18:15:33+05:30 Cprogrammer Exp mbhangui $"; + static char *x = "$Id: qmail-dkim.c,v 1.76 2024-01-10 23:01:23+05:30 Cprogrammer Exp mbhangui $"; #ifdef HASDKIM x = sccsidmakeargsh; @@ -1372,7 +1370,18 @@ getversion_qmail_dkim_c() /* * $Log: qmail-dkim.c,v $ - * Revision 1.75 2023-02-17 11:49:48+05:30 Cprogrammer + * Revision 1.76 2024-01-10 23:01:23+05:30 Cprogrammer + * reset sgoptind, sgoptpos for repeated calls to subgetopt + * + * Revision 1.75 2024-01-10 10:05:58+05:30 Cprogrammer + * use bouncehost/me control file if BOUNCEDOMAIN is not set + * set DKIMSIGN to private key from dkimkeys control file + * + * Revision 1.74 2023-11-20 11:03:04+05:30 Cprogrammer + * Added env variable EXCLUDE_DKIMSIGN to exclude headers from DKIM signing + * exclude Arc-Authentication-Results header from DKIM signing + * + * Revision 1.73 2023-02-17 11:49:48+05:30 Cprogrammer * added env variable NODKIMKEYS to disable reading of dkimkeys control file * disable dkimkeys when doing DKIMSIGNEXTRA * diff --git a/report.c b/report.c new file mode 100644 index 0000000..5b0a52c --- /dev/null +++ b/report.c @@ -0,0 +1,119 @@ +/* + * $Log: report.c,v $ + * Revision 1.6 2023-12-06 17:02:13+05:30 Cprogrammer + * added comment on report format for qmail-rspawn + * + * Revision 1.5 2021-08-29 23:27:08+05:30 Cprogrammer + * define functions as noreturn + * + * Revision 1.4 2021-08-28 23:07:59+05:30 Cprogrammer + * moved dtype enum delivery variable from variables.h to getDomainToken.h + * + * Revision 1.3 2021-05-30 00:16:51+05:30 Cprogrammer + * renamed local to local_delivery + * + * Revision 1.2 2021-05-26 07:36:54+05:30 Cprogrammer + * fixed extra colon char in error messages + * + * Revision 1.1 2021-05-23 06:35:28+05:30 Cprogrammer + * Initial revision + * + */ +#include +#include "substdio.h" +#include "subfd.h" +#include "strerr.h" +#include "report.h" +#include "getDomainToken.h" + +extern dtype delivery; + +/*- + * qmail-rspawn doesn't use exit code of qmail-remote. It needs a report in + * the following format + * "[r,h,s]recipient_report\0[K,Z,D]message_report\0" + * + * recipient_report start with one of the letters r, h, s + * as below + * r - Recipient report: acceptance. + * s - Recipient report: temporary rejection. + * h - Recipient report: permanent rejection. + * + * message_report start with one of the letters K, Z, D + * as below + * K - Message report: success. + * Z - Message report: temporary failure. + * D - Message report: permanent failure. + * + * Examples of qmail-remote report + * + * Success + * "rFrom RCPT \0\n" + * "KHost example.com accepted message\0\n" + * + * temp failure + * "sFrom RCPT \0\n" + * "ZTemporary failure accepting message\0\n" + * + * perm failure + * "hFrom RCPT \0\n" + * "Dexample.org does not like recipient\0\n" + * + * qmail-lspawn uses the exit code of qmail-local + * 0 - Success + * 111 - Temporary failure + * 100 - Permanent failure + */ +void +report(int errCode, char *s1, char *s2, char *s3, char *s4, char *s5, char *s6) +{ + if (delivery == local_delivery) /*- strerr_die does not return */ + strerr_die6x(errCode, s1, s2, s3, s4, s5, s6); + if (!errCode) { /*- should never happen */ + if (substdio_put(subfdoutsmall, "r\0Kspawn accepted message.\n\0", 28) == -1) + _exit(111); + if (s1) { + if (substdio_puts(subfdoutsmall, s1) == -1 || + substdio_put(subfdoutsmall, "\n", 1) == -1) + _exit(111); + } else + if (substdio_put(subfdoutsmall, "spawn said: 250 ok notification queued\n\0", 41) == -1) + _exit(111); + } else { + /*- h - hard, s - soft */ + if (substdio_put(subfdoutsmall, errCode == 111 ? "s" : "h", 1) == -1) + _exit(111); + if (s1 && substdio_puts(subfdoutsmall, s1) == -1) + _exit(111); + if (s2 && substdio_puts(subfdoutsmall, s2) == -1) + _exit(111); + if (s3 && substdio_puts(subfdoutsmall, s3) == -1) + _exit(111); + if (s4 && substdio_puts(subfdoutsmall, s4) == -1) + _exit(111); + if (s5 && substdio_puts(subfdoutsmall, s5) == -1) + _exit(111); + if (s6 && substdio_puts(subfdoutsmall, s6) == -1) + _exit(111); + if (substdio_put(subfdoutsmall, "\0", 1) == -1) + _exit(111); + if (substdio_puts(subfdoutsmall, + errCode == 111 ? "Zspawn said: Message deferred" : "Dspawn said: Giving up on filter\n") == -1) + _exit(111); + if (substdio_put(subfdoutsmall, "\0", 1) == -1) + _exit(111); + } + substdio_flush(subfdoutsmall); + /*- For qmail-rspawn to stop complaining unable to run qmail-remote */ + _exit(0); +} + +void +getversion_report_c() +{ + static char *x = "$Id: report.c,v 1.6 2023-12-06 17:02:13+05:30 Cprogrammer Exp mbhangui $"; + + x = sccsidreporth; + x = sccsidgetdomainth; + x++; +} diff --git a/report.h b/report.h new file mode 100644 index 0000000..3d9615e --- /dev/null +++ b/report.h @@ -0,0 +1,25 @@ +/* + * $Log: report.h,v $ + * Revision 1.4 2022-01-30 09:38:19+05:30 Cprogrammer + * define report() as no_return + * + * Revision 1.3 2021-05-30 00:17:09+05:30 Cprogrammer + * moved dtype enum to variables.h + * + * Revision 1.2 2021-05-26 07:37:41+05:30 Cprogrammer + * made delivery variable extern + * + * Revision 1.1 2021-05-23 06:35:03+05:30 Cprogrammer + * Initial revision + * + */ +#ifndef _REPORT_H +#define _REPORT_H + +#ifndef lint +static char sccsidreporth[] = "$Id: report.h,v 1.4 2022-01-30 09:38:19+05:30 Cprogrammer Exp mbhangui $"; +#endif + +void report(int, char *, char *, char *, char *, char *, char *); + +#endif diff --git a/spawn-filter.9 b/spawn-filter.9 index 018708c..1e2fc98 100644 --- a/spawn-filter.9 +++ b/spawn-filter.9 @@ -1,27 +1,43 @@ +.\" vim: tw=75 .TH spawn-filter 8 .SH NAME -spawn-filter \- Helper for running filters for qmail-local and qmail-remote +spawn-filter \- qmail-local / qmail-remote interceptor + .SH SYNOPSIS -.B spawn-filter args +\fBspawn-filter\fR \fIargs\fR + .SH DESCRIPTION -.B spawn-filter -is a utility to help qmail run any filter during local or remote delivery. It -can run any filter which expects to read mess on fd 0 and writes back the message on fd 1. -The filter can be turned on individually for local and remote mails by defining -.B QMAILLOCAL -and -.B QMAILREMOTE -environment variables respectively in -.B qmail-send -supervise or rc script. If spawn-filter is invoked as qmail-local, it executes the -original -.B qmail-local -after runing the mail through the filter. If spawn-filter is invoked as qmail-remote, it -executes the original -.B qmail-remote -after running the mail through the filter. Hence QMAILLOCAL should be set as QMAILHOME/bin/spawn-filter -for filtering local mails and QMAILREMOTE as QMAILHOME/bin/spawn-filter for filtering -remote mails. +\fBspawn-filter\fR is a \fBqmail-local\fR / \fBqmail-remote\fR interceptor +to help qmail run custom filters for email being sent by \fBqmail-local\fR +or \fBqmail-remote\fR. It can run any script which reads messages on fd 0 +and writes the output on fd 1. Whatever is output on fd 1, will be the +input on descriptor 0 for \fBqmail-local\fR and \fBqmail-remote\fR. Thus +the output of the filter program becomes the message that will be delivered +to the destination. The filter can be turned on individually for local and +remote mails by defining, \fBQMAILLOCAL\fR and \fBQMAILREMOTE\fR +environment variables, to the path of \fBspawn-filter\fR respectively in +\fBqmail-send\fR's supervise or rc script. If \fBspawn-filter\fR is invoked +as \fBqmail-local\fR or \fBqmail-remote, it executes \fBqmail-local\fR or +\fBqmail-remote\fR after running the custom filter. The filter script or +program is run as a child of \fBspawn-filter\fR. + +\fBspawn-filter\fR is run by \fBqmail-lspawn\fR or \fBqmail-rspawn\fR with the +same \fIargs\fR that is passed to \fBqmail-local\fR or \fBqmail-remote\fR. +If \fBQMAILLOCAL\fR is set as \fIQMAILHOME/bin/spawn-filter\fR, +\fBqmail-lspawn\fR runs \fBspawn-filter\fR with the same \fIargs\fR that is +passed to \fBqmail-local\fR. If \fBQMAILREMOTE\fR is set as +\fIQMAILHOME/bin/spawn-filter\fR, \fBqmail-rspawn\fR runs +\fBspawn-filter\fR with the same \fIargs\fR that is passed to +\fBqmail-remote\fR. + +\fBspawn-filter\fR unsets \fBQMAILREMOTE\fR when it runs as +\fBqmail-local\fR. Similarly, it unsets \fBQMAILLOCAL\fR when it runs as +\fBqmail-remote\fR. This is useful in scripts to figure out whether +\fBspawn-filter\fR is running as \fBqmail-local\fR or \fBqmail-remote\fR. +You can set \fBQLOCAL\fR, \fBQREMOTE\fR environment variable to make +spawn-filter run an alternate \fBqmail-local\fR, \fBqmail-remote\fR +programs. The alternate programs are expected to support the same interface +as the original \fBqmail-local\fR and \fBqmail-remote\fR. Filters can be run by defining the environment variable \fBFILTERARGS\fR or by using the control file \fIfilterargs\fR (see below). \fBspawn-filter\fR @@ -33,56 +49,107 @@ set using the control file \fIfilterargs\fR (see below the section on control files). The environment variable \fBFILTERARGS\fR takes precedence over the control file. +\fBspawn-filter\fR sets multiple environment variables which can be +conveniently used in programs/scripts which get invoked by setting +\fBFILTERARGS\fR environment variable or by rules in the \fBfilterargs\fR +control file. See the section on \fBEnvironment Variables\fR below. + +\fBspawn-filter\fR unsets FILTERARGS, QMAILLOCAL, QMAILREMOTE before +running \fBqmail-local\fR or \fBqmail-remote\fR. \fBspawn-filter\fR unsets +FILTERARGS before running filter. + +.SH Control Files + .TP 5 .I filterargs -The format of this file is of the form -.B domain:args -for both local and remote mails. -.B domain:remote:args -for remote mails and -.B domain:local:args -for local mails. +This control file can be used to setup additional filters. This file has +the following format. .EX -indimail.org:remote:QMAILHOME/bin/qmail-dkim:DKIMQUEUE=/bin/cat +\fBdomain:args\fR + or +\fBdomain:args:envstr\fR .EE -.TP 0 -The sequence in which the filter program is run is given below +for both local and remote deliveries + +.EX +\fBdomain:remote:args\fR + or +\fBdomain:remote:args:envstr\fR +.EE + +for remote deliveries and + +.EX +\fBdomain:local:args\fR + or +\fBdomain:local:args:envstr\fR +.EE + +for local deliveries. + +\fIdomain\fR can be an exact match, wildcard or a regular expression (if +QREGEX environment variable is defined). If there are multiple lines which +match \fIdomain\fR, the first line that matches \fIdomain\fR will be used. + +For local deliveries, \fIdomain\fR refers to the recipient domain. You can +have the match done on sender domain by setting \fBMATCH_SENDER_DOMAIN\fR. + +For remote deliveries, \fIdomain\fR refers to the sender domain. You can +have the match done on recipient domain by setting +\fBMATCH_RECIPIENT_DOMAIN\fR. + +.EX +sagredo.eu:remote:QMAILHOME/bin/qmail-dkim:DKIMQUEUE=/bin/cat +.EE + +\fIenvstr\fR mentioned above is a string of environment variable additions +or removals. e.g. + +.EX +QREGEX=1,DKIMSIGNOPTIONS=-z 4,HOME= +.EE + +sets QREGEX to 1, DKIMSIGNOPTIONS to "-z 4" and unsets HOME envrionment +variable. .TP 5 -1. create two pipes and fork -.TP 5 -2. dup write end of the first pipe to descriptor 1, dup write end of the second pipe to descriptor 2 in the child and exec the filter program -.TP 5 -3. dup read end of the pipe to descriptor 0 in parent and exec qmail-local for local mails and qmail-remote for remote mails. -.TP 5 -4. Wait for filter to exit and read read end of second pipe for any error messages. -.TP 5 -5. Report success or failure -.TP 0 +.I databytes +Maximum size of mail that will be accepted before passing it to +\fBqmail-remote\fR or \fBqmail-local\fR + +If the environment variable \fBDATABYTES\fR is set, it overrides +\fIdatabytes\fR. The value of databytes determines the maximum size of a +message that \fBspawn-filter\fR will accept. -This gives the ability for the any filter program to read the mail message from descriptor 0 before -passing it to qmail-local/qmail-remote through the pipe. +.SH Environment Variables +\fBspawn-filter\fR sets few environment variables. The following +environment variables are set for both local and remote deliveries -.B spawn-filter -will attempt to make the descriptor 0 seekable if the environment variable MAKE_SEEKABLE -is defined. This may be necessary for certain filter programs which could do lseek(). +.TS +l l. +Environment variable | Description +------------------------------------------------------------ +DOMAIN | domain part of recipient address +_EXT | the address extension +_SENDER | envelope sender address +_RECIPIENT | envelope recipient address +QMAILREMOTE | set for remote deliveries +QMAILLOCAL | set for local deliveries -.B spawn-filter -sets the environment variable -.B DOMAIN -to the recipient domain. This can be conveniently used in programs/scripts which get invoked by -setting -.B FILTERARGS -environment variable or by rules in the control file -.BR filterargs . +.TE .SH "EXIT CODES" -.B spawn-filter -exits 111 for any error or if it is not able to exec -QMAILHOME/bin/qmail-local (for local mails) or -QMAILHOME/bin/qmail-remote (for remote mails). +\fBspawn-filter\fR exits 111 for any error (non-zero exit status by called +program) or if it is not able to exec QMAILHOME/bin/qmail-local (for local +mails) or QMAILHOME/bin/qmail-remote (for remote mails). It exits 100 if +the program/script defined by \fBFILTERARGS\fR (or defined in the control +file \fBfilterargs\fR) returns 100. If the program/script defined by +\fBFILTERARGS\fR returns 2, then the mail gets blackholed. If the +program/script defined by \fBFILTERARGS\fR exits non-zero status (other +than 2), temporary error is issued and the mail stays in the queue. For all +other cases where no errors occur, it exits 0. .SH "SEE ALSO" qmail-lspawn(8), @@ -91,12 +158,9 @@ qmail-local(8), qmail-remote(8), qmail-smtpd(8), qmail-control(5), -qmail-queue(8) +qmail-queue(8), +qmail-command(8) .SH "AUTHORS" -Manvendra Bhangui. -.SH PROBLEMS -Problems with -.B spawn-filter -should be forwarded to "Manvendra Bhangui" +"Manvendra Bhangui" . diff --git a/spawn-filter.c b/spawn-filter.c index 4bcba4e..b0f9e1e 100644 --- a/spawn-filter.c +++ b/spawn-filter.c @@ -1,225 +1,56 @@ /* - * netqmail-version without spam filter - * - * $Log: spawn-filter.c,v $ - * Revision 1.41 2009-04-03 11:42:48+05:30 Cprogrammer - * create pipe for error messages - * - * Revision 1.40 2009-04-02 15:17:54+05:30 Cprogrammer - * unset QMAILLOCAL in qmail-remote and unset QMAILREMOTE in qmail-local - * - * Revision 1.39 2008-06-12 08:40:55+05:30 Cprogrammer - * added rulesfile argument - * - * Revision 1.38 2008-05-25 17:16:43+05:30 Cprogrammer - * made message more readable by adding a blank space - * - * Revision 1.37 2007-12-20 13:51:54+05:30 Cprogrammer - * avoid loops with FILTERARGS, SPAMFILTERARGS - * removed compiler warning - * - * Revision 1.36 2006-06-07 14:11:28+05:30 Cprogrammer - * added SPAMEXT, SPAMHOST, SPAMSENDER, QQEH environment variable - * unset FILTERARGS before calling filters - * - * Revision 1.35 2006-01-22 10:14:45+05:30 Cprogrammer - * BUG fix for spam mails wrongly getting blackholed - * - * Revision 1.34 2005-08-23 17:36:48+05:30 Cprogrammer - * gcc 4 compliance - * delete sender in spam notification - * - * Revision 1.33 2005-04-02 19:07:47+05:30 Cprogrammer - * use internal wildmat version - * - * Revision 1.32 2004-11-22 19:50:53+05:30 Cprogrammer - * include regex.h after sys/types.h to avoid compilation prob on RH 7.3 - * - * Revision 1.31 2004-10-22 20:30:35+05:30 Cprogrammer - * added RCS id - * - * Revision 1.30 2004-10-21 21:56:21+05:30 Cprogrammer - * change for two additional arguments to strerr_die() - * - * Revision 1.29 2004-10-11 14:06:14+05:30 Cprogrammer - * use control_readulong instead of control_readint - * - * Revision 1.28 2004-09-22 23:14:20+05:30 Cprogrammer - * replaced atoi() with scan_int() - * - * Revision 1.27 2004-09-08 10:54:49+05:30 Cprogrammer - * incorrect exit code in report() function for remote - * mails. Caused qmail-rspawn to report "Unable to run qmail-remote" - * - * Revision 1.26 2004-07-17 21:23:31+05:30 Cprogrammer - * change qqeh code in qmail-remote - * - * Revision 1.25 2004-07-15 23:40:46+05:30 Cprogrammer - * fixed compilation warning - * - * Revision 1.24 2004-07-02 16:15:25+05:30 Cprogrammer - * override control files rejectspam, spamredirect by - * environment variables REJECTSPAM and SPAMREDIRECT - * allow patterns in domain specification in the control files - * spamfilterargs, filterargs, rejectspam and spamredirect - * - * Revision 1.23 2004-06-03 22:58:34+05:30 Cprogrammer - * fixed compilation problem without indimail - * - * Revision 1.22 2004-05-23 22:18:17+05:30 Cprogrammer - * added envrules filename as argument - * - * Revision 1.21 2004-05-19 23:15:07+05:30 Cprogrammer - * added comments - * - * Revision 1.20 2004-05-12 22:37:47+05:30 Cprogrammer - * added check DATALIMIT check - * - * Revision 1.19 2004-05-03 22:17:36+05:30 Cprogrammer - * use QUEUE_BASE instead of auto_qmail - * - * Revision 1.18 2004-02-13 14:51:24+05:30 Cprogrammer - * added envrules - * - * Revision 1.17 2004-01-20 06:56:56+05:30 Cprogrammer - * unset FILTERARGS for notifications - * - * Revision 1.16 2004-01-20 01:52:08+05:30 Cprogrammer - * report string length corrected - * - * Revision 1.15 2004-01-10 09:44:36+05:30 Cprogrammer - * added comment for exit codes of bogofilter - * - * Revision 1.14 2004-01-08 00:32:49+05:30 Cprogrammer - * use TMPDIR environment variable for temporary directory - * send spam reports to central spam logger - * - * Revision 1.13 2003-12-30 00:44:42+05:30 Cprogrammer - * set argv[0] from spamfilterprog - * - * Revision 1.12 2003-12-22 18:34:25+05:30 Cprogrammer - * replaced spfcheck() with address_match() - * - * Revision 1.11 2003-12-20 01:35:06+05:30 Cprogrammer - * added wait_pid to prevent zombies - * - * Revision 1.10 2003-12-17 23:33:39+05:30 Cprogrammer - * improved logic for getting remote/local tokens - * - * Revision 1.9 2003-12-16 10:38:24+05:30 Cprogrammer - * fixed incorrect address being returned if filterargs contained local: or - * remote: directives - * - * Revision 1.8 2003-12-15 20:46:19+05:30 Cprogrammer - * added case 100 to bounce mail - * - * Revision 1.7 2003-12-15 13:51:44+05:30 Cprogrammer - * code to run additional filters using /bin/sh - * - * Revision 1.6 2003-12-14 11:36:18+05:30 Cprogrammer - * added option to blackhole spammers - * - * Revision 1.5 2003-12-13 21:08:46+05:30 Cprogrammer - * extensive rewrite - * common report() function for local/remote mails to report errors - * - * Revision 1.4 2003-12-12 20:20:55+05:30 Cprogrammer - * use -a option to prevent using header addresses - * - * Revision 1.3 2003-12-09 23:37:16+05:30 Cprogrammer - * change for spawn-filter to be called as qmail-local or qmail-remote - * - * Revision 1.2 2003-12-08 23:48:23+05:30 Cprogrammer - * new function getDomainToken() to retrieve domain specific values - * read rejectspam and spamredirect only if SPAMEXITCODE is set - * - * Revision 1.1 2003-12-07 13:02:00+05:30 Cprogrammer - * Initial revision - * + * $Id: spawn-filter.c,v 1.87 2024-01-23 01:23:36+05:30 Cprogrammer Exp mbhangui $ */ +#include +#include +#include +#include +#include #include "fmt.h" #include "str.h" #include "strerr.h" #include "env.h" #include "substdio.h" -#include "subfd.h" #include "stralloc.h" #include "error.h" -#include "control.h" #include "wait.h" -#include "qregex.h" +#include "scan.h" +#include "makeargs.h" +#include "control.h" +#include "report.h" #include "getDomainToken.h" +#include "qregex.h" #include "auto_qmail.h" -#include -#include -#include -#include -#include - -#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) static int mkTempFile(int); -static void report(int, char *, char *, char *, char *, char *, char *); -static int run_mailfilter(char *, char *, char **); -int wildmat_internal(char *, char *); +static int run_mailfilter(char *, char *, char *, char **); +static int check_size(char *); +static void set_environ(char *, char *, char *, char *); -static int remotE; extern dtype delivery; -stralloc sender = { 0 }; -stralloc recipient = { 0 }; +static stralloc sender = { 0 }; +static stralloc recipient = { 0 }; +static stralloc q = { 0 }; static void -report(int errCode, char *s1, char *s2, char *s3, char *s4, char *s5, char *s6) -{ - if (!remotE) /*- strerr_die does not return */ - strerr_die(errCode, s1, s2, s3, s4, s5, s6, 0, 0, (struct strerr *) 0); - /*- h - hard, s - soft */ - if (substdio_put(subfdoutsmall, errCode == 111 ? "s" : "h", 1) == -1) - _exit(111); - if (s1 && substdio_puts(subfdoutsmall, s1) == -1) - _exit(111); - if (s2 && substdio_puts(subfdoutsmall, s2) == -1) - _exit(111); - if (s3 && substdio_puts(subfdoutsmall, s3) == -1) - _exit(111); - if (s4 && substdio_puts(subfdoutsmall, s4) == -1) - _exit(111); - if (s5 && substdio_puts(subfdoutsmall, s5) == -1) - _exit(111); - if (s6 && substdio_puts(subfdoutsmall, s6) == -1) - _exit(111); - if (substdio_put(subfdoutsmall, "\0", 1) == -1) - _exit(111); - if (substdio_puts(subfdoutsmall, - errCode == 111 ? "Zspawn-filter said: Message deferred" : "DGiving up on spawn-filter\n") == -1) - _exit(111); - if (substdio_put(subfdoutsmall, "\0", 1) == -1) - _exit(111); - substdio_flush(subfdoutsmall); - /*- For qmail-rspawn to stop complaining unable to run qmail-remote */ - _exit(0); -} - -void -set_environ(char *host, char *sender, char *recipient) +set_environ(char *host, char *ext, char *sender_p, char *recipient_p) { - if (!env_put2("DOMAIN", host)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!env_put2("_SENDER", sender)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!env_put2("_RECIPIENT", recipient)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + if (ext && !env_put2("_EXT", ext)) + report(111, "spawn-filter: out of memory", ". (#4.3.0)", 0, 0, 0, 0); + if (!env_put2("DOMAIN", host) || + !env_put2("_SENDER", sender_p) || + !env_put2("_RECIPIENT", recipient_p)) + report(111, "spawn-filter: out of memory", ". (#4.3.0)", 0, 0, 0, 0); return; } static int -run_mailfilter(char *domain, char *mailprog, char **argv) +run_mailfilter(char *domain, char *ext, char *mailprog, char **argv) { char strnum[FMT_ULONG]; pid_t filt_pid; int pipefd[2], pipefe[2]; - int wstat, filt_exitcode, len = 0; + int wstat, filt_exitcode, e, len = 0; char *filterargs; static stralloc filterdefs = { 0 }; static char errstr[1024]; @@ -227,15 +58,17 @@ run_mailfilter(char *domain, char *mailprog, char **argv) char ch; static substdio errbuf; - if (!(filterargs = env_get("FILTERARGS"))) - { + if (!(filterargs = env_get("FILTERARGS"))) { if (control_readfile(&filterdefs, "control/filterargs", 0) == -1) report(111, "spawn-filter: Unable to read filterargs: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); filterargs = getDomainToken(domain, &filterdefs); } - if (!filterargs) - { - execv(mailprog, argv); + if (!filterargs) { + /*- Avoid loop if program(s) defined by FILTERARGS call qmail-inject, etc */ + if (!env_unset("FILTERARGS") || !env_unset("SPAMFILTER") || + !env_unset("QMAILREMOTE") || !env_unset("QMAILLOCAL")) + report(111, "spawn-filter: out of memory", ". (#4.3.0)", 0, 0, 0, 0); + execv(mailprog, argv); /*- do the delivery (qmail-local/qmail-remote) */ report(111, "spawn-filter: could not exec ", mailprog, ": ", error_str(errno), ". (#4.3.0)", 0); _exit(111); /*- To make compiler happy */ } @@ -248,7 +81,7 @@ run_mailfilter(char *domain, char *mailprog, char **argv) case -1: report(111, "spawn-filter: Trouble creating child filter: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); case 0: /*- Filter Program */ - set_environ(domain, sender.s, recipient.s); + set_environ(domain, ext, sender.s, recipient.s); /*- Mail content read from fd 0 */ if (mkTempFile(0)) report(111, "spawn-filter: lseek error: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); @@ -264,63 +97,71 @@ run_mailfilter(char *domain, char *mailprog, char **argv) close(pipefe[1]); /*- Avoid loop if program(s) defined by FILTERARGS call qmail-inject, etc */ if (!env_unset("FILTERARGS") || !env_unset("SPAMFILTER")) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - execl("/bin/sh", "/bin/sh", "-c", filterargs, (char *) 0); + report(111, "spawn-filter: out of memory", ". (#4.3.0)", 0, 0, 0, 0); + execl("/bin/sh", "sh", "-c", filterargs, (char *) 0); report(111, "spawn-filter: could not exec /bin/sh: ", filterargs, ": ", error_str(errno), ". (#4.3.0)", 0); default: close(pipefe[1]); close(pipefd[1]); - if (dup2(pipefd[0], 0)) - { + if (dup2(pipefd[0], 0)) { + e = errno; close(pipefd[0]); close(pipefe[0]); wait_pid(&wstat, filt_pid); + errno = e; report(111, "spawn-filter: dup2 error: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); } if (pipefd[0] != 0) close(pipefd[0]); - if (mkTempFile(0)) - { + if (mkTempFile(0)) { + e = errno; close(0); close(pipefe[0]); wait_pid(&wstat, filt_pid); + errno = e; report(111, "spawn-filter: lseek error: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); } break; } /*- Process message if exit code is 0, bounce if 100 */ - if (wait_pid(&wstat, filt_pid) != filt_pid) - { + if (wait_pid(&wstat, filt_pid) != filt_pid) { + e = errno; close(0); close(pipefe[0]); + errno = e; report(111, "spawn-filter: waitpid surprise: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); } - if (wait_crashed(wstat)) - { + if (wait_crashed(wstat)) { + e = errno; close(0); close(pipefe[0]); + errno = e; report(111, "spawn-filter: filter crashed: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); } switch (filt_exitcode = wait_exitcode(wstat)) { case 0: - execv(mailprog, argv); + execv(mailprog, argv); /*- do the delivery (qmail-local/qmail-remote) */ report(111, "spawn-filter: could not exec ", mailprog, ": ", error_str(errno), ". (#4.3.0)", 0); + case 2: + report(0, "blackholed", filterargs, 0, 0, 0, 0); /*- Blackhole */ case 100: - report(100, "Mail Rejected (#5.7.1)", 0, 0, 0, 0, 0); + report(100, "Mail Rejected by ", filterargs, " (#5.7.1)", 0, 0, 0); default: + e = errno; substdio_fdbuf(&errbuf, read, pipefe[0], inbuf, sizeof(inbuf)); for (len = 0; substdio_bget(&errbuf, &ch, 1) && len < (sizeof(errstr) - 1); len++) errstr[len] = ch; errstr[len] = 0; strnum[fmt_ulong(strnum, filt_exitcode)] = 0; + errno = e; report(111, filterargs, ": (spawn-filter) exit code: ", strnum, *errstr ? ": " : 0, *errstr ? errstr : 0, ". (#4.3.0)"); } /*- Not reached */ return(111); } -int +static int mkTempFile(int seekfd) { char inbuf[2048], outbuf[2048], strnum[FMT_ULONG]; @@ -332,21 +173,17 @@ mkTempFile(int seekfd) if (lseek(seekfd, 0, SEEK_SET) == 0) return (0); - if (errno == EBADF) - { + if (errno == EBADF) { strnum[fmt_ulong(strnum, seekfd)] = 0; report(111, "spawn-filter: fd ", strnum, ": ", error_str(errno), ". (#4.3.0)", 0); } if (!(tmpdir = env_get("TMPDIR"))) tmpdir = "/tmp"; - if (!stralloc_copys(&tmpFile, tmpdir)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_cats(&tmpFile, "/qmailFilterXXX")) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_catb(&tmpFile, strnum, fmt_ulong(strnum, (unsigned long) getpid()))) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_0(&tmpFile)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + if (!stralloc_copys(&tmpFile, tmpdir) || + !stralloc_cats(&tmpFile, "/qmailFilterXXX") || + !stralloc_catb(&tmpFile, strnum, fmt_ulong(strnum, (unsigned long) getpid())) || + !stralloc_0(&tmpFile)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); if ((fd = open(tmpFile.s, O_RDWR | O_EXCL | O_CREAT, 0600)) == -1) report(111, "spawn-filter: ", tmpFile.s, ": ", error_str(errno), ". (#4.3.0)", 0); unlink(tmpFile.s); @@ -368,80 +205,433 @@ mkTempFile(int seekfd) return (0); } +static int +check_size(char *size) +{ + char *x; + unsigned long databytes = -1, msgsize; + + if (!(x = env_get("DATABYTES"))) { + if (control_readulong(&databytes, "control/databytes") == -1) + report(111, "spawn-filter: Unable to read databytes: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + } else + scan_ulong(x, &databytes); + if (databytes == -1) + return (0); + scan_ulong(size, &msgsize); + if (msgsize > databytes) + return(1); + else + return(0); +} + +static char *setup_qargs(char t) +{ + static char *qargs; + + if (!qargs) + qargs= env_get(t == 'l' ? "QLOCAL" : "QREMOTE"); + if (!qargs) { + if (!stralloc_copys(&q, auto_qmail) || + !stralloc_catb(&q, t == 'l' ? "/bin/qmail-local" : "/bin/qmail-remote", t == 'l' ? 16 : 17) || + !stralloc_0(&q)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); + qargs = q.s; + } + return qargs; +} + int main(int argc, char **argv) { - char *ptr, *mailprog, *domain, *ext; - int len; + char *ptr, *mailprog, *domain, *size = "0", *ext; + char sizebuf[FMT_ULONG]; + int at, len, i; + struct stat statbuf; + stralloc defaultdomain = { 0 }; len = str_len(argv[0]); for (ptr = argv[0] + len;*ptr != '/' && ptr != argv[0];ptr--); if (*ptr && *ptr == '/') ptr++; ptr += 6; - if (*ptr == 'l') /*- qmail-local Filter */ - { - mailprog = "bin/qmail-local"; - ext = argv[6]; - domain = argv[7]; - remotE = 0; + if (*ptr == 'l') { /*- qmail-local Filter */ + if (!str_diff(argv[1], "-n") || !str_diff(argv[1], "-N")) { + i = 8; + ext = argv[6]; + } else { + i = 7; + ext = argv[5]; + } + if (env_get("MATCH_SENDER_DOMAIN")) { + at = str_rchr(argv[i], '@'); + if (argv[i][at] && argv[i][at + 1]) + domain = argv[i] + at + 1; + else { + if (!(domain = env_get("DEFAULT_DOMAIN"))) { + if (control_readfile(&defaultdomain, "control/defaultdomain", 0) == -1) + report(111, "spawn-filter: Unable to read defaultdomain: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + domain = defaultdomain.s; + } + } + } else /*- default for qmail-local is to match on recipient domain */ + domain = argv[i - 1]; /*- recipient domain */ delivery = local_delivery; if (!env_unset("QMAILREMOTE")) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); /*- sender */ - if (!stralloc_copys(&sender, argv[8])) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_0(&sender)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + if (!stralloc_copys(&sender, i == 8 ? argv[8] : argv[7]) || !stralloc_0(&sender)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); /*- recipient */ if (*ext) { /*- EXT */ if (!stralloc_copys(&recipient, ext)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); } else /*- user */ - if (!stralloc_copys(&recipient, argv[2])) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_cats(&recipient, "@")) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_cats(&recipient, domain)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_0(&recipient)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + if (!stralloc_copys(&recipient, i == 8 ? argv[2] : argv[1]) || + !stralloc_cats(&recipient, "@") || + !stralloc_cats(&recipient, i == 8 ? argv[7] : argv[6]) || + !stralloc_0(&recipient)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); } else - if (*ptr == 'r') /*- qmail-remote Filter */ - { - mailprog = "bin/qmail-remote"; - domain = argv[1]; - remotE = 1; + if (*ptr == 'r') { /*- qmail-remote Filter */ + if (env_get("MATCH_RECIPIENT_DOMAIN")) + domain = argv[1]; + else { /*- default for qmail-remote is to match on sender domain */ + at = str_rchr(argv[2], '@'); + if (argv[2][at] && argv[2][at + 1]) + domain = argv[2] + at + 1; + else { + if (!(domain = env_get("DEFAULT_DOMAIN"))) { + if (control_readfile(&defaultdomain, "control/defaultdomain", 0) == -1) + report(111, "spawn-filter: Unable to read defaultdomain: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + domain = defaultdomain.s; + } + } + } + ext = argv[3]; delivery = remote_delivery; if (!env_unset("QMAILLOCAL")) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); /*- sender */ - if (!stralloc_copys(&sender, argv[2])) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_0(&sender)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); + if (!stralloc_copys(&sender, argv[2]) || !stralloc_0(&sender)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); /*- recipient */ - if (!stralloc_copys(&recipient, argv[3])) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - if (!stralloc_0(&recipient)) - report(111, "spawn-filter: out of mem: ", error_str(errno), ". (#4.3.0)", 0, 0, 0); - } else - { + if (!stralloc_copys(&recipient, argv[5]) || !stralloc_0(&recipient)) + report(111, "spawn-filter: out of memory. (#4.3.0)", 0, 0, 0, 0, 0); + } else { report(111, "spawn-filter: Incorrect usage. ", argv[0], " (#4.3.0)", 0, 0, 0); _exit(111); } if (chdir(auto_qmail) == -1) report(111, "spawn-filter: Unable to switch to ", auto_qmail, ": ", error_str(errno), ". (#4.3.0)", 0); - run_mailfilter(domain, mailprog, argv); + + mailprog = setup_qargs(*ptr); /*- take care not to modify ptr before this line */ + + if (!fstat(0, &statbuf)) { + sizebuf[fmt_ulong(sizebuf, statbuf.st_size)] = 0; + size = sizebuf; + } else + size = "0"; + /*- DATABYTES Check */ + if (check_size(size)) + report(100, "sorry, that message size exceeds my databytes limit (#5.3.4)", 0, 0, 0, 0, 0); + run_mailfilter(domain, ext, mailprog, argv); report(111, "spawn-filter: could not exec ", mailprog, ": ", error_str(errno), ". (#4.3.0)", 0); + _exit(111); /*- Not reached */ return(0); } +#ifndef lint void getversion_qmail_spawn_filter_c() { - static char *x = "$Id: spawn-filter.c,v 1.41 2009-04-03 11:42:48+05:30 Cprogrammer Stab mbhangui $"; + static char *x = "$Id: spawn-filter.c,v 1.87 2024-01-23 01:23:36+05:30 Cprogrammer Exp mbhangui $"; + x = sccsidreporth; + x = sccsidgetdomainth; + x = sccsidmakeargsh; x++; } +#endif + +/* + * $Log: spawn-filter.c,v $ + * Revision 1.87 2024-01-23 01:23:36+05:30 Cprogrammer + * include buffer_defs.h for buffer size definitions + * + * Revision 1.86 2024-01-09 12:38:29+05:30 Cprogrammer + * display filter used for mail rejected message + * + * Revision 1.85 2023-12-05 23:19:48+05:30 Cprogrammer + * setup qmail-local, qmail-remote arguments after envrules + * + * Revision 1.84 2023-10-04 23:19:41+05:30 Cprogrammer + * use env variable QLOCAL, QREMOTE to execute alternate qmail-local, qmail-remote + * + * Revision 1.83 2022-03-05 13:39:33+05:30 Cprogrammer + * use auto_prefix/bin for qmail-inject, auto_prefix/sbin for qmail-local, qmail-remote paths + * + * Revision 1.82 2021-08-28 23:08:25+05:30 Cprogrammer + * moved dtype enum delivery variable from variables.h to getDomainToken.h + * + * Revision 1.81 2021-08-28 21:48:46+05:30 Cprogrammer + * match sender domain for remote delivery + * match recipient domain for local delivery + * allow overrides with MATCH_SENDER_DOMAIN, MATCH_RECIPIENT_DOMAIN + * + * Revision 1.80 2021-06-15 12:21:12+05:30 Cprogrammer + * moved makeargs.h to libqmail + * + * Revision 1.79 2021-06-01 01:55:17+05:30 Cprogrammer + * removed rate limit code, added to qmail-send, slowq-send + * + * Revision 1.78 2021-05-26 10:47:10+05:30 Cprogrammer + * handle access() error other than ENOENT + * + * Revision 1.77 2021-05-26 07:38:04+05:30 Cprogrammer + * moved getDomainToken() to getDomainToken.c + * + * Revision 1.76 2021-05-23 07:12:36+05:30 Cprogrammer + * moved report() to report.c + * moved rate functions to get_rate.c + * + * Revision 1.75 2021-01-28 18:15:34+05:30 Cprogrammer + * fixed indentation + * + * Revision 1.74 2020-12-08 14:15:41+05:30 Cprogrammer + * save original errno + * + * Revision 1.73 2020-11-26 22:23:03+05:30 Cprogrammer + * indicate the filter name in report to qmail-rspawn + * + * Revision 1.72 2020-11-01 23:11:56+05:30 Cprogrammer + * unset FILTERARGS, SPAMFILTER, QMAILLOCAL, QMAILREMOTE before calling qmail-local, qmail-remote + * + * Revision 1.71 2020-05-11 10:59:51+05:30 Cprogrammer + * fixed shadowing of global variables by local variables + * + * Revision 1.70 2020-04-08 15:59:13+05:30 Cprogrammer + * fixed spamignore control file not being read + * + * Revision 1.69 2020-04-01 16:14:54+05:30 Cprogrammer + * added header for makeargs() function + * + * Revision 1.68 2019-09-30 22:59:06+05:30 Cprogrammer + * use sh as argv0 instead of IndiMailfilter + * + * Revision 1.67 2019-07-18 10:48:31+05:30 Cprogrammer + * use strerr_die?x macro instead of strerr_die() function + * + * Revision 1.66 2018-01-31 12:08:27+05:30 Cprogrammer + * moved qmail-local, qmail-remote to sbin + * + * Revision 1.65 2016-06-05 13:22:05+05:30 Cprogrammer + * fixed stupid error message + * + * Revision 1.64 2014-03-26 15:32:26+05:30 Cprogrammer + * report deliveries blackholed by filters in delivery log + * + * Revision 1.63 2014-03-12 15:36:37+05:30 Cprogrammer + * define REG_NOERROR for OSX / Systems with REG_NOERROR undefined + * + * Revision 1.62 2014-03-07 02:07:42+05:30 Cprogrammer + * do not abort if regcomp() fails + * + * Revision 1.61 2014-03-04 02:41:38+05:30 Cprogrammer + * fix BUG by doing chdir back to auto_qmail + * ability to have regular expressions on rate control + * ability to have global definition for rate control + * + * Revision 1.60 2014-01-22 15:43:29+05:30 Cprogrammer + * apply envrules for RATELIMIT_DIR + * + * Revision 1.59 2013-09-06 13:58:23+05:30 Cprogrammer + * added comments + * + * Revision 1.58 2013-09-05 09:20:05+05:30 Cprogrammer + * changed variables to double + * + * Revision 1.57 2013-08-29 18:27:15+05:30 Cprogrammer + * switched to switch statement + * + * Revision 1.56 2013-08-27 09:42:18+05:30 Cprogrammer + * added rate limiting by domain + * + * Revision 1.55 2011-06-09 21:28:11+05:30 Cprogrammer + * blackhole mails if filter program exits 2 + * + * Revision 1.54 2011-02-08 22:17:37+05:30 Cprogrammer + * added missing unset of QMAILLOCAL when executing qmail-remote + * + * Revision 1.53 2011-01-08 16:41:27+05:30 Cprogrammer + * added comments + * + * Revision 1.52 2010-07-10 10:43:09+05:30 Cprogrammer + * fixed matching of local/remote directives in filterargs control file + * + * Revision 1.51 2010-07-10 09:36:11+05:30 Cprogrammer + * standardized environment variables set for filters + * + * Revision 1.50 2010-07-09 08:22:42+05:30 Cprogrammer + * implemented sender based envrules using control file fromd.envrules + * + * Revision 1.49 2009-11-09 20:32:52+05:30 Cprogrammer + * Use control file queue_base to process multiple indimail queues + * + * Revision 1.48 2009-09-08 13:22:28+05:30 Cprogrammer + * removed dependency of indimail on spam filtering + * + * Revision 1.47 2009-05-01 10:43:40+05:30 Cprogrammer + * added errstr argument to envrules(), address_match() + * + * Revision 1.46 2009-04-29 21:03:40+05:30 Cprogrammer + * check address_match() for failure + * + * Revision 1.45 2009-04-29 14:18:50+05:30 Cprogrammer + * conditional declaration of spf_fn + * + * Revision 1.44 2009-04-29 09:01:03+05:30 Cprogrammer + * spamignore can be a cdb file + * + * Revision 1.43 2009-04-29 08:24:37+05:30 Cprogrammer + * change for address_match() function + * + * Revision 1.42 2009-04-19 13:40:07+05:30 Cprogrammer + * set environment variable DOMAIN for use in programs called as FILTERS + * + * Revision 1.41 2009-04-03 11:42:48+05:30 Cprogrammer + * create pipe for error messages + * + * Revision 1.40 2009-04-02 15:17:54+05:30 Cprogrammer + * unset QMAILLOCAL in qmail-remote and unset QMAILREMOTE in qmail-local + * + * Revision 1.39 2008-06-12 08:40:55+05:30 Cprogrammer + * added rulesfile argument + * + * Revision 1.38 2008-05-25 17:16:43+05:30 Cprogrammer + * made message more readable by adding a blank space + * + * Revision 1.37 2007-12-20 13:51:54+05:30 Cprogrammer + * avoid loops with FILTERARGS, SPAMFILTERARGS + * removed compiler warning + * + * Revision 1.36 2006-06-07 14:11:28+05:30 Cprogrammer + * added SPAMEXT, SPAMHOST, SPAMSENDER, QQEH environment variable + * unset FILTERARGS before calling filters + * + * Revision 1.35 2006-01-22 10:14:45+05:30 Cprogrammer + * BUG fix for spam mails wrongly getting blackholed + * + * Revision 1.34 2005-08-23 17:36:48+05:30 Cprogrammer + * gcc 4 compliance + * delete sender in spam notification + * + * Revision 1.33 2005-04-02 19:07:47+05:30 Cprogrammer + * use internal wildmat version + * + * Revision 1.32 2004-11-22 19:50:53+05:30 Cprogrammer + * include regex.h after sys/types.h to avoid compilation prob on RH 7.3 + * + * Revision 1.31 2004-10-22 20:30:35+05:30 Cprogrammer + * added RCS id + * + * Revision 1.30 2004-10-21 21:56:21+05:30 Cprogrammer + * change for two additional arguments to strerr_die() + * + * Revision 1.29 2004-10-11 14:06:14+05:30 Cprogrammer + * use control_readulong instead of control_readint + * + * Revision 1.28 2004-09-22 23:14:20+05:30 Cprogrammer + * replaced atoi() with scan_int() + * + * Revision 1.27 2004-09-08 10:54:49+05:30 Cprogrammer + * incorrect exit code in report() function for remote + * mails. Caused qmail-rspawn to report "Unable to run qmail-remote" + * + * Revision 1.26 2004-07-17 21:23:31+05:30 Cprogrammer + * change qqeh code in qmail-remote + * + * Revision 1.25 2004-07-15 23:40:46+05:30 Cprogrammer + * fixed compilation warning + * + * Revision 1.24 2004-07-02 16:15:25+05:30 Cprogrammer + * override control files rejectspam, spamredirect by + * environment variables REJECTSPAM and SPAMREDIRECT + * allow patterns in domain specification in the control files + * spamfilterargs, filterargs, rejectspam and spamredirect + * + * Revision 1.23 2004-06-03 22:58:34+05:30 Cprogrammer + * fixed compilation problem without indimail + * + * Revision 1.22 2004-05-23 22:18:17+05:30 Cprogrammer + * added envrules filename as argument + * + * Revision 1.21 2004-05-19 23:15:07+05:30 Cprogrammer + * added comments + * + * Revision 1.20 2004-05-12 22:37:47+05:30 Cprogrammer + * added check DATALIMIT check + * + * Revision 1.19 2004-05-03 22:17:36+05:30 Cprogrammer + * use QUEUE_BASE instead of auto_qmail + * + * Revision 1.18 2004-02-13 14:51:24+05:30 Cprogrammer + * added envrules + * + * Revision 1.17 2004-01-20 06:56:56+05:30 Cprogrammer + * unset FILTERARGS for notifications + * + * Revision 1.16 2004-01-20 01:52:08+05:30 Cprogrammer + * report string length corrected + * + * Revision 1.15 2004-01-10 09:44:36+05:30 Cprogrammer + * added comment for exit codes of bogofilter + * + * Revision 1.14 2004-01-08 00:32:49+05:30 Cprogrammer + * use TMPDIR environment variable for temporary directory + * send spam reports to central spam logger + * + * Revision 1.13 2003-12-30 00:44:42+05:30 Cprogrammer + * set argv[0] from spamfilterprog + * + * Revision 1.12 2003-12-22 18:34:25+05:30 Cprogrammer + * replaced spfcheck() with address_match() + * + * Revision 1.11 2003-12-20 01:35:06+05:30 Cprogrammer + * added wait_pid to prevent zombies + * + * Revision 1.10 2003-12-17 23:33:39+05:30 Cprogrammer + * improved logic for getting remote/local tokens + * + * Revision 1.9 2003-12-16 10:38:24+05:30 Cprogrammer + * fixed incorrect address being returned if filterargs contained local: or + * remote: directives + * + * Revision 1.8 2003-12-15 20:46:19+05:30 Cprogrammer + * added case 100 to bounce mail + * + * Revision 1.7 2003-12-15 13:51:44+05:30 Cprogrammer + * code to run additional filters using /bin/sh + * + * Revision 1.6 2003-12-14 11:36:18+05:30 Cprogrammer + * added option to blackhole spammers + * + * Revision 1.5 2003-12-13 21:08:46+05:30 Cprogrammer + * extensive rewrite + * common report() function for local/remote mails to report errors + * + * Revision 1.4 2003-12-12 20:20:55+05:30 Cprogrammer + * use -a option to prevent using header addresses + * + * Revision 1.3 2003-12-09 23:37:16+05:30 Cprogrammer + * change for spawn-filter to be called as qmail-local or qmail-remote + * + * Revision 1.2 2003-12-08 23:48:23+05:30 Cprogrammer + * new function getDomainToken() to retrieve domain specific values + * read rejectspam and spamredirect only if SPAMEXITCODE is set + * + * Revision 1.1 2003-12-07 13:02:00+05:30 Cprogrammer + * Initial revision + * + */ diff --git a/str.h b/str.h index 9475cbb..2edf187 100644 --- a/str.h +++ b/str.h @@ -2,6 +2,7 @@ #define STR_H extern unsigned int str_copy(); +extern unsigned int str_copyb(); extern int str_diff(); extern int str_diffn(); extern unsigned int str_len(); diff --git a/wildmat.c b/wildmat.c index 746b645..5e30d3d 100644 --- a/wildmat.c +++ b/wildmat.c @@ -129,7 +129,7 @@ wildmat_internal(text, p) } #if defined(TEST) -include < stdio.h > +#include /*- Yes, we use gets not fgets. Sue me. */ int