]> mj.ucw.cz Git - bouncer.git/commitdiff
Options and config
authorMartin Mares <mj@ucw.cz>
Fri, 4 Nov 2016 21:12:59 +0000 (22:12 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 4 Nov 2016 21:12:59 +0000 (22:12 +0100)
Makefile
bouncer.c

index bfd62635db748bf1eaf674f9aa178202c53543c9..7743cf8a5f492c7d9ce7c51b9c7829e14123e644 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 PKG_CFLAGS := $(shell pkg-config --cflags libucw libipset)
 PKG_LIBS := $(shell pkg-config --libs libucw libipset)
 
-CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99 $(PKG_CFLAGS)
+CFLAGS=-O2 -Wall -Wextra -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -Wno-missing-field-initializers -std=gnu99 $(PKG_CFLAGS)
 LDLIBS=$(PKG_LIBS)
 
 all: bouncer
index 595be73471667afc5e1cd43b7e41271d8b7050ff..d747a3aa53401b3d6c8573e5494a703306129899 100644 (file)
--- a/bouncer.c
+++ b/bouncer.c
@@ -14,6 +14,7 @@
 #include <ucw/clists.h>
 #include <ucw/conf.h>
 #include <ucw/mainloop.h>
+#include <ucw/opt.h>
 #include <ucw/string.h>
 
 #include <alloca.h>
@@ -86,10 +87,30 @@ static bool addr_parse(struct addr *addr, const char *src)
 
 /*** Configuration ***/
 
-static uns max_culprits = 3;   // FIXME
-static uns max_failures = 3;   // FIXME
-static uns max_idle_time = 600;        // FIXME
-static uns max_banned_time = 600;      // FIXME
+static uns max_failures = ~0U;
+static uns max_suspect_time = 86400;
+static uns max_banned_time = 86400;
+static uns max_suspects = ~0U;
+static uns max_banned = ~0U;
+
+/*
+ * FIXME:
+ * - names of ipsets
+ * - name of socket
+ * - logging
+ * - PAM module name(s) to match
+ */
+
+static struct cf_section bouncer_cf = {
+  CF_ITEMS {
+    CF_UNS("MaxSuspects", &max_suspects),
+    CF_UNS("MaxBanned", &max_banned),
+    CF_UNS("MaxSuspectTime", &max_suspect_time),
+    CF_UNS("MaxBannedTime", &max_banned_time),
+    CF_UNS("MaxFailures", &max_failures),
+    CF_END
+  }
+};
 
 /*** An interface to IP sets ***/
 
@@ -190,14 +211,14 @@ static void is_modify(bool add, struct addr addr)
 /*** Handling of login failures ***/
 
 struct culprit_node {
-  cnode n;
+  cnode n;                     // In either suspect_list or banned_list
   union {
     struct addr addr;
     byte addr_bytes[16];
   };
-  timestamp_t last_fail;
   uns fail_count;
   bool banned;
+  timestamp_t last_fail;       // Not updated when banned
 };
 
 #define HASH_NODE struct culprit_node
@@ -211,11 +232,11 @@ struct culprit_node {
 #define HASH_LOOKUP_DETECT_NEW
 #include <ucw/hashtable.h>
 
-static uns num_culprits;
-static clist culprit_lru, culprit_bans;
+static clist suspect_list, banned_list;
+static uns num_suspects, num_banned;
 static struct main_timer cleanup_timer;
 
-static void cleanup_list(clist *list, timestamp_t max_time, timestamp_t *next)
+static void cleanup_list(clist *list, uns *counter, timestamp_t max_time, uns max_count, timestamp_t *next)
 {
   timestamp_t now = main_get_now();
 
@@ -226,8 +247,11 @@ static void cleanup_list(clist *list, timestamp_t max_time, timestamp_t *next)
        break;
 
       timestamp_t expire_in = c->last_fail + max_time - now;
-      if (num_culprits > max_culprits)
-       expire_in = 0;
+      if (*counter > max_count)
+       {
+         // FIXME: Warn with rate limit
+         expire_in = 0;
+       }
 
       if (expire_in > now)
        {
@@ -247,15 +271,15 @@ static void cleanup_list(clist *list, timestamp_t max_time, timestamp_t *next)
 
       clist_remove(&c->n);
       culprit_remove(c);
-      num_culprits--;
+      (*counter)--;
     }
 }
 
 static void culprit_cleanup(void)
 {
   timestamp_t next_cleanup = main_get_now() + (timestamp_t)3600 * 1000;
-  cleanup_list(&culprit_bans, (timestamp_t)max_banned_time * 1000, &next_cleanup);
-  cleanup_list(&culprit_lru, (timestamp_t)max_idle_time * 1000, &next_cleanup);
+  cleanup_list(&suspect_list, &num_suspects, (timestamp_t)max_suspect_time * 1000, max_suspects, &next_cleanup);
+  cleanup_list(&banned_list, &num_banned, (timestamp_t)max_banned_time * 1000, max_banned, &next_cleanup);
   timer_add(&cleanup_timer, next_cleanup);
 }
 
@@ -267,30 +291,34 @@ static void handle_failed_login(struct addr addr)
   struct culprit_node *c = culprit_lookup((byte *) &addr, &is_new);
   if (is_new)
     {
+      c->last_fail = now;
       c->fail_count = 1;
       c->banned = 0;
-      clist_add_tail(&culprit_lru, &c->n);
-      num_culprits++;
-      // FIXME: Warn on overflow, but not too frequently
+      clist_add_tail(&suspect_list, &c->n);
+      num_suspects++;
       DBG("%s: first fail", AFMT(addr));
     }
   else if (!c->banned)
     {
+      c->last_fail = now;
       c->fail_count++;
       clist_remove(&c->n);
-      clist_add_tail(&culprit_lru, &c->n);
+      clist_add_tail(&suspect_list, &c->n);
       DBG("%s: next fail, cnt=%u", AFMT(addr), c->fail_count);
     }
-  c->last_fail = now;
 
   if (!c->banned && c->fail_count >= max_failures)
     {
       DBG("%s: banned", AFMT(addr));
       c->banned = 1;
       clist_remove(&c->n);
-      clist_add_tail(&culprit_bans, &c->n);
+      num_suspects--;
+      clist_add_tail(&banned_list, &c->n);
+      num_banned++;
       is_modify(1, c->addr);
     }
+
+  culprit_cleanup();
 }
 
 static void culprit_timer(struct main_timer *tm UNUSED)
@@ -301,8 +329,8 @@ static void culprit_timer(struct main_timer *tm UNUSED)
 static void fail_init(void)
 {
   culprit_init();
-  clist_init(&culprit_lru);
-  clist_init(&culprit_bans);
+  clist_init(&suspect_list);
+  clist_init(&banned_list);
   cleanup_timer.handler = culprit_timer;
 }
 
@@ -457,13 +485,28 @@ static void sk_init(void)
 
 /*** Main ***/
 
-int main(void)
+static struct opt_section options = {
+  OPT_ITEMS {
+    OPT_HELP("Bouncer -- A Daemon for Turning Away Mischievous Guests"),
+    OPT_HELP(""),
+    OPT_HELP("Options:"),
+    OPT_HELP_OPTION,
+    OPT_CONF_OPTIONS,
+    OPT_END
+  }
+};
+
+int main(int argc UNUSED, char **argv)
 {
+  cf_def_file = "config";      // FIXME
+  cf_declare_section("Bouncer", &bouncer_cf, 0);
+  opt_parse(&options, argv+1);
+
   main_init();
   is_init();
   fail_init();
 
-  msg(L_INFO, "Clearing previous state");
+  // FIXME msg(L_INFO, "Clearing previous state");
   is_flush(IS_IPV4);
   is_flush(IS_IPV6);