comparison 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
comparison
equal deleted inserted replaced
381:879a470c6ac3 382:c378e9d03f37
121 rates rcpt_daily_counts; // protected with rate_mutex 121 rates rcpt_daily_counts; // protected with rate_mutex
122 auth_addresses auth_hourly_addresses; // protected with rate_mutex 122 auth_addresses auth_hourly_addresses; // protected with rate_mutex
123 auth_addresses auth_daily_addresses; // protected with rate_mutex 123 auth_addresses auth_daily_addresses; // protected with rate_mutex
124 124
125 125
126 struct ns_map {
127 // all the strings are owned by the keys/values in the ns_host string map
128 string_map ns_host; // nameserver name -> host name that uses this name server
129 ns_mapper ns_ip; // nameserver name -> ipv4 address of the name server
130 ~ns_map();
131 void add(const char *name, const char *refer);
132 };
133
134 126
135 ns_map::~ns_map() { 127 ns_map::~ns_map() {
136 for (string_map::iterator i=ns_host.begin(); i!=ns_host.end(); i++) { 128 for (string_map::iterator i=ns_host.begin(); i!=ns_host.end(); i++) {
137 const char *x = (*i).first; 129 const char *x = (*i).first;
138 const char *y = (*i).second; 130 const char *y = (*i).second;
193 } 185 }
194 pthread_mutex_unlock(&rate_mutex); 186 pthread_mutex_unlock(&rate_mutex);
195 } 187 }
196 188
197 189
198 void add_auth_address(const char *user, int &hourly, int &daily, int32_t ip); 190 void add_auth_address(const char *user, int &hourly, int &daily, uint32_t ip);
199 void add_auth_address(const char *user, int &hourly, int &daily, int32_t ip) { 191 void add_auth_address(const char *user, int &hourly, int &daily, uint32_t ip) {
200 pthread_mutex_lock(&rate_mutex); 192 pthread_mutex_lock(&rate_mutex);
201 auth_addresses::iterator i = auth_hourly_addresses.find(user); 193 auth_addresses::iterator i = auth_hourly_addresses.find(user);
202 if (i == auth_hourly_addresses.end()) { 194 if (i == auth_hourly_addresses.end()) {
203 user = strdup(user); 195 user = strdup(user);
204 auth_hourly_addresses[user] = new int32_t_set; 196 auth_hourly_addresses[user] = new uint32_t_set;
205 auth_hourly_addresses[user]->insert(ip); 197 auth_hourly_addresses[user]->insert(ip);
206 hourly = 1; 198 hourly = 1;
207 } 199 }
208 else { 200 else {
209 int32_t_set::iterator k = ((*i).second)->find(ip); 201 uint32_t_set::iterator k = ((*i).second)->find(ip);
210 if (k == ((*i).second)->end()) ((*i).second)->insert(ip); 202 if (k == ((*i).second)->end()) ((*i).second)->insert(ip);
211 hourly = ((*i).second)->size(); 203 hourly = ((*i).second)->size();
212 } 204 }
213 205
214 auth_addresses::iterator j = auth_daily_addresses.find(user); 206 auth_addresses::iterator j = auth_daily_addresses.find(user);
215 if (j == auth_daily_addresses.end()) { 207 if (j == auth_daily_addresses.end()) {
216 user = strdup(user); 208 user = strdup(user);
217 auth_daily_addresses[user] = new int32_t_set; 209 auth_daily_addresses[user] = new uint32_t_set;
218 auth_daily_addresses[user]->insert(ip); 210 auth_daily_addresses[user]->insert(ip);
219 daily = 1; 211 daily = 1;
220 } 212 }
221 else { 213 else {
222 int32_t_set::iterator k = ((*j).second)->find(ip); 214 uint32_t_set::iterator k = ((*j).second)->find(ip);
223 if (k == ((*j).second)->end()) ((*j).second)->insert(ip); 215 if (k == ((*j).second)->end()) ((*j).second)->insert(ip);
224 daily = ((*j).second)->size(); 216 daily = ((*j).second)->size();
225 } 217 }
226 pthread_mutex_unlock(&rate_mutex); 218 pthread_mutex_unlock(&rate_mutex);
227 } 219 }
305 // Ask a dns question and get an A record answer in network byte order. 297 // Ask a dns question and get an A record answer in network byte order.
306 // We don't try very hard, just using the default resolver retry settings. 298 // We don't try very hard, just using the default resolver retry settings.
307 // If we cannot get an answer, we just accept the mail. 299 // If we cannot get an answer, we just accept the mail.
308 // If the qtype is ns_t_txt, the answer is placed in txt_answer which 300 // If the qtype is ns_t_txt, the answer is placed in txt_answer which
309 // must be non-null, and the return value can be ignored. 301 // must be non-null, and the return value can be ignored.
302 // A null string is returned in txt_answer in the case of errors.
310 // If the qtype is ns_t_a, the ip address is returned in network byte order. 303 // If the qtype is ns_t_a, the ip address is returned in network byte order.
304 // IP address 0 is returned in case of errors.
311 // 305 //
312 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);
313 uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *txt_answer, size_t txt_size) { 306 uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *txt_answer, size_t txt_size) {
307 if (txt_answer) txt_answer[0] = '\0'; // return null string if there are no txt answers
308
314 // tell sendmail we are still working 309 // tell sendmail we are still working
315 #if _FFR_SMFI_PROGRESS 310 #if _FFR_SMFI_PROGRESS
316 if (priv.eom) smfi_progress(priv.ctx); 311 if (priv.eom) smfi_progress(priv.ctx);
317 #endif 312 #endif
318 313
417 memcpy(&address, ns_rr_rdata(rr), sizeof(address)); 412 memcpy(&address, ns_rr_rdata(rr), sizeof(address));
418 ret_address = address; 413 ret_address = address;
419 } 414 }
420 } 415 }
421 } 416 }
422 if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 5)) { 417 if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 7)) {
418 txt_answer[0] = '\0'; // return null string if there are no txt answers
423 txt_size--; // allow room for terminating null; 419 txt_size--; // allow room for terminating null;
424 txt_answer[0] = '\0'; // return null string if there are no answers
425 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { 420 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) {
426 size_t offset = 0; 421 size_t offset = 0;
427 if (ns_rr_type(rr) == qtype) { 422 if (ns_rr_type(rr) == qtype) {
428 size_t rdlen = ns_rr_rdlen(rr); 423 size_t rdlen = ns_rr_rdlen(rr);
429 const unsigned char *rdata = ns_rr_rdata(rr); 424 const unsigned char *rdata = ns_rr_rdata(rr);
437 rdata += m; 432 rdata += m;
438 rdlen -= m; 433 rdlen -= m;
439 } 434 }
440 } 435 }
441 txt_answer[offset] = '\0'; // trailing null 436 txt_answer[offset] = '\0'; // trailing null
442 if (strcasecmp(txt_answer, "v=spf1 ") == 0) break; 437 if (strncasecmp(txt_answer, "v=spf1 ", 7) == 0) break;
438 }
439 if (strncasecmp(txt_answer, "v=spf1 ", 7) != 0) {
440 txt_answer[0] = '\0'; // return null string if there are no spf1 txt answers
443 } 441 }
444 } 442 }
445 } 443 }
446 pthread_mutex_unlock(&resolve_mutex); 444 pthread_mutex_unlock(&resolve_mutex);
447 #ifdef RESOLVER_DEBUG 445 #ifdef RESOLVER_DEBUG
889 if (res_result < 0) glom.length = 0; // represent all errors as zero length answers 887 if (res_result < 0) glom.length = 0; // represent all errors as zero length answers
890 else glom.length = (size_t)res_result; 888 else glom.length = (size_t)res_result;
891 #else 889 #else
892 glom.length = sizeof(glom.answer); 890 glom.length = sizeof(glom.answer);
893 glom.answer = 0; 891 glom.answer = 0;
894 struct hostent *host = gethostbyname(question+1); 892 int t = int8_t(question[0]);
895 if (host && (host->h_addrtype == AF_INET)) { 893 if (t != ns_t_a) {
896 memcpy(&glom.answer, host->h_addr, sizeof(glom.answer)); 894 glom.length = 0;
895 }
896 else {
897 struct hostent *host = gethostbyname(question+1);
898 if (host && (host->h_addrtype == AF_INET)) {
899 memcpy(&glom.answer, host->h_addr, sizeof(glom.answer));
900 }
897 } 901 }
898 #endif 902 #endif
899 903
900 // write the answer 904 // write the answer
901 char *buf = (char *)&glom; 905 char *buf = (char *)&glom;
925 929
926 930
927 //////////////////////////////////////////////// 931 ////////////////////////////////////////////////
928 // check a single dns list, return ip address in network byte order 932 // check a single dns list, return ip address in network byte order
929 // 933 //
930 uint32_t check_single(mlfiPriv &priv, int32_t ip, const char *suffix); 934 uint32_t check_single(mlfiPriv &priv, uint32_t ip, const char *suffix);
931 uint32_t check_single(mlfiPriv &priv, int32_t ip, const char *suffix) { 935 uint32_t check_single(mlfiPriv &priv, uint32_t ip, const char *suffix) {
932 // make a dns question 936 // make a dns question
933 const u_char *src = (const u_char *)&ip; 937 const u_char *src = (const u_char *)&ip;
934 if (src[0] == 127) return 0; // don't do dns lookups on localhost 938 if (src[0] == 127) return 0; // don't do dns lookups on localhost
935 if (src[0] == 10) return 0; // don't do dns lookups on rfc1918 space 939 if (src[0] == 10) return 0; // don't do dns lookups on rfc1918 space
936 if ((src[0] == 192) && (src[1] == 168)) return 0; 940 if ((src[0] == 192) && (src[1] == 168)) return 0;
947 951
948 952
949 //////////////////////////////////////////////// 953 ////////////////////////////////////////////////
950 // check a single dnsbl 954 // check a single dnsbl
951 // 955 //
952 bool check_single(mlfiPriv &priv, int32_t ip, DNSBL &bl); 956 bool check_single(mlfiPriv &priv, uint32_t ip, DNSBL &bl);
953 bool check_single(mlfiPriv &priv, int32_t ip, DNSBL &bl) { 957 bool check_single(mlfiPriv &priv, uint32_t ip, DNSBL &bl) {
954 return check_single(priv, ip, bl.suffix); 958 return check_single(priv, ip, bl.suffix);
955 } 959 }
956 960
957 961
958 //////////////////////////////////////////////// 962 ////////////////////////////////////////////////
959 // check a single dnswl 963 // check a single dnswl
960 // 964 //
961 bool check_single(mlfiPriv &priv, int32_t ip, DNSWL &wl); 965 bool check_single(mlfiPriv &priv, uint32_t ip, DNSWL &wl);
962 bool check_single(mlfiPriv &priv, int32_t ip, DNSWL &wl) { 966 bool check_single(mlfiPriv &priv, uint32_t ip, DNSWL &wl) {
963 uint32_t r = ntohl(check_single(priv, ip, wl.suffix)); 967 uint32_t r = ntohl(check_single(priv, ip, wl.suffix));
964 uint32_t v = (uint32_t)0x7f000000; 968 uint32_t v = (uint32_t)0x7f000000;
965 uint32_t m = (uint32_t)0xffff0000; 969 uint32_t m = (uint32_t)0xffff0000;
966 uint32_t m2 = (uint32_t)0x000000ff; 970 uint32_t m2 = (uint32_t)0x000000ff;
967 if ((r & m) == v) { 971 if ((r & m) == v) {
1024 1028
1025 //////////////////////////////////////////////// 1029 ////////////////////////////////////////////////
1026 // check the hosts from the body against the content filter and uribl dnsbls 1030 // check the hosts from the body against the content filter and uribl dnsbls
1027 // 1031 //
1028 // 1032 //
1029 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int32_t &ip, const char *&found); 1033 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, uint32_t &ip, const char *&found);
1030 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int32_t &ip, const char *&found) { 1034 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, uint32_t &ip, const char *&found) {
1031 found = NULL; // normally ip address style 1035 found = NULL; // normally ip address style
1032 if (!priv.content_suffix && !priv.uribl_suffix) return false; // nothing to check 1036 if (!priv.content_suffix && !priv.uribl_suffix) return false; // nothing to check
1033 string_set &hosts = priv.memory->get_hosts(); 1037 string_set &hosts = priv.memory->get_hosts();
1034 string_set &ignore = *priv.content_host_ignore; 1038 string_set &ignore = *priv.content_host_ignore;
1035 1039
1036 int count = 0; 1040 int count = 0;
1037 int cnt = hosts.size(); // number of hosts we could look at 1041 int cnt = hosts.size(); // number of hosts we could look at
1038 int32_t_set ips; 1042 uint32_t_set ips;
1039 ns_map nameservers; 1043 ns_map nameservers;
1040 for (string_set::iterator i=hosts.begin(); i!=hosts.end(); i++) { 1044 for (string_set::iterator i=hosts.begin(); i!=hosts.end(); i++) {
1041 host = *i; // a reference into hosts, which will live until this smtp transaction is closed 1045 host = *i; // a reference into hosts, which will live until this smtp transaction is closed
1042 1046
1043 // don't bother looking up hosts on the ignore list 1047 // don't bother looking up hosts on the ignore list
1070 snprintf(buf, sizeof(buf), "host %s not found", host); 1074 snprintf(buf, sizeof(buf), "host %s not found", host);
1071 } 1075 }
1072 my_syslog(&priv, buf); 1076 my_syslog(&priv, buf);
1073 } 1077 }
1074 if (ip) { 1078 if (ip) {
1075 int32_t_set::iterator i = ips.find(ip); 1079 uint32_t_set::iterator i = ips.find(ip);
1076 if (i == ips.end()) { 1080 if (i == ips.end()) {
1077 // we haven't looked this up yet 1081 // we haven't looked this up yet
1078 ips.insert(ip); 1082 ips.insert(ip);
1079 // check dnsbl style list 1083 // check dnsbl style list
1080 if (priv.content_suffix && check_single(priv, ip, priv.content_suffix)) { 1084 if (priv.content_suffix && check_single(priv, ip, priv.content_suffix)) {
1108 snprintf(buf, sizeof(buf), "ns %s not found", host); 1112 snprintf(buf, sizeof(buf), "ns %s not found", host);
1109 } 1113 }
1110 my_syslog(&priv, buf); 1114 my_syslog(&priv, buf);
1111 } 1115 }
1112 if (ip) { 1116 if (ip) {
1113 int32_t_set::iterator i = ips.find(ip); 1117 uint32_t_set::iterator i = ips.find(ip);
1114 if (i == ips.end()) { 1118 if (i == ips.end()) {
1115 ips.insert(ip); 1119 ips.insert(ip);
1116 if (check_single(priv, ip, priv.content_suffix)) { 1120 if (check_single(priv, ip, priv.content_suffix)) {
1117 msg = priv.content_message; 1121 msg = priv.content_message;
1118 string_map::iterator j = nameservers.ns_host.find(host); 1122 string_map::iterator j = nameservers.ns_host.find(host);
1647 sfsistat mlfi_eom(SMFICTX *ctx) 1651 sfsistat mlfi_eom(SMFICTX *ctx)
1648 { 1652 {
1649 sfsistat rc; 1653 sfsistat rc;
1650 mlfiPriv &priv = *MLFIPRIV; 1654 mlfiPriv &priv = *MLFIPRIV;
1651 const char *host = NULL; 1655 const char *host = NULL;
1652 int32_t ip; 1656 uint32_t ip;
1653 // process end of message 1657 // process end of message
1654 priv.eom = true; 1658 priv.eom = true;
1655 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; 1659 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE;
1656 else { 1660 else {
1657 // assert env_to not empty, it contains the 1661 // assert env_to not empty, it contains the
1845 for (rates::iterator i=rcpt_hourly_counts.begin(); i!=rcpt_hourly_counts.end(); i++) { 1849 for (rates::iterator i=rcpt_hourly_counts.begin(); i!=rcpt_hourly_counts.end(); i++) {
1846 (*i).second = 0; 1850 (*i).second = 0;
1847 } 1851 }
1848 for (auth_addresses::iterator j=auth_hourly_addresses.begin(); j!=auth_hourly_addresses.end(); j++) { 1852 for (auth_addresses::iterator j=auth_hourly_addresses.begin(); j!=auth_hourly_addresses.end(); j++) {
1849 delete (*j).second; 1853 delete (*j).second;
1850 (*j).second = new int32_t_set; 1854 (*j).second = new uint32_t_set;
1851 } 1855 }
1852 pthread_mutex_unlock(&rate_mutex); 1856 pthread_mutex_unlock(&rate_mutex);
1853 loop1 = 0; 1857 loop1 = 0;
1854 } 1858 }
1855 if (loop2 == 480) { 1859 if (loop2 == 480) {
1859 for (rates::iterator i=rcpt_daily_counts.begin(); i!=rcpt_daily_counts.end(); i++) { 1863 for (rates::iterator i=rcpt_daily_counts.begin(); i!=rcpt_daily_counts.end(); i++) {
1860 (*i).second = 0; 1864 (*i).second = 0;
1861 } 1865 }
1862 for (auth_addresses::iterator j=auth_daily_addresses.begin(); j!=auth_daily_addresses.end(); j++) { 1866 for (auth_addresses::iterator j=auth_daily_addresses.begin(); j!=auth_daily_addresses.end(); j++) {
1863 delete (*j).second; 1867 delete (*j).second;
1864 (*j).second = new int32_t_set; 1868 (*j).second = new uint32_t_set;
1865 } 1869 }
1866 pthread_mutex_unlock(&rate_mutex); 1870 pthread_mutex_unlock(&rate_mutex);
1867 loop2 = 0; 1871 loop2 = 0;
1868 } 1872 }
1869 CONFIG &dc = *config; 1873 CONFIG &dc = *config;