[Mimedefang] Sendmail Macros in check_relay()

Martin Blapp mb at imp.ch
Mon Jul 9 08:40:47 EDT 2007


Hi,

It was a rather easy job :-)) Here is the patch, if anyone likes to use
it.

I think you could adapt the generic mimedefang structure to have access to
some generic values.

> It's relatively cheap, but given the architecture of MIMEDefang, it's
> very difficult to get macros before the MAIL FROM: callback.  If you
> do try to hack it, please be prepared for a big job.

First some filter stuff:

#
# Get the trusted nets from SpamAssassin
#
if ($Features{"SpamAssassin"}) {
 	$trusted_nets = $SASpamTester->{conf}->{trusted_networks};
}

#
# Regex which detects dynamic relays
#
$dynhostsregex = "(?!^server|vhost|mail|mx|static)(?:dial|ppp|^[0-9]|^user|[^\.]dynamic|^OL[0-9]{2,3}-|^(?:j|cc|cm|cp)[0-9]{5,6}|^bgp[0-9]
{3}|-cuda[0-9]-|\.upc-[a-z]\.|\.zoog0[0-9]\.|\.gig0[09]\.|^p[09]{4}-|^la02-|^YahooBB|^c906|c911|^c[ocp][0-9]{3,5]|p[0-9]{4}-|vapoajzmm\.co
m|detainment\.net|shrubalthaea\.com|\.lmndr\.com|^pcp0|^sndr|^cs24|^dyna|dsl|hsd1|^pcp[0-9]|^usen-|line|catv|client|bredband|broadband|cli
ent|dip0|securepop|pool|^ip|^pl[0-9]{3}.|^pub|port-ip|^i3ED|^chello|\.catv|cpiak|^zaqdb|cable|cust|\.fix\.|\.ipt\.|\.dyn\.|[\.\-][0-9]{1,3
}[\.\-][0-9]{1,3})";

filter_relay () {
 	my ($ip, $name, $load) = @_;

         #
         # Don't make any tests for trusted networks if SA is available
         #
         if ($Features{"SpamAssassin"} && $trusted_nets->contains_ip($ip)) {
                 return ('CONTINUE', "ok");
         }

         #
         # DNS check if load is too high. If the load is over
         # limit, we tempfail all messages from dynamic relays.
         # Same procedure if the reverse dns entry of the relay
         # is missing.
         #
         # On the MX side, this must be defined in the config:
         # define(`confMILTER_MACROS_CONNECT', confMILTER_MACROS_CONNECT`, {load_avg}')
         #
         # And you definitly need a local mimedefang patch. See below
         #
         if ($load > $maxload) {
                 my $dyndns;
                 $dyndns = &checkdyndns($ip, $name);
                 if ($dyndns) {
                         md_syslog('err', "filter_relay(): tempfail $name, load ($load) too high, max: ($maxload)");
                         return ('TEMPFAIL', "Please try again later.");
                 } else {
                         md_syslog('err', "filter_relay(): accept $name even if there is high load ($load)");
                 }
         }
}

#
# Returns true if the host looks like a dynamic relay or is
# equal to the ip.
#
sub checkdyndns {
         my ($ip, $name) = @_;

         if ($name eq "" || $name eq $ip ||
             $name =~ /$dynhostsregex/i) {
                 return 1;
         }
         return 0;
}

Here is the mimedefang patch:

--- mimedefang.c	Fri Feb  9 17:29:25 2007
+++ mimedefang.c	Mon Jul  9 11:15:18 2007
@@ -156,6 +156,7 @@
      char *dir;			/* Work directory */
      char *heloArg;		/* HELO argument */
      char *qid;                  /* Queue ID */
+    int load_avg;		/* Load Average */
      int fd;			/* File for message body */
      int headerFD;		/* File for message headers */
      int cmdFD;			/* File for commands */
@@ -536,6 +537,8 @@
  	}
  	data->hostip[64] = 0;
      }
