Mercurial > dnsbl
comparison src/dnsbl.cpp @ 178:d6531c702be3
embedded dcc filtering
author | carl |
---|---|
date | Thu, 04 Oct 2007 22:45:21 -0700 |
parents | a4d313c2460b |
children | 8b86a894514d |
comparison
equal
deleted
inserted
replaced
177:a4d313c2460b | 178:d6531c702be3 |
---|---|
253 authenticated = NULL; | 253 authenticated = NULL; |
254 client_name = NULL; | 254 client_name = NULL; |
255 have_whites = false; | 255 have_whites = false; |
256 only_whites = true; | 256 only_whites = true; |
257 want_spamassassin = false; | 257 want_spamassassin = false; |
258 want_dccgrey = false; | |
259 want_dccbulk = false; | |
260 content_context = NULL; | |
258 memory = NULL; | 261 memory = NULL; |
259 scanner = NULL; | 262 scanner = NULL; |
260 assassin = NULL; | |
261 content_suffix = NULL; | 263 content_suffix = NULL; |
262 content_message = NULL; | 264 content_message = NULL; |
263 uribl_suffix = NULL; | 265 uribl_suffix = NULL; |
264 uribl_message = NULL; | 266 uribl_message = NULL; |
265 content_host_ignore = NULL; | 267 content_host_ignore = NULL; |
268 assassin = NULL; | |
269 dccifd = NULL; | |
266 } | 270 } |
267 | 271 |
268 mlfiPriv::~mlfiPriv() { | 272 mlfiPriv::~mlfiPriv() { |
269 return_fd(); | 273 return_fd(); |
270 pthread_mutex_lock(&config_mutex); | 274 pthread_mutex_lock(&config_mutex); |
283 if (client_name) free(client_name); | 287 if (client_name) free(client_name); |
284 discard(env_to); | 288 discard(env_to); |
285 if (memory) delete memory; | 289 if (memory) delete memory; |
286 if (scanner) delete scanner; | 290 if (scanner) delete scanner; |
287 if (assassin) delete assassin; | 291 if (assassin) delete assassin; |
292 if (dccifd) delete dccifd; | |
288 if (!final) { | 293 if (!final) { |
289 mailaddr = NULL; | 294 mailaddr = NULL; |
290 queueid = NULL; | 295 queueid = NULL; |
291 authenticated = NULL; | 296 authenticated = NULL; |
292 client_name = NULL; | 297 client_name = NULL; |
293 have_whites = false; | 298 have_whites = false; |
294 only_whites = true; | 299 only_whites = true; |
295 want_spamassassin = false; | 300 want_spamassassin = false; |
301 want_dccgrey = false; | |
302 want_dccbulk = false; | |
303 content_context = NULL; | |
296 memory = NULL; | 304 memory = NULL; |
297 scanner = NULL; | 305 scanner = NULL; |
298 assassin = NULL; | |
299 content_suffix = NULL; | 306 content_suffix = NULL; |
300 content_message = NULL; | 307 content_message = NULL; |
301 uribl_suffix = NULL; | 308 uribl_suffix = NULL; |
302 uribl_message = NULL; | 309 uribl_message = NULL; |
303 content_host_ignore = NULL; | 310 content_host_ignore = NULL; |
311 assassin = NULL; | |
312 dccifd = NULL; | |
304 } | 313 } |
305 } | 314 } |
306 | 315 |
307 void mlfiPriv::get_fd() { | 316 void mlfiPriv::get_fd() { |
308 err = true; | 317 err = true; |
402 } | 411 } |
403 | 412 |
404 void mlfiPriv::need_content_filter(char *rcpt, CONTEXT &con) { | 413 void mlfiPriv::need_content_filter(char *rcpt, CONTEXT &con) { |
405 register_string(env_to, rcpt, &con); | 414 register_string(env_to, rcpt, &con); |
406 if (!memory) { | 415 if (!memory) { |
407 // first recipient that needs content filtering sets all | 416 // first recipient that needs content filtering sets |
408 // the content filtering parameters | 417 // some of the content filtering parameters |
409 memory = new recorder(this, con.get_html_tags(), con.get_content_tlds(), con.get_content_cctlds()); | 418 memory = new recorder(this, con.get_html_tags(), con.get_content_tlds(), con.get_content_cctlds()); |
410 scanner = new url_scanner(memory); | 419 scanner = new url_scanner(memory); |
411 content_suffix = con.get_content_suffix(); | 420 content_suffix = con.get_content_suffix(); |
412 content_message = con.get_content_message(); | 421 content_message = con.get_content_message(); |
413 uribl_suffix = con.get_uribl_suffix(); | 422 uribl_suffix = con.get_uribl_suffix(); |
716 | 725 |
717 //////////////////////////////////////////////// | 726 //////////////////////////////////////////////// |
718 // lookup the domain name part of a hostname on the uribl | 727 // lookup the domain name part of a hostname on the uribl |
719 // | 728 // |
720 // if we find part of the hostname on the uribl, return | 729 // if we find part of the hostname on the uribl, return |
721 // true and point found to the part of the hostname that we found. | 730 // true and point found to the part of the hostname that we found |
731 // as a string registered in hosts. | |
722 // otherwise, return false and preserve the value of found. | 732 // otherwise, return false and preserve the value of found. |
723 // | 733 // |
724 bool uriblookup(mlfiPriv &priv ,char *hostname, char *top, char *&found) ; | 734 bool uriblookup(mlfiPriv &priv, string_set &hosts, char *hostname, char *top, char *&found) ; |
725 bool uriblookup(mlfiPriv &priv, char *hostname, char *top, char *&found) { | 735 bool uriblookup(mlfiPriv &priv, string_set &hosts, char *hostname, char *top, char *&found) { |
726 // top is pointer to '.' char at end of base domain, or null for ip address form | 736 // top is pointer to '.' char at end of base domain, or null for ip address form |
727 // so for hostname of www.fred.mydomain.co.uk | 737 // so for hostname of www.fred.mydomain.co.uk |
728 // top points to-----------------------^ | 738 // top points to-----------------------^ |
729 // and we end up looking at only mydomain.co.uk, ignoring the www.fred stuff | 739 // and we end up looking at only mydomain.co.uk, ignoring the www.fred stuff |
730 char buf[maxlen]; | 740 char buf[maxlen]; |
740 if (debug_syslog > 2) { | 750 if (debug_syslog > 2) { |
741 char tmp[maxlen]; | 751 char tmp[maxlen]; |
742 snprintf(tmp, sizeof(tmp), "found %s on %s", hostname, priv.uribl_suffix); | 752 snprintf(tmp, sizeof(tmp), "found %s on %s", hostname, priv.uribl_suffix); |
743 my_syslog(tmp); | 753 my_syslog(tmp); |
744 } | 754 } |
745 found = hostname; | 755 found = register_string(hosts, hostname); |
746 return true; | 756 return true; |
747 } | 757 } |
748 return false; | 758 return false; |
749 } | 759 } |
750 | 760 |
755 // hostname MUST not have a trailing dot | 765 // hostname MUST not have a trailing dot |
756 // If tld, two level lookup. | 766 // If tld, two level lookup. |
757 // Else, look up three level domain. | 767 // Else, look up three level domain. |
758 // | 768 // |
759 // if we find part of the hostname on the uribl, return | 769 // if we find part of the hostname on the uribl, return |
760 // true and point found to the part of the hostname that we found. | 770 // true and point found to the part of the hostname that we found |
771 // as a string registered in hosts. | |
761 // otherwise, return false and preserve the value of found. | 772 // otherwise, return false and preserve the value of found. |
762 // | 773 // |
763 bool check_uribl(mlfiPriv &priv, char *hostname, char *&found) ; | 774 bool check_uribl(mlfiPriv &priv, string_set &hosts, char *hostname, char *&found) ; |
764 bool check_uribl(mlfiPriv &priv, char *hostname, char *&found) { | 775 bool check_uribl(mlfiPriv &priv, string_set &hosts, char *hostname, char *&found) { |
765 in_addr ip; | 776 in_addr ip; |
766 if (inet_aton(hostname, &ip)) { | 777 if (inet_aton(hostname, &ip)) { |
767 const u_char *src = (const u_char *)&ip.s_addr; | 778 const u_char *src = (const u_char *)&ip.s_addr; |
768 if (src[0] == 127) return false; // don't do dns lookups on localhost | 779 if (src[0] == 127) return false; // don't do dns lookups on localhost |
769 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space | 780 if (src[0] == 10) return false; // don't do dns lookups on rfc1918 space |
770 if ((src[0] == 192) && (src[1] == 168)) return false; | 781 if ((src[0] == 192) && (src[1] == 168)) return false; |
771 if ((src[0] == 172) && (16 <= src[1]) && (src[1] <= 31)) return false; | 782 if ((src[0] == 172) && (16 <= src[1]) && (src[1] <= 31)) return false; |
772 static char adr[sizeof "255.255.255.255"]; | 783 char adr[sizeof "255.255.255.255 "]; |
773 snprintf(adr, sizeof(adr), "%u.%u.%u.%u", src[3], src[2], src[1], src[0]); | 784 snprintf(adr, sizeof(adr), "%u.%u.%u.%u", src[3], src[2], src[1], src[0]); |
774 return (uriblookup(priv, adr, NULL, found)); | 785 return (uriblookup(priv, hosts, adr, NULL, found)); |
775 } | 786 } |
776 | 787 |
777 char *top, *top2, *top3; | 788 char *top, *top2, *top3; |
778 top = strrchr(hostname, '.'); | 789 top = strrchr(hostname, '.'); |
779 if (top) { | 790 if (top) { |
783 | 794 |
784 if (top2) { | 795 if (top2) { |
785 string_set::iterator i = priv.memory->get_cctlds()->find(top2+1); | 796 string_set::iterator i = priv.memory->get_cctlds()->find(top2+1); |
786 string_set::iterator x = priv.memory->get_cctlds()->end(); | 797 string_set::iterator x = priv.memory->get_cctlds()->end(); |
787 // if we have a 2-level-cctld, just look at top three levels of the name | 798 // if we have a 2-level-cctld, just look at top three levels of the name |
788 if (i != x) return uriblookup(priv, hostname, top2, found); | 799 if (i != x) return uriblookup(priv, hosts, hostname, top2, found); |
789 | 800 |
790 *top2 = '\0'; | 801 *top2 = '\0'; |
791 top3 = strrchr(hostname, '.'); | 802 top3 = strrchr(hostname, '.'); |
792 *top2 = '.'; | 803 *top2 = '.'; |
793 | 804 |
794 // if we have more than 3 levels in the name, look at the top three levels of the name | 805 // if we have more than 3 levels in the name, look at the top three levels of the name |
795 if (top3 && uriblookup(priv, hostname, top2, found)) return true; | 806 if (top3 && uriblookup(priv, hosts, hostname, top2, found)) return true; |
796 // if that was not found, fall thru to looking at the top two levels | 807 // if that was not found, fall thru to looking at the top two levels |
797 } | 808 } |
798 // look at the top two levels of the name | 809 // look at the top two levels of the name |
799 return uriblookup(priv, hostname, top, found); | 810 return uriblookup(priv, hosts, hostname, top, found); |
800 } | 811 } |
801 return false; | 812 return false; |
802 } | 813 } |
803 | 814 |
804 | 815 |
840 count++; | 851 count++; |
841 ip = dns_interface(priv, host, true, &nameservers); | 852 ip = dns_interface(priv, host, true, &nameservers); |
842 if (debug_syslog > 2) { | 853 if (debug_syslog > 2) { |
843 char buf[maxlen]; | 854 char buf[maxlen]; |
844 if (ip) { | 855 if (ip) { |
845 char adr[sizeof "255.255.255.255"]; | 856 char adr[sizeof "255.255.255.255 "]; |
846 adr[0] = '\0'; | 857 adr[0] = '\0'; |
847 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | 858 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); |
848 snprintf(buf, sizeof(buf), "host %s found at %s", host, adr); | 859 snprintf(buf, sizeof(buf), "host %s found at %s", host, adr); |
849 } | 860 } |
850 else { | 861 else { |
861 if (priv.content_suffix && check_single(priv, ip, priv.content_suffix)) { | 872 if (priv.content_suffix && check_single(priv, ip, priv.content_suffix)) { |
862 msg = priv.content_message; | 873 msg = priv.content_message; |
863 return true; | 874 return true; |
864 } | 875 } |
865 // Check uribl & surbl style list | 876 // Check uribl & surbl style list |
866 if (priv.uribl_suffix && check_uribl(priv, host, found)) { | 877 if (priv.uribl_suffix && check_uribl(priv, hosts, host, found)) { |
867 msg = priv.uribl_message; | 878 msg = priv.uribl_message; |
868 return true; | 879 return true; |
869 } | 880 } |
870 } | 881 } |
871 } | 882 } |
878 ip = (*i).second; | 889 ip = (*i).second; |
879 if (!ip) ip = dns_interface(priv, host, false, NULL); | 890 if (!ip) ip = dns_interface(priv, host, false, NULL); |
880 if (debug_syslog > 2) { | 891 if (debug_syslog > 2) { |
881 char buf[maxlen]; | 892 char buf[maxlen]; |
882 if (ip) { | 893 if (ip) { |
883 char adr[sizeof "255.255.255.255"]; | 894 char adr[sizeof "255.255.255.255 "]; |
884 adr[0] = '\0'; | 895 adr[0] = '\0'; |
885 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | 896 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); |
886 snprintf(buf, sizeof(buf), "ns %s found at %s", host, adr); | 897 snprintf(buf, sizeof(buf), "ns %s found at %s", host, adr); |
887 } | 898 } |
888 else { | 899 else { |
974 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); | 985 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); |
975 if (priv.client_name) priv.client_name = strdup(priv.client_name); | 986 if (priv.client_name) priv.client_name = strdup(priv.client_name); |
976 if (spamc != spamc_empty) { | 987 if (spamc != spamc_empty) { |
977 priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); | 988 priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); |
978 } | 989 } |
990 if (dccifd_port) { | |
991 priv.dccifd = new DccInterface(dccifd_port, &priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); | |
992 } | |
979 return SMFIS_CONTINUE; | 993 return SMFIS_CONTINUE; |
980 } | 994 } |
981 | 995 |
982 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) | 996 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) |
983 { | 997 { |
992 smfi_setreply(ctx, "550", "5.7.1", "bogus recipient"); | 1006 smfi_setreply(ctx, "550", "5.7.1", "bogus recipient"); |
993 return SMFIS_REJECT; | 1007 return SMFIS_REJECT; |
994 } | 1008 } |
995 | 1009 |
996 if (priv.assassin) priv.assassin->mlfi_envrcpt(ctx, loto); | 1010 if (priv.assassin) priv.assassin->mlfi_envrcpt(ctx, loto); |
1011 if (priv.dccifd) priv.dccifd->mlfi_envrcpt(loto); | |
997 // priv.mailaddr sending original message to loto | 1012 // priv.mailaddr sending original message to loto |
998 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); | 1013 CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); |
999 VERIFYP ver = con.find_verify(loto); | 1014 VERIFYP ver = con.find_verify(loto); |
1000 char *fromvalue = con.find_from(priv.mailaddr, true); | 1015 char *fromvalue = con.find_from(priv.mailaddr, true); |
1001 // loto sending a reply back to priv.mailaddr | 1016 // loto sending a reply back to priv.mailaddr |
1038 // check the dns based lists | 1053 // check the dns based lists |
1039 st = (check_dnsbl(priv, con.get_dnsbl_list(), rejectlist)) ? reject : oksofar; | 1054 st = (check_dnsbl(priv, con.get_dnsbl_list(), rejectlist)) ? reject : oksofar; |
1040 } | 1055 } |
1041 if (st == reject) { | 1056 if (st == reject) { |
1042 // reject the recipient based on some dnsbl | 1057 // reject the recipient based on some dnsbl |
1043 char adr[sizeof "255.255.255.255"]; | 1058 char adr[sizeof "255.255.255.255 "]; |
1044 adr[0] = '\0'; | 1059 adr[0] = '\0'; |
1045 inet_ntop(AF_INET, (const u_char *)&priv.ip, adr, sizeof(adr)); | 1060 inet_ntop(AF_INET, (const u_char *)&priv.ip, adr, sizeof(adr)); |
1046 char buf[maxlen]; | 1061 char buf[maxlen]; |
1047 snprintf(buf, sizeof(buf), rejectlist->message, adr, adr); | 1062 snprintf(buf, sizeof(buf), rejectlist->message, adr, adr); |
1048 smfi_setreply(ctx, "550", "5.7.1", buf); | 1063 smfi_setreply(ctx, "550", "5.7.1", buf); |
1087 w->sent(loto); // don't free it, the whitelister takes ownership of the string | 1102 w->sent(loto); // don't free it, the whitelister takes ownership of the string |
1088 } | 1103 } |
1089 else { | 1104 else { |
1090 free(loto); | 1105 free(loto); |
1091 } | 1106 } |
1107 // remember first content filtering context | |
1108 if (con.get_content_filtering()) { | |
1109 if (!priv.content_context) priv.content_context = &con; | |
1110 else if (con.get_require() && (priv.content_context != &con)) { | |
1111 smfi_setreply(ctx, "452", "4.2.1", "incompatible filtering contexts"); | |
1112 return SMFIS_TEMPFAIL; | |
1113 } | |
1114 } | |
1092 // accept the recipient | 1115 // accept the recipient |
1093 if (!con.get_content_filtering()) st = white; | 1116 if (!con.get_content_filtering()) st = white; |
1094 if (st == oksofar) { | 1117 if (st == oksofar) { |
1095 // but remember the non-whites | 1118 // but remember the non-whites |
1096 priv.need_content_filter(rcptaddr, con); | 1119 priv.need_content_filter(rcptaddr, con); |
1097 priv.only_whites = false; | 1120 priv.only_whites = false; |
1098 priv.want_spamassassin |= (priv.assassin) && // have spam assassin available and | 1121 priv.want_spamassassin |= (priv.assassin) && // have spam assassin available and |
1099 (con.get_spamassassin_limit() != 0); // want to use it with a non-zero score | 1122 (con.get_spamassassin_limit() != 0); // want to use it with a non-zero score |
1123 priv.want_dccgrey |= (priv.dccifd) && // have dcc interface and | |
1124 (con.get_grey()); // want to use it for greylisting | |
1125 priv.want_dccbulk |= (priv.dccifd) && // have dcc interface and | |
1126 (con.get_bulk() != 0); // want to use it for bulk detection | |
1100 } | 1127 } |
1101 if (st == white) { | 1128 if (st == white) { |
1102 priv.have_whites = true; | 1129 priv.have_whites = true; |
1103 } | 1130 } |
1104 return SMFIS_CONTINUE; | 1131 return SMFIS_CONTINUE; |
1108 { | 1135 { |
1109 mlfiPriv &priv = *MLFIPRIV; | 1136 mlfiPriv &priv = *MLFIPRIV; |
1110 if (priv.authenticated) return SMFIS_CONTINUE; | 1137 if (priv.authenticated) return SMFIS_CONTINUE; |
1111 if (priv.only_whites) return SMFIS_CONTINUE; | 1138 if (priv.only_whites) return SMFIS_CONTINUE; |
1112 if (priv.want_spamassassin) priv.assassin->mlfi_header(headerf, headerv); | 1139 if (priv.want_spamassassin) priv.assassin->mlfi_header(headerf, headerv); |
1140 if (priv.want_dccgrey || priv.want_dccbulk) priv.dccifd->mlfi_header(ctx, headerf, headerv); | |
1113 return SMFIS_CONTINUE; | 1141 return SMFIS_CONTINUE; |
1114 } | 1142 } |
1115 | 1143 |
1116 sfsistat mlfi_eoh(SMFICTX* ctx) | 1144 sfsistat mlfi_eoh(SMFICTX* ctx) |
1117 { | 1145 { |
1118 mlfiPriv &priv = *MLFIPRIV; | 1146 mlfiPriv &priv = *MLFIPRIV; |
1119 if (priv.authenticated) return SMFIS_CONTINUE; | 1147 if (priv.authenticated) return SMFIS_CONTINUE; |
1120 if (priv.only_whites) return SMFIS_CONTINUE; | 1148 if (priv.only_whites) return SMFIS_CONTINUE; |
1121 if (priv.want_spamassassin) priv.assassin->mlfi_eoh(); | 1149 if (priv.want_spamassassin) priv.assassin->mlfi_eoh(); |
1150 if (priv.want_dccgrey || priv.want_dccbulk) priv.dccifd->mlfi_eoh(); | |
1122 return SMFIS_CONTINUE; | 1151 return SMFIS_CONTINUE; |
1123 } | 1152 } |
1124 | 1153 |
1125 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len) | 1154 sfsistat mlfi_body(SMFICTX *ctx, u_char *data, size_t len) |
1126 { | 1155 { |
1127 mlfiPriv &priv = *MLFIPRIV; | 1156 mlfiPriv &priv = *MLFIPRIV; |
1128 if (priv.authenticated) return SMFIS_CONTINUE; | 1157 if (priv.authenticated) return SMFIS_CONTINUE; |
1129 if (priv.only_whites) return SMFIS_CONTINUE; | 1158 if (priv.only_whites) return SMFIS_CONTINUE; |
1130 if (priv.want_spamassassin) priv.assassin->mlfi_body(data, len); | 1159 if (priv.want_spamassassin) priv.assassin->mlfi_body(data, len); |
1160 if (priv.want_dccgrey || priv.want_dccbulk) priv.dccifd->mlfi_body(data, len); | |
1131 priv.scanner->scan(data, len); | 1161 priv.scanner->scan(data, len); |
1132 return SMFIS_CONTINUE; | 1162 return SMFIS_CONTINUE; |
1133 } | 1163 } |
1134 | 1164 |
1135 sfsistat mlfi_eom(SMFICTX *ctx) | 1165 sfsistat mlfi_eom(SMFICTX *ctx) |
1141 int ip; | 1171 int ip; |
1142 status st; | 1172 status st; |
1143 // process end of message | 1173 // process end of message |
1144 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; | 1174 if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; |
1145 else { | 1175 else { |
1176 // assert env_to not empty, it contains the | |
1177 // non-whitelisted folks that want content filtering | |
1146 int score = (priv.want_spamassassin) ? priv.assassin->mlfi_eom() : 0; | 1178 int score = (priv.want_spamassassin) ? priv.assassin->mlfi_eom() : 0; |
1147 // assert env_to not empty | 1179 bool greylist = false; |
1148 char buf[maxlen]; | 1180 int dccbulk = 0; |
1149 string msg; | 1181 if (priv.want_dccgrey || priv.want_dccbulk) priv.dccifd->mlfi_eom(greylist, dccbulk); |
1150 string_set alive; | 1182 |
1151 bool random = false; | 1183 if (priv.want_dccgrey && greylist) { |
1152 int limit = 0; | 1184 smfi_setreply(ctx, "452", "4.2.1", "temporary greylist embargoed"); |
1153 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { | 1185 rc = SMFIS_TEMPFAIL; |
1154 char *rcpt = (*i).first; | 1186 } |
1155 CONTEXT &con = *((*i).second); | 1187 else { |
1156 if (!con.acceptable_content(*priv.memory, score, msg)) { | 1188 char buf[maxlen]; |
1157 // bad html tags or excessive hosts or high spam assassin score | 1189 string msg; |
1158 smfi_delrcpt(ctx, rcpt); | 1190 string_set alive; |
1191 bool random = false; | |
1192 int limit = 0; | |
1193 for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { | |
1194 char *rcpt = (*i).first; | |
1195 CONTEXT &con = *((*i).second); | |
1196 if (!con.acceptable_content(*priv.memory, score, dccbulk, msg)) { | |
1197 // bad html tags or excessive hosts or | |
1198 // high spam assassin score or dcc bulk threshold exceedeed | |
1199 smfi_delrcpt(ctx, rcpt); | |
1200 } | |
1201 else { | |
1202 alive.insert(rcpt); | |
1203 random |= con.get_host_random(); | |
1204 limit = max(limit, con.get_host_limit()); | |
1205 } | |
1206 } | |
1207 bool rejecting = alive.empty(); // if alive is empty, we must have set msg above in acceptable_content() | |
1208 if (!rejecting) { | |
1209 char *fmt, *found; | |
1210 if (check_hosts(priv, random, limit, fmt, host, ip, found)) { | |
1211 if (found) { | |
1212 // uribl style | |
1213 snprintf(buf, sizeof(buf), fmt, host, found); | |
1214 } | |
1215 else { | |
1216 // dnsbl style | |
1217 char adr[sizeof "255.255.255.255 "]; | |
1218 adr[0] = '\0'; | |
1219 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | |
1220 snprintf(buf, sizeof(buf), fmt, host, adr); | |
1221 } | |
1222 msg = string(buf); | |
1223 rejecting = true; | |
1224 } | |
1225 } | |
1226 if (!rejecting) { | |
1227 rc = SMFIS_CONTINUE; | |
1228 } | |
1229 else if (!priv.have_whites) { | |
1230 // can reject the entire message | |
1231 snprintf(buf, sizeof(buf), "%s", msg.c_str()); | |
1232 smfi_setreply(ctx, "550", "5.7.1", buf); | |
1233 rc = SMFIS_REJECT; | |
1159 } | 1234 } |
1160 else { | 1235 else { |
1161 alive.insert(rcpt); | 1236 // need to accept it but remove the recipients that don't want it |
1162 random |= con.get_host_random(); | 1237 for (string_set::iterator i=alive.begin(); i!=alive.end(); i++) { |
1163 limit = max(limit, con.get_host_limit()); | 1238 char *rcpt = *i; |
1164 } | 1239 smfi_delrcpt(ctx, rcpt); |
1165 } | 1240 } |
1166 bool rejecting = alive.empty(); // if alive is empty, we must have set msg above in acceptable_content() | 1241 rc = SMFIS_CONTINUE; |
1167 if (!rejecting) { | 1242 } |
1168 char *fmt, *found; | |
1169 if (check_hosts(priv, random, limit, fmt, host, ip, found)) { | |
1170 if (found) { | |
1171 // uribl style | |
1172 snprintf(buf, sizeof(buf), fmt, host, found); | |
1173 } | |
1174 else { | |
1175 // dnsbl style | |
1176 char adr[sizeof "255.255.255.255"]; | |
1177 adr[0] = '\0'; | |
1178 inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); | |
1179 snprintf(buf, sizeof(buf), fmt, host, adr); | |
1180 } | |
1181 msg = string(buf); | |
1182 rejecting = true; | |
1183 } | |
1184 } | |
1185 if (!rejecting) { | |
1186 rc = SMFIS_CONTINUE; | |
1187 } | |
1188 else if (!priv.have_whites) { | |
1189 // can reject the entire message | |
1190 snprintf(buf, sizeof(buf), "%s", msg.c_str()); | |
1191 smfi_setreply(ctx, "550", "5.7.1", buf); | |
1192 rc = SMFIS_REJECT; | |
1193 } | |
1194 else { | |
1195 // need to accept it but remove the recipients that don't want it | |
1196 for (string_set::iterator i=alive.begin(); i!=alive.end(); i++) { | |
1197 char *rcpt = *i; | |
1198 smfi_delrcpt(ctx, rcpt); | |
1199 } | |
1200 rc = SMFIS_CONTINUE; | |
1201 } | 1243 } |
1202 } | 1244 } |
1203 // reset for a new message on the same connection | 1245 // reset for a new message on the same connection |
1204 mlfi_abort(ctx); | 1246 mlfi_abort(ctx); |
1205 return rc; | 1247 return rc; |