EE,

What are the chances of including this patch in the basic simscan-toaster?

While I'm inclined to believe that greylisting is best implemented at the
firewall, what are the drawbacks to having it in the toaster?

-------- Original Message --------
Subject: [simscan] [PATCH] Updated greylisting patch for simscan 1.2
Date: Mon, 13 Nov 2006 20:10:55 +0100
From: Florian G. Pflug <[EMAIL PROTECTED]>
Reply-To: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]

Hi

I've updates the greylisting patch to simscan 1.2
It now uses log_message log initial blocking, and
the first successfull attempt by a sender.

greetings, Florian Pflug


!DSPAM:4558c2c627411592547952!


-- 
-Eric 'shubes'
diff -Naur simscan-1.2/configure.in simscan-1.2.greylist/configure.in
--- simscan-1.2/configure.in	2005-09-30 23:15:47.000000000 +0200
+++ simscan-1.2.greylist/configure.in	2006-11-12 13:12:45.000000000 +0100
@@ -282,6 +282,25 @@
 
 #----------------------------------------------------------------------
 
+AC_ARG_ENABLE(greylist, [  --enable-greylist=y|n   Turn on greylisting. default no.],
+    ENABLE_GREYLIST="$enableval",
+    [
+      ENABLE_GREYLIST=no
+    ] )
+case $ENABLE_GREYLIST in
+1*|y*|Y*)
+        ENABLE_GREYLIST=1
+        AC_DEFINE_UNQUOTED([ENABLE_GREYLIST], $ENABLE_GREYLIST, [enable greylisting])
+        ;;
+*)
+        ENABLE_GREYLIST=0
+        ;;
+esac
+
+AC_SUBST(ENABLE_GREYLIST)
+
+#----------------------------------------------------------------------
+
 AC_MSG_CHECKING(whether we can locate the qmail directory)
 qmaildir=""
 for f in /var/qmail
@@ -796,4 +815,14 @@
     ;;
 esac
 
+case $ENABLE_GREYLIST in
+  1*|y*|Y*)
+    echo " greylisting           = ON"
+    ;;
+
+  *)
+    echo " greylisting           = OFF"
+    ;;
+esac
+
 echo ""
diff -Naur simscan-1.2/Makefile.am simscan-1.2.greylist/Makefile.am
--- simscan-1.2/Makefile.am	2004-11-04 16:27:45.000000000 +0100
+++ simscan-1.2.greylist/Makefile.am	2006-11-12 13:12:45.000000000 +0100
@@ -17,9 +17,11 @@
 	$(INSTALL) simscan @qmaildir@/bin/simscan
 	$(INSTALL) simscanmk @qmaildir@/bin/simscanmk
 	$(INSTALL) -m 750 -d @workdir@
+	test "@ENABLE_GREYLIST@" = "1" && $(INSTALL) -m 2750 -d @workdir@/scanner
+	test "@ENABLE_GREYLIST@" = "1" && $(INSTALL) -m 2750 -d @workdir@/greylist
 	strip @qmaildir@/bin/simscan
 	strip @qmaildir@/bin/simscanmk
-	chown @ENABLE_USER@ @workdir@ @qmaildir@/bin/simscan
+	chown -R @ENABLE_USER@ @workdir@ @qmaildir@/bin/simscan
 	chmod 4711 @qmaildir@/bin/simscan
 
 AUTOMAKE_OPTIONS = foreign no-dependencies 
diff -Naur simscan-1.2/simscan.c simscan-1.2.greylist/simscan.c
--- simscan-1.2/simscan.c	2005-10-05 23:12:42.000000000 +0200
+++ simscan-1.2.greylist/simscan.c	2006-11-12 13:26:32.000000000 +0100
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
+#include <utime.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
@@ -68,7 +70,6 @@
        91   Envelope format error.
 */
 
-
 #ifdef QUARANTINEDIR 
 void quarantine_msg(char *message_name);
 #endif