+    data->load_avg = 0;
+    data->load_avg = smfi_getsymval(ctx, "{load_avg}");

      /* Is host IP equivalent to loopback?  If so, replace with 127.0.0.1 */
      /* (We have enough room because data->hostip can hold 64 chars + nul) */
@@ -555,7 +557,7 @@
      if (doRelayCheck) {
  	char buf2[SMALLBUF];
  	int n = MXRelayOK(MultiplexorSocketName, buf2, data->hostip,
-			  data->hostname);
+			  data->hostname, data->load_avg);
  	if (n == MD_REJECT) {
  	    /* Can't call smfi_setreply from connect callback */
  	    /* set_dsn(ctx, buf2, 5); */
--- mimedefang.h	Fri Feb  2 21:37:06 2007
+++ mimedefang.h	Mon Jul  9 11:16:02 2007
@@ -27,7 +27,7 @@
  extern int MXScanDir(char const *sockname, char const *dir);
  extern int MXCommand(char const *sockname, char const *cmd, char *buf, int len);
  extern int MXRelayOK(char const *sockname, char *msg,
-		     char const *ip, char const *name);
+		     char const *ip, char const *name, int load);
  extern int MXHeloOK(char const *sockname, char *msg,
  		    char const *helo, char const *ip, char const *name);
  extern int MXSenderOK(char const *sockname, char *msg,
--- utils.c	Mon Jul  9 12:02:56 2007
+++ utils.c	Mon Jul  9 11:25:32 2007
@@ -566,7 +566,8 @@
  MXRelayOK(char const *sockname,
  	  char *msg,
  	  char const *ip,
-	  char const *name)
+	  char const *name,
+	  int load)
  {
      char cmd[SMALLBUF];
      char ans[SMALLBUF];
@@ -579,7 +580,7 @@
      if (!name || !*name) {
  	name = ip;
      }
-    if (percent_encode_command(1, cmd, sizeof(cmd), "relayok", ip, name, NULL) < 0) {
+    if (percent_encode_command(1, cmd, sizeof(cmd), "relayok", ip, name, load, NULL) < 0) {
  	return MD_TEMPFAIL;
      }
      if (MXCommand(sockname, cmd, ans, SMALLBUF-1) < 0) return MD_TEMPFAIL;
--- mimedefang.pl.in.orig	Mon Jul  9 12:10:16 2007
+++ mimedefang.pl.in	Mon Jul  9 12:11:40 2007
@@ -5219,10 +5219,11 @@
  	    next;
  	}

-	if ($_ =~ /^relayok (\S*)\s+(\S*)/) {
+	if ($_ =~ /^relayok (\S*)\s+(\S*)\s*(\S*)/) {
  	    $ip = percent_decode($1);
  	    $name = percent_decode($2);
-	    relay_ok($ip, $name);
+	    my $load = percent_decode($3);
+	    relay_ok($ip, $name, $load);
  	    chdir($Features{'Path:SPOOLDIR'});
  	    next;
  	}
@@ -6569,11 +6570,12 @@
  # %ARGUMENTS:
  #  hostip -- IP address of relay host
  #  hostname -- name of relay host
+#  load average -- the 1 minute load average
  # %RETURNS:
  #  Nothing, but prints "ok 1" if we accept connection, "ok 0" if not.
  #***********************************************************************
-sub relay_ok ($$) {
-    my($hostip, $hostname) = @_;
+sub relay_ok ($$$) {
+    my($hostip, $hostname, $systemload) = @_;
      if (!defined(&filter_relay)) {
  	send_filter_answer('CONTINUE', "ok",
  			   "filter_relay", "host $hostip ($hostname)");
@@ -6583,7 +6585,7 @@
      # Set up globals
      $RelayAddr     = $hostip;
      $RelayHostname = $hostname;
-    my($ok, $msg, $code, $dsn, $delay) = filter_relay($hostip, $hostname);
+    my($ok, $msg, $code, $dsn, $delay) = filter_relay($hostip, $hostname, $systemload);
      send_filter_answer($ok, $msg, "filter_relay", "host $hostip ($hostname)", $code, $dsn, $delay);
  }




More information about the MIMEDefang mailing list