[Mimedefang] [PATCH] filter_data implementation
Martin Blapp
mbr at freebsd.org
Wed May 27 06:10:51 EDT 2009
Hi all,
And here the patch again, this time with examples and parts
of the manpage.
--
Martin
--- mimedefang.c 2009-05-24 07:40:40.000000000 +0200
+++ mimedefang.c 2009-05-24 06:27:35.000000000 +0200
@@ -233,6 +233,9 @@
/* Do recipient check? */
static int doRecipientCheck = 0;
+/* Do precontent check */
+static int doPreContentCheck = 0;
+
/* Keep directories around if multiplexor fails? */
static int keepFailedDirectories = 0;
@@ -978,12 +981,67 @@
*%RETURNS:
* Standard milter reply code
*%DESCRIPTION:
-* Does a post-DATA callback
+* Does a post-DATA callback before any content is submitted
***********************************************************************/
#ifdef MILTER_BUILDLIB_HAS_DATA
static sfsistat mf_data(SMFICTX *ctx)
{
- return SMFIS_CONTINUE;
+ struct privdata *data = DATA;
+ char ans[SMALLBUF];
+ sfsistat retcode = SMFIS_CONTINUE;
+ int i;
+
+ DEBUG_ENTER("mf_data");
+ if (!data) {
+ syslog(LOG_WARNING, "postdata: Unable to obtain private data from milter
context");
+ DEBUG_EXIT("mf_data", "SMFIS_TEMPFAIL");
+ return SMFIS_TEMPFAIL;
+ }
+
+ /* Post data check if enabled */
+ if (doPreContentCheck) {
+ int n;
+
+ n = MXDataOK(MultiplexorSocketName, ans, data->sender, data->hostip,
+ data->hostname, data->firstRecip, data->heloArg,
+ data->dir, data->qid);
+
+ if (n == MD_REJECT) {
+ /* Reject this mail with all recipients */
+ set_dsn(ctx, ans, 5);
+
+ DEBUG_EXIT("mf_data", "SMFIS_REJECT");
+ return SMFIS_REJECT;
+ }
+ if (n <= MD_TEMPFAIL) {
+ /* Tempfail this mail with all recipients */
+ set_dsn(ctx, ans, 4);
+
+ DEBUG_EXIT("mf_data", "SMFIS_TEMPFAIL");
+ return SMFIS_TEMPFAIL;
+ }
+ if (n == MD_ACCEPT_AND_NO_MORE_FILTERING) {
+ /* Called in case we don't need content filtering */
+ set_dsn(ctx, ans, 2);
+ cleanup(ctx);
+ DEBUG_EXIT("mf_data", "SMFIS_ACCEPT");
+ return SMFIS_ACCEPT;
+ }
+ if (n == MD_DISCARD) {
+ set_dsn(ctx, ans, 2);
+
+ cleanup(ctx);
+ DEBUG_EXIT("mf_data", "SMFIS_DISCARD");
+ return SMFIS_DISCARD;
+ }
+ if (n == MD_CONTINUE) {
+ /* Called only in case we need to delay */
+ set_dsn(ctx, ans, 2);
+ return SMFIS_CONTINUE;
+ }
+ }
+ DEBUG_EXIT("mf_data", "SMFIS_CONTINUE");
+ return retcode;
}
#endif
@@ -2092,6 +2150,7 @@
fprintf(stderr, " -r -- Do relay check before
processing body\n");
fprintf(stderr, " -s -- Do sender check before
processing body\n");
fprintf(stderr, " -t -- Do recipient checks before
processing body\n");
+ fprintf(stderr, " -A -- Do pre content check for
processing body\n");
fprintf(stderr, " -q -- Allow new connections to be
queued by multiplexor\n");
fprintf(stderr, " -P file -- Write process-ID of daemon to
specified file\n");
fprintf(stderr, " -T -- Log filter times to syslog\n");
@@ -2189,7 +2248,7 @@
}
/* Process command line options */
- while ((c = getopt(argc, argv,
"NCDHL:MP:R:S:TU:Xa:b:cdhkm:p:qrstvx:z:")) != -1) {
+ while ((c = getopt(argc, argv,
"ANCDHL:MP:R:S:TU:Xa:b:cdhkm:p:qrstvx:z:")) != -1) {
switch (c) {
case 'N':
#ifdef MILTER_BUILDLIB_HAS_NEGOTIATE
@@ -2346,6 +2405,9 @@
case 't':
doRecipientCheck = 1;
break;
+ case 'A':
+ doPreContentCheck = 1;
+ break;
case 'h':
usage();
break;
--- mimedefang.h 2009-05-24 07:40:40.000000000 +0200
+++ mimedefang.h 2009-05-24 06:26:27.000000000 +0200
@@ -40,6 +40,10 @@
char const *dir, char const *qid,
char const *rcpt_mailer, char const *rcpt_host,
char const *rcpt_addr);
+extern int MXDataOK(char const *sockname, char *msg,
+ char const *sender, char const *ip, char const *name,
+ char const *firstRecip, char const *helo,
+ char const *dir, char const *qid);
extern int safeWriteHeader(int fd, char *str);
extern void split_on_space(char *buf, char **first, char **rest);
--- mimedefang.pl.in 2009-05-24 07:41:08.000000000 +0200
+++ mimedefang.pl.in 2009-05-24 07:10:42.000000000 +0200
@@ -5645,6 +5645,21 @@
chdir($Features{'Path:SPOOLDIR'});
next;
}
+ if ($_ =~ /^dataok (\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)/)
{
+ $sender = percent_decode($1);
+ $ip = percent_decode($2);
+ $name = percent_decode($3);
+ $firstRecip = percent_decode($4);
+ $helo = percent_decode($5);
+ $CWD = percent_decode($6);
+ $QueueID = percent_decode($7);
+ $MsgID = $QueueID;
+
+ chdir($CWD);
+ data_ok($sender, $ip, $name, $firstRecip, $helo);
+ chdir($Features{'Path:SPOOLDIR'});
+ next;
+ }
# If "filter_unknown_cmd" is defined, call it
if (defined(&filter_unknown_cmd)) {
@@ -7074,6 +7089,39 @@
}
#***********************************************************************
+# %PROCEDURE: data_ok
+# %ARGUMENTS:
+# sender -- e-mail address of sender
+# ip -- IP address of relay host
+# name -- name of relay host
+# firstRecip -- first recipient of message
+# helo -- arg to SMTP HELO command
+# %RETURNS:
+# Nothing, but prints "ok 1" if we accept the message,
+# "ok 0" if not.
+#***********************************************************************
+sub data_ok ($$$$$) {
+ my($sender, $ip, $name, $firstRecip, $helo) = @_;
+ if (!defined(&filter_data)) {
+ send_filter_answer('CONTINUE', "ok",
+ "filter_data", "data");
+ return;
+ }
+
+ # Set up globals
+ $Sender = $sender;
+ $RelayAddr = $ip;
+ $RelayHostname = $name;
+ $Helo = $helo;
+ my($ok, $msg, $code, $dsn, $delay) =
+ filter_data($sender, $ip, $name,
+ $firstRecip, $helo);
+ send_filter_answer($ok, $msg,
+ "filter_data", "data",
+ $code, $dsn, $delay);
+}
+
+#***********************************************************************
# %PROCEDURE: print_message_structure
# %ARGUMENTS:
# None
--- utils.c 2009-05-24 07:40:40.000000000 +0200
+++ utils.c 2009-05-24 06:29:06.000000000 +0200
@@ -801,6 +801,69 @@
}
/**********************************************************************
+* %FUNCTION: MXDataOK
+* %ARGUMENTS:
+* sockname -- multiplexor socket name
+* msg -- buffer of at least SMALLBUF size for error messages
+* sender -- sender's e-mail address
+* ip -- sending relay's IP address
+* name -- sending relay's host name
+* firstRecip -- first recipient of the message
+* helo -- argument to "HELO/EHLO" (may be NULL)
+* dir -- MIMEDefang working directory
+* qid -- Sendmail queue identifier
+* %RETURNS:
+* 1 if it's OK to accept this message; 0 if not, -1 if error.
+***********************************************************************/
+int
+MXDataOK(char const *sockname,
+ char *msg,
+ char const *sender,
+ char const *ip,
+ char const *name,
+ char const *firstRecip,
+ char const *helo,
+ char const *dir,
+ char const *qid)
+{
+ char cmd[SMALLBUF];
+ char ans[SMALLBUF];
+ int i, l, l2;
+
+ *msg = 0;
+
+ if (!sender || !*sender) {
+ sender = "UNKNOWN";
+ }
+
+ if (!ip || !*ip) {
+ ip = "UNKNOWN";
+ }
+ if (!name || !*name) {
+ name = ip;
+ }
+
+ if (!firstRecip || !*firstRecip) {
+ firstRecip = "UNKNOWN";
+ }
+ if (!helo) {
+ helo = "UNKNOWN";
+ }
+
+ if (percent_encode_command(0, cmd, sizeof(cmd),
+ "dataok", sender, ip, name, firstRecip,
+ helo, dir, qid, NULL) < 0) {
+ return MD_TEMPFAIL;
+ }
+
+ /* Add newline */
+ strcat(cmd, "\n");
+
+ if (MXCommand(sockname, cmd, ans, SMALLBUF-1) < 0) return MD_TEMPFAIL;
+ return munch_mx_return(ans, msg);
+}
+
+/**********************************************************************
* %FUNCTION: writen
* %ARGUMENTS:
* fd -- file to write to
--- examples/init-script.in 2008-03-07 21:59:28.000000000 +0100
+++ examples/init-script.in 2009-05-24 08:06:00.000000000 +0200
@@ -61,6 +61,9 @@
# "yes" turns on the multiplexor recipient checking function
# MX_RECIPIENT_CHECK=no
+# "yes" turns on the multiplexor data checking function
+# MX_DATA_CHECK=no
+
# Set to yes if you want the multiplexor to log events to syslog
MX_LOG=yes
@@ -268,6 +271,7 @@
`[ "$MX_HELO_CHECK" = "yes" ] && echo "-H"` \
`[ "$MX_SENDER_CHECK" = "yes" ] && echo "-s"` \
`[ "$MX_RECIPIENT_CHECK" = "yes" ] && echo "-t"` \
+ `[ "$MX_DATA_CHECK" = "yes" ] && echo "-A"` \
`[ "$KEEP_FAILED_DIRECTORIES" = "yes" ] && echo "-k"` \
`[ "$MD_EXTRA" != "" ] && echo $MD_EXTRA` \
`[ "$MD_SKIP_BAD_RCPTS" = "yes" ] && echo "-N"` \
--- redhat/mimedefang-init.in 2008-08-15 20:03:41.000000000 +0200
+++ redhat/mimedefang-init.in 2009-05-24 08:06:31.000000000 +0200
@@ -141,6 +141,7 @@
$([ "$MX_HELO_CHECK" = "yes" ] && echo "-H") \
$([ "$MX_SENDER_CHECK" = "yes" ] && echo "-s") \
$([ "$MX_RECIPIENT_CHECK" = "yes" ] && echo "-t") \
+ $([ "$MX_DATA_CHECK" = "yes" ] && echo "-A") \
$([ "$KEEP_FAILED_DIRECTORIES" = "yes" ] && echo "-k") \
$([ -n "$MD_EXTRA" ] && echo "$MD_EXTRA") \
$([ "$ALLOW_NEW_CONNECTIONS_TO_QUEUE" = "yes" ] && echo "-q") \
--- redhat/mimedefang-sysconfig.in 2008-03-07 21:59:28.000000000 +0100
+++ redhat/mimedefang-sysconfig.in 2009-05-24 08:07:22.000000000 +0200
@@ -145,6 +145,9 @@
# If "yes", turn on the multiplexor recipient checking function
# MX_RECIPIENT_CHECK=no
+# If "yes", turn on the multiplexor post data checking function
+# MX_DATA_CHECK=no
+
# Ask for filter_tick to be called every 60 seconds
# MX_TICK_REQUEST=60
--- mimedefang-filter.5.in 2009-01-05 16:06:45.000000000 +0100
+++ mimedefang-filter.5.in 2009-05-24 08:18:35.000000000 +0200
@@ -811,21 +811,21 @@
The host name of the relay. This is the name of the host that is
attempting
to send e-mail to your host. May be "undef" if the host name could not be
determined. This variable is available in \fBfilter_relay\fR,
-\fBfilter_sender\fR and \fBfilter_recipient\fR.
+\fBfilter_sender\fR, \fBfilter_recipient\fR and \fBfilter_data\fR.
.TP
.B $RelayAddr
The IP address of the sending relay (as a string consisting of four
dot-separated decimal numbers.) One potential use of \fB$RelayAddr\fR
is to limit mailing to certain lists to people within your organization.
-This variable is available in \fBfilter_relay\fR, \fBfilter_sender\fR
-and \fBfilter_recipient\fR.
+This variable is available in \fBfilter_relay\fR, \fBfilter_sender\fR,
+\fBfilter_recipient\fR and \fBfilter_data\fR.
.TP
.B $Helo
The argument given to the SMTP "HELO" command. This variable is
available in \fBfilter_sender\fR and \fBfilter_recipient\fR,
-but \fInot\fR in \fBfilter_relay\fR.
+\fBfilter_data\fR, but \fInot\fR in \fBfilter_relay\fR.
.TP
.B $Subject
@@ -833,8 +833,8 @@
.TP
.B $Sender
-The sender of the e-mail. This variable is set in \fBfilter_sender\fR
-and \fBfilter_recipient\fR.
+The sender of the e-mail. This variable is set in \fBfilter_sender\fR,
+\fBfilter_recipient\fR and \fBfilter_data\fR.
.TP
.B @Recipients
@@ -856,16 +856,16 @@
.B $QueueID
The Sendmail queue identifier if it could be determined. Otherwise,
contains the string "NOQUEUE". This variable \fIis\fR set correctly
-in \fBfilter_sender\fR and \fBfilter_recipient\fR, but it is \fInot\fR
-available in \fBfilter_relay\fR.
+in \fBfilter_sender\fR,\fBfilter_recipient\fR and \fBfilter_data\fR,
+but it is \fInot\fR available in \fBfilter_relay\fR.
.TP
.B $MsgID
Set to $QueueID if the queue ID could be determined; otherwise, set
to $MessageID. This identifier should be used in logging, because it
matches the identifier used by Sendmail to log messages. Note that this
-variable \fIis\fR set correctly in \fBfilter_sender\fR
-and \fBfilter_recipient\fR, but it is \fInot\fR available in
+variable \fIis\fR set correctly in \fBfilter_sender\fR,
+\fBfilter_recipient\fR and \fBfilter_data\fR, but it is \fInot\fR available
in
\fBfilter_relay\fR.
.TP
@@ -1396,16 +1396,16 @@
.TP
.B read_commands_file()
-This function should only be called from \fBfilter_sender\fR and
-\fBfilter_recipient\fR. This will read the \fBCOMMANDS\fR file (as
-described in mimedefang-protocol(7)), and will fill or update the
-following global variables: $Sender, @Recipients, %RecipientMailers,
-$RelayAddr, $RealRelayAddr, $RelayHostname, $RealRelayHostname,
-$QueueID, $Helo, %SendmailMacros.
+This function should only be called from \fBfilter_sender\fR,
+\fBfilter_recipient\fR and \fBfilter_data\fR. This will read the
+\fBCOMMANDS\fR file (as described in mimedefang-protocol(7)),
+and will fill or update the following global variables: $Sender,
+ at Recipients, %RecipientMailers, $RelayAddr, $RealRelayAddr,
+$RelayHostname, $RealRelayHostname, $QueueID, $Helo, %SendmailMacros.
If you do not call \fBread_commands_file\fR, then the only information
-available in \fBfilter_sender\fR and \fBfilter_recipient\fR is that
-which is passed as an argument to the function.
+available in \fBfilter_sender\fR, \fBfilter_recipient\fR or
\fBfilter_data\fR
+is that which is passed as an argument to the function.
.TP
.B stream_by_domain()
@@ -2008,6 +2008,12 @@
defined a filter_recipient routine, it is called.
.TP
+.B 4. SMTP DATA: COMMAND
+If you invoked \fBmimedefang\fR with the \fB\-A\fR option and have
+defined a filter_data routine, it is called. At this point, no body
+data have been received by the filter.
+
+.TP
.B 5. END OF SMTP DATA
filter_begin is called. For each MIME part, filter is called. Then
filter_end is called.
@@ -2087,7 +2093,7 @@
.PP
\fINote\fR: The IP validation header works only in message-oriented
functions. It (obviously) has no effect on \fBfilter_relay\fR,
-\fBfilter_sender\fR and \fBfilter_recipient\fR, because no header
+\fBfilter_sender\fR, \fBfilter_recipient\fR and \fBfilter_data\fR, because
no header
information is available yet. You must take this into account when
writing your filter; you must defer relay-based decisions to
the message filter for mail arriving from your other MX hosts.
@@ -2104,7 +2110,7 @@
It is available to all functions, all the time.
.TP
-.B In filter_relay, filter_sender or filter_recipient
+.B In filter_relay, filter_sender, filter_recipient or filter_data
Not guaranteed to be available to any other function, not even
from one filter_recipient call to the next, when receiving a
multi-recipient email message.
@@ -2124,8 +2130,8 @@
.PP
The "built-in" globals like $Subject, $Sender, etc. are always available
to filter_begin, filter and filter_end. Some are available to filter_relay,
-filter_sender or filter_recipient, but you should check the documentation
-of the variable above for details.
+filter_sender, filter_recipient or filter_data, but you should check the
+documentation of the variable above for details.
.SH MAINTAINING STATE
@@ -2146,6 +2152,10 @@
.TP
.B 4
+filter_data
+
+.TP
+.B 5
filter_begin, filter, filter_multipart, filter_end
.PP
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: patch-filter_data.txt
URL: <https://lists.mimedefang.org/pipermail/mimedefang_lists.mimedefang.org/attachments/20090527/6ad344cb/attachment.txt>
More information about the MIMEDefang
mailing list