diff options
author | Yorhel <git@yorhel.nl> | 2014-08-29 11:50:41 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2014-08-29 11:50:41 +0200 |
commit | 1cf4252f2d313bc1e3f460a1d379a49b751d1170 (patch) | |
tree | 4385788e5553fe7376e4063961e8c7a9cbce7663 /lib/Multi | |
parent | 9a1bd46a568094ff62cfc85bc488b116042718b8 (diff) |
API: Make sure to honor the new login throttle
Diffstat (limited to 'lib/Multi')
-rw-r--r-- | lib/Multi/API.pm | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/lib/Multi/API.pm b/lib/Multi/API.pm index 1e4700d9..3dfaa2c9 100644 --- a/lib/Multi/API.pm +++ b/lib/Multi/API.pm @@ -14,7 +14,7 @@ use POE::Filter::VNDBAPI 'encode_filters'; use Digest::SHA 'sha256_hex'; use Encode 'encode_utf8'; use Time::HiRes 'time'; # important for throttling -use VNDBUtil 'normalize_query'; +use VNDBUtil 'normalize_query', 'norm_ip'; use JSON::XS; @@ -40,7 +40,7 @@ sub spawn { package_states => [ $p => [qw| _start shutdown log server_error client_connect client_error client_input - login login_res dbstats dbstats_res get_results get_vn get_vn_res + login login_throttle login_res dbstats dbstats_res get_results get_vn get_vn_res get_release get_release_res get_producer get_producer_res get_character get_character_res get_votelist get_votelist_res get_vnlist get_vnlist_res get_wishlist get_wishlist_res set_votelist set_vnlist @@ -420,9 +420,9 @@ sub login { return cerr $c, badarg => 'Invalid client version', field => 'clientver' if $arg->{clientver} !~ /^[a-zA-Z0-9_.\/-]{1,25}$/; if(exists $arg->{username}) { - # fetch user info - $_[KERNEL]->post(pg => query => "SELECT id, salt, encode(passwd, 'hex') as passwd FROM users WHERE username = ?", - [ $arg->{username} ], 'login_res', [ $c, $arg ]); + # check login throttle + $_[KERNEL]->post(pg => query => "SELECT timeout FROM login_throttle WHERE ip = ?", + [ norm_ip($c->{ip}) ], 'login_throttle', [ $c, $arg ]); } else { $c->{client} = $arg->{client}; $c->{clientver} = $arg->{clientver}; @@ -432,14 +432,36 @@ sub login { } -sub login_res { # num, res, [ c, arg ] +sub login_throttle { my($num, $res, $c, $arg) = (@_[ARG0, ARG1], $_[ARG2][0], $_[ARG2][1]); + my $tm = @$res && $res->[0]{timeout} > time ? $res->[0]{timeout} : time; + $tm = int $tm; + return cerr $c, auth => "Too many failed login attempts" + if $tm-time() > $VNDB::S{login_throttle}[1]; + + # fetch user info + $_[KERNEL]->post(pg => query => "SELECT id, salt, encode(passwd, 'hex') as passwd FROM users WHERE username = ?", + [ $arg->{username} ], 'login_res', [ $c, $arg, $tm ]); +} + + +sub login_res { # num, res, [ c, arg, tm ] + my($num, $res, $c, $arg, $tm) = (@_[ARG0, ARG1], $_[ARG2][0], $_[ARG2][1], $_[ARG2][2]); + return cerr $c, auth => "No user with the name '$arg->{username}'" if $num == 0; return cerr $c, auth => "Account disabled" if $res->[0]{salt} =~ /^ +$/; my $encrypted = sha256_hex($VNDB::S{global_salt}.encode_utf8($arg->{password}).encode_utf8($res->[0]{salt})); - return cerr $c, auth => "Wrong password for user '$arg->{username}'" if lc($encrypted) ne lc($res->[0]{passwd}); + + if(lc($encrypted) ne lc($res->[0]{passwd})) { + $tm += $VNDB::S{login_throttle}[0]; + $_[KERNEL]->post(pg => do => 'UPDATE login_throttle SET timeout = ? WHERE ip = ?', [ $tm, $c->{ip} ]); + $_[KERNEL]->post(pg => do => + 'INSERT INTO login_throttle (ip, timeout) SELECT ?, ? WHERE NOT EXISTS(SELECT 1 FROM login_throttle WHERE ip = ?)', + [ $c->{ip}, $tm, $c->{ip} ]); + return cerr $c, auth => "Wrong password for user '$arg->{username}'"; + } $c->{uid} = $res->[0]{id}; $c->{username} = $arg->{username}; |