comparison src/dnsbl.cpp @ 136:f4746d8a12a3

add smtp auth rate limits
author carl
date Tue, 26 Sep 2006 13:59:14 -0700
parents f9917ce924a3
children a6190f7798f4
comparison
equal deleted inserted replaced
135:8e813497582e 136:f4746d8a12a3
84 84
85 pthread_mutex_t config_mutex; 85 pthread_mutex_t config_mutex;
86 pthread_mutex_t syslog_mutex; 86 pthread_mutex_t syslog_mutex;
87 pthread_mutex_t resolve_mutex; 87 pthread_mutex_t resolve_mutex;
88 pthread_mutex_t fd_pool_mutex; 88 pthread_mutex_t fd_pool_mutex;
89 pthread_mutex_t rate_mutex;
89 90
90 std::set<int> fd_pool; 91 std::set<int> fd_pool;
91 int NULL_SOCKET = -1; 92 int NULL_SOCKET = -1;
92 const time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open a socket to the dns resolver process 93 const time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open a socket to the dns resolver process
93 char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process 94 char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process
94 int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests 95 int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests
95 time_t last_error_time; 96 time_t last_error_time;
96 int resolver_sock_count = 0; // protected with fd_pool_mutex 97 int resolver_sock_count = 0; // protected with fd_pool_mutex
97 int resolver_pool_size = 0; // protected with fd_pool_mutex 98 int resolver_pool_size = 0; // protected with fd_pool_mutex
99 rcpt_rates rcpt_counts; // protected with rate_mutex
98 100
99 101
100 struct ns_map { 102 struct ns_map {
101 // all the strings are owned by the keys/values in the ns_host string map 103 // all the strings are owned by the keys/values in the ns_host string map
102 string_map ns_host; // nameserver name -> host name that uses this name server 104 string_map ns_host; // nameserver name -> host name that uses this name server
137 #else 139 #else
138 int answer; // without a resolver, we return a single ip4 address, 0 == no answer 140 int answer; // without a resolver, we return a single ip4 address, 0 == no answer
139 #endif 141 #endif
140 } __attribute__ ((packed)); 142 } __attribute__ ((packed));
141 143
144
145 ////////////////////////////////////////////////
146 // helper to manipulate recipient counts
147 //
148 int incr_rcpt_count(char *user);
149 int incr_rcpt_count(char *user) {
150 pthread_mutex_lock(&rate_mutex);
151 rcpt_rates::iterator i = rcpt_counts.find(user);
152 int c = (i == rcpt_counts.end()) ? 0 : (*i).second;
153 rcpt_counts[user] = c++;
154 pthread_mutex_unlock(&rate_mutex);
155 return c;
156 }
142 157
143 //////////////////////////////////////////////// 158 ////////////////////////////////////////////////
144 // helper to discard the strings held by a context_map 159 // helper to discard the strings held by a context_map
145 // 160 //
146 void discard(context_map &cm); 161 void discard(context_map &cm);
222 pthread_mutex_unlock(&config_mutex); 237 pthread_mutex_unlock(&config_mutex);
223 get_fd(); 238 get_fd();
224 ip = 0; 239 ip = 0;
225 mailaddr = NULL; 240 mailaddr = NULL;
226 queueid = NULL; 241 queueid = NULL;
227 authenticated = false; 242 authenticated = NULL;
228 have_whites = false; 243 have_whites = false;
229 only_whites = true; 244 only_whites = true;
230 memory = NULL; 245 memory = NULL;
231 scanner = NULL; 246 scanner = NULL;
232 content_suffix = NULL; 247 content_suffix = NULL;
243 pthread_mutex_unlock(&config_mutex); 258 pthread_mutex_unlock(&config_mutex);
244 reset(true); 259 reset(true);
245 } 260 }
246 261
247 void mlfiPriv::reset(bool final) { 262 void mlfiPriv::reset(bool final) {
248 if (mailaddr) free(mailaddr); 263 if (mailaddr) free(mailaddr);
249 if (queueid) free(queueid); 264 if (queueid) free(queueid);
265 if (authenticated) free(authenticated);
250 discard(env_to); 266 discard(env_to);
251 if (memory) delete memory; 267 if (memory) delete memory;
252 if (scanner) delete scanner; 268 if (scanner) delete scanner;
253 if (!final) { 269 if (!final) {
254 mailaddr = NULL; 270 mailaddr = NULL;
255 queueid = NULL; 271 queueid = NULL;
256 authenticated = false; 272 authenticated = NULL;
257 have_whites = false; 273 have_whites = false;
258 only_whites = true; 274 only_whites = true;
259 memory = NULL; 275 memory = NULL;
260 scanner = NULL; 276 scanner = NULL;
261 content_suffix = NULL; 277 content_suffix = NULL;
910 926
911 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from) 927 sfsistat mlfi_envfrom(SMFICTX *ctx, char **from)
912 { 928 {
913 mlfiPriv &priv = *MLFIPRIV; 929 mlfiPriv &priv = *MLFIPRIV;
914 priv.mailaddr = to_lower_string(from[0]); 930 priv.mailaddr = to_lower_string(from[0]);
915 priv.authenticated = (smfi_getsymval(ctx, "{auth_authen}") != NULL); 931 priv.authenticated = smfi_getsymval(ctx, "{auth_authen}");
932 if (priv.authenticated) priv.authenticated = strdup(priv.authenticated);
916 return SMFIS_CONTINUE; 933 return SMFIS_CONTINUE;
917 } 934 }
918 935
919 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt) 936 sfsistat mlfi_envrcpt(SMFICTX *ctx, char **rcpt)
920 { 937 {
934 } 951 }
935 free(loto); 952 free(loto);
936 char *fromvalue = con.find_from(priv.mailaddr); 953 char *fromvalue = con.find_from(priv.mailaddr);
937 status st; 954 status st;
938 if (priv.authenticated) { 955 if (priv.authenticated) {
939 st = white; 956 int c = incr_rcpt_count(priv.authenticated);
957 int l = dc.default_context->find_rate(priv.authenticated);
958 if (c > l) {
959 smfi_setreply(ctx, "550", "5.7.1", "recipient rate limit exceeded");
960 return SMFIS_REJECT;
961 }
962 else {
963 if (debug_syslog > 1) {
964 char buf[maxlen];
965 char msg[maxlen];
966 snprintf(msg, sizeof(msg), "authenticated id %s (%d recipients, %d limit)", priv.authenticated, c, l);
967 my_syslog(&priv, msg);
968 }
969 st = white;
970 }
940 } 971 }
941 else if (fromvalue == token_black) { 972 else if (fromvalue == token_black) {
942 st = black; 973 st = black;
943 } 974 }
944 else if (fromvalue == token_white) { 975 else if (fromvalue == token_white) {
1125 1156
1126 //////////////////////////////////////////////// 1157 ////////////////////////////////////////////////
1127 // thread to watch the old config files for changes 1158 // thread to watch the old config files for changes
1128 // and reload when needed. we also cleanup old 1159 // and reload when needed. we also cleanup old
1129 // configs whose reference count has gone to zero. 1160 // configs whose reference count has gone to zero.
1161 // we also clear the SMTP AUTH recipient counts hourly
1130 // 1162 //
1131 void* config_loader(void *arg); 1163 void* config_loader(void *arg);
1132 void* config_loader(void *arg) { 1164 void* config_loader(void *arg) {
1165 int loop = 0;
1133 typedef set<CONFIG *> configp_set; 1166 typedef set<CONFIG *> configp_set;
1134 configp_set old_configs; 1167 configp_set old_configs;
1135 while (loader_run) { 1168 while (loader_run) {
1136 sleep(180); // look for modifications every 3 minutes 1169 sleep(180); // look for modifications every 3 minutes
1137 if (!loader_run) break; 1170 if (!loader_run) break;
1171 loop++;
1172 if (loop == 20) {
1173 // three minutes thru each loop, 20 loops per hour
1174 // clear the recipient counts
1175 pthread_mutex_lock(&rate_mutex);
1176 rcpt_counts.clear();
1177 pthread_mutex_unlock(&rate_mutex);
1178 }
1138 CONFIG &dc = *config; 1179 CONFIG &dc = *config;
1139 time_t then = dc.load_time; 1180 time_t then = dc.load_time;
1140 struct stat st; 1181 struct stat st;
1141 bool reload = false; 1182 bool reload = false;
1142 for (string_set::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) { 1183 for (string_set::iterator i=dc.config_files.begin(); i!=dc.config_files.end(); i++) {