comparison src/dnsbl.cpp @ 44:6b79046b18c2

changes for 3.2
author carl
date Fri, 09 Jul 2004 07:53:02 -0700
parents acbe44bbba22
children 66c66a6ee65f
comparison
equal deleted inserted replaced
43:acbe44bbba22 44:6b79046b18c2
114 typedef map<char *, char *, ltstr> string_map; 114 typedef map<char *, char *, ltstr> string_map;
115 typedef map<char *, string_map *, ltstr> from_map; 115 typedef map<char *, string_map *, ltstr> from_map;
116 typedef map<char *, DNSBLP, ltstr> dnsblp_map; 116 typedef map<char *, DNSBLP, ltstr> dnsblp_map;
117 typedef map<char *, DNSBLLP, ltstr> dnsbllp_map; 117 typedef map<char *, DNSBLLP, ltstr> dnsbllp_map;
118 typedef set<char *, ltstr> string_set; 118 typedef set<char *, ltstr> string_set;
119 typedef set<int> int_set;
119 typedef list<char *> string_list; 120 typedef list<char *> string_list;
120 typedef map<char *, int, ltstr> ns_map; 121 typedef map<char *, int, ltstr> ns_map;
121 122
122 struct CONFIG { 123 struct CONFIG {
123 // the only mutable stuff once it has been loaded from the config file 124 // the only mutable stuff once it has been loaded from the config file
133 string_map env_to_chkfrom; // map recipient to a named from map 134 string_map env_to_chkfrom; // map recipient to a named from map
134 char * content_suffix; // for sbl url body filtering 135 char * content_suffix; // for sbl url body filtering
135 char * content_message; // "" 136 char * content_message; // ""
136 char * host_limit_message; // error message for excessive host names 137 char * host_limit_message; // error message for excessive host names
137 int host_limit; // limit on host names 138 int host_limit; // limit on host names
139 bool host_random; // pick a random selection of host names rather than error for excessive hosts
138 char * tag_limit_message; // error message for excessive bad html tags 140 char * tag_limit_message; // error message for excessive bad html tags
139 int tag_limit; // limit on bad html tags 141 int tag_limit; // limit on bad html tags
140 string_set html_tags; // set of valid html tags 142 string_set html_tags; // set of valid html tags
141 string_set tlds; // set of valid tld components 143 string_set tlds; // set of valid tld components
142 CONFIG(); 144 CONFIG();
148 load_time = 0; 150 load_time = 0;
149 content_suffix = NULL; 151 content_suffix = NULL;
150 content_message = NULL; 152 content_message = NULL;
151 host_limit_message = NULL; 153 host_limit_message = NULL;
152 host_limit = 0; 154 host_limit = 0;
155 host_random = false;
153 tag_limit_message = NULL; 156 tag_limit_message = NULL;
154 tag_limit = 0; 157 tag_limit = 0;
155 } 158 }
156 CONFIG::~CONFIG() { 159 CONFIG::~CONFIG() {
157 for (dnsblp_map::iterator i=dnsbls.begin(); i!=dnsbls.end(); i++) { 160 for (dnsblp_map::iterator i=dnsbls.begin(); i!=dnsbls.end(); i++) {
584 static status check_hosts(mlfiPriv &priv, char *&host, int &ip) { 587 static status check_hosts(mlfiPriv &priv, char *&host, int &ip) {
585 CONFIG &dc = *priv.pc; 588 CONFIG &dc = *priv.pc;
586 if (!dc.content_suffix) return oksofar; 589 if (!dc.content_suffix) return oksofar;
587 int count = 0; 590 int count = 0;
588 ns_map nameservers; 591 ns_map nameservers;
589 int lim = priv.pc->host_limit; 592 bool ran = priv.pc->host_random;
593 int lim = priv.pc->host_limit; // we should not look at more than this many hosts
594 int cnt = priv.memory->hosts.size(); // number of hosts we could look at
595 int_set ips; // remove duplicate ip addresses
590 for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) { 596 for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) {
597 host = *i; // a reference into priv.memory->hosts, which will live until this smtp transaction is closed
598 if ((cnt > lim) && (lim > 0) && ran) {
599 // try to only look at lim/cnt fraction of the available cnt host names
600 int r = rand() % cnt;
601 if (r >= lim) {
602 char buf[1000];
603 snprintf(buf, sizeof(buf), "host %s skipped", host);
604 my_syslog(&priv, buf);
605 continue;
606 }
607 }
591 count++; 608 count++;
592 if ((count > lim) && (lim > 0)) { 609 if ((count > lim) && (lim > 0) && (!ran)) {
593 discard(nameservers); 610 discard(nameservers);
594 return reject_host; 611 return reject_host;
595 } 612 }
596 host = *i; // a reference into priv.memory->hosts, which will live until this smtp transaction is closed 613 ip = protected_dns_interface(host, true, &nameservers);
597 ip = protected_dns_interface(host, true, &nameservers);
598 if (debug_syslog) { 614 if (debug_syslog) {
599 char buf[200]; 615 char buf[1000];
600 if (ip) { 616 if (ip) {
601 char adr[sizeof "255.255.255.255"]; 617 char adr[sizeof "255.255.255.255"];
602 adr[0] = '\0'; 618 adr[0] = '\0';
603 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); 619 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr));
604 snprintf(buf, sizeof(buf), "host %s found at %s", host, adr); 620 snprintf(buf, sizeof(buf), "host %s found at %s", host, adr);
607 snprintf(buf, sizeof(buf), "host %s not found", host); 623 snprintf(buf, sizeof(buf), "host %s not found", host);
608 } 624 }
609 my_syslog(&priv, buf); 625 my_syslog(&priv, buf);
610 } 626 }
611 if (ip) { 627 if (ip) {
612 status st = check_single(ip, dc.content_suffix); 628 int_set::iterator i = ips.find(ip);
613 if (st == reject) { 629 if (i == ips.end()) {
614 discard(nameservers); 630 ips.insert(ip);
615 return st; 631 status st = check_single(ip, dc.content_suffix);
632 if (st == reject) {
633 discard(nameservers);
634 return st;
635 }
616 } 636 }
617 } 637 }
618 } 638 }
619 lim *= 4; // allow average of 3 ns per host name 639 lim *= 4; // allow average of 3 ns per host name
620 for (ns_map::iterator i=nameservers.begin(); i!=nameservers.end(); i++) { 640 for (ns_map::iterator i=nameservers.begin(); i!=nameservers.end(); i++) {
621 count++; 641 count++;
622 if ((count > lim) && (lim > 0)) { 642 if ((count > lim) && (lim > 0)) {
643 if (ran) continue; // don't complain
623 discard(nameservers); 644 discard(nameservers);
624 return reject_host; 645 return reject_host;
625 } 646 }
626 host = (*i).first; // a transient reference that needs to be replaced before we return it 647 host = (*i).first; // a transient reference that needs to be replaced before we return it
627 ip = (*i).second; 648 ip = (*i).second;
638 snprintf(buf, sizeof(buf), "ns %s not found", host); 659 snprintf(buf, sizeof(buf), "ns %s not found", host);
639 } 660 }
640 my_syslog(&priv, buf); 661 my_syslog(&priv, buf);
641 } 662 }
642 if (ip) { 663 if (ip) {
643 status st = check_single(ip, dc.content_suffix); 664 int_set::iterator i = ips.find(ip);
644 if (st == reject) { 665 if (i == ips.end()) {
645 host = register_string(priv.memory->hosts, host); // put a copy into priv.memory->hosts, and return that reference 666 ips.insert(ip);
646 discard(nameservers); 667 status st = check_single(ip, dc.content_suffix);
647 return st; 668 if (st == reject) {
669 host = register_string(priv.memory->hosts, host); // put a copy into priv.memory->hosts, and return that reference
670 discard(nameservers);
671 return st;
672 }
648 } 673 }
649 } 674 }
650 } 675 }
651 discard(nameservers); 676 discard(nameservers);
652 host = NULL; 677 host = NULL;
881 if (dc.content_suffix) { 906 if (dc.content_suffix) {
882 fprintf(stdout, "\ncontent filtering enabled with %s %s\n", dc.content_suffix, dc.content_message); 907 fprintf(stdout, "\ncontent filtering enabled with %s %s\n", dc.content_suffix, dc.content_message);
883 } 908 }
884 if (dc.host_limit) { 909 if (dc.host_limit) {
885 fprintf(stdout, "\ncontent filtering for host names enabled with limit %d %s\n", dc.host_limit, dc.host_limit_message); 910 fprintf(stdout, "\ncontent filtering for host names enabled with limit %d %s\n", dc.host_limit, dc.host_limit_message);
911 }
912 if (dc.host_random) {
913 fprintf(stdout, "\nrandom selection of host names, host limit message is not used\n");
886 } 914 }
887 if (dc.tag_limit) { 915 if (dc.tag_limit) {
888 fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.tag_limit, dc.tag_limit_message); 916 fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.tag_limit, dc.tag_limit_message);
889 } 917 }
890 fprintf(stdout, "\nfiles\n"); 918 fprintf(stdout, "\nfiles\n");
994 my_syslog(buf); 1022 my_syslog(buf);
995 return; 1023 return;
996 } 1024 }
997 dc.config_files.push_back(fn); 1025 dc.config_files.push_back(fn);
998 map<char*, int, ltstr> commands; 1026 map<char*, int, ltstr> commands;
999 enum {dummy, tld, content, hostlimit, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc}; 1027 enum {dummy, tld, content, hostlimit, hostrandom, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc};
1000 commands["tld" ] = tld; 1028 commands["tld" ] = tld;
1001 commands["content" ] = content; 1029 commands["content" ] = content;
1002 commands["host_limit" ] = hostlimit; 1030 commands["host_limit" ] = hostlimit;
1031 commands["host_random"] = hostrandom;
1003 commands["html_limit" ] = htmllimit; 1032 commands["html_limit" ] = htmllimit;
1004 commands["html_tag" ] = htmltag; 1033 commands["html_tag" ] = htmltag;
1005 commands["dnsbl" ] = dnsbl; 1034 commands["dnsbl" ] = dnsbl;
1006 commands["dnsbl_list" ] = dnsbll; 1035 commands["dnsbl_list" ] = dnsbll;
1007 commands["env_from" ] = envfrom; 1036 commands["env_from" ] = envfrom;
1063 dc.host_limit = atoi(limit); 1092 dc.host_limit = atoi(limit);
1064 dc.host_limit_message = register_string(msg); 1093 dc.host_limit_message = register_string(msg);
1065 processed = true; 1094 processed = true;
1066 } break; 1095 } break;
1067 1096
1097 case hostrandom: {
1098 dc.host_random = true;
1099 processed = true;
1100 } break;
1101
1068 case htmllimit: { 1102 case htmllimit: {
1069 char *limit = strtok(NULL, delim); 1103 char *limit = strtok(NULL, delim);
1070 if (!limit) break; // no integer limit 1104 if (!limit) break; // no integer limit
1071 char *msg = limit + strlen(limit); 1105 char *msg = limit + strlen(limit);
1072 if ((msg - line) >= strlen(orig)) break; // line ended with the limit 1106 if ((msg - line) >= strlen(orig)) break; // line ended with the limit