[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

policy-maxsameipsource.diff



Hello, this is a rather big diff that does three things:

1. fixes a bug when type() was used before SS->...buffer's was
initialized.  (Rik proposed a better one for this)

2. introduces "maxsameipsource" policy attribute with numeric value,
which allows to set max connection limit on a per network range basis. 
(Old global parameter is always checked first.)

3. improves policy debugging code to the point where it is acually
useful for non-Boolean attributes.

There is one thing that I did not figure how to do right: I'd like to
drop connection after issueing 4xx code, but I don't.  This leads to
problems when the remote tries to reuse the connection.  Maybe Matti
could into this please?

Index: include/policy.h
===================================================================
RCS file: /cvsroot/zmailer/include/policy.h,v
retrieving revision 1.12
diff -u -r1.12 policy.h
--- include/policy.h	2003/05/02 21:55:00	1.12
+++ include/policy.h	2003/07/11 14:01:07
@@ -89,9 +89,10 @@
 #define P_A_TestRcptDnsRBL	23
 #define P_A_WarnRcptDnsRBL	24
 #define P_A_Filtering           25
+#define P_A_MaxSameIpSource	26
 
 #define P_A_FirstAttr	        2
-#define P_A_LastAttr	        25
+#define P_A_LastAttr	        26
 /* Note: Attribute codes outside range 1..31 cause problems at policystate
          processing!  If you ever need modify these, fix the  policytest.c,
 	 and  policytest.h: struct policystate { char values[]; } array,
@@ -142,7 +143,8 @@
 	"rcpt-dns-rbl",
 	"test-rcpt-dns-rbl",
 	"warn-rcpt-dns-rbl",
-	"filtering"
+	"filtering",
+	"maxsameipsource"
 };
 #define KA(x) ((((x)>0)&&((x)<=P_A_LastAttr))?_KA[(x) & 0xFF]:"??")
 
Index: smtpserver/readpolicy.c
===================================================================
RCS file: /cvsroot/zmailer/smtpserver/readpolicy.c,v
retrieving revision 1.11
diff -u -r1.11 readpolicy.c
--- smtpserver/readpolicy.c	2003/05/02 21:55:00	1.11
+++ smtpserver/readpolicy.c	2003/07/11 14:01:07
@@ -180,6 +180,7 @@
   { "trust-whoson",	P_A_TrustWhosOn		},
 #endif
   { "filtering",	P_A_Filtering		},
+  { "maxsameipsource",	P_A_MaxSameIpSource	},
   { NULL, 0 },
 };
 
Index: smtpserver/policytest.c
===================================================================
RCS file: /cvsroot/zmailer/smtpserver/policytest.c,v
retrieving revision 1.75
diff -u -r1.75 policytest.c
--- smtpserver/policytest.c	2003/06/19 00:01:09	1.75
+++ smtpserver/policytest.c	2003/07/11 14:01:07
@@ -130,17 +130,25 @@
     return (strcmp(value,str) == 0);
 }
 
-static char *showresults __((char *values[]));
-static char *showresults(values)
-char *values[];
+static char *showresults __((struct policystate *state));
+static char *showresults(state)
+struct policystate *state;
 {
     static char buf[2000];
     int i;
+    char **values=state->values;
 
     buf[0] = '\0';
     for (i = P_A_FirstAttr; i <= P_A_LastAttr; ++i) {
 	sprintf(buf+strlen(buf),"%s ",KA(i));
-	sprintf(buf+strlen(buf),"%s ",values[i] ? values[i] : ".");
+	if (i == P_A_InboundSizeLimit )
+	    sprintf(buf+strlen(buf),"%li ",state->maxinsize);
+	else if (i == P_A_OutboundSizeLimit )
+	    sprintf(buf+strlen(buf),"%li ",state->maxoutsize);
+	else if (i == P_A_MaxSameIpSource )
+	    sprintf(buf+strlen(buf),"%li ",state->maxsameiplimit);
+	else
+	    sprintf(buf+strlen(buf),"%s ",values[i] ? values[i] : ".");
     }
     return buf;
 }
@@ -167,6 +175,10 @@
 		 (state->origrequest & (1<<i)) ? "" : "not ",
 		 state->values[i]?state->values[i]:".");
 	}
+
+	type(NULL,0,NULL," maxinsize=%li", state->maxinsize);
+	type(NULL,0,NULL," maxoutsize=%li", state->maxoutsize);
+	type(NULL,0,NULL," maxsameiplimit=%li", state->maxsameiplimit);
 }
 
 static void mask_ip_bits __((unsigned char *, int, int));
@@ -455,6 +467,11 @@
 	  sscanf(str+2,"%li", &state->maxoutsize);
 	  goto nextattr;
 
+	} else if (str[1] == P_A_MaxSameIpSource) {
+
+	  sscanf(str+2,"%li", &state->maxsameiplimit);
+	  goto nextattr;
+
 	} else if ((str[2] != '+' && str[2] != '-') &&
 		   !state->values[str[1] & 0xFF]) {
 
@@ -530,7 +547,7 @@
 	  type(NULL,0,NULL," checkaddr(): domain of '%s'",pbuf+2);
 	result = resolveattributes(rel, maxrecursions, state, pbuf, 1);
 	if (debug) {
-	  type(NULL,0,NULL," Results: %s", showresults(state->values));
+	  type(NULL,0,NULL," Results: %s", showresults(state));
 	}
 	return (result);
     }
@@ -539,7 +556,7 @@
 	  type(NULL,0,NULL," checkaddr(): user of '%s'",pbuf+2);
 	result = resolveattributes(rel, maxrecursions, state, pbuf, 1);
 	if (debug) {
-	  type(NULL,0,NULL," Results: %s", showresults(state->values));
+	  type(NULL,0,NULL," Results: %s", showresults(state));
 	}
 	return (result);
     } else if (pbuf[1] == P_K_IPv4)
@@ -588,7 +605,7 @@
       return -1;
     } else
       if (debug) {
-	type(NULL,0,NULL,"   %s", showresults(state->values));
+	type(NULL,0,NULL," Results:  %s", showresults(state));
       }
     return 0;
 }
@@ -748,6 +765,7 @@
 #ifdef HAVE_WHOSON_H
     state->whoson_result = whosonrc;
 #endif
+    state->maxsameiplimit = -1;
     return 0;
 }
 
@@ -799,7 +817,8 @@
 			 1 << P_A_FullTrustNet      |
 			 1 << P_A_TrustRecipients   |
 			 1 << P_A_TrustWhosOn       |
-			 1 << P_A_Filtering          );
+			 1 << P_A_Filtering         |
+			 1 << P_A_MaxSameIpSource    );
     if (!myaddress)
       state->request |= ( 1 << P_A_TestDnsRBL       |
 			  1 << P_A_RcptDnsRBL        );
@@ -833,7 +852,7 @@
       }
 
       if (debug)
-	type(NULL,0,NULL,"   %s", showresults(state->values));
+	type(NULL,0,NULL," Results:  %s", showresults(state));
 
       return 0;
     }
@@ -1336,7 +1355,7 @@
 		       1 << P_A_FREEZENET    |
 		       1 << P_A_RELAYCUSTNET |
 		       1 << P_A_InboundSizeLimit  |
-		       1 << P_A_OutboundSizeLimit   );
+		       1 << P_A_OutboundSizeLimit  );
     state->request |= ( 1 << P_A_RcptDnsRBL );	/* bag */
 
     check_domain(rel, state, str, len);
@@ -1830,4 +1849,12 @@
 struct policystate *state;
 {
     return state->maxinsize;
+}
+
+long
+policysameiplimit(rel, state)
+struct policytest *rel;
+struct policystate *state;
+{
+    return state->maxsameiplimit;
 }
Index: smtpserver/policytest.h
===================================================================
RCS file: /cvsroot/zmailer/smtpserver/policytest.h,v
retrieving revision 1.20
diff -u -r1.20 policytest.h
--- smtpserver/policytest.h	2003/05/05 09:29:38	1.20
+++ smtpserver/policytest.h	2003/07/11 14:01:07
@@ -44,6 +44,7 @@
     char *rblmsg;
     long maxinsize;
     long maxoutsize;
+    long maxsameiplimit;
     int  islocaldomain;
 #ifdef HAVE_WHOSON_H
     int whoson_result;
@@ -118,6 +119,7 @@
 extern int policytestaddr __((struct policytest * rel, struct policystate * ps, PolicyTest how, Usockaddr * raddr));
 extern char *policymsg __((struct policytest *rel, struct policystate *ps));
 extern long  policyinsizelimit __((struct policytest *rel, struct policystate *ps));
+extern long  policysameiplimit __((struct policytest *rel, struct policystate *ps));
 
 extern struct policytest *policydb;
 
Index: smtpserver/smtpserver.c
===================================================================
RCS file: /cvsroot/zmailer/smtpserver/smtpserver.c,v
retrieving revision 1.147
diff -u -r1.147 smtpserver.c
--- smtpserver/smtpserver.c	2003/06/09 13:18:22	1.147
+++ smtpserver/smtpserver.c	2003/07/11 14:01:07
@@ -1225,6 +1225,7 @@
 
 
 	  sameipcount = childsameip(&SS.raddr, &childcnt);
+	  SS.sameipcount = sameipcount;
 	  /* We query, and warn the remote when
 	     the count exceeds the limit, and we
 	     simply -- and FAST -- reject the
@@ -1357,6 +1358,13 @@
 	    pid = getpid();
 
 	    openlogfp(&SS, daemon_flg);
+
+	/* Actually all modes use this write-out buffer */
+	/* needs to go before any type()'s = [crosser] */
+	SS.sslwrbuf = emalloc(8192);
+	SS.sslwrspace = 8192;
+	SS.sslwrin = SS.sslwrout = 0;
+
 #ifdef HAVE_WHOSON_H
 	    type(NULL,0,NULL,
 		 "connection from %s ipcnt %d childs %d ident: %s whoson: %s",
@@ -1387,7 +1395,7 @@
 	      exit(0);	/* Now exit.. */
 	    }
 	    if (sameipcount > MaxSameIpSource && sameipcount > 1) {
-	      type(&SS, -450, NULL, "Too many simultaneous connections from same IP address (%d max %d)\r\n", sameipcount, MaxSameIpSource);
+	      type(&SS, -450, NULL, "Too many simultaneous connections from same IP address (%d max %d)", sameipcount, MaxSameIpSource);
 	      type(&SS,  450, NULL, "Come again later");
 	      typeflush(&SS);
 	      MIBMtaEntry->ss.MaxSameIpSourceCloses ++;
@@ -1948,12 +1956,14 @@
     int policystatus;
     struct hostent *hostent;
     int localport;
+    long maxsameip;
 
 #ifdef USE_TRANSLATION
     char lang[4];
 
     lang[0] = '\0';
 #endif
+
     SS->VerboseCommand = 0;
 
     SS->tarpit = tarpit_initial;
@@ -2082,11 +2092,6 @@
       }
     }
 
