comparison src/context.cpp @ 278:368572c57013

add limits on unique ip addresses per hour per authenticated user
author Carl Byington <carl@five-ten-sg.com>
date Tue, 17 Dec 2013 15:35:23 -0800
parents bdcf203e3f7b
children 802e2b779ed1
comparison
equal deleted inserted replaced
277:7163e9b04bdb 278:368572c57013
704 } 704 }
705 } 705 }
706 706
707 707
708 CONTEXT::CONTEXT(CONTEXTP parent_, const char *name_) { 708 CONTEXT::CONTEXT(CONTEXTP parent_, const char *name_) {
709 parent = parent_; 709 parent = parent_;
710 name = name_; 710 name = name_;
711 verify_host = NULL; 711 verify_host = NULL;
712 verifier = NULL; 712 verifier = NULL;
713 generic_regx = NULL; 713 generic_regx = NULL;
714 generic_message = NULL; 714 generic_message = NULL;
715 white_regx = NULL; 715 white_regx = NULL;
716 autowhite_file = NULL; 716 autowhite_file = NULL;
717 whitelister = NULL; 717 whitelister = NULL;
718 env_from_default = (parent) ? token_inherit : token_unknown; 718 env_from_default = (parent) ? token_inherit : token_unknown;
719 content_filtering = (parent) ? parent->content_filtering : false; 719 content_filtering = (parent) ? parent->content_filtering : false;
720 content_suffix = NULL; 720 content_suffix = NULL;
721 content_message = NULL; 721 content_message = NULL;
722 uribl_suffix = NULL; 722 uribl_suffix = NULL;
723 uribl_message = NULL; 723 uribl_message = NULL;
724 host_limit = (parent) ? parent->host_limit : 0; 724 host_limit = (parent) ? parent->host_limit : 0;
725 host_limit_message = NULL; 725 host_limit_message = NULL;
726 host_random = (parent) ? parent->host_random : false; 726 host_random = (parent) ? parent->host_random : false;
727 tag_limit = (parent) ? parent->tag_limit : 0; 727 tag_limit = (parent) ? parent->tag_limit : 0;
728 tag_limit_message = NULL; 728 tag_limit_message = NULL;
729 spamassassin_limit = (parent) ? parent->spamassassin_limit : 0; 729 spamassassin_limit = (parent) ? parent->spamassassin_limit : 0;
730 require_match = (parent) ? parent->require_match : false; 730 require_match = (parent) ? parent->require_match : false;
731 require_rdns = (parent) ? parent->require_rdns : false; 731 require_rdns = (parent) ? parent->require_rdns : false;
732 dcc_greylist = (parent) ? parent->dcc_greylist : false; 732 dcc_greylist = (parent) ? parent->dcc_greylist : false;
733 dcc_bulk_threshold = (parent) ? parent->dcc_bulk_threshold : 0; 733 dcc_bulk_threshold = (parent) ? parent->dcc_bulk_threshold : 0;
734 dnsbl_list_parsed = false; 734 dnsbl_list_parsed = false;
735 dnswl_list_parsed = false; 735 dnswl_list_parsed = false;
736 default_rcpt_rate = 36000; // 10 per second 736 default_rate_limit = 36000; // 10 per second
737 rcpt_daily_multiple = 3; 737 default_address_limit = 10;
738 daily_rate_multiple = 3;
739 daily_address_multiple = 3;
738 } 740 }
739 741
740 742
741 CONTEXT::~CONTEXT() { 743 CONTEXT::~CONTEXT() {
742 for (dnsblp_map::iterator i=dnsbl_names.begin(); i!=dnsbl_names.end(); i++) { 744 for (dnsblp_map::iterator i=dnsbl_names.begin(); i!=dnsbl_names.end(); i++) {
843 else 845 else
844 return NULL; 846 return NULL;
845 } 847 }
846 848
847 849
848 int CONTEXT::find_rate(const char *user) { 850 int CONTEXT::find_rate_limit(const char *user) {
849 if (rcpt_per_hour.empty()) return default_rcpt_rate; 851 if (rcpt_per_hour.empty()) return default_rate_limit;
850 rcpt_rates::iterator i = rcpt_per_hour.find(user); // look for authen id, or sender user@email limiting 852 rates::iterator i = rcpt_per_hour.find(user); // look for authen id, or sender user@email limiting
851 if (i != rcpt_per_hour.end()) return (*i).second; // found authen id, or user@email limiting 853 if (i != rcpt_per_hour.end()) return (*i).second; // found authen id, or user@email limiting
852 const char *f = strchr(user, '@'); 854 const char *f = strchr(user, '@');
853 if (!f) return default_rcpt_rate; 855 if (!f) return default_rate_limit;
854 i = rcpt_per_hour.find(f); // look for @domain limiting 856 i = rcpt_per_hour.find(f); // look for @domain limiting
855 if (i != rcpt_per_hour.end()) return (*i).second; // found @domain limiting 857 if (i != rcpt_per_hour.end()) return (*i).second; // found @domain limiting
856 return default_rcpt_rate; 858 return default_rate_limit;
859 }
860
861
862 int CONTEXT::find_address_limit(const char *user) {
863 if (addresses_per_hour.empty()) return default_address_limit;
864 rates::iterator i = addresses_per_hour.find(user); // look for authen id, or sender user@email limiting
865 if (i != addresses_per_hour.end()) return (*i).second; // found authen id, or user@email limiting
866 const char *f = strchr(user, '@');
867 if (!f) return default_address_limit;
868 i = addresses_per_hour.find(f); // look for @domain limiting
869 if (i != addresses_per_hour.end()) return (*i).second; // found @domain limiting
870 return default_address_limit;
857 } 871 }
858 872
859 873
860 bool CONTEXT::is_unauthenticated_limited(const char *user) { 874 bool CONTEXT::is_unauthenticated_limited(const char *user) {
861 rcpt_rates::iterator i = rcpt_per_hour.find(user); // look for sender user@email limiting 875 rates::iterator i = rcpt_per_hour.find(user); // look for sender user@email limiting
862 if (i != rcpt_per_hour.end()) return true; // found user@email limiting 876 if (i != rcpt_per_hour.end()) return true; // found user@email limiting
863 const char *f = strchr(user, '@'); 877 const char *f = strchr(user, '@');
864 if (!f) return false; 878 if (!f) return false;
865 i = rcpt_per_hour.find(f); // look for sender @domain limiting 879 i = rcpt_per_hour.find(f); // look for sender @domain limiting
866 return (i != rcpt_per_hour.end()); // found @domain limiting 880 return (i != rcpt_per_hour.end()); // found @domain limiting
1209 } 1223 }
1210 } 1224 }
1211 printf("%s }; \n", indent); 1225 printf("%s }; \n", indent);
1212 1226
1213 if (isdefault) { 1227 if (isdefault) {
1214 printf("%s rate_limit %d %d { \n", indent, default_rcpt_rate, rcpt_daily_multiple); 1228 printf("%s rate_limit %d %d %d %d { \n", indent, default_rate_limit, daily_rate_multiple, default_address_limit, daily_address_multiple);
1215 for (rcpt_rates::iterator j=rcpt_per_hour.begin(); j!=rcpt_per_hour.end(); j++) { 1229 for (rates::iterator j=rcpt_per_hour.begin(); j!=rcpt_per_hour.end(); j++) {
1216 const char *u = (*j).first; 1230 const char *u = (*j).first;
1217 int l = (*j).second; 1231 int l = (*j).second;
1218 printf("%s \"%s\" \t%d; \n", indent, u, l); 1232 rates::iterator k = addresses_per_hour.find(u);
1233 int a = (k==addresses_per_hour.end()) ? default_address_limit : (*k).second;
1234 printf("%s \"%s\" \t%d %d; \n", indent, u, l, a);
1219 } 1235 }
1220 printf("%s }; \n", indent); 1236 printf("%s }; \n", indent);
1221 } 1237 }
1222 1238
1223 printf("%s }; \n", indent); 1239 printf("%s }; \n", indent);
1751 1767
1752 //////////////////////////////////////////////// 1768 ////////////////////////////////////////////////
1753 // 1769 //
1754 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me); 1770 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me);
1755 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me) { 1771 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
1756 const char *def = tok.next(); 1772 me.set_default_rate_limit(tok.nextint());
1757 tok.push(def); 1773 me.set_daily_rate_multiple(tok.nextint());
1758 if (def != token_lbrace) me.set_default_rate(tok.nextint()); 1774 me.set_default_address_limit(tok.nextint());
1759 1775 me.set_daily_address_multiple(tok.nextint());
1760 def = tok.next();
1761 tok.push(def);
1762 if (def != token_lbrace) me.set_daily_multiple(tok.nextint());
1763
1764 if (!tsa(tok, token_lbrace)) return false; 1776 if (!tsa(tok, token_lbrace)) return false;
1765 while (true) { 1777 while (true) {
1766 const char *have = tok.next(); 1778 const char *have = tok.next();
1767 if (!have) break; 1779 if (!have) break;
1768 if (have == token_rbrace) break; 1780 if (have == token_rbrace) break;
1769 if (have == token_semi) { 1781 me.add_rate_limit(have, tok.nextint());
1770 // optional separators 1782 me.add_address_limit(have, tok.nextint());
1771 } 1783 if (!tsa(tok, token_semi)) return false;
1772 else {
1773 me.add_rate(have, tok.nextint());
1774 }
1775 } 1784 }
1776 return tsa(tok, token_semi); 1785 return tsa(tok, token_semi);
1777 } 1786 }
1778 1787
1779 1788