[Mimedefang] Adding headers during filter sender() and 2.68 Beta 1 issue.

Martin Blapp mbr at freebsd.org
Wed May 27 05:41:37 EDT 2009


Hi all,

And here it is, a filter_data implementation. David, please
add a 'sponsored by T-Systems Switzerland' notice to the
changelog if that is possible.

Some of you may notice that only the first recipient is available
here. If the complete list of recipients is needed, one needs to
parse/read the COMMANDs/Result files to get the recipient list.

There may be issues with the LOG because I'm receiving now this
error message. Maybe david knows how to fix it, else I'll have a
look at it this evening.

May 24 07:53:11 vm1 mimedefang-multiplexor[81799]: Slave 0 stderr: Warning:
unable to close filehandle LOGF properly.

--
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                -- Process body. If not set,
content filtering will be skipped\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	2009-05-24 07:41:08.000000000 +0200
+++ mimedefang.pl	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





More information about the MIMEDefang mailing list