diff src/dnsbl.cpp @ 382:c378e9d03f37

start parsing spf txt records
author Carl Byington <carl@five-ten-sg.com>
date Mon, 06 Mar 2017 12:21:05 -0800
parents 879a470c6ac3
children 7b7066a51c33
line wrap: on
line diff
--- a/src/dnsbl.cpp	Tue Feb 28 17:02:07 2017 -0800
+++ b/src/dnsbl.cpp	Mon Mar 06 12:21:05 2017 -0800
@@ -123,14 +123,6 @@
 auth_addresses auth_daily_addresses;        // protected with rate_mutex
 
 
-struct ns_map {
-    // all the strings are owned by the keys/values in the ns_host string map
-    string_map  ns_host;    // nameserver name -> host name that uses this name server
-    ns_mapper   ns_ip;      // nameserver name -> ipv4 address of the name server
-    ~ns_map();
-    void add(const char *name, const char *refer);
-};
-
 
 ns_map::~ns_map() {
     for (string_map::iterator i=ns_host.begin(); i!=ns_host.end(); i++) {
@@ -195,18 +187,18 @@
 }
 
 
-void add_auth_address(const char *user, int &hourly, int &daily, int32_t ip);
-void add_auth_address(const char *user, int &hourly, int &daily, int32_t ip) {
+void add_auth_address(const char *user, int &hourly, int &daily, uint32_t ip);
+void add_auth_address(const char *user, int &hourly, int &daily, uint32_t ip) {
     pthread_mutex_lock(&rate_mutex);
         auth_addresses::iterator i = auth_hourly_addresses.find(user);
         if (i == auth_hourly_addresses.end()) {
             user = strdup(user);
-            auth_hourly_addresses[user] = new int32_t_set;
+            auth_hourly_addresses[user] = new uint32_t_set;
             auth_hourly_addresses[user]->insert(ip);
             hourly = 1;
         }
         else {
-            int32_t_set::iterator k = ((*i).second)->find(ip);
+            uint32_t_set::iterator k = ((*i).second)->find(ip);
             if (k == ((*i).second)->end()) ((*i).second)->insert(ip);
             hourly = ((*i).second)->size();
         }
@@ -214,12 +206,12 @@
         auth_addresses::iterator j = auth_daily_addresses.find(user);
         if (j == auth_daily_addresses.end()) {
             user = strdup(user);
-            auth_daily_addresses[user] = new int32_t_set;
+            auth_daily_addresses[user] = new uint32_t_set;
             auth_daily_addresses[user]->insert(ip);
             daily = 1;
         }
         else {
-            int32_t_set::iterator k = ((*j).second)->find(ip);
+            uint32_t_set::iterator k = ((*j).second)->find(ip);
             if (k == ((*j).second)->end()) ((*j).second)->insert(ip);
             daily = ((*j).second)->size();
         }
@@ -307,10 +299,13 @@
 //  If we cannot get an answer, we just accept the mail.
 //  If the qtype is ns_t_txt, the answer is placed in txt_answer which
 //  must be non-null, and the return value can be ignored.
+//  A null string is returned in txt_answer in the case of errors.
 //  If the qtype is ns_t_a, the ip address is returned in network byte order.
+//  IP address 0 is returned in case of errors.
 //
-uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip = false, ns_map *nameservers = NULL, char *txt_answer = NULL, size_t txt_size = 0);
 uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *txt_answer, size_t txt_size) {
+    if (txt_answer) txt_answer[0] = '\0';   // return null string if there are no txt answers
+
     // tell sendmail we are still working
     #if _FFR_SMFI_PROGRESS
         if (priv.eom) smfi_progress(priv.ctx);
@@ -419,9 +414,9 @@
                     }
                 }
             }
-            if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 5)) {
+            if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 7)) {
+                txt_answer[0] = '\0';  // return null string if there are no txt answers
                 txt_size--; // allow room for terminating null;
-                txt_answer[0] = '\0';   // return null string if there are no answers
                 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) {
                     size_t offset = 0;
                     if (ns_rr_type(rr) == qtype) {
@@ -439,7 +434,10 @@
                         }
                     }
                     txt_answer[offset] = '\0';  // trailing null
-                    if (strcasecmp(txt_answer, "v=spf1 ") == 0) break;
+                    if (strncasecmp(txt_answer, "v=spf1 ", 7) == 0) break;
+                }
+                if (strncasecmp(txt_answer, "v=spf1 ", 7) != 0) {
+                    txt_answer[0] = '\0';  // return null string if there are no spf1 txt answers
                 }
             }
         }
@@ -891,10 +889,16 @@
 #else
         glom.length = sizeof(glom.answer);
         glom.answer = 0;
