changeset 44:6b79046b18c2

changes for 3.2
author carl
date Fri, 09 Jul 2004 07:53:02 -0700
parents acbe44bbba22
children 2eef08791e11
files ChangeLog dnsbl.conf dnsbl.rc sendmail.st src/dnsbl.cpp src/scanner.cpp xml/dnsbl.in xml/sample.conf
diffstat 8 files changed, 87 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jul 05 22:24:22 2004 -0700
+++ b/ChangeLog	Fri Jul 09 07:53:02 2004 -0700
@@ -11,7 +11,7 @@
         subsystem that were tripping the html tag detector.
 
         Help with changes required to allow dnsbl to drop root
-        priviledges.
+        priviledges. Move the socket to /var/run/dnsbl/dnsbl.sock
 
     Change parser to handle &#xnnn; obfuscated urls with charaters
     specified in hex.
@@ -20,3 +20,16 @@
     positives in .zip or .tar.gz file attachments.
 
     Add sendmail queueid to the dnsbl syslog messages.
+
+    Fix one place where host names were not forced to lower case.
+    Discovered by Nigel Horne <njh@bandsman.co.uk>
+
+    Remove duplicate dns queries within the same smtp transaction from
+    the body content filtering.  This helps if the mail server does not
+    have a nearby caching dns server.
+
+    Add host_soft_limit config keyword.  Use only one of host_limit or
+    host_soft_limit, since the last one wins.  The host_limit is a hard
+    upper limit on the number of host names in a message.  The
+    host_soft_limit allows unlimited host names, but only checks a
+    random sample of them against the dnsbl.
--- a/dnsbl.conf	Mon Jul 05 22:24:22 2004 -0700
+++ b/dnsbl.conf	Fri Jul 09 07:53:02 2004 -0700
@@ -2,7 +2,8 @@
 # content scanning parameters
 #
 content         sbl-xbl.spamhaus.org        'Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s'
-host_limit      20                          'Mail containing too many host names rejected'
+#host_limit     20                          'Mail containing too many host names rejected'
+host_soft_limit 20
 html_limit      20                          'Mail containing excessive bad html tags rejected'
 include html-tags.conf
 include tld.conf
--- a/dnsbl.rc	Mon Jul 05 22:24:22 2004 -0700
+++ b/dnsbl.rc	Fri Jul 09 07:53:02 2004 -0700
@@ -22,8 +22,7 @@
         echo -n "Starting dnsbl-milter: "
         if [ ! -f /var/lock/subsys/dnsbl ]; then
             cd /etc/dnsbl   # conf file is here
-            #su -l dnsbl -s /bin/sh -c "/usr/sbin/dnsbl -d -p local:/var/run/dnsbl.sock "
-            /usr/sbin/dnsbl -d -p local:/var/run/dnsbl.sock
+            /usr/sbin/dnsbl -d -p local:/var/run/dnsbl/dnsbl.sock
             RETVAL=$?
             pid=`pidof -s /usr/sbin/dnsbl`
             if [ $pid ]
Binary file sendmail.st has changed
--- a/src/dnsbl.cpp	Mon Jul 05 22:24:22 2004 -0700
+++ b/src/dnsbl.cpp	Fri Jul 09 07:53:02 2004 -0700
@@ -116,6 +116,7 @@
 typedef map<char *, DNSBLP, ltstr>        dnsblp_map;
 typedef map<char *, DNSBLLP, ltstr>       dnsbllp_map;
 typedef set<char *, ltstr>                string_set;
+typedef set<int>                          int_set;
 typedef list<char *>                      string_list;
 typedef map<char *, int, ltstr>           ns_map;
 
@@ -135,6 +136,7 @@
     char *      content_message;    // ""
     char *      host_limit_message; // error message for excessive host names
     int         host_limit;         // limit on host names
+    bool        host_random;        // pick a random selection of host names rather than error for excessive hosts
     char *      tag_limit_message;  // error message for excessive bad html tags
     int         tag_limit;          // limit on bad html tags
     string_set  html_tags;          // set of valid html tags