-    /* Actually all modes use this write-out buffer */
-    SS->sslwrbuf = emalloc(8192);
-    SS->sslwrspace = 8192;
-    SS->sslwrin = SS->sslwrout = 0;
-
 #ifdef HAVE_OPENSSL
     if (ssmtp_connected) {
       if (tls_start_servertls(SS)) {
@@ -2112,6 +2117,8 @@
 				      POLICY_SOURCEADDR,
 				      (void *) &SS->raddr);
     SS->reject_net = (SS->policyresult < 0);
+    maxsameip = policysameiplimit(policydb, &SS->policystate);
+    if (maxsameip == 0) SS->reject_net = 1; /* count=0 equivalent to reject */
     if (debug) typeflush(SS);
     if (SS->policyresult == 0) /* Alternates to this condition are:
 				  Always reject, or Always freeze.. */
@@ -2149,6 +2156,12 @@
 	}
 	type(SS, -550, NULL, "If you feel we mistreat you, do contact us.");
 	type(SS, 550, NULL, "Ask HELP for our contact information.");
+    } else if ((maxsameip >= 0) && (SS->sameipcount > maxsameip)) {
+	smtp_tarpit(SS);
+	type(SS, -450, NULL, "%s - Too many simultaneous connections from this IP address (%li of %li)",
+	       SS->myhostname, SS->sameipcount, maxsameip);
+	type(SS,  450, NULL, "Come again later");
+	MIBMtaEntry->ss.MaxSameIpSourceCloses ++;
     } else
 #ifdef USE_TRANSLATION
 	if (hdr220lines[0] == NULL) {
Index: smtpserver/smtpserver.h
===================================================================
RCS file: /cvsroot/zmailer/smtpserver/smtpserver.h,v
retrieving revision 1.81
diff -u -r1.81 smtpserver.h
--- smtpserver/smtpserver.h	2003/06/09 14:08:46	1.81
+++ smtpserver/smtpserver.h	2003/07/11 14:01:07
@@ -326,6 +326,7 @@
 #endif
 
     int unknown_cmd_count;
+    long sameipcount;
 
 #ifdef HAVE_SASL2
     char  *volatile auth_type;


-
To unsubscribe from this list: send the line "unsubscribe zmailer" in
the body of a message to majordomo@nic.funet.fi