* When rejecting a message due to RBL, give the alleged spammers the
authorArt Cancro <ajc@citadel.org>
Wed, 7 Sep 2005 03:08:07 +0000 (03:08 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 7 Sep 2005 03:08:07 +0000 (03:08 +0000)
  relevant TXT record if there is one.  Hopefully.  This needs testing.

citadel/ChangeLog
citadel/locate_host.c
citadel/locate_host.h

index c66ca2ed268356228e8c5f9aa9b7e03bcb8feb35..5651cb27c1f86ebdd73788f6187f1517f781cdeb 100644 (file)
@@ -1,4 +1,8 @@
 $Log$
+Revision 654.23  2005/09/07 03:08:06  ajc
+* When rejecting a message due to RBL, give the alleged spammers the
+  relevant TXT record if there is one.  Hopefully.  This needs testing.
+
 Revision 654.22  2005/09/02 03:50:42  ajc
 * serv_network.c: fixed a bug in digest generation that was causing the
   tops of some messages to be cut off.
@@ -7079,4 +7083,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
-
index a3ff5c028529102ac7f926f3b9de46fd1193475a..561595453ad1080953efb954ac8d3617d5753168 100644 (file)
 #include "tools.h"
 #include "domain.h"
 
+#ifdef HAVE_RESOLV_H
+#include <arpa/nameser.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
+#include <resolv.h>
+#endif
+
+
 void locate_host(char *tbuf, size_t n,
                char *abuf, size_t na,
                const struct in_addr *addr)
@@ -35,7 +44,6 @@ void locate_host(char *tbuf, size_t n,
        int a1, a2, a3, a4;
        char address_string[SIZ];
 
-       lprintf(CTDL_DEBUG, "locate_host() called\n");
 
 #ifdef HAVE_NONREENTRANT_NETDB
        begin_critical_section(S_NETDB);
@@ -83,7 +91,122 @@ bad_dns:
 #endif
 
        tbuf[63] = 0;
-       lprintf(CTDL_DEBUG, "locate_host() exiting\n");
+}
+
+
+#define RESULT_SIZE 4096 /* What is the longest result text we support? */
+
+int rblcheck_backend(char *domain, char *txtbuf, int txtbufsize) {
+       int a, b, c;
+       char *result = NULL;
+       u_char fixedans[ PACKETSZ ];
+       u_char *answer;
+       int need_to_free_answer = 0;
+       const u_char *cp;
+       u_char *rp;
+       const u_char *cend;
+       const u_char *rend;
+       int len;
+
+       /* Make our DNS query. */
+       //res_init();
+       answer = fixedans;
+       len = res_query( domain, C_IN, T_A, answer, PACKETSZ );
+
+       /* Was there a problem? If so, the domain doesn't exist. */
+       if( len == -1 ) {
+               if (txtbuf != NULL) {
+                       strcpy(txtbuf, "");
+               }
+               return(0);
+       }
+
+       if( len > PACKETSZ )
+       {
+               answer = malloc( len );
+               need_to_free_answer = 1;
+               len = res_query( domain, C_IN, T_A, answer, len );
+               if( len == -1 ) {
+                       if (txtbuf != NULL) {
+                               snprintf(txtbuf, txtbufsize,
+                                       "Message rejected due to known spammer source IP address");
+                       }
+                       if (need_to_free_answer) free(answer);
+                       return(1);
+               }
+       }
+
+       result = ( char * )malloc( RESULT_SIZE );
+       result[ 0 ] = '\0';
+
+
+       /* Make another DNS query for textual data; this shouldn't
+          be a performance hit, since it'll now be cached at the
+          nameserver we're using. */
+       res_init();
+       len = res_query( domain, C_IN, T_TXT, answer, PACKETSZ );
+
+       /* Just in case there's no TXT record... */
+       if( len == -1 )
+       {
+               if (txtbuf != NULL) {
+                       snprintf(txtbuf, txtbufsize,
+                               "Message rejected due to known spammer source IP address");
+               }
+               if (need_to_free_answer) free(answer);
+               free(result);
+               return(1);
+       }
+
+       /* Skip the header and the address we queried. */
+       cp = answer + sizeof( HEADER );
+       while( *cp != '\0' )
+       {
+               a = *cp++;
+               while( a-- )
+                       cp++;
+       }
+
+       /* This seems to be a bit of magic data that we need to
+          skip. I wish there were good online documentation
+          for programming for libresolv, so I'd know what I'm
+          skipping here. Anyone reading this, feel free to
+          enlighten me. */
+       cp += 1 + NS_INT16SZ + NS_INT32SZ;
+
+       /* Skip the type, class and ttl. */
+       cp += ( NS_INT16SZ * 2 ) + NS_INT32SZ;
+
+       /* Get the length and end of the buffer. */
+       NS_GET16( c, cp );
+       cend = cp + c;
+
+       /* Iterate over any multiple answers we might have. In
+          this context, it's unlikely, but anyway. */
+       rp = result;
+       rend = result + RESULT_SIZE - 1;
+       while( cp < cend && rp < rend )
+       {
+               a = *cp++;
+               if( a != 0 )
+                       for( b = a; b > 0 && cp < cend && rp < rend;
+                         b-- )
+                       {
+                               if( *cp == '\n' || *cp == '"' ||
+                                 *cp == '\\' )
+                               {
+                                       *rp++ = '\\';
+                               }
+                               *rp++ = *cp++;
+                       }
+       }
+       *rp = '\0';
+       if (txtbuf != NULL) {
+               snprintf(txtbuf, txtbufsize, "%s", result);
+       }
+       if (need_to_free_answer) free(answer);
+       free(result);
+       return(1);
 }
 
 
@@ -99,6 +222,7 @@ int rbl_check_addr(struct in_addr *addr, char *message_to_spammer)
        int rbl;
        int num_rbl;
        char rbl_domains[SIZ];
+       char txt_answer[1024];
 
        strcpy(message_to_spammer, "ok");
 
@@ -119,10 +243,9 @@ int rbl_check_addr(struct in_addr *addr, char *message_to_spammer)
                        a4, a3, a2, a1);
                 extract_token(&tbuf[strlen(tbuf)], rbl_domains, rbl, '|', (sizeof tbuf - strlen(tbuf)));
 
-               if (gethostbyname(tbuf) != NULL) {
-                       strcpy(message_to_spammer,
-                               "5.7.1 Message rejected due to known spammer source IP address"
-                       );
+               if (rblcheck_backend(tbuf, txt_answer, sizeof txt_answer)) {
+                       sprintf(message_to_spammer, "5.7.1 %s", txt_answer);
+                       lprintf(CTDL_INFO, "RBL: %s\n", txt_answer);
                        return(1);
                }
        }
index e2abe7967a08d56bd610bd5933373d8eacdc1363..b71d389c74d0e6503c4eb50056b95a33b4e3a139 100644 (file)
@@ -4,3 +4,4 @@ void locate_host(char *tbuf, size_t n,
                const struct in_addr *addr);
 int rbl_check(char *message_to_spammer);
 int hostname_to_dotted_quad(char *addr, char *host);
+int rblcheck_backend(char *domain, char *txtbuf, int txtbufsize);