@@ -150,6 +152,7 @@
     content_message    = NULL;
     host_limit_message = NULL;
     host_limit         = 0;
+    host_random        = false;
     tag_limit_message  = NULL;
     tag_limit          = 0;
 }
@@ -586,17 +589,30 @@
     if (!dc.content_suffix) return oksofar;
     int count = 0;
     ns_map nameservers;
-    int lim = priv.pc->host_limit;
+    bool ran = priv.pc->host_random;
+    int  lim = priv.pc->host_limit;         // we should not look at more than this many hosts
+    int  cnt = priv.memory->hosts.size();   // number of hosts we could look at
+    int_set ips;    // remove duplicate ip addresses
     for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) {
+        host = *i;  // a reference into priv.memory->hosts, which will live until this smtp transaction is closed
+        if ((cnt > lim) && (lim > 0) && ran) {
+            // try to only look at lim/cnt fraction of the available cnt host names
+            int r = rand() % cnt;
+            if (r >= lim) {
+                char buf[1000];
+                snprintf(buf, sizeof(buf), "host %s skipped", host);
+                my_syslog(&priv, buf);
+                continue;
+            }
+        }
         count++;
-        if ((count > lim) && (lim > 0)) {
+        if ((count > lim) && (lim > 0) && (!ran)) {
             discard(nameservers);
             return reject_host;
         }
-        host = *i;  // a reference into priv.memory->hosts, which will live until this smtp transaction is closed
         ip   = protected_dns_interface(host, true, &nameservers);
         if (debug_syslog) {
-            char buf[200];
+            char buf[1000];
             if (ip) {
                 char adr[sizeof "255.255.255.255"];
                 adr[0] = '\0';
@@ -609,6 +625,9 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
+            int_set::iterator i = ips.find(ip);
+            if (i == ips.end()) {
+                ips.insert(ip);
             status st = check_single(ip, dc.content_suffix);
             if (st == reject) {
                 discard(nameservers);
@@ -616,10 +635,12 @@
             }
         }
     }
+    }
     lim *= 4;   // allow average of 3 ns per host name
     for (ns_map::iterator i=nameservers.begin(); i!=nameservers.end(); i++) {
         count++;
         if ((count > lim) && (lim > 0)) {
+            if (ran) continue; // don't complain
             discard(nameservers);
             return reject_host;
         }
@@ -640,6 +661,9 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
+            int_set::iterator i = ips.find(ip);
+            if (i == ips.end()) {
+                ips.insert(ip);
             status st = check_single(ip, dc.content_suffix);
             if (st == reject) {
                 host = register_string(priv.memory->hosts, host);   // put a copy into priv.memory->hosts, and return that reference
@@ -648,6 +672,7 @@
             }
         }
     }
+    }
     discard(nameservers);
     host = NULL;
     int bin = priv.memory->binary_tags;
@@ -884,6 +909,9 @@
     if (dc.host_limit) {
         fprintf(stdout, "\ncontent filtering for host names enabled with limit %d %s\n", dc.host_limit, dc.host_limit_message);
     }
+    if (dc.host_random) {
+        fprintf(stdout, "\nrandom selection of host names, host limit message is not used\n");
+    }
     if (dc.tag_limit) {
         fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.tag_limit, dc.tag_limit_message);
     }
@@ -996,10 +1024,11 @@
     }
     dc.config_files.push_back(fn);
     map<char*, int, ltstr> commands;
-    enum {dummy, tld, content, hostlimit, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc};
+    enum {dummy, tld, content, hostlimit, hostrandom, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc};
     commands["tld"        ] = tld;
     commands["content"    ] = content;
     commands["host_limit" ] = hostlimit;
+    commands["host_random"] = hostrandom;
     commands["html_limit" ] = htmllimit;
     commands["html_tag"   ] = htmltag;
     commands["dnsbl"      ] = dnsbl;
@@ -1065,6 +1094,11 @@
                     processed = true;
                     } break;
 
+                case hostrandom: {
+                    dc.host_random = true;
+                    processed = true;
+                    } break;
+
                 case htmllimit: {
                     char *limit = strtok(NULL, delim);
                     if (!limit) break;                          // no integer limit
--- a/src/scanner.cpp	Mon Jul 05 22:24:22 2004 -0700
+++ b/src/scanner.cpp	Fri Jul 09 07:53:02 2004 -0700
@@ -959,7 +959,7 @@
                     char *p2 = strrchr((const char *)pending, '.');
                     if (p1 && (p1 != p2)) {
                         // have two periods, so three components
-                        for (int i=1; i<count; i++) pending[i] = tolower(pending[i]);
+                        for (int i=0; i<count; i++) pending[i] = tolower(pending[i]);
                         // is last component a tld?
                         string_set::iterator i = memory->tlds->find(p2+1);
                         if (i != memory->tlds->end()) memory->new_url((char*)pending);
@@ -1013,7 +1013,11 @@
                     if (p              &&                                       // have a leading /
                         strchr(p, '.') &&                                       // require at least one . in a dns name
                         (strncasecmp((const char *)pending, "http", 4) == 0)) { // must start with protocol
-                        memory->new_url(++p);                           // we seem to have a host name, skip the last /
+                        // we seem to have a host name
+                        p++;                    // skip the last /
+                        int c = strlen(p);
+                        for (int i=0; i<c; i++) p[i] = tolower(p[i]);
+                        memory->new_url(p);     // record it
                     }
                 }
                 st = u_init;
--- a/xml/dnsbl.in	Mon Jul 05 22:24:22 2004 -0700
+++ b/xml/dnsbl.in	Fri Jul 09 07:53:02 2004 -0700
@@ -171,18 +171,18 @@
 line in your sendmail.mc and rebuild the .cf file
 
 <pre>
-INPUT_MAIL_FILTER(`dnsbl', `S=local:/var/run/dnsbl.sock, F=T, T=C:30s;S:2m;R:2m;E:5m')
+INPUT_MAIL_FILTER(`dnsbl', `S=local:/var/run/dnsbl/dnsbl.sock, F=T, T=C:30s;S:2m;R:2m;E:5m')
 </pre>
 
 Read the sample <a
-href="http://www.five-ten-sg.com/dnsbl.conf">var/dnsbl/dnsbl.conf</a>
+href="http://www.five-ten-sg.com/dnsbl.conf">/etc/dnsbl/dnsbl.conf</a>
 file and modify it to fit your configuration.  You can test your
 configuration files, and see a readable internal dump of them on stdout
 with
 
 <pre>
-cd /var/dnsbl
-./dnsbl -c
+cd /etc/dnsbl
+/usr/sbin/dnsbl -c
 </pre>
 
 <pre>
--- a/xml/sample.conf	Mon Jul 05 22:24:22 2004 -0700
+++ b/xml/sample.conf	Fri Jul 09 07:53:02 2004 -0700
@@ -17,11 +17,19 @@
 # host_limit:
 #   second token is the integer count of the number of host names
 #       or urls that are allowed in any one mail body. Zero is
-#       unlimited.
+#       unlimited. If the actual number of host names in the message
+#       is larger than this limit, the message is rejected.
 #   third  token? is a string enclosed in single quotes, so it
 #       is not really a token. This is the error message supplied
 #       to the smtp client.
 #
+# host_soft_limit:
+#   second token is the integer count of the number of host names
+#       or urls that are checked in any one mail body. Zero is
+#       unlimited. If the actual number of host names in the message
+#       is larger than this limit, only a random selection of them
+#       are checked against the dnsbl.
+#
 # html_limit:
 #   second token is the integer count of the number of bad html tags
 #       that are allowed in any one mail body. Zero is unlimited.
@@ -103,6 +111,7 @@
 #
 content         sbl-xbl.spamhaus.org        'Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s'
 host_limit      20                          'Mail containing too many host names rejected'
+host_soft_limit 20
 html_limit      20                          'Mail containing excessive bad html tags rejected'
 include html-tags.conf
 include tld.conf