Mercurial > dnsbl
comparison src/dnsbl.cpp @ 27:43a4f6b3e668 stable-2-3
add configurable host name limit and bad html tag limits.
author | carl |
---|---|
date | Sat, 22 May 2004 22:30:45 -0700 |
parents | fdae7ab30cfc |
children | 33e1e3910506 |
comparison
equal
deleted
inserted
replaced
26:fdae7ab30cfc | 27:43a4f6b3e668 |
---|---|
66 #define WHITE "white" | 66 #define WHITE "white" |
67 #define BLACK "black" | 67 #define BLACK "black" |
68 #define OK "ok" | 68 #define OK "ok" |
69 #define MANY "many" | 69 #define MANY "many" |
70 | 70 |
71 enum status {oksofar, // not rejected yet | 71 enum status {oksofar, // not rejected yet |
72 white, // whitelisted by envelope from | 72 white, // whitelisted by envelope from |
73 black, // blacklisted by envelope from or to | 73 black, // blacklisted by envelope from or to |
74 reject}; // rejected by a dns list | 74 reject, // rejected by a dns list |
75 reject_tag, // too many bad html tags | |
76 reject_host}; // too many hosts/urls in body | |
75 | 77 |
76 using namespace std; | 78 using namespace std; |
77 | 79 |
78 extern "C" { | 80 extern "C" { |
79 #include "libmilter/mfapi.h" | 81 #include "libmilter/mfapi.h" |
123 from_map env_from; | 125 from_map env_from; |
124 string_map env_to_dnsbll; // map recipient to a named dnsbll | 126 string_map env_to_dnsbll; // map recipient to a named dnsbll |
125 string_map env_to_chkfrom; // map recipient to a named from map | 127 string_map env_to_chkfrom; // map recipient to a named from map |
126 char * content_suffix; // for sbl url body filtering | 128 char * content_suffix; // for sbl url body filtering |
127 char * content_message; // "" | 129 char * content_message; // "" |
128 char * limit_message; // error message for excessive bad html tags | 130 char * host_limit_message; // error message for excessive host names |
129 int bad_tag_limit; // limit on bad html tags | 131 int host_limit; // limit on host names |
132 char * tag_limit_message; // error message for excessive bad html tags | |
133 int tag_limit; // limit on bad html tags | |
130 string_set html_tags; // set of valid html tags | 134 string_set html_tags; // set of valid html tags |
131 CONFIG(); | 135 CONFIG(); |
132 ~CONFIG(); | 136 ~CONFIG(); |
133 }; | 137 }; |
134 CONFIG::CONFIG() { | 138 CONFIG::CONFIG() { |
135 reference_count = 0; | 139 reference_count = 0; |
136 load_time = 0; | 140 load_time = 0; |
137 content_suffix = NULL; | 141 content_suffix = NULL; |
138 content_message = NULL; | 142 content_message = NULL; |
139 limit_message = NULL; | 143 host_limit_message = NULL; |
140 bad_tag_limit = 0; | 144 host_limit = 0; |
145 tag_limit_message = NULL; | |
146 tag_limit = 0; | |
141 } | 147 } |
142 CONFIG::~CONFIG() { | 148 CONFIG::~CONFIG() { |
143 for (dnsblp_map::iterator i=dnsbls.begin(); i!=dnsbls.end(); i++) { | 149 for (dnsblp_map::iterator i=dnsbls.begin(); i!=dnsbls.end(); i++) { |
144 DNSBLP d = (*i).second; | 150 DNSBLP d = (*i).second; |
145 // delete the underlying DNSBL objects. | 151 // delete the underlying DNSBL objects. |
481 CONFIG &dc = *priv.pc; | 487 CONFIG &dc = *priv.pc; |
482 if (!dc.content_suffix) return oksofar; | 488 if (!dc.content_suffix) return oksofar; |
483 int count = 0; | 489 int count = 0; |
484 for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) { | 490 for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) { |
485 count++; | 491 count++; |
486 if (count > 20) return oksofar; // silly to check too many hosts | 492 int lim = priv.pc->host_limit; |
493 if ((count > lim) && (lim > 0)) return reject_host; | |
487 host = *i; | 494 host = *i; |
488 if (debug_syslog) { | 495 if (debug_syslog) { |
489 char buf[200]; | 496 char buf[200]; |
490 snprintf(buf, sizeof(buf), "looking for host %s", host); | 497 snprintf(buf, sizeof(buf), "looking for host %s", host); |
491 my_syslog(buf); | 498 my_syslog(buf); |
492 } | 499 } |
493 ip = protected_dns_interface(host, true); | 500 ip = protected_dns_interface(host, true); |
494 if (ip) { | 501 if (ip) { |
495 if (debug_syslog) { | 502 // if (debug_syslog) { |
496 char adr[sizeof "255.255.255.255"]; | 503 // char adr[sizeof "255.255.255.255"]; |
497 adr[0] = '\0'; | 504 // adr[0] = '\0'; |
498 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | 505 // inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); |
499 char buf[200]; | 506 // char buf[200]; |
500 snprintf(buf, sizeof(buf), "found host %s at %s", host, adr); | 507 // snprintf(buf, sizeof(buf), "found host %s at %s", host, adr); |
501 my_syslog(buf); | 508 // my_syslog(buf); |
502 } | 509 // } |
503 status st = check_single(ip, dc.content_suffix); | 510 status st = check_single(ip, dc.content_suffix); |
504 if (st == reject) return st; | 511 if (st == reject) return st; |
505 } | 512 } |
506 } | 513 } |
507 host = NULL; | 514 host = NULL; |
508 int bin = priv.memory->binary_tags; | 515 int bin = priv.memory->binary_tags; |
509 int bad = priv.memory->bad_html_tags; | 516 int bad = priv.memory->bad_html_tags; |
510 int lim = priv.pc->bad_tag_limit; | 517 int lim = priv.pc->tag_limit; |
511 if (bin > bad) return oksofar; // probably .zip or .tar.gz with random content | 518 if (bin > bad) return oksofar; // probably .zip or .tar.gz with random content |
512 if ((bad > lim) && (lim > 0)) return reject; | 519 if ((bad > lim) && (lim > 0)) return reject_tag; |
513 return oksofar; | 520 return oksofar; |
514 } | 521 } |
515 | 522 |
516 | 523 |
517 //////////////////////////////////////////////// | 524 //////////////////////////////////////////////// |
612 return SMFIS_CONTINUE; | 619 return SMFIS_CONTINUE; |
613 } | 620 } |
614 | 621 |
615 sfsistat mlfi_eom(SMFICTX *ctx) | 622 sfsistat mlfi_eom(SMFICTX *ctx) |
616 { | 623 { |
617 sfsistat rc; | 624 sfsistat rc; |
618 mlfiPriv &priv = *MLFIPRIV; | 625 mlfiPriv &priv = *MLFIPRIV; |
619 char *host = NULL; | 626 char *host = NULL; |
620 int ip; | 627 int ip; |
628 status st; | |
621 // process end of message | 629 // process end of message |
622 if (priv.authenticated || | 630 if (priv.authenticated || |
623 priv.only_whites || | 631 priv.only_whites || |
624 (check_hosts(priv, host, ip) == oksofar)) rc = SMFIS_CONTINUE; | 632 ((st=check_hosts(priv, host, ip)) == oksofar)) rc = SMFIS_CONTINUE; |
625 else { | 633 else { |
626 if (!priv.have_whites) { | 634 if (!priv.have_whites) { |
627 // can reject the entire message | 635 // can reject the entire message |
628 char buf[2000]; | 636 char buf[2000]; |
629 if (!host) { | 637 if (st == reject_tag) { |
630 // must be rejected due to excessive bad html tags | 638 // rejected due to excessive bad html tags |
631 snprintf(buf, sizeof(buf), priv.pc->limit_message); | 639 snprintf(buf, sizeof(buf), priv.pc->tag_limit_message); |
640 } | |
641 else if (st == reject_host) { | |
642 // rejected due to excessive unique host/urls | |
643 snprintf(buf, sizeof(buf), priv.pc->host_limit_message); | |
632 } | 644 } |
633 else { | 645 else { |
634 char adr[sizeof "255.255.255.255"]; | 646 char adr[sizeof "255.255.255.255"]; |
635 adr[0] = '\0'; | 647 adr[0] = '\0'; |
636 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | 648 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); |
728 fprintf(stdout, "\n"); | 740 fprintf(stdout, "\n"); |
729 } | 741 } |
730 if (dc.content_suffix) { | 742 if (dc.content_suffix) { |
731 fprintf(stdout, "\ncontent filtering enabled with %s %s\n", dc.content_suffix, dc.content_message); | 743 fprintf(stdout, "\ncontent filtering enabled with %s %s\n", dc.content_suffix, dc.content_message); |
732 } | 744 } |
733 if (dc.bad_tag_limit) { | 745 if (dc.host_limit) { |
734 fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.bad_tag_limit, dc.limit_message); | 746 fprintf(stdout, "\ncontent filtering for host names enabled with limit %d %s\n", dc.host_limit, dc.host_limit_message); |
747 } | |
748 if (dc.tag_limit) { | |
749 fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.tag_limit, dc.tag_limit_message); | |
735 } | 750 } |
736 fprintf(stdout, "\nfiles\n"); | 751 fprintf(stdout, "\nfiles\n"); |
737 for (string_list::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) { | 752 for (string_list::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) { |
738 char *f = *i; | 753 char *f = *i; |
739 fprintf(stdout, "config includes %s\n", f); | 754 fprintf(stdout, "config includes %s\n", f); |
828 | 843 |
829 static void load_conf(CONFIG &dc, char *fn); | 844 static void load_conf(CONFIG &dc, char *fn); |
830 static void load_conf(CONFIG &dc, char *fn) { | 845 static void load_conf(CONFIG &dc, char *fn) { |
831 dc.config_files.push_back(fn); | 846 dc.config_files.push_back(fn); |
832 map<char*, int, ltstr> commands; | 847 map<char*, int, ltstr> commands; |
833 enum {dummy, content, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc}; | 848 enum {dummy, content, hostlimit, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc}; |
834 commands["content" ] = content; | 849 commands["content" ] = content; |
850 commands["host_limit" ] = hostlimit; | |
835 commands["html_limit" ] = htmllimit; | 851 commands["html_limit" ] = htmllimit; |
836 commands["html_tag" ] = htmltag; | 852 commands["html_tag" ] = htmltag; |
837 commands["dnsbl" ] = dnsbl; | 853 commands["dnsbl" ] = dnsbl; |
838 commands["dnsbl_list" ] = dnsbll; | 854 commands["dnsbl_list" ] = dnsbll; |
839 commands["env_from" ] = envfrom; | 855 commands["env_from" ] = envfrom; |
873 dc.content_suffix = register_string(suff); | 889 dc.content_suffix = register_string(suff); |
874 dc.content_message = register_string(msg); | 890 dc.content_message = register_string(msg); |
875 processed = true; | 891 processed = true; |
876 } break; | 892 } break; |
877 | 893 |
894 case hostlimit: { | |
895 char *limit = strtok(NULL, delim); | |
896 if (!limit) break; // no integer limit | |
897 char *msg = limit + strlen(limit); | |
898 if ((msg - line) >= strlen(orig)) break; // line ended with the limit | |
899 msg = strchr(msg+1, '\''); | |
900 if (!msg) break; // no reply message template | |
901 msg++; // move over the leading ' | |
902 if ((msg - line) >= strlen(orig)) break; // line ended with the leading quote | |
903 char *last = strchr(msg, '\''); | |
904 if (!last) break; // no trailing quote | |
905 *last = '\0'; // make it a null terminator | |
906 dc.host_limit = atoi(limit); | |
907 dc.host_limit_message = register_string(msg); | |
908 processed = true; | |
909 } break; | |
910 | |
878 case htmllimit: { | 911 case htmllimit: { |
879 char *limit = strtok(NULL, delim); | 912 char *limit = strtok(NULL, delim); |
880 if (!limit) break; // no integer limit | 913 if (!limit) break; // no integer limit |
881 char *msg = limit + strlen(limit); | 914 char *msg = limit + strlen(limit); |
882 if ((msg - line) >= strlen(orig)) break; // line ended with the limit | 915 if ((msg - line) >= strlen(orig)) break; // line ended with the limit |
885 msg++; // move over the leading ' | 918 msg++; // move over the leading ' |
886 if ((msg - line) >= strlen(orig)) break; // line ended with the leading quote | 919 if ((msg - line) >= strlen(orig)) break; // line ended with the leading quote |
887 char *last = strchr(msg, '\''); | 920 char *last = strchr(msg, '\''); |
888 if (!last) break; // no trailing quote | 921 if (!last) break; // no trailing quote |
889 *last = '\0'; // make it a null terminator | 922 *last = '\0'; // make it a null terminator |
890 dc.bad_tag_limit = atoi(limit); | 923 dc.tag_limit = atoi(limit); |
891 dc.limit_message = register_string(msg); | 924 dc.tag_limit_message = register_string(msg); |
892 processed = true; | 925 processed = true; |
893 } break; | 926 } break; |
894 | 927 |
895 case htmltag: { | 928 case htmltag: { |
896 char *tag = next_token(delim); | 929 char *tag = next_token(delim); |
897 if (!tag) break; // no html tag value | 930 if (!tag) break; // no html tag value |
931 dc.html_tags.insert(tag); // base version | |
898 char buf[200]; | 932 char buf[200]; |
899 snprintf(buf, sizeof(buf), "/%s", tag); | 933 snprintf(buf, sizeof(buf), "/%s", tag); |
900 dc.html_tags.insert(tag); | 934 dc.html_tags.insert(register_string(buf)); // leading / |
901 dc.html_tags.insert(register_string(buf)); | 935 snprintf(buf, sizeof(buf), "%s/", tag); |
936 dc.html_tags.insert(register_string(buf)); // trailing / | |
902 processed = true; | 937 processed = true; |
903 } break; | 938 } break; |
904 | 939 |
905 case dnsbl: { | 940 case dnsbl: { |
906 // have a new dnsbl to use | 941 // have a new dnsbl to use |