diff 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
line wrap: on
line diff
--- a/src/context.cpp	Wed Dec 11 22:57:06 2013 -0800
+++ b/src/context.cpp	Tue Dec 17 15:35:23 2013 -0800
@@ -733,8 +733,10 @@
     dcc_bulk_threshold  = (parent) ? parent->dcc_bulk_threshold : 0;
     dnsbl_list_parsed   = false;
     dnswl_list_parsed   = false;
-    default_rcpt_rate   = 36000;        // 10 per second
-    rcpt_daily_multiple = 3;
+    default_rate_limit      = 36000;        // 10 per second
+    default_address_limit   = 10;
+    daily_rate_multiple     = 3;
+    daily_address_multiple  = 3;
 }
 
 
@@ -845,20 +847,32 @@
 }
 
 
-int CONTEXT::find_rate(const char *user) {
-    if (rcpt_per_hour.empty()) return default_rcpt_rate;
-    rcpt_rates::iterator i = rcpt_per_hour.find(user);  // look for authen id, or sender user@email limiting
+int CONTEXT::find_rate_limit(const char *user) {
+    if (rcpt_per_hour.empty()) return default_rate_limit;
+    rates::iterator i = rcpt_per_hour.find(user);       // look for authen id, or sender user@email limiting
     if (i != rcpt_per_hour.end()) return (*i).second;   // found authen id, or user@email limiting
     const char *f = strchr(user, '@');
-    if (!f) return default_rcpt_rate;
+    if (!f) return default_rate_limit;
     i = rcpt_per_hour.find(f);                          // look for @domain limiting
     if (i != rcpt_per_hour.end()) return (*i).second;   // found @domain limiting
-    return default_rcpt_rate;
+    return default_rate_limit;
+}
+
+
+int CONTEXT::find_address_limit(const char *user) {
+    if (addresses_per_hour.empty()) return default_address_limit;
+    rates::iterator i = addresses_per_hour.find(user);      // look for authen id, or sender user@email limiting
+    if (i != addresses_per_hour.end()) return (*i).second;  // found authen id, or user@email limiting
+    const char *f = strchr(user, '@');
+    if (!f) return default_address_limit;
+    i = addresses_per_hour.find(f);                         // look for @domain limiting
+    if (i != addresses_per_hour.end()) return (*i).second;  // found @domain limiting
+    return default_address_limit;
 }
 
 
 bool CONTEXT::is_unauthenticated_limited(const char *user) {
-    rcpt_rates::iterator i = rcpt_per_hour.find(user);  // look for sender user@email limiting
+    rates::iterator i = rcpt_per_hour.find(user);       // look for sender user@email limiting
     if (i != rcpt_per_hour.end()) return true;          // found user@email limiting
     const char *f = strchr(user, '@');
     if (!f) return false;
@@ -1211,11 +1225,13 @@
     printf("%s     }; \n", indent);
 
     if (isdefault) {
-        printf("%s     rate_limit %d %d { \n", indent, default_rcpt_rate, rcpt_daily_multiple);
-        for (rcpt_rates::iterator j=rcpt_per_hour.begin(); j!=rcpt_per_hour.end(); j++) {
+        printf("%s     rate_limit %d %d %d %d { \n", indent, default_rate_limit, daily_rate_multiple, default_address_limit, daily_address_multiple);
+        for (rates::iterator j=rcpt_per_hour.begin(); j!=rcpt_per_hour.end(); j++) {
             const char *u = (*j).first;
             int         l = (*j).second;
-            printf("%s         \"%s\" \t%d; \n", indent, u, l);
+            rates::iterator k = addresses_per_hour.find(u);
+            int             a = (k==addresses_per_hour.end()) ? default_address_limit : (*k).second;
+            printf("%s         \"%s\" \t%d %d; \n", indent, u, l, a);
         }
         printf("%s     }; \n", indent);
     }
@@ -1753,25 +1769,18 @@
 //
 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me);
 bool parse_rate(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
-    const char *def = tok.next();
-    tok.push(def);
-    if (def != token_lbrace) me.set_default_rate(tok.nextint());
-
-    def = tok.next();
-    tok.push(def);
-    if (def != token_lbrace) me.set_daily_multiple(tok.nextint());
-
+    me.set_default_rate_limit(tok.nextint());
+    me.set_daily_rate_multiple(tok.nextint());
+    me.set_default_address_limit(tok.nextint());
+    me.set_daily_address_multiple(tok.nextint());
     if (!tsa(tok, token_lbrace)) return false;
     while (true) {
         const char *have = tok.next();
         if (!have) break;
         if (have == token_rbrace) break;
-        if (have == token_semi) {
-            // optional separators
-        }
-        else {
-            me.add_rate(have, tok.nextint());
-        }
+        me.add_rate_limit(have, tok.nextint());
+        me.add_address_limit(have, tok.nextint());
+        if (!tsa(tok, token_semi)) return false;
     }
     return tsa(tok, token_semi);
 }