+        int t = int8_t(question[0]);
+        if (t != ns_t_a) {
+            glom.length = 0;
+        }
+        else {
         struct hostent *host = gethostbyname(question+1);
         if (host && (host->h_addrtype == AF_INET)) {
             memcpy(&glom.answer, host->h_addr, sizeof(glom.answer));
         }
+        }
 #endif
 
         // write the answer
@@ -927,8 +931,8 @@
 ////////////////////////////////////////////////
 //  check a single dns list, return ip address in network byte order
 //
-uint32_t check_single(mlfiPriv &priv, int32_t ip, const char *suffix);
-uint32_t check_single(mlfiPriv &priv, int32_t ip, const char *suffix) {
+uint32_t check_single(mlfiPriv &priv, uint32_t ip, const char *suffix);
+uint32_t check_single(mlfiPriv &priv, uint32_t ip, const char *suffix) {
     // make a dns question
     const u_char *src = (const u_char *)&ip;
     if (src[0] == 127) return 0;    // don't do dns lookups on localhost
@@ -949,8 +953,8 @@
 ////////////////////////////////////////////////
 //  check a single dnsbl
 //
-bool check_single(mlfiPriv &priv, int32_t ip, DNSBL &bl);
-bool check_single(mlfiPriv &priv, int32_t ip, DNSBL &bl) {
+bool check_single(mlfiPriv &priv, uint32_t ip, DNSBL &bl);
+bool check_single(mlfiPriv &priv, uint32_t ip, DNSBL &bl) {
     return check_single(priv, ip, bl.suffix);
 }
 
@@ -958,8 +962,8 @@
 ////////////////////////////////////////////////
 //  check a single dnswl
 //
-bool check_single(mlfiPriv &priv, int32_t ip, DNSWL &wl);
-bool check_single(mlfiPriv &priv, int32_t ip, DNSWL &wl) {
+bool check_single(mlfiPriv &priv, uint32_t ip, DNSWL &wl);
+bool check_single(mlfiPriv &priv, uint32_t ip, DNSWL &wl) {
     uint32_t r = ntohl(check_single(priv, ip, wl.suffix));
     uint32_t v = (uint32_t)0x7f000000;
     uint32_t m = (uint32_t)0xffff0000;
@@ -1026,8 +1030,8 @@
 //  check the hosts from the body against the content filter and uribl dnsbls
 //
 //
-bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int32_t &ip, const char *&found);
-bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int32_t &ip, const char *&found) {
+bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, uint32_t &ip, const char *&found);
+bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, uint32_t &ip, const char *&found) {
     found = NULL;   // normally ip address style
     if (!priv.content_suffix && !priv.uribl_suffix) return false;   // nothing to check
     string_set &hosts  = priv.memory->get_hosts();
@@ -1035,7 +1039,7 @@
 
     int count = 0;
     int   cnt = hosts.size();   // number of hosts we could look at
-    int32_t_set ips;
+    uint32_t_set ips;
     ns_map  nameservers;
     for (string_set::iterator i=hosts.begin(); i!=hosts.end(); i++) {
         host = *i;  // a reference into hosts, which will live until this smtp transaction is closed
@@ -1072,7 +1076,7 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
-            int32_t_set::iterator i = ips.find(ip);
+            uint32_t_set::iterator i = ips.find(ip);
             if (i == ips.end()) {
                 // we haven't looked this up yet
                 ips.insert(ip);
@@ -1110,7 +1114,7 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
-            int32_t_set::iterator i = ips.find(ip);
+            uint32_t_set::iterator i = ips.find(ip);
             if (i == ips.end()) {
                 ips.insert(ip);
                 if (check_single(priv, ip, priv.content_suffix)) {
@@ -1649,7 +1653,7 @@
     sfsistat  rc;
     mlfiPriv   &priv = *MLFIPRIV;
     const char *host = NULL;
-    int32_t     ip;
+    uint32_t    ip;
     // process end of message
     priv.eom = true;
     if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE;
@@ -1847,7 +1851,7 @@
                 }
                 for (auth_addresses::iterator j=auth_hourly_addresses.begin(); j!=auth_hourly_addresses.end(); j++) {
                     delete (*j).second;
-                    (*j).second = new int32_t_set;
+                    (*j).second = new uint32_t_set;
                 }
             pthread_mutex_unlock(&rate_mutex);
             loop1 = 0;
@@ -1861,7 +1865,7 @@
                 }
                 for (auth_addresses::iterator j=auth_daily_addresses.begin(); j!=auth_daily_addresses.end(); j++) {
                     delete (*j).second;
-                    (*j).second = new int32_t_set;
+                    (*j).second = new uint32_t_set;
                 }
             pthread_mutex_unlock(&rate_mutex);
             loop2 = 0;