[Exim] Patch for ORBS-style A RR entry based rejection

Góra strony
Delete this message
Reply to this message
Autor: Chuan-kai Lin
Data:  
Dla: exim-users
Temat: [Exim] Patch for ORBS-style A RR entry based rejection
Greetings,

I am the system administrator at the National Taiwan University,
where we use exim to handle the mail messages for our 10K users.
The system has been running for about a year now, and we are very
satisfied with it. If any developers are reading this (I hope
so, see below), thanks for the great work!

We have been trying to establish a spam filtering capability
lately, and have realized that ORBS could be a valuable resource
because of its less restrictive policies. However, not being
able to tell automated entries, manual entries, and netblock
entries makes it really hard for us to adopt in practice. ORBS
uses returned A RR record to tell one from the other (please
see http://www.orbs.org/usingindex.html for details), and based
on my limited survey, no MTAs to date seem to support this
feature. What a shame! So 6:30 this morning, I downloaded the
source code and started a hacking session...

And attached to this message is what I have came up with. The
rbl_domains syntax has been extended to include the A RR value
to match, but you can also leave it out, and it will do exactly
what it does now (activate if A RR record presents).

Could somebody please take a look at it and provide some opinions?
The patch is against 3.12, but you should not have too much
problems applying it on version 3.13. Also I am not subscribed
to the list, and would greatly appreciate it if you could CC all
messages to me.

Cheers,

-- Chuan-kai Lin
diff -ur exim-3.12/doc/spec.txt exim-3.12-orbs/doc/spec.txt
--- exim-3.12/doc/spec.txt    Wed May 10 17:39:05 2000
+++ exim-3.12-orbs/doc/spec.txt    Wed May 10 17:36:58 2000
@@ -6505,21 +6505,23 @@
     This option is part of the support for Realtime Blocking Lists (RBL). It
     can be set to a colon-separated list of DNS RBL domains in which to look
     up the inverted IP address of a calling host. An RBL domain name may be
-    followed by '/warn' or '/reject' to specify what is to be done if the host
-    is found, for example:
+    followed by @addr, in which case addr will be matched against the IP
+    address obtained from the DNS lookup.  You may also attach '/warn' or
+    '/reject' in the end to specify what is to be done if the host is found,
+    for example:


-      rbl_domains = dul.maps.vix.com/warn : rbl.maps.vix.com/reject
+      rbl_domains = relays.orbs.org@127.0.0.2/warn : rbl.maps.vix.com/reject


-    If neither is present, the action is controlled by the setting of
-    rbl_reject_recipients. When a lookup succeeds, and the action is 'reject',
-    mail from the host is blocked by refusing all recipients, except those
-    listed in recipients_reject_except. When the action is 'warn', the inci-
-    dent is just logged, and a header may be added to the message (see
-    rbl_warn_header). If a lookup times out or otherwise fails to give a
-    decisive answer, the address is not blocked (by that entry in the list).
-    When blocking occurs, an associated TXT record is looked up in the DNS,
-    and if it exists, its contents are returned as part of the 550 rejection
-    message. For further details, see section 43.1.
+    If neither '/warn' or '/reject' is present, the action is controlled by
+    the setting of rbl_reject_recipients. When a lookup succeeds, and the
+    action is 'reject', mail from the host is blocked by refusing all
+    recipients, except those listed in recipients_reject_except. When the
+    action is 'warn', the incident is just logged, and a header may be added
+    to the message (see rbl_warn_header). If a lookup times out or otherwise
+    fails to give a decisive answer, the address is not blocked (by that
+    entry in the list). When blocking occurs, an associated TXT record is
+    looked up in the DNS, and if it exists, its contents are returned as part
+    of the 550 rejection message. For further details, see section 43.1.


rbl_hosts

diff -ur exim-3.12/src/functions.h exim-3.12-orbs/src/functions.h
--- exim-3.12/src/functions.h    Wed Dec  8 17:57:05 1999
+++ exim-3.12-orbs/src/functions.h    Wed May 10 17:25:45 2000
@@ -90,7 +90,7 @@
 extern int   host_aton(char *, int *);
 extern void  host_build_hostlist(host_item **, char *);
 extern void  host_build_sender_fullhost(void);
-extern int   host_check_rbl(char *, char *, char **);
+extern int   host_check_rbl(char *, char *, char *, char **);
 extern BOOL  host_find_byname(host_item *, char **, BOOL);
 extern BOOL  host_find_bydns(host_item *, BOOL, BOOL, BOOL, BOOL, char **,
                BOOL *);
diff -ur exim-3.12/src/host.c exim-3.12-orbs/src/host.c
--- exim-3.12/src/host.c    Wed May 10 17:39:05 2000
+++ exim-3.12-orbs/src/host.c    Wed May 10 17:28:46 2000
@@ -1880,11 +1880,14 @@


/* Anti-spamming "realtime blocking lists" are appearing on the DNS. This
function, given an IP address and the domain of one such list, looks up the
-address in the blocking domain.
+address in the blocking domain. The addition of the rbl_addr argument is
+specifically designed for use with ORBS, in which sites are blacklisted in
+different categories by returning different address on lookup.

 Arguments:
   address      the string version of the address
   domain       the rbl domain to use
+  rbl_addr     the wanted A/AAAA record from the rbl lookup
   buffer       somewhere to point an error message


 Returns:    DNS_SUCCEED   successful lookup (i.e. the address is blocked)
@@ -1894,7 +1897,7 @@
 */


 int
-host_check_rbl(char *address, char *domain, char **bufptr)
+host_check_rbl(char *address, char *domain, char *rbl_addr, char **bufptr)
 {
 int bin[4];
 int rc;
@@ -1958,16 +1961,37 @@
   *bufptr = "";
   if (dns_basic_lookup(name, T_TXT) == DNS_SUCCEED)
     {
-    dns_record *rr;
+    dns_record *rr, *txt_rr, *addr_rr;


+    txt_rr = addr_rr = NULL;
     for (rr = dns_next_rr(RESET_ANSWERS); rr != NULL; rr = dns_next_rr(RESET_NEXT))
-      if (rr->type == T_TXT) break;
+      {
+      if (rr->type == T_TXT) txt_rr = rr;
+      if (rr->type == type) addr_rr = rr;
+      }
+
+    if (rbl_addr != NULL && addr_rr != NULL)
+      {
+      char *lookup_addr;
+      
+      lookup_addr = dns_address_from_rr(addr_rr);
+      if (strcmp(lookup_addr, rbl_addr) != 0)
+        {
+        HDEBUG(8)
+          {
+          debug_printf("RBL lookup for %s resulted in mismatch\n", name);
+          debug_printf("=> that means it is not black listed in the specified category at %s\n", domain);
+          }
+        }
+        /* So now what do we do about the string from store_get? */
+        return DNS_NOMATCH;
+      }


-    if (rr != NULL)
+    if (txt_rr != NULL)
       {
-      int len = (rr->data)[0];
+      int len = (txt_rr->data)[0];
       if (len > 511) len = 127;
-      *bufptr = string_sprintf("%.*s", len, (const char *)(rr->data + 1));
+      *bufptr = string_sprintf("%.*s", len, (const char *)(txt_rr->data + 1));
       }


     HDEBUG(8)
@@ -2141,7 +2165,7 @@
   while (len > 0 && isspace(buffer[len-1])) len--;
   buffer[len] = 0;
   if (strcmp(buffer, "q") == 0) break;
-  (void) host_check_rbl(buffer, "rbl.maps.vix.com", &bufptr);
+  (void) host_check_rbl(buffer, "rbl.maps.vix.com", NULL, &bufptr);
   printf("\n> ");
   }


diff -ur exim-3.12/src/smtp_in.c exim-3.12-orbs/src/smtp_in.c
--- exim-3.12/src/smtp_in.c    Wed Dec  8 17:57:09 1999
+++ exim-3.12-orbs/src/smtp_in.c    Wed May 10 17:22:31 2000
@@ -1272,9 +1272,14 @@
       {
       BOOL reject = rbl_reject_recipients;
       char *s = strrchr(domain, '/');
+      char *a = strchr(domain, '@');


       DEBUG(9) debug_printf("checking RBL domain %s\n", domain);


+      /* Adjust lookup matching address per domain */
+      
+      if (a != NULL) *a++ = 0;
+
       /* Adjust rejection per domain */


       if (s != NULL)
@@ -1291,7 +1296,7 @@
       add the warning header, even if reject is true, because there may be
       recipients that are allowed through by an exception list. */


-      switch(host_check_rbl(sender_host_address, domain, &rbl_msg_buffer))
+      switch(host_check_rbl(sender_host_address, domain, a, &rbl_msg_buffer))
         {
         case DNS_SUCCEED:
         if (rbl_warn_header)