X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;ds=sidebyside;f=aux%2Fcgi%2Frecovery.cgi;h=f63175a6ac0bbe09122534b9acd70ce9ff8b61c8;hb=d67dd1bf5a247e20141b9907f5a452da73624235;hp=6d6f3a17dbd21d8dfb597126d29c3890920f9b95;hpb=b9aab20d149543fcd4d6a541af32eb4d3c51019c;p=blerg.git diff --git a/aux/cgi/recovery.cgi b/aux/cgi/recovery.cgi index 6d6f3a1..f63175a 100755 --- a/aux/cgi/recovery.cgi +++ b/aux/cgi/recovery.cgi @@ -1,7 +1,10 @@ #!/usr/bin/perl use CGI::Fast qw/:cgi/; -use Digest::SHA qw/hmac_sha256_base64/; +use Digest::SHA qw/hmac_sha256/; +use MIME::Base64 qw/encode_base64url/; use Blerg::Database; +use Mail::Message; +use Time::HiRes qw/sleep/; use strict; use v5.10; @@ -37,31 +40,31 @@ sub generate_reset_url { my $expiry = time + $validity; my $counter = Blerg::Database::auth_get_counter($username) or return undef; - my $data = "$username;$expiry;$counter"; + my $data = "$username:$expiry:$counter"; # HMAC-SHA256 it - my $hmac = hmac_sha256_base64($data, $hmac_key); + my $hmac = encode_base64url(hmac_sha256($data, $hmac_key)); - return Blerg::Database::BASEURL . "#/recovery/$data;$hmac"; + return Blerg::Database::BASEURL . "#/recovery/$data:$hmac"; } sub validate_reset_data { my ($data) = @_; my ($payload, $hmac); - if ($data =~ /^(.*);([^;]+)$/) { + if ($data =~ /^(.*):([^:]+)$/) { $payload = $1; $hmac = $2; } else { return undef; } - my $computed_hmac = hmac_sha256_base64($payload, $hmac_key); + my $computed_hmac = encode_base64url(hmac_sha256($payload, $hmac_key)); if ($hmac ne $computed_hmac) { return undef; } - my ($username, $expiry, $counter) = split(';', $payload); + my ($username, $expiry, $counter) = split(':', $payload); if (time > $expiry || $counter != Blerg::Database::auth_get_counter($username)) { return undef; @@ -93,9 +96,56 @@ while (my $q = new CGI::Fast) { print generate_reset_url($username, $validity); } when ('mail') { + print header(-type => 'application/json'); + + if (!(defined $q->param('username') and defined $q->param('email'))) { + say '{"status": "failed"}'; + next REQUEST; + } + + # Sleep for a bit to scramble the timing + sleep(rand(1.0) + 1); + + # From here on, we report success so as not to leak user information + my $username = $q->param('username'); + if (!Blerg::Database::exists($username)) { + say '{"status": "success"}'; + next REQUEST; + } + # check that the user has a validated mail address - # generate reset message - # send mail + my $email_conf_path = Blerg::Database::configuration->{data_path} . "/$username/email"; + my $email; + if (!open EMAIL, $email_conf_path) { + say '{"status": "success"}'; + next REQUEST; + } + $email = ; + close EMAIL; + + if ($q->param('email') ne $email) { + say '{"status": "success"}'; + next REQUEST; + } + + my $url = generate_reset_url($username, 900); + Mail::Message->build( + From => Mail::Address->new('BlergBot', 'noreply@blerg.cc'), + To => $email, + Subject => 'Blërg Password Recovery', + Mail::Message::Field->new('Content-Type', 'text/plain', 'charset="utf8"'), + data => <send; + + say '{"status": "success"}'; } when ('validate') { print header(-type => 'application/json');