commit 57a8716

default  ·  2024-12-19 17:54:15 +0000 UTC
parent f82c7a5
Added bad login throttling.
3 files changed,  +120, -3
M data.c
M html.c
M snac.h
M data.c
+105, -0
  1@@ -3821,3 +3821,108 @@ xs_str *make_url(const char *href, const char *proxy, int by_token)
  2 
  3     return url;
  4 }
  5+
  6+
  7+/** bad login throttle **/
  8+
  9+xs_str *_badlogin_fn(const char *addr)
 10+{
 11+    xs *md5 = xs_md5_hex(addr, strlen(addr));
 12+    xs *dir = xs_fmt("%s/badlogin", srv_basedir);
 13+
 14+    mkdirx(dir);
 15+
 16+    return xs_fmt("%s/%s", dir, md5);
 17+}
 18+
 19+
 20+int _badlogin_read(const char *fn, int *failures)
 21+/* reads a badlogin file */
 22+{
 23+    int ok = 0;
 24+    FILE *f;
 25+
 26+    pthread_mutex_lock(&data_mutex);
 27+
 28+    if ((f = fopen(fn, "r")) != NULL) {
 29+        xs *l = xs_readline(f);
 30+        fclose(f);
 31+
 32+        if (sscanf(l, "%d", failures) == 1)
 33+            ok = 1;
 34+    }
 35+
 36+    pthread_mutex_unlock(&data_mutex);
 37+
 38+    return ok;
 39+}
 40+
 41+
 42+int badlogin_check(const char *user, const char *addr)
 43+/* checks if this address is authorized to try a login */
 44+{
 45+    int valid = 1;
 46+
 47+    if (xs_type(addr) == XSTYPE_STRING) {
 48+        xs *fn = _badlogin_fn(addr);
 49+        double mt = mtime(fn);
 50+
 51+        if (mt > 0) {
 52+            int badlogin_expire = xs_number_get(xs_dict_get_def(srv_config,
 53+                                        "badlogin_expire", "300"));
 54+
 55+            mt += badlogin_expire;
 56+
 57+            /* if file is expired, delete and give pass */
 58+            if (mt < time(NULL)) {
 59+                srv_debug(1, xs_fmt("Login from %s for %s allowed again", addr, user));
 60+                unlink(fn);
 61+            }
 62+            else {
 63+                int failures;
 64+
 65+                if (_badlogin_read(fn, &failures)) {
 66+                    int badlogin_max = xs_number_get(xs_dict_get_def(srv_config,
 67+                                            "badlogin_retries", "5"));
 68+
 69+                    if (failures >= badlogin_max) {
 70+                        valid = 0;
 71+
 72+                        xs *d = xs_str_iso_date((time_t) mt);
 73+
 74+                        srv_debug(1,
 75+                            xs_fmt("Login from %s for %s forbidden until %s", addr, user, d));
 76+                    }
 77+                }
 78+            }
 79+        }
 80+    }
 81+
 82+    return valid;
 83+}
 84+
 85+
 86+void badlogin_inc(const char *user, const char *addr)
 87+/* increments a bad login from this address */
 88+{
 89+    if (xs_type(addr) == XSTYPE_STRING) {
 90+        int failures = 0;
 91+        xs *fn = _badlogin_fn(addr);
 92+        FILE *f;
 93+
 94+        _badlogin_read(fn, &failures);
 95+
 96+        pthread_mutex_lock(&data_mutex);
 97+
 98+        if ((f = fopen(fn, "w")) != NULL) {
 99+            failures++;
100+
101+            fprintf(f, "%d %s %s\n", failures, addr, user);
102+            fclose(f);
103+
104+            srv_log(xs_fmt("Registered %d login failure(s) from %s for %s", failures, addr, user));
105+        }
106+
107+        pthread_mutex_unlock(&data_mutex);
108+    }
109+}
M html.c
+12, -3
 1@@ -29,9 +29,18 @@ int login(snac *snac, const xs_dict *headers)
 2         xs *l1 = xs_split_n(s2, ":", 1);
 3 
 4         if (xs_list_len(l1) == 2) {
 5-            logged_in = check_password(
 6-                xs_list_get(l1, 0), xs_list_get(l1, 1),
 7-                xs_dict_get(snac->config, "passwd"));
 8+            const char *user = xs_list_get(l1, 0);
 9+            const char *pwd  = xs_list_get(l1, 1);
10+            const char *addr = xs_or(xs_dict_get(headers, "remote-addr"),
11+                                     xs_dict_get(headers, "x-forwarded-for"));
12+
13+            if (badlogin_check(user, addr)) {
14+                logged_in = check_password(user, pwd,
15+                    xs_dict_get(snac->config, "passwd"));
16+
17+                if (!logged_in)
18+                    badlogin_inc(user, addr);
19+            }
20         }
21     }
22 
M snac.h
+3, -0
1@@ -425,3 +425,6 @@ typedef struct {
2 t_announcement *announcement(double after);
3 
4 xs_str *make_url(const char *href, const char *proxy, int by_token);
5+
6+int badlogin_check(const char *user, const char *addr);
7+void badlogin_inc(const char *user, const char *addr);