From 8955f58c951da1402f5eb76bc2a7982548e970f4 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Thu, 26 Feb 2015 03:52:03 -0600 Subject: [PATCH] Add auxilliary CGI for account recovery --- aux/cgi/recovery.cgi | 122 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100755 aux/cgi/recovery.cgi diff --git a/aux/cgi/recovery.cgi b/aux/cgi/recovery.cgi new file mode 100755 index 0000000..d0742b6 --- /dev/null +++ b/aux/cgi/recovery.cgi @@ -0,0 +1,122 @@ +#!/usr/bin/perl +use CGI::Fast qw/:cgi/; +use Digest::SHA qw/hmac_sha256_base64/; +use Blerg::Database; +use strict; +use v5.10; + +my $hmac_key; +open HMAC_KEY, "$ENV{BLERG_HOME}/etc/hmac_key" + or die "Could not open $ENV{BLERG_HOME}/etc/hmac_key"; +read(HMAC_KEY, $hmac_key, 256); +close HMAC_KEY; + +sub print_404 { + print header(-type => 'text/html', + -status => '404 Not Found'); + print < +

404 Not Found

+DOC +} + +sub print_403 { + print header(-type => 'text/html', + -status => '403 Forbidden'); + print < +

403 Forbidden

+Please log in first. +DOC +} + +sub generate_reset_url { + my ($username, $validity) = @_; + + # generate reset data + my $expiry = time + $validity; + my $counter = Blerg::Database::auth_get_counter($username) + or return undef; + my $data = "$username;$expiry;$counter"; + + # HMAC-SHA256 it + my $hmac = hmac_sha256_base64($data, $hmac_key); + + return Blerg::Database::BASEURL . "#/recovery/$data;$hmac"; +} + +sub validate_reset_data { + my ($data) = @_; + my ($payload, $hmac); + + if ($data =~ /^(.*);([^;]+)$/) { + $payload = $1; + $hmac = $2; + } else { + return undef; + } + + my $computed_hmac = hmac_sha256_base64($payload, $hmac_key); + if ($hmac ne $computed_hmac) { + return undef; + } + + my ($username, $expiry, $counter) = split(';', $payload); + if (time > $expiry + || $counter != Blerg::Database::auth_get_counter($username)) { + return undef; + } + + return $username; +} + +REQUEST: +while (my $q = new CGI::Fast) { + my (undef, $cmd, $args) = split '/', $ENV{PATH_INFO}, 3; + + given ($cmd) { + when ('new') { + # determine that authentication is valid. + my $auth = $q->cookie('auth'); + if (!defined $auth) { + print_403; + next REQUEST; + } + my ($username, $token) = split('/', $auth); + if (!Blerg::Database::auth_check_token($username, $token)) { + print_403; + next REQUEST; + } + + my $validity = 365 * 86400; # One year + print header(-type => 'text/plain'); + print generate_reset_url($username, $validity); + } + when ('mail') { + # check that the user has a validated mail address + # generate reset message + # send mail + } + when ('validate') { + print header(-type => 'application/json'); + + my $username = validate_reset_data($q->param('data')); + + if (!defined $username) { + say '{"status": "failure"}'; + next REQUEST; + } + + my $password = $q->param('password'); + if (Blerg::Database::auth_set_password($username, $password)) { + say '{"status": "success"}'; + } else { + say '{"status": "failure"}'; + } + } + default { + print_404; + print "$cmd $args"; + } + } +} -- 2.25.1