diff options
Diffstat (limited to '')
| -rw-r--r-- | data.c | 105 | ||||
| -rw-r--r-- | html.c | 15 | ||||
| -rw-r--r-- | snac.h | 3 |
3 files changed, 120 insertions, 3 deletions
| @@ -3821,3 +3821,108 @@ xs_str *make_url(const char *href, const char *proxy, int by_token) | |||
| 3821 | 3821 | ||
| 3822 | return url; | 3822 | return url; |
| 3823 | } | 3823 | } |
| 3824 | |||
| 3825 | |||
| 3826 | /** bad login throttle **/ | ||
| 3827 | |||
| 3828 | xs_str *_badlogin_fn(const char *addr) | ||
| 3829 | { | ||
| 3830 | xs *md5 = xs_md5_hex(addr, strlen(addr)); | ||
| 3831 | xs *dir = xs_fmt("%s/badlogin", srv_basedir); | ||
| 3832 | |||
| 3833 | mkdirx(dir); | ||
| 3834 | |||
| 3835 | return xs_fmt("%s/%s", dir, md5); | ||
| 3836 | } | ||
| 3837 | |||
| 3838 | |||
| 3839 | int _badlogin_read(const char *fn, int *failures) | ||
| 3840 | /* reads a badlogin file */ | ||
| 3841 | { | ||
| 3842 | int ok = 0; | ||
| 3843 | FILE *f; | ||
| 3844 | |||
| 3845 | pthread_mutex_lock(&data_mutex); | ||
| 3846 | |||
| 3847 | if ((f = fopen(fn, "r")) != NULL) { | ||
| 3848 | xs *l = xs_readline(f); | ||
| 3849 | fclose(f); | ||
| 3850 | |||
| 3851 | if (sscanf(l, "%d", failures) == 1) | ||
| 3852 | ok = 1; | ||
| 3853 | } | ||
| 3854 | |||
| 3855 | pthread_mutex_unlock(&data_mutex); | ||
| 3856 | |||
| 3857 | return ok; | ||
| 3858 | } | ||
| 3859 | |||
| 3860 | |||
| 3861 | int badlogin_check(const char *user, const char *addr) | ||
| 3862 | /* checks if this address is authorized to try a login */ | ||
| 3863 | { | ||
| 3864 | int valid = 1; | ||
| 3865 | |||
| 3866 | if (xs_type(addr) == XSTYPE_STRING) { | ||
| 3867 | xs *fn = _badlogin_fn(addr); | ||
| 3868 | double mt = mtime(fn); | ||
| 3869 | |||
| 3870 | if (mt > 0) { | ||
| 3871 | int badlogin_expire = xs_number_get(xs_dict_get_def(srv_config, | ||
| 3872 | "badlogin_expire", "300")); | ||
| 3873 | |||
| 3874 | mt += badlogin_expire; | ||
| 3875 | |||
| 3876 | /* if file is expired, delete and give pass */ | ||
| 3877 | if (mt < time(NULL)) { | ||
| 3878 | srv_debug(1, xs_fmt("Login from %s for %s allowed again", addr, user)); | ||
| 3879 | unlink(fn); | ||
| 3880 | } | ||
| 3881 | else { | ||
| 3882 | int failures; | ||
| 3883 | |||
| 3884 | if (_badlogin_read(fn, &failures)) { | ||
| 3885 | int badlogin_max = xs_number_get(xs_dict_get_def(srv_config, | ||
| 3886 | "badlogin_retries", "5")); | ||
| 3887 | |||
| 3888 | if (failures >= badlogin_max) { | ||
| 3889 | valid = 0; | ||
| 3890 | |||
| 3891 | xs *d = xs_str_iso_date((time_t) mt); | ||
| 3892 | |||
| 3893 | srv_debug(1, | ||
| 3894 | xs_fmt("Login from %s for %s forbidden until %s", addr, user, d)); | ||
| 3895 | } | ||
| 3896 | } | ||
| 3897 | } | ||
| 3898 | } | ||
| 3899 | } | ||
| 3900 | |||
| 3901 | return valid; | ||
| 3902 | } | ||
| 3903 | |||
| 3904 | |||
| 3905 | void badlogin_inc(const char *user, const char *addr) | ||
| 3906 | /* increments a bad login from this address */ | ||
| 3907 | { | ||
| 3908 | if (xs_type(addr) == XSTYPE_STRING) { | ||
| 3909 | int failures = 0; | ||
| 3910 | xs *fn = _badlogin_fn(addr); | ||
| 3911 | FILE *f; | ||
| 3912 | |||
| 3913 | _badlogin_read(fn, &failures); | ||
| 3914 | |||
| 3915 | pthread_mutex_lock(&data_mutex); | ||
| 3916 | |||
| 3917 | if ((f = fopen(fn, "w")) != NULL) { | ||
| 3918 | failures++; | ||
| 3919 | |||
| 3920 | fprintf(f, "%d %s %s\n", failures, addr, user); | ||
| 3921 | fclose(f); | ||
| 3922 | |||
| 3923 | srv_log(xs_fmt("Registered %d login failure(s) from %s for %s", failures, addr, user)); | ||
| 3924 | } | ||
| 3925 | |||
| 3926 | pthread_mutex_unlock(&data_mutex); | ||
| 3927 | } | ||
| 3928 | } | ||
| @@ -29,9 +29,18 @@ int login(snac *snac, const xs_dict *headers) | |||
| 29 | xs *l1 = xs_split_n(s2, ":", 1); | 29 | xs *l1 = xs_split_n(s2, ":", 1); |
| 30 | 30 | ||
| 31 | if (xs_list_len(l1) == 2) { | 31 | if (xs_list_len(l1) == 2) { |
| 32 | logged_in = check_password( | 32 | const char *user = xs_list_get(l1, 0); |
| 33 | xs_list_get(l1, 0), xs_list_get(l1, 1), | 33 | const char *pwd = xs_list_get(l1, 1); |
| 34 | xs_dict_get(snac->config, "passwd")); | 34 | const char *addr = xs_or(xs_dict_get(headers, "remote-addr"), |
| 35 | xs_dict_get(headers, "x-forwarded-for")); | ||
| 36 | |||
| 37 | if (badlogin_check(user, addr)) { | ||
| 38 | logged_in = check_password(user, pwd, | ||
| 39 | xs_dict_get(snac->config, "passwd")); | ||
| 40 | |||
| 41 | if (!logged_in) | ||
| 42 | badlogin_inc(user, addr); | ||
| 43 | } | ||
| 35 | } | 44 | } |
| 36 | } | 45 | } |
| 37 | 46 | ||
| @@ -425,3 +425,6 @@ typedef struct { | |||
| 425 | t_announcement *announcement(double after); | 425 | t_announcement *announcement(double after); |
| 426 | 426 | ||
| 427 | xs_str *make_url(const char *href, const char *proxy, int by_token); | 427 | xs_str *make_url(const char *href, const char *proxy, int by_token); |
| 428 | |||
| 429 | int badlogin_check(const char *user, const char *addr); | ||
| 430 | void badlogin_inc(const char *user, const char *addr); | ||