Mercurial > dnsbl
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 |