comparison src/dnsbl.cpp @ 214:82886d4dd71f stable-6-0-19

Fixes to compile on Fedora 9 and for const correctness.
author Carl Byington <carl@five-ten-sg.com>
date Tue, 10 Jun 2008 08:58:42 -0700
parents 4db1457cd11a
children 784030ac71f1
comparison
equal deleted inserted replaced
213:44ffef730bc4 214:82886d4dd71f
93 pthread_mutex_t rate_mutex; 93 pthread_mutex_t rate_mutex;
94 94
95 std::set<int> fd_pool; 95 std::set<int> fd_pool;
96 int NULL_SOCKET = -1; 96 int NULL_SOCKET = -1;
97 const time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open a socket to the dns resolver process 97 const time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open a socket to the dns resolver process
98 char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process 98 const char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process
99 int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests 99 int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests
100 char *dccifd_port = NULL; // unix domain socket to talk to the dcc interface daemon 100 const char *dccifd_port = NULL; // unix domain socket to talk to the dcc interface daemon
101 time_t last_error_time; 101 time_t last_error_time;
102 int resolver_sock_count = 0; // protected with fd_pool_mutex 102 int resolver_sock_count = 0; // protected with fd_pool_mutex
103 int resolver_pool_size = 0; // protected with fd_pool_mutex 103 int resolver_pool_size = 0; // protected with fd_pool_mutex
104 rcpt_rates rcpt_counts; // protected with rate_mutex 104 rcpt_rates rcpt_counts; // protected with rate_mutex
105 105
107 struct ns_map { 107 struct ns_map {
108 // all the strings are owned by the keys/values in the ns_host string map 108 // all the strings are owned by the keys/values in the ns_host string map
109 string_map ns_host; // nameserver name -> host name that uses this name server 109 string_map ns_host; // nameserver name -> host name that uses this name server
110 ns_mapper ns_ip; // nameserver name -> ip address of the name server 110 ns_mapper ns_ip; // nameserver name -> ip address of the name server
111 ~ns_map(); 111 ~ns_map();
112 void add(char *name, char *refer); 112 void add(const char *name, const char *refer);
113 }; 113 };
114 114
115 115
116 ns_map::~ns_map() { 116 ns_map::~ns_map() {
117 for (string_map::iterator i=ns_host.begin(); i!=ns_host.end(); i++) { 117 for (string_map::iterator i=ns_host.begin(); i!=ns_host.end(); i++) {
118 char *x = (*i).first; 118 const char *x = (*i).first;
119 char *y = (*i).second; 119 const char *y = (*i).second;
120 free(x); 120 free((void*)x);
121 free(y); 121 free((void*)y);
122 } 122 }
123 ns_ip.clear(); 123 ns_ip.clear();
124 ns_host.clear(); 124 ns_host.clear();
125 } 125 }
126 126
127 127
128 void ns_map::add(char *name, char *refer) { 128 void ns_map::add(const char *name, const char *refer) {
129 string_map::iterator i = ns_host.find(name); 129 string_map::iterator i = ns_host.find(name);
130 if (i != ns_host.end()) return; 130 if (i != ns_host.end()) return;
131 char *x = strdup(name); 131 char *x = strdup(name);
132 char *y = strdup(refer); 132 char *y = strdup(refer);
133 ns_ip[x] = 0; 133 ns_ip[x] = 0;
136 } 136 }
137 137
138 // packed structure to allow a single socket write to dump the 138 // packed structure to allow a single socket write to dump the
139 // length and the following answer. The packing attribute is gcc specific. 139 // length and the following answer. The packing attribute is gcc specific.
140 struct glommer { 140 struct glommer {
141 int length; 141 size_t length;
142 #ifdef NS_PACKETSZ 142 #ifdef NS_PACKETSZ
143 u_char answer[NS_PACKETSZ*4]; // with a resolver, we return resolver answers 143 u_char answer[NS_PACKETSZ*4]; // with a resolver, we return resolver answers
144 #else 144 #else
145 int answer; // without a resolver, we return a single ip4 address, 0 == no answer 145 int answer; // without a resolver, we return a single ip4 address, 0 == no answer
146 #endif 146 #endif
147 } __attribute__ ((packed)); 147 } __attribute__ ((packed));
148 148
149 149
150 //////////////////////////////////////////////// 150 ////////////////////////////////////////////////
151 // helper to manipulate recipient counts 151 // helper to manipulate recipient counts
152 // 152 //
153 int incr_rcpt_count(char *user); 153 int incr_rcpt_count(const char *user);
154 int incr_rcpt_count(char *user) { 154 int incr_rcpt_count(const char *user) {
155 pthread_mutex_lock(&rate_mutex); 155 pthread_mutex_lock(&rate_mutex);
156 rcpt_rates::iterator i = rcpt_counts.find(user); 156 rcpt_rates::iterator i = rcpt_counts.find(user);
157 int c = 1; 157 int c = 1;
158 if (i == rcpt_counts.end()) { 158 if (i == rcpt_counts.end()) {
159 user = strdup(user); 159 user = strdup(user);
170 // helper to discard the strings held by a context_map 170 // helper to discard the strings held by a context_map
171 // 171 //
172 void discard(context_map &cm); 172 void discard(context_map &cm);
173 void discard(context_map &cm) { 173 void discard(context_map &cm) {
174 for (context_map::iterator i=cm.begin(); i!=cm.end(); i++) { 174 for (context_map::iterator i=cm.begin(); i!=cm.end(); i++) {
175 char *x = (*i).first; 175 const char *x = (*i).first;
176 free(x); 176 free((void*)x);
177 } 177 }
178 cm.clear(); 178 cm.clear();
179 } 179 }
180 180
181 181
182 //////////////////////////////////////////////// 182 ////////////////////////////////////////////////
183 // helper to register a string in a context_map 183 // helper to register a string in a context_map
184 // 184 //
185 void register_string(context_map &cm, char *name, CONTEXT *con); 185 void register_string(context_map &cm, const char *name, CONTEXT *con);
186 void register_string(context_map &cm, char *name, CONTEXT *con) { 186 void register_string(context_map &cm, const char *name, CONTEXT *con) {
187 context_map::iterator i = cm.find(name); 187 context_map::iterator i = cm.find(name);
188 if (i != cm.end()) return; 188 if (i != cm.end()) return;
189 char *x = strdup(name); 189 char *x = strdup(name);
190 cm[x] = con; 190 cm[x] = con;
191 } 191 }
278 pthread_mutex_lock(&config_mutex); 278 pthread_mutex_lock(&config_mutex);
279 pc->reference_count--; 279 pc->reference_count--;
280 bool last = (!pc->reference_count) && (pc != config); 280 bool last = (!pc->reference_count) && (pc != config);
281 pthread_mutex_unlock(&config_mutex); 281 pthread_mutex_unlock(&config_mutex);
282 if (last) delete pc; // free this config, since we were the last reference to it 282 if (last) delete pc; // free this config, since we were the last reference to it
283 if (helo) free(helo); 283 if (helo) free((void*)helo);
284 reset(true); 284 reset(true);
285 } 285 }
286 286
287 void mlfiPriv::reset(bool final) { 287 void mlfiPriv::reset(bool final) {
288 while (!delayer.empty()) { 288 while (!delayer.empty()) {
289 DELAYWHITEP dwp = delayer.front(); 289 DELAYWHITEP dwp = delayer.front();
290 delete dwp; 290 delete dwp;
291 delayer.pop_front(); 291 delayer.pop_front();
292 } 292 }
293 if (mailaddr) free(mailaddr); 293 if (mailaddr) free((void*)mailaddr);
294 if (queueid) free(queueid); 294 if (queueid) free((void*)queueid);
295 if (authenticated) free(authenticated); 295 if (authenticated) free((void*)authenticated);
296 if (client_name) free(client_name); 296 if (client_name) free((void*)client_name);
297 delayer.clear(); 297 delayer.clear();
298 discard(env_to); 298 discard(env_to);
299 if (memory) delete memory; 299 if (memory) delete memory;
300 if (scanner) delete scanner; 300 if (scanner) delete scanner;
301 if (assassin) delete assassin; 301 if (assassin) delete assassin;
421 } 421 }
422 } 422 }
423 return rs; 423 return rs;
424 } 424 }
425 425
426 void mlfiPriv::need_content_filter(char *rcpt, CONTEXT &con) { 426 void mlfiPriv::need_content_filter(const char *rcpt, CONTEXT &con) {
427 register_string(env_to, rcpt, &con); 427 register_string(env_to, rcpt, &con);
428 if (!memory) { 428 if (!memory) {
429 // first recipient that needs content filtering sets 429 // first recipient that needs content filtering sets
430 // some of the content filtering parameters 430 // some of the content filtering parameters
431 memory = new recorder(this, con.get_html_tags(), con.get_content_tlds(), con.get_content_cctlds()); 431 memory = new recorder(this, con.get_html_tags(), con.get_content_tlds(), con.get_content_cctlds());
451 451
452 452
453 //////////////////////////////////////////////// 453 ////////////////////////////////////////////////
454 // syslog a message 454 // syslog a message
455 // 455 //
456 void my_syslog(mlfiPriv *priv, char *text) { 456 void my_syslog(mlfiPriv *priv, const char *text) {
457 char buf[maxlen]; 457 char buf[maxlen];
458 if (priv) { 458 if (priv) {
459 snprintf(buf, sizeof(buf), "%s: %s", priv->queueid, text); 459 snprintf(buf, sizeof(buf), "%s: %s", priv->queueid, text);
460 text = buf; 460 text = buf;
461 } 461 }
471 else { 471 else {
472 printf("%s \n", text); 472 printf("%s \n", text);
473 } 473 }
474 } 474 }
475 475
476 void my_syslog(mlfiPriv *priv, string text) { 476 void my_syslog(mlfiPriv *priv, const string text) {
477 if (debug_syslog > 3) { 477 if (debug_syslog > 3) {
478 char buf[maxlen]; 478 char buf[maxlen];
479 strncpy(buf, text.c_str(), sizeof(buf)); 479 strncpy(buf, text.c_str(), sizeof(buf));
480 buf[maxlen-1] = '\0'; // ensure null termination 480 buf[maxlen-1] = '\0'; // ensure null termination
481 my_syslog(priv, buf); 481 my_syslog(priv, buf);
482 } 482 }
483 } 483 }
484 484
485 void my_syslog(char *text) { 485 void my_syslog(const char *text) {
486 my_syslog(NULL, text); 486 my_syslog(NULL, text);
487 } 487 }
488 488
489 489
490 //////////////////////////////////////////////// 490 ////////////////////////////////////////////////
577 // ask a dns question and get an A record answer - we don't try 577 // ask a dns question and get an A record answer - we don't try
578 // very hard, just using the default resolver retry settings. 578 // very hard, just using the default resolver retry settings.
579 // If we cannot get an answer, we just accept the mail. 579 // If we cannot get an answer, we just accept the mail.
580 // 580 //
581 // 581 //
582 int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers); 582 int dns_interface(mlfiPriv &priv, const char *question, bool maybe_ip, ns_map *nameservers);
583 int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers) { 583 int dns_interface(mlfiPriv &priv, const char *question, bool maybe_ip, ns_map *nameservers) {
584 // tell sendmail we are still working 584 // tell sendmail we are still working
585 #if _FFR_SMFI_PROGRESS 585 #if _FFR_SMFI_PROGRESS
586 if (priv.eom) smfi_progress(priv.ctx); 586 if (priv.eom) smfi_progress(priv.ctx);
587 #endif 587 #endif
588 588
637 while (ns_parserr(&handle, ns_s_ns, rrnum++, &rr) == 0) { 637 while (ns_parserr(&handle, ns_s_ns, rrnum++, &rr) == 0) {
638 if (ns_rr_type(rr) == ns_t_ns) { 638 if (ns_rr_type(rr) == ns_t_ns) {
639 char nam[NS_MAXDNAME+1]; 639 char nam[NS_MAXDNAME+1];
640 char *n = nam; 640 char *n = nam;
641 const u_char *p = ns_rr_rdata(rr); 641 const u_char *p = ns_rr_rdata(rr);
642 while (((n-nam) < NS_MAXDNAME) && ((p-glom.answer) < glom.length) && *p) { 642 while (((n-nam) < NS_MAXDNAME) && ((size_t)(p-glom.answer) < glom.length) && *p) {
643 size_t s = *(p++); 643 size_t s = *(p++);
644 if (s > 191) { 644 if (s > 191) {
645 // compression pointer 645 // compression pointer
646 s = (s-192)*256 + *(p++); 646 s = (s-192)*256 + *(p++);
647 if (s >= glom.length) break; // pointer outside bounds of answer 647 if (s >= glom.length) break; // pointer outside bounds of answer
648 p = glom.answer + s; 648 p = glom.answer + s;
649 s = *(p++); 649 s = *(p++);
650 } 650 }
651 if (s > 0) { 651 if (s > 0) {
652 if ((n-nam) >= (NS_MAXDNAME-s)) break; // destination would overflow name buffer 652 if ((size_t)(n-nam) >= (NS_MAXDNAME-s)) break; // destination would overflow name buffer
653 if ((p-glom.answer) >= (glom.length-s)) break; // source outside bounds of answer 653 if ((size_t)(p-glom.answer) >= (glom.length-s)) break; // source outside bounds of answer
654 memcpy(n, p, s); 654 memcpy(n, p, s);
655 n += s; 655 n += s;
656 p += s; 656 p += s;
657 *(n++) = '.'; 657 *(n++) = '.';
658 } 658 }
695 695
696 696
697 //////////////////////////////////////////////// 697 ////////////////////////////////////////////////
698 // check a single dnsbl 698 // check a single dnsbl
699 // 699 //
700 bool check_single(mlfiPriv &priv, int ip, char *suffix); 700 bool check_single(mlfiPriv &priv, int ip, const char *suffix);
701 bool check_single(mlfiPriv &priv, int ip, char *suffix) { 701 bool check_single(mlfiPriv &priv, int ip, const char *suffix) {
702 // make a dns question 702 // make a dns question
703 const u_char *src = (const u_char *)&ip; 703 const u_char *src = (const u_char *)&ip;
704 if (src[0] == 127) return false; // don't do dns lookups on localhost 704 if (src[0] == 127) return false; // don't do dns lookups on localhost
705 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space 705 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space
706 if ((src[0] == 192) && (src[1] == 168)) return false; 706 if ((src[0] == 192) && (src[1] == 168)) return false;
756 // if we find part of the hostname on the uribl, return 756 // if we find part of the hostname on the uribl, return
757 // true and point found to the part of the hostname that we found 757 // true and point found to the part of the hostname that we found
758 // as a string registered in hosts. 758 // as a string registered in hosts.
759 // otherwise, return false and preserve the value of found. 759 // otherwise, return false and preserve the value of found.
760 // 760 //
761 bool uriblookup(mlfiPriv &priv, string_set &hosts, char *hostname, char *top, char *&found) ; 761 bool uriblookup(mlfiPriv &priv, string_set &hosts, const char *hostname, const char *top, const char *&found) ;
762 bool uriblookup(mlfiPriv &priv, string_set &hosts, char *hostname, char *top, char *&found) { 762 bool uriblookup(mlfiPriv &priv, string_set &hosts, const char *hostname, const char *top, const char *&found) {
763 // top is pointer to '.' char at end of base domain, or null for ip address form 763 // top is pointer to '.' char at end of base domain, or null for ip address form
764 // so for hostname of www.fred.mydomain.co.uk 764 // so for hostname of www.fred.mydomain.co.uk
765 // top points to-----------------------^ 765 // top points to-----------------------^
766 // and we end up looking at only mydomain.co.uk, ignoring the www.fred stuff 766 // and we end up looking at only mydomain.co.uk, ignoring the www.fred stuff
767 char buf[maxlen]; 767 char buf[maxlen];
768 if (top) { 768 if (top) {
769 // add one more component 769 // add one more component
770 *top = '\0'; 770 const char *x = (const char *)memrchr(hostname, '.', top-hostname);
771 char *x = strrchr(hostname, '.');
772 if (x) hostname = x+1; 771 if (x) hostname = x+1;
773 *top = '.';
774 } 772 }
775 snprintf(buf, sizeof(buf), "%s.%s.", hostname, priv.uribl_suffix); 773 snprintf(buf, sizeof(buf), "%s.%s.", hostname, priv.uribl_suffix);
776 if (dns_interface(priv, buf, false, NULL)) { 774 if (dns_interface(priv, buf, false, NULL)) {
777 if (debug_syslog > 2) { 775 if (debug_syslog > 2) {
778 char tmp[maxlen]; 776 char tmp[maxlen];
796 // if we find part of the hostname on the uribl, return 794 // if we find part of the hostname on the uribl, return
797 // true and point found to the part of the hostname that we found 795 // true and point found to the part of the hostname that we found
798 // as a string registered in hosts. 796 // as a string registered in hosts.
799 // otherwise, return false and preserve the value of found. 797 // otherwise, return false and preserve the value of found.
800 // 798 //
801 bool check_uribl(mlfiPriv &priv, string_set &hosts, char *hostname, char *&found) ; 799 bool check_uribl(mlfiPriv &priv, string_set &hosts, const char *hostname, const char *&found) ;
802 bool check_uribl(mlfiPriv &priv, string_set &hosts, char *hostname, char *&found) { 800 bool check_uribl(mlfiPriv &priv, string_set &hosts, const char *hostname, const char *&found) {
803 in_addr ip; 801 in_addr ip;
804 if (inet_aton(hostname, &ip)) { 802 if (inet_aton(hostname, &ip)) {
805 const u_char *src = (const u_char *)&ip.s_addr; 803 const u_char *src = (const u_char *)&ip.s_addr;
806 if (src[0] == 127) return false; // don't do dns lookups on localhost 804 if (src[0] == 127) return false; // don't do dns lookups on localhost
807 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space 805 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space
811 snprintf(adr, sizeof(adr), "%u.%u.%u.%u", src[3], src[2], src[1], src[0]); 809 snprintf(adr, sizeof(adr), "%u.%u.%u.%u", src[3], src[2], src[1], src[0]);
812 // cannot use inet_ntop here since we want the octets reversed. 810 // cannot use inet_ntop here since we want the octets reversed.
813 return (uriblookup(priv, hosts, adr, NULL, found)); 811 return (uriblookup(priv, hosts, adr, NULL, found));
814 } 812 }
815 813
816 char *top, *top2, *top3; 814 const char *top, *top2, *top3;
817 top = strrchr(hostname, '.'); 815 top = strrchr(hostname, '.');
818 if (top) { 816 if (top) {
819 *top = '\0'; 817 top2 = (const char *)memrchr(hostname, '.', top-hostname);
820 top2 = strrchr(hostname, '.');
821 *top = '.';
822 818
823 if (top2) { 819 if (top2) {
824 string_set::iterator i = priv.memory->get_cctlds()->find(top2+1); 820 string_set::iterator i = priv.memory->get_cctlds()->find(top2+1);
825 string_set::iterator x = priv.memory->get_cctlds()->end(); 821 string_set::iterator x = priv.memory->get_cctlds()->end();
826 // if we have a 2-level-cctld, just look at top three levels of the name 822 // if we have a 2-level-cctld, just look at top three levels of the name
827 if (i != x) return uriblookup(priv, hosts, hostname, top2, found); 823 if (i != x) return uriblookup(priv, hosts, hostname, top2, found);
828 824
829 *top2 = '\0';
830 top3 = strrchr(hostname, '.');
831 *top2 = '.';
832
833 // if we have more than 3 levels in the name, look at the top three levels of the name 825 // if we have more than 3 levels in the name, look at the top three levels of the name
826 top3 = (const char *)memrchr(hostname, '.', top2-hostname);
834 if (top3 && uriblookup(priv, hosts, hostname, top2, found)) return true; 827 if (top3 && uriblookup(priv, hosts, hostname, top2, found)) return true;
828
835 // if that was not found, fall thru to looking at the top two levels 829 // if that was not found, fall thru to looking at the top two levels
836 } 830 }
837 // look at the top two levels of the name 831 // look at the top two levels of the name
838 return uriblookup(priv, hosts, hostname, top, found); 832 return uriblookup(priv, hosts, hostname, top, found);
839 } 833 }
843 837
844 //////////////////////////////////////////////// 838 ////////////////////////////////////////////////
845 // check the hosts from the body against the content filter and uribl dnsbls 839 // check the hosts from the body against the content filter and uribl dnsbls
846 // 840 //
847 // 841 //
848 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&msg, char *&host, int &ip, char *&found); 842 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int &ip, const char *&found);
849 bool check_hosts(mlfiPriv &priv, bool random, int limit, char *&msg, char *&host, int &ip, char *&found) { 843 bool check_hosts(mlfiPriv &priv, bool random, int limit, const char *&msg, const char *&host, int &ip, const char *&found) {
850 found = NULL; // normally ip address style 844 found = NULL; // normally ip address style
851 if (!priv.content_suffix && !priv.uribl_suffix) return false; // nothing to check 845 if (!priv.content_suffix && !priv.uribl_suffix) return false; // nothing to check
852 CONFIG &dc = *priv.pc;
853 string_set &hosts = priv.memory->get_hosts(); 846 string_set &hosts = priv.memory->get_hosts();
854 string_set &ignore = *priv.content_host_ignore; 847 string_set &ignore = *priv.content_host_ignore;
855 848
856 int count = 0; 849 int count = 0;
857 int cnt = hosts.size(); // number of hosts we could look at 850 int cnt = hosts.size(); // number of hosts we could look at
935 ips.insert(ip); 928 ips.insert(ip);
936 if (check_single(priv, ip, priv.content_suffix)) { 929 if (check_single(priv, ip, priv.content_suffix)) {
937 msg = priv.content_message; 930 msg = priv.content_message;
938 string_map::iterator j = nameservers.ns_host.find(host); 931 string_map::iterator j = nameservers.ns_host.find(host);
939 if (j != nameservers.ns_host.end()) { 932 if (j != nameservers.ns_host.end()) {
940 char *refer = (*j).second; 933 const char *refer = (*j).second;
941 char buf[maxlen]; 934 char buf[maxlen];
942 snprintf(buf, sizeof(buf), "%s with nameserver %s", refer, host); 935 snprintf(buf, sizeof(buf), "%s with nameserver %s", refer, host);
943 host = register_string(hosts, buf); // put a copy into hosts, and return that reference 936 host = register_string(hosts, buf); // put a copy into hosts, and return that reference
944 } 937 }
945 else { 938 else {
962 // that. So the <> wrapper is now optional. It may have mixed case, just 955 // that. So the <> wrapper is now optional. It may have mixed case, just
963 // as the mail client sent it. We dup the string and convert the duplicate 956 // as the mail client sent it. We dup the string and convert the duplicate
964 // to lower case. Some clients enclose the entire address in single quotes, 957 // to lower case. Some clients enclose the entire address in single quotes,
965 // so we strip those as well. 958 // so we strip those as well.
966 // 959 //
967 char *to_lower_string(char *email); 960 const char *to_lower_string(const char *email);
968 char *to_lower_string(char *email) { 961 const char *to_lower_string(const char *email) {
969 int n = strlen(email); 962 int n = strlen(email);
970 if (email[0] == '<') { 963 if (email[0] == '<') {
971 // assume it also ends with > 964 // assume it also ends with >
972 n -= 2; 965 n -= 2;
973 if (n < 1) return strdup(email); // return "<>" 966 if (n < 1) return strdup(email); // return "<>"
1010 1003
1011 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from) 1004 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from)
1012 { 1005 {
1013 mlfiPriv &priv = *MLFIPRIV; 1006 mlfiPriv &priv = *MLFIPRIV;
1014 priv.mailaddr = to_lower_string(from[0]); 1007 priv.mailaddr = to_lower_string(from[0]);
1015 priv.queueid = strdup(smfi_getsymval(ctx, "i")); 1008 priv.queueid = strdup(smfi_getsymval(ctx, (char*)"i"));
1016 priv.authenticated = smfi_getsymval(ctx, "{auth_authen}"); 1009 priv.authenticated = smfi_getsymval(ctx, (char*)"{auth_authen}");
1017 priv.client_name = smfi_getsymval(ctx, "_"); 1010 priv.client_name = smfi_getsymval(ctx, (char*)"_");
1018 if (!priv.helo) priv.helo = strdup("unknown"); 1011 if (!priv.helo) priv.helo = strdup("unknown");
1019 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); 1012 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated);
1020 if (priv.client_name) priv.client_name = strdup(priv.client_name); 1013 if (priv.client_name) priv.client_name = strdup(priv.client_name);
1021 if (spamc != spamc_empty) { 1014 if (spamc != spamc_empty) {
1022 priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); 1015 priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid);
1030 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) 1023 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt)
1031 { 1024 {
1032 DNSBLP rejectlist = NULL; // list that caused the reject 1025 DNSBLP rejectlist = NULL; // list that caused the reject
1033 mlfiPriv &priv = *MLFIPRIV; 1026 mlfiPriv &priv = *MLFIPRIV;
1034 CONFIG &dc = *priv.pc; 1027 CONFIG &dc = *priv.pc;
1035 char *rcptaddr = rcpt[0]; 1028 const char *rcptaddr = rcpt[0];
1036 char *loto = to_lower_string(rcptaddr); 1029 const char *loto = to_lower_string(rcptaddr);
1037 1030
1038 // some version of sendmail allowed rcpt to:<> and passed it thru to the milters 1031 // some version of sendmail allowed rcpt to:<> and passed it thru to the milters
1039 if (strcmp(loto, "<>") == 0) { 1032 if (strcmp(loto, "<>") == 0) {
1040 smfi_setreply(ctx, "550", "5.7.1", "bogus recipient"); 1033 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"bogus recipient");
1041 return SMFIS_REJECT; 1034 return SMFIS_REJECT;
1042 } 1035 }
1043 // priv.mailaddr sending original message to loto 1036 // priv.mailaddr sending original message to loto
1044 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); 1037 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr));
1045 VERIFYP ver = con.find_verify(loto); 1038 VERIFYP ver = con.find_verify(loto);
1046 char *fromvalue = con.find_from(priv.mailaddr, true); 1039 const char *fromvalue = con.find_from(priv.mailaddr, true);
1047 // tell spam assassin and dccifd about this recipient 1040 // tell spam assassin and dccifd about this recipient
1048 if (priv.assassin) priv.assassin->mlfi_envrcpt(ctx, loto); 1041 if (priv.assassin) priv.assassin->mlfi_envrcpt(ctx, loto);
1049 if (priv.dccifd) priv.dccifd->mlfi_envrcpt(ctx, loto, con.get_grey() && !priv.authenticated); 1042 if (priv.dccifd) priv.dccifd->mlfi_envrcpt(ctx, loto, con.get_grey() && !priv.authenticated);
1050 // loto sending a reply back to priv.mailaddr 1043 // loto sending a reply back to priv.mailaddr
1051 CONTEXT &con2 = *(dc.find_context(priv.mailaddr)->find_context(loto)); 1044 CONTEXT &con2 = *(dc.find_context(priv.mailaddr)->find_context(loto));
1052 char *replyvalue = con2.find_from(loto); 1045 const char *replyvalue = con2.find_from(loto);
1053 if (debug_syslog > 1) { 1046 if (debug_syslog > 1) {
1054 char buf[maxlen]; 1047 char buf[maxlen];
1055 char msg[maxlen]; 1048 char msg[maxlen];
1056 snprintf(msg, sizeof(msg), "from <%s> to <%s> using context %s state %s reply state %s", priv.mailaddr, loto, con.get_full_name(buf,maxlen), fromvalue, replyvalue); 1049 snprintf(msg, sizeof(msg), "from <%s> to <%s> using context %s state %s reply state %s", priv.mailaddr, loto, con.get_full_name(buf,maxlen), fromvalue, replyvalue);
1057 my_syslog(&priv, msg); 1050 my_syslog(&priv, msg);
1058 } 1051 }
1059 free(loto); 1052 free((void*)loto);
1060 status st; 1053 status st;
1061 if (replyvalue == token_black) { 1054 if (replyvalue == token_black) {
1062 smfi_setreply(ctx, "550", "5.7.1", "recipient can not reply due to blacklisting"); 1055 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"recipient can not reply due to blacklisting");
1063 return SMFIS_REJECT; 1056 return SMFIS_REJECT;
1064 } 1057 }
1065 if (priv.authenticated) { 1058 if (priv.authenticated) {
1066 int c = incr_rcpt_count(priv.authenticated); 1059 int c = incr_rcpt_count(priv.authenticated);
1067 int l = dc.default_context->find_rate(priv.authenticated); 1060 int l = dc.default_context->find_rate(priv.authenticated);
1068 if (debug_syslog > 1) { 1061 if (debug_syslog > 1) {
1069 char buf[maxlen];
1070 char msg[maxlen]; 1062 char msg[maxlen];
1071 snprintf(msg, sizeof(msg), "authenticated id %s (%d recipients, %d limit)", priv.authenticated, c, l); 1063 snprintf(msg, sizeof(msg), "authenticated id %s (%d recipients, %d limit)", priv.authenticated, c, l);
1072 my_syslog(&priv, msg); 1064 my_syslog(&priv, msg);
1073 } 1065 }
1074 if (c > l) { 1066 if (c > l) {
1075 smfi_setreply(ctx, "550", "5.7.1", "recipient rate limit exceeded"); 1067 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"recipient rate limit exceeded");
1076 return SMFIS_REJECT; 1068 return SMFIS_REJECT;
1077 } 1069 }
1078 st = white; 1070 st = white;
1079 } 1071 }
1080 else if (fromvalue == token_black) { 1072 else if (fromvalue == token_black) {
1092 char adr[sizeof "255.255.255.255 "]; 1084 char adr[sizeof "255.255.255.255 "];
1093 adr[0] = '\0'; 1085 adr[0] = '\0';
1094 inet_ntop(AF_INET, (const u_char *)&priv.ip, adr, sizeof(adr)); 1086 inet_ntop(AF_INET, (const u_char *)&priv.ip, adr, sizeof(adr));
1095 char buf[maxlen]; 1087 char buf[maxlen];
1096 snprintf(buf, sizeof(buf), rejectlist->message, adr, adr); 1088 snprintf(buf, sizeof(buf), rejectlist->message, adr, adr);
1097 smfi_setreply(ctx, "550", "5.7.1", buf); 1089 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", buf);
1098 return SMFIS_REJECT; 1090 return SMFIS_REJECT;
1099 } 1091 }
1100 if (st == oksofar) { 1092 if (st == oksofar) {
1101 char *msg = con.generic_match(priv.client_name); 1093 const char *msg = con.generic_match(priv.client_name);
1102 if (msg) { 1094 if (msg) {
1103 // reject the recipient based on generic reverse dns 1095 // reject the recipient based on generic reverse dns
1104 char buf[maxlen]; 1096 char buf[maxlen];
1105 snprintf(buf, sizeof(buf), msg, priv.client_name); 1097 snprintf(buf, sizeof(buf), msg, priv.client_name);
1106 smfi_setreply(ctx, "550", "5.7.1", buf); 1098 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", buf);
1107 return SMFIS_REJECT; 1099 return SMFIS_REJECT;
1108 } 1100 }
1109 } 1101 }
1110 if (st == black) { 1102 if (st == black) {
1111 // reject the recipient based on blacklisting either from or to 1103 // reject the recipient based on blacklisting either from or to
1112 smfi_setreply(ctx, "550", "5.7.1", "no such user"); 1104 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"no such user");
1113 return SMFIS_REJECT; 1105 return SMFIS_REJECT;
1114 } 1106 }
1115 if (ver) { 1107 if (ver) {
1116 // try to verify this from/to pair of addresses even if it might be explicitly whitelisted 1108 // try to verify this from/to pair of addresses even if it might be explicitly whitelisted
1117 char *loto = to_lower_string(rcptaddr); 1109 const char *loto = to_lower_string(rcptaddr);
1118 bool rc = ver->ok(priv.mailaddr, loto); 1110 bool rc = ver->ok(priv.mailaddr, loto);
1119 free(loto); 1111 free((void*)loto);
1120 if (!rc) { 1112 if (!rc) {
1121 smfi_setreply(ctx, "550", "5.7.1", "no such user"); 1113 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"no such user");
1122 return SMFIS_REJECT; 1114 return SMFIS_REJECT;
1123 } 1115 }
1124 } 1116 }
1125 // we will accept the recipient, but add an auto-whitelist entry 1117 // we will accept the recipient, but add an auto-whitelist entry
1126 // if needed to ensure we can accept replies 1118 // if needed to ensure we can accept replies
1127 loto = to_lower_string(rcptaddr); 1119 loto = to_lower_string(rcptaddr);
1128 WHITELISTERP w = con2.find_autowhite(loto, priv.mailaddr); 1120 WHITELISTERP w = con2.find_autowhite(loto, priv.mailaddr);
1129 // check if local part is too big 1121 // check if local part is too big
1130 const int max_local_size = 30; 1122 const int max_local_size = 30;
1131 char *p = strchr(loto, '@'); 1123 const char *p = strchr(loto, '@');
1132 int len = (p) ? p-loto : max_local_size; 1124 int len = (p) ? p-loto : max_local_size;
1133 if (len >= max_local_size) w = NULL; // too big, pretend we don't have a whitelister 1125 if (len >= max_local_size) w = NULL; // too big, pretend we don't have a whitelister
1134 // record it if we have a whitelister 1126 // record it if we have a whitelister
1135 if (w) { 1127 if (w) {
1136 DELAYWHITEP dwp = new DELAYWHITE(loto, w, &con2); 1128 DELAYWHITEP dwp = new DELAYWHITE(loto, w, &con2);
1137 priv.delayer.push_back(dwp); 1129 priv.delayer.push_back(dwp);
1138 } 1130 }
1139 else { 1131 else {
1140 free(loto); 1132 free((void*)loto);
1141 } 1133 }
1142 1134
1143 // accept the recipient 1135 // accept the recipient
1144 if (!con.get_content_filtering()) st = white; 1136 if (!con.get_content_filtering()) st = white;
1145 1137
1146 if (st == oksofar) { 1138 if (st == oksofar) {
1147 // remember first content filtering context 1139 // remember first content filtering context
1148 if (con.get_content_filtering()) { 1140 if (con.get_content_filtering()) {
1149 if (!priv.content_context) priv.content_context = &con; 1141 if (!priv.content_context) priv.content_context = &con;
1150 else if (con.get_require() && (priv.content_context != &con)) { 1142 else if (con.get_require() && (priv.content_context != &con)) {
1151 smfi_setreply(ctx, "452", "4.2.1", "incompatible filtering contexts"); 1143 smfi_setreply(ctx, (char*)"452", (char*)"4.2.1", (char*)"incompatible filtering contexts");
1152 return SMFIS_TEMPFAIL; 1144 return SMFIS_TEMPFAIL;
1153 } 1145 }
1154 } 1146 }
1155 // remember the non-whites 1147 // remember the non-whites
1156 priv.need_content_filter(rcptaddr, con); 1148 priv.need_content_filter(rcptaddr, con);
1187 mlfiPriv &priv = *MLFIPRIV; 1179 mlfiPriv &priv = *MLFIPRIV;
1188 // delayed autowhitelisting 1180 // delayed autowhitelisting
1189 while (!priv.delayer.empty()) { 1181 while (!priv.delayer.empty()) {
1190 DELAYWHITEP dwp = priv.delayer.front(); 1182 DELAYWHITEP dwp = priv.delayer.front();
1191 if (!priv.is_bulk_precedence) { 1183 if (!priv.is_bulk_precedence) {
1192 char *loto = dwp->get_loto(); 1184 const char *loto = dwp->get_loto();
1193 WHITELISTERP w = dwp->get_w(); 1185 WHITELISTERP w = dwp->get_w();
1194 CONTEXTP con2 = dwp->get_con(); 1186 CONTEXTP con2 = dwp->get_con();
1195 if (debug_syslog > 1) { 1187 if (debug_syslog > 1) {
1196 char buf[maxlen]; 1188 char buf[maxlen];
1197 char msg[maxlen]; 1189 char msg[maxlen];
1223 } 1215 }
1224 1216
1225 sfsistat mlfi_eom(SMFICTX *ctx) 1217 sfsistat mlfi_eom(SMFICTX *ctx)
1226 { 1218 {
1227 sfsistat rc; 1219 sfsistat rc;
1228 mlfiPriv &priv = *MLFIPRIV; 1220 mlfiPriv &priv = *MLFIPRIV;
1229 CONFIG &dc = *priv.pc; 1221 const char *host = NULL;
1230 char *host = NULL;
1231 int ip; 1222 int ip;
1232 status st;
1233 // process end of message 1223 // process end of message
1234 priv.eom = true; 1224 priv.eom = true;
1235 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; 1225 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE;
1236 else { 1226 else {
1237 // assert env_to not empty, it contains the 1227 // assert env_to not empty, it contains the
1245 string msg; 1235 string msg;
1246 string_set alive; 1236 string_set alive;
1247 bool random = false; 1237 bool random = false;
1248 int limit = 0; 1238 int limit = 0;
1249 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { 1239 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) {
1250 char *rcpt = (*i).first; 1240 const char *rcpt = (*i).first;
1251 CONTEXT &con = *((*i).second); 1241 CONTEXT &con = *((*i).second);
1252 if (!con.acceptable_content(*priv.memory, score, bulk, msg)) { 1242 if (!con.acceptable_content(*priv.memory, score, bulk, msg)) {
1253 // bad html tags or excessive hosts or 1243 // bad html tags or excessive hosts or
1254 // high spam assassin score or dcc bulk threshold exceedeed 1244 // high spam assassin score or dcc bulk threshold exceedeed
1255 smfi_delrcpt(ctx, rcpt); 1245 smfi_delrcpt(ctx, (char*)rcpt);
1256 } 1246 }
1257 else { 1247 else {
1258 alive.insert(rcpt); 1248 alive.insert(rcpt);
1259 random |= con.get_host_random(); 1249 random |= con.get_host_random();
1260 limit = max(limit, con.get_host_limit()); 1250 limit = max(limit, con.get_host_limit());
1261 } 1251 }
1262 } 1252 }
1263 bool rejecting = alive.empty(); // if alive is empty, we must have set msg above in acceptable_content() 1253 bool rejecting = alive.empty(); // if alive is empty, we must have set msg above in acceptable_content()
1264 if (!rejecting) { 1254 if (!rejecting) {
1265 char *fmt, *found; 1255 const char *fmt;
1256 const char *found;
1266 if (check_hosts(priv, random, limit, fmt, host, ip, found)) { 1257 if (check_hosts(priv, random, limit, fmt, host, ip, found)) {
1267 if (found) { 1258 if (found) {
1268 // uribl style 1259 // uribl style
1269 snprintf(buf, sizeof(buf), fmt, host, found); 1260 snprintf(buf, sizeof(buf), fmt, host, found);
1270 } 1261 }
1279 rejecting = true; 1270 rejecting = true;
1280 } 1271 }
1281 } 1272 }
1282 if (!rejecting) { 1273 if (!rejecting) {
1283 if (priv.want_dccgrey && grey) { 1274 if (priv.want_dccgrey && grey) {
1284 smfi_setreply(ctx, "452", "4.2.1", "temporary greylist embargoed"); 1275 smfi_setreply(ctx, (char*)"452", (char*)"4.2.1", (char*)"temporary greylist embargoed");
1285 rc = SMFIS_TEMPFAIL; 1276 rc = SMFIS_TEMPFAIL;
1286 } 1277 }
1287 else rc = SMFIS_CONTINUE; 1278 else rc = SMFIS_CONTINUE;
1288 } 1279 }
1289 else if (!priv.have_whites) { 1280 else if (!priv.have_whites) {
1290 // can reject the entire message 1281 // can reject the entire message
1291 snprintf(buf, sizeof(buf), "%s", msg.c_str()); 1282 snprintf(buf, sizeof(buf), "%s", msg.c_str());
1292 smfi_setreply(ctx, "550", "5.7.1", buf); 1283 smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", buf);
1293 rc = SMFIS_REJECT; 1284 rc = SMFIS_REJECT;
1294 } 1285 }
1295 else { 1286 else {
1296 // need to accept it but remove the recipients that don't want it 1287 // need to accept it but remove the recipients that don't want it
1297 for (string_set::iterator i=alive.begin(); i!=alive.end(); i++) { 1288 for (string_set::iterator i=alive.begin(); i!=alive.end(); i++) {
1298 char *rcpt = *i; 1289 const char *rcpt = *i;
1299 smfi_delrcpt(ctx, rcpt); 1290 smfi_delrcpt(ctx, (char*)rcpt);
1300 } 1291 }
1301 rc = SMFIS_CONTINUE; 1292 rc = SMFIS_CONTINUE;
1302 } 1293 }
1303 } 1294 }
1304 // reset for a new message on the same connection 1295 // reset for a new message on the same connection
1322 return SMFIS_CONTINUE; 1313 return SMFIS_CONTINUE;
1323 } 1314 }
1324 1315
1325 struct smfiDesc smfilter = 1316 struct smfiDesc smfilter =
1326 { 1317 {
1327 "DNSBL", // filter name 1318 (char*)"DNSBL", // filter name
1328 SMFI_VERSION, // version code -- do not change 1319 SMFI_VERSION, // version code -- do not change
1329 SMFIF_DELRCPT, // flags 1320 SMFIF_DELRCPT, // flags
1330 mlfi_connect, // connection info filter 1321 mlfi_connect, // connection info filter
1331 mlfi_helo, // SMTP HELO command filter 1322 mlfi_helo, // SMTP HELO command filter
1332 mlfi_envfrom, // envelope sender filter 1323 mlfi_envfrom, // envelope sender filter
1388 CONFIG &dc = *config; 1379 CONFIG &dc = *config;
1389 time_t then = dc.load_time; 1380 time_t then = dc.load_time;
1390 struct stat st; 1381 struct stat st;
1391 bool reload = false; 1382 bool reload = false;
1392 for (string_set::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) { 1383 for (string_set::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) {
1393 char *fn = *i; 1384 const char *fn = *i;
1394 if (stat(fn, &st)) reload = true; // file disappeared 1385 if (stat(fn, &st)) reload = true; // file disappeared
1395 else if (st.st_mtime > then) reload = true; // file modified 1386 else if (st.st_mtime > then) reload = true; // file modified
1396 if (reload) break; 1387 if (reload) break;
1397 } 1388 }
1398 if (reload) { 1389 if (reload) {
1417 } 1408 }
1418 return NULL; 1409 return NULL;
1419 } 1410 }
1420 1411
1421 1412
1422 void usage(char *prog); 1413 void usage(const char *prog);
1423 void usage(char *prog) 1414 void usage(const char *prog)
1424 { 1415 {
1425 fprintf(stderr, "Usage: %s [-d [level]] [-c] [-s] [-e from|to] [-b dccifd-addr] -r port -p sm-sock-addr [-t timeout]\n", prog); 1416 fprintf(stderr, "Usage: %s [-d [level]] [-c] [-s] [-e from|to] [-b dccifd-addr] -r port -p sm-sock-addr [-t timeout]\n", prog);
1426 fprintf(stderr, "where dccifd_addr is for the connection to dccifd\n"); 1417 fprintf(stderr, "where dccifd_addr is for the connection to dccifd\n");
1427 fprintf(stderr, " and should be local-domain-socket-file-name\n"); 1418 fprintf(stderr, " and should be local-domain-socket-file-name\n");
1428 fprintf(stderr, "where port is for the connection to our own dns resolver processes\n"); 1419 fprintf(stderr, "where port is for the connection to our own dns resolver processes\n");
1440 fprintf(stderr, " addresses in the argument to the -e switch\n"); 1431 fprintf(stderr, " addresses in the argument to the -e switch\n");
1441 } 1432 }
1442 1433
1443 1434
1444 1435
1445 void setup_socket(char *sock); 1436 void setup_socket(const char *sock);
1446 void setup_socket(char *sock) { 1437 void setup_socket(const char *sock) {
1447 unlink(sock); 1438 unlink(sock);
1448 } 1439 }
1449 1440
1450 1441
1451 /* 1442 /*
1467 token_init(); 1458 token_init();
1468 bool check = false; 1459 bool check = false;
1469 bool stress = false; 1460 bool stress = false;
1470 bool setconn = false; 1461 bool setconn = false;
1471 bool setreso = false; 1462 bool setreso = false;
1472 char *email = NULL; 1463 const char *email = NULL;
1473 int c; 1464 int c;
1474 const char *args = "b:r:p:t:e:d:chs"; 1465 const char *args = "b:r:p:t:e:d:chs";
1475 extern char *optarg; 1466 extern char *optarg;
1476 1467
1477 // Process command line options 1468 // Process command line options
1519 exit(EX_SOFTWARE); 1510 exit(EX_SOFTWARE);
1520 } 1511 }
1521 break; 1512 break;
1522 1513
1523 case 'e': 1514 case 'e':
1524 if (email) free(email); 1515 if (email) free((void*)email);
1525 email = strdup(optarg); 1516 email = strdup(optarg);
1526 break; 1517 break;
1527 1518
1528 case 'c': 1519 case 'c':
1529 check = true; 1520 check = true;
1585 CONTEXTP con = conf->find_context(to); 1576 CONTEXTP con = conf->find_context(to);
1586 char buf[maxlen]; 1577 char buf[maxlen];
1587 fprintf(stdout, "envelope to <%s> finds context %s\n", to, con->get_full_name(buf,maxlen)); 1578 fprintf(stdout, "envelope to <%s> finds context %s\n", to, con->get_full_name(buf,maxlen));
1588 CONTEXTP fc = con->find_context(from); 1579 CONTEXTP fc = con->find_context(from);
1589 fprintf(stdout, "envelope from <%s> finds context %s\n", from, fc->get_full_name(buf,maxlen)); 1580 fprintf(stdout, "envelope from <%s> finds context %s\n", from, fc->get_full_name(buf,maxlen));
1590 char *st = fc->find_from(from); 1581 const char *st = fc->find_from(from);
1591 fprintf(stdout, "envelope from <%s> finds status %s\n", from, st); 1582 fprintf(stdout, "envelope from <%s> finds status %s\n", from, st);
1592 delete conf; 1583 delete conf;
1593 } 1584 }
1594 } 1585 }
1595 return 0; 1586 return 0;