Here is an improved version of a patch that I posted once previously.  I
recently submitted it to Tom and he pointed out that it didn't necessarily
do what it should have since it was based on certain assumptions.  I've
updated it so that it doesn't just ignore IPs that have any rule in the
tcp.smtp file, but only those that are explicitly allowed to relay.

It takes the remote IP and compares it to the rules in tcp.smtp.  It
aborts open_smtp_relay early if there is a rule in tcp.smtp that meets the
following conditions:
  1. It covers the remote IP (obviously)
  2. It specifies "allow" (currently it only recognizes all lower case,
since that's the form I've always seen and is what vpopmail uses.  If it
needs to support upper as well, that's easy).
  3. It specifies 'RELAYCLIENT=""'

Under those conditions, it assumes that the remote client is covered by a
static tcprules mapping and doesn't update tcp.smtp.  Otherwise it will do
the update as normal.

The reason I originally wrote this is that under high-volumes, there is no
good reason to continuously update the tcp.smtp file to allow relaying by
addresses that are already allowed to relay.  This also coveres things
like webmail servers, which are constantly logging into the IMAP server
unless you have an IMAP proxy, and can yield many tcprules updates under
load.

Please take a look and see what you think, as it is something I think
would be a valuable addition to the main vpopmail tree.

Thanks,
Josh
-- 
Joshua Megerman
SJGames MIB #5273 - OGRE AI Testing Division
You can't win; You can't break even; You can't even quit the game.
  - Layman's translation of the Laws of Thermodynamics
[EMAIL PROTECTED]
diff -urN ../clean/vpopmail-5.4.16/vpopmail.c vpopmail-5.4.16/vpopmail.c
--- ../clean/vpopmail-5.4.16/vpopmail.c	2006-01-17 14:30:52.000000000 -0500
+++ vpopmail-5.4.16/vpopmail.c	2006-05-10 15:31:40.000000000 -0400
@@ -2903,6 +2903,9 @@
  */
 int open_smtp_relay()
 {
+  if (check_static_relay()) {
+    return(0);
+  }
 #ifdef USE_SQL
 
 int result;
@@ -3095,6 +3098,83 @@
 
 /************************************************************************/
 
+#ifdef POP_AUTH_OPEN_RELAY 
+/* check_static_relay() looks to see if the remote IP address is in the
+ * TCP_RULES file, and if so returns true.  Used to not update the relay
+ * table with IP addresses that are already covered by another rule.
+ */
+
+int check_static_relay()
+{
+  FILE *fs;
+  char tmpbuf1[MAX_BUFF], tmpbuf2[MAX_BUFF];
+  int found = 0, ipfound = 0, i = 1, x, y, z;
+  char *ipaddr, *p, *q, *r, *ip[4];
+
+  /* get the remote IP address as a string */
+  ipaddr = get_remote_ip();
+  strcpy(tmpbuf2, ipaddr);
+
+  q = strtok(tmpbuf2, ".");
+  ip[0] = q;
+  while ((i < 4) && q) {
+    q = strtok(NULL, ".");
+    ip[i] = q;
+    i++;
+  }
+
+  /* open the tcp.smtp file and read in the static rules - these addresses
+   * are handled by tcprules and not the relay table */
+  fs = fopen(TCP_FILE, "r");
+  if ( fs != NULL ) {
+    /* read each entry and compare it to the remote IP address */
+    while (( fgets(tmpbuf1, sizeof(tmpbuf1), fs ) != NULL ) && (!found)){
+      if ( p = strchr(tmpbuf1, ':') ) {
+        *p = '\0';
+	if ( !(strncmp(ipaddr, tmpbuf1, strlen(tmpbuf1))) ) {
+          ipfound = 1;
+        } else if (q = strchr(tmpbuf1, '-')) {
+          ipfound = 1;
+          q = strtok(tmpbuf1, ".");
+          if ( strcmp(ip[0], q) ) {
+            ipfound = 0;
+          }
+          i = 1;
+          while ((i < 4) && q && ipfound) {
+            q = strtok(NULL, ".");
+            if ( strcmp(ip[i], q) ) {
+              ipfound = 0;
+            } else {
+              i++;
+            }
+          }
+          if (r = strchr(q, '-')) {
+            x = atoi(ip[i]);
+            y = atoi(q);
+            z = atoi(r+1);
+            if ((x >= y) && (x <= z)) {
+              ipfound = 1;
+            }
+          }
+        }
+        if (ipfound) {
+          if (q = strstr(p+1, "allow")) {
+            if (q = strstr(p+1, "RELAYCLIENT=\"\"")) {
+              found = 1;
+            }
+          }
+        }
+      }
+    }
+    fclose(fs);
+  }
+
+  return(found);
+}
+#endif /* POP_AUTH_OPEN_RELAY */
+
+/************************************************************************/
+
 int vfd_copy(int to, int from)
 {
   if (to == from) return 0;

Reply via email to