@@ -85,6 +86,11 @@
 char message_name[BUFFER_SIZE];
 char workdir[BUFFER_SIZE];
 char unique_ext[BUFFER_SIZE];
+#ifdef ENABLE_GREYLIST
+char greylist_initial[BUFFER_SIZE];
+char greylist_allowed[BUFFER_SIZE];
+char greylist_dir[BUFFER_SIZE];
+#endif
 
 void format_dir(char *workdir);
 void exit_clean(int error_code);
@@ -123,8 +129,9 @@
 int  PerDomainSpam;
 int  PerDomainTrophie;
 int  PerDomainSpamPassthru;
-int  MaxDomains;
-char Domains[MAXDOMAINS][MAXDOMLEN];
+#ifdef ENABLE_GREYLIST
+int  PerDomainGreylist;
+#endif
 
 void set_per_domain();
 void init_per_domain();
@@ -187,7 +194,7 @@
 #endif
 
 struct timeval start,stop;
-double utime;
+double delta;
 #define SECS(tv) (tv.tv_sec + tv.tv_usec / 1000000.0)
 
 /* write a received line */
@@ -208,6 +215,27 @@
 
 void log_message( char *state, char *subject, int spam );
 
+#ifdef ENABLE_GREYLIST
+/*
+ * Timing for greylisting.
+ * 
+ * Algorithm: When a sender with a source ip for which no record yet exists
+ *            connects, his delivery will fail with a temporary error.
+ *            All following delivery attempts by that sender will fail with
+ *            a temporary error too, until GREYLIST_MIN_DELAY seconds after
+ *            his _first_ attempt.
+ *            Delivery attempts started between GREYLIST_MIN_DELAY and 
+ *            GREYLIST_MAX_DELAY seconds after the first delivery attempt 
+ *            will succeed, and cause all future mails from that sender to
+ *            be accepted immediatly. 
+ */
+#define GREYLIST_MIN_DELAY 60
+#define GREYLIST_MAX_DELAY 36*3600
+
+void format_greylist(char* greylist_dir, char* greylist_initial, char* greylist_allowed);
+int check_greylist();
+#endif
+
 int main(int argc, char **argv)
 {
 #ifdef HAS_ULIMIT_NPROC
@@ -255,9 +283,23 @@
 
   /* format the new directory name */
   format_dir(workdir);
+  
+  /* format greylist names */
+#ifdef ENABLE_GREYLIST
+  format_greylist(greylist_dir, greylist_initial, greylist_allowed);
+#endif
 
   if ( DebugFlag > 0 ) {
+#ifdef ENABLE_GREYLIST
+    fprintf(stderr,
+      "simscan: starting: work dir: %s, greylistdir: %s, sourceip: %s\n",
+      workdir,
+      greylist_dir,
+      getenv("TCPREMOTEIP")
+    );  
+#else
     fprintf(stderr, "simscan: starting: work dir: %s\n", workdir);  
+#endif
   }
 
   /* create the working directory, allow group access too */
@@ -269,6 +311,17 @@
     _exit(EXIT_400);
   }
 
+#ifdef ENABLE_GREYLIST
+  /* create the working directory, allow group access too */
+  if ( (mkdir(greylist_dir, 0750) == -1) && (errno != EEXIST) ) {
+    if ( DebugFlag > 0 ) {
+      fprintf(stderr, "simscan: error making graylist dir, exit 400, errno: %d\n",
+        errno);
+    }
+    _exit(EXIT_400);
+  }
+#endif
+
   /* change to the new working directory */
   if ( chdir(workdir) != 0 ) {
     if ( DebugFlag > 0 ) {
@@ -361,6 +414,31 @@
   set_per_domain();
 #endif
 
+#ifdef ENABLE_GREYLIST
+  switch ( check_greylist() ) {
+    case -2: 
+      if ( DebugFlag > 0 ) { fprintf(stderr, "simscan: greylisting disabled\n"); }
+      break;
+    case 1:
+      log_message("GREYLIST DELAYED", "-", 0);
+#ifdef ENABLE_CUSTOM_SMTP_REJECT
+      snprintf(RejectMsg,sizeof(RejectMsg), 
+       "ZFirst connection from %s. Just retry, and you mail will be accepted",
+         getenv("TCPREMOTEIP") );
+      write(4,RejectMsg, strlen(RejectMsg));
+      exit_clean(EXIT_MSG);
+#else
+      exit_clean(EXIT_400); 
+#endif
+      break;
+    case 2:
+      log_message("GREYLIST ACCEPTED", "-", 0);
+      break;
+    default: 
+      break;
+  }
+#endif
+
 #ifdef ENABLE_REGEX
   /* check for regexs to block */
   if ( check_regex() == 2 ) {
@@ -608,10 +686,10 @@
 
   #ifdef ENABLE_RECEIVED
   gettimeofday(&stop,(struct timezone *) 0);
-  utime=SECS(stop)-SECS(start);
+  delta=SECS(stop)-SECS(start);
   snprintf(buffer,sizeof(buffer),
 "Received: by simscan %s ppid: %d, pid: %d, t: %3.4fs\n         scanners:%s\n",
-    VERSION,getppid(),getpid(),utime,
+    VERSION,getppid(),getpid(),delta,
     strlen(runned_scanners) > 0 ? runned_scanners : "none");
   if ( write(pim[1], buffer,strlen(buffer)) == -1 ) {
     if ( DebugFlag > 0 ) {
@@ -1082,10 +1160,36 @@
   snprintf(unique_ext, sizeof(unique_ext),"%ld.%ld.%ld", 
     mytime.tv_sec, mytime.tv_usec, (long int)getpid());
 
+#ifdef ENABLE_GREYLIST
   snprintf(workdir,BUFFER_SIZE, "%s/%s", WORKDIR, unique_ext); 
+#else
+  snprintf(workdir,BUFFER_SIZE, "%s/scanner/%s", WORKDIR, unique_ext); 
+#endif
 
 }
 
+#ifdef ENABLE_GREYLIST
+/*
+ * create path to state file for TCPREMOTEIP
+ */
+void format_greylist(char* greylist_dir, char* greylist_initial, char* greylist_allowed)
+{
+  char h=0, *ip=getenv("TCPREMOTEIP") ;
+  int i, l=strlen(ip) ;
+  
+  /* Compute hash */
+  for(i=0; i < l; i++)
+    h = ip[i] ^ (
+      ((h & 0xf0)>>4) |
+      ((h & 0x0f)<<4)
+    ) ;
+
+  snprintf(greylist_dir,BUFFER_SIZE, "%s/greylist/%02hhx", WORKDIR, h);
+  snprintf(greylist_initial,BUFFER_SIZE, "%s/greylist/%02hhx/%s.initial", WORKDIR, h, ip);
+  snprintf(greylist_allowed,BUFFER_SIZE, "%s/greylist/%02hhx/%s.allowed", WORKDIR, h, ip);
+}
+#endif
+
 /* 
  * From vpopmail source 
  * recursively remove a directory and all it's files
@@ -1377,6 +1481,7 @@
   PerDomainSpam = 0;
   PerDomainTrophie = 0;
   PerDomainSpamPassthru = 0;
+  PerDomainGreylist = 0;
   per_domain_lookup("");
 }
 
@@ -1469,6 +1574,15 @@
       }
       if ( DebugFlag > 1 ) fprintf(stderr, "simscan: spampassthru = %s/%d\n", val,PerDomainSpamPassthru);
 #endif   
+#ifdef ENABLE_GREYLIST
+    } else if ( strcasecmp(parm,"greylist") == 0 ) {
+      if ( DebugFlag > 1 ) fprintf(stderr, "simscan: greylist = %s\n", val);
+      if ( strcasecmp(val, "yes") == 0 ) {
+        PerDomainGreylist = 1; 
+      } else if ( strcasecmp(val, "no") == 0 ) {
+        PerDomainGreylist = 0; 
+      }
+#endif
     } else {
       if ( DebugFlag > 1 ) fprintf(stderr, "simscan: unimplemented flag %s = %s\n", parm, val);  
     }
@@ -1635,6 +1749,61 @@
 
 #endif
 
+#ifdef ENABLE_GREYLIST
+int check_greylist () {
+  struct stat statbuf ;
+  double elapsed ;
+  FILE* fh ;
+  
+  /* Always allow authenticated senders */
+  if (getenv("RELAYCLIENT")) {
+    log_message("RELAYCLIENT", "-", 0);
+    return 0;
+  }
+
+#ifdef ENABLE_PER_DOMAIN
+  if ( PerDomainGreylist == 0 ) return(-2);
+#endif
+
+  /* Is the sender allowed to send? */
+  if (lstat(greylist_allowed, &statbuf) == 0) {
+    utime(greylist_allowed, NULL);
+    return 0;
+  }
+  
+  /* Have we ever seen him? */
+  if (lstat(greylist_initial, &statbuf) != 0) {
+    /* Here for the first time. */
+    if ( (fh = fopen(greylist_initial, "w")) == NULL) {
+      fprintf(stderr, "simscan: could not create: %s\n", greylist_initial);
+      exit_clean(EXIT_400);
+    }
+    fclose(fh);
+    return 1;
+  }
+
+  elapsed = difftime(time(NULL), statbuf.st_mtime) ;
+  if (elapsed < GREYLIST_MIN_DELAY) {
+    /* Sender needs to be patient */
+    return 1;
+  }
+  else if (elapsed > GREYLIST_MAX_DELAY) {
+    /* He's too late. Pretent he's here for the first time. */
+    utime(greylist_initial, NULL);
+    return 1;
+  }
+  
+  /* Sender is at the right place in the right timeframe. */
+  if ( (fh = fopen(greylist_allowed, "w")) == NULL) {
+    fprintf(stderr, "simscan: could not create: %s\n", greylist_allowed);
+    exit_clean(EXIT_400);
+  }
+  fclose(fh);
+  unlink(greylist_initial);
+  return 2;
+}
+#endif
+
 #ifdef ENABLE_REGEX
 /*  check_regex - returns 0 if no match
  *                returns 1 if there was an error matching
@@ -1875,17 +2044,17 @@
  float reqhits;
 
   gettimeofday(&stop,(struct timezone *) 0);
-  utime=SECS(stop)-SECS(start);
+  delta=SECS(stop)-SECS(start);
 
   if ( spam == 1 ) {
     if ( PerDomainHits == 1 ) reqhits = PDHits;
     else reqhits = ReqHits;
     fprintf(stderr, "simscan:[%d]:%s (%.2f/%.2f):%3.4fs:%s:%s:%s:%s",
-      getppid(), state, SpamHits,reqhits, utime, subject,
+      getppid(), state, SpamHits,reqhits, delta, subject,
       getenv("TCPREMOTEIP"), MailFrom, RcptTo[0]);
   } else {
     fprintf(stderr, "simscan:[%d]:%s:%3.4fs:%s:%s:%s:%s",
-      getppid(),state,utime,subject,getenv("TCPREMOTEIP"),MailFrom,RcptTo[0]);
+      getppid(),state,delta,subject,getenv("TCPREMOTEIP"),MailFrom,RcptTo[0]);
   }
 
   for(i=1;i<MaxRcptTo;++i) {


!DSPAM:4558c2c627411592547952!


---------------------------------------------------------------------
     QmailToaster hosted by: VR Hosted <http://www.vr.org>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to