summaryrefslogtreecommitdiff
path: root/lib/VNDB/Util/Auth.pm
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2010-11-06 16:46:01 +0100
committerYorhel <git@yorhel.nl>2010-11-06 16:46:01 +0100
commite625403d6108b3f95361ece3c4311dae88747107 (patch)
tree0f456df20316562333d4ae76ce1a02b703279747 /lib/VNDB/Util/Auth.pm
parent09307455ced2b60ea2abb161fc59f8efdafefdfa (diff)
Fixed cross-site request forgery vulnerabilities
Diffstat (limited to 'lib/VNDB/Util/Auth.pm')
-rw-r--r--lib/VNDB/Util/Auth.pm56
1 files changed, 55 insertions, 1 deletions
diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm
index 45b39249..24e316ce 100644
--- a/lib/VNDB/Util/Auth.pm
+++ b/lib/VNDB/Util/Auth.pm
@@ -10,9 +10,11 @@ use Digest::SHA qw|sha1_hex sha256_hex|;
use Time::HiRes;
use Encode 'encode_utf8';
use POSIX 'strftime';
+use YAWF ':html';
+use VNDB::Func;
-our @EXPORT = qw| authInit authLogin authLogout authInfo authCan authPreparePass |;
+our @EXPORT = qw| authInit authLogin authLogout authInfo authCan authPreparePass authGetCode authCheckCode |;
# initializes authentication information and checks the vndb_auth cookie
@@ -142,5 +144,57 @@ sub _rmcookie {
}
+# Generate a code to be used later on to validate that the form was indeed
+# submitted from our site and by the same user/visitor. Not limited to
+# logged-in users.
+# Arguments:
+# form-id (string, can be empty, but makes the validation stronger)
+# time (optional, time() to encode in the code)
+sub authGetCode {
+ my $self = shift;
+ my $id = shift;
+ my $time = (shift || time)/3600; # accuracy of an hour
+ my $uid = pack('N', $self->{_auth} ? $self->{_auth}{id} : 0);
+ return lc substr sha1_hex($self->{form_salt} . $uid . encode_utf8($id||'') . pack('N', int $time)), 0, 16;
+}
+
+
+# Validates the correctness of the returned code, creates an error page and
+# returns false if it's invalid, returns true otherwise. Codes are valid for at
+# least two and at most three hours.
+# Arguments:
+# [ form-id, [ code ] ]
+# If the code is not given, uses the 'formcode' form parameter instead. If
+# form-id is not given, the path of the current requests is used.
+sub authCheckCode {
+ my $self = shift;
+ my $id = shift || '/'.$self->reqPath();
+ my $code = shift || $self->reqParam('formcode');
+ return _incorrectcode($self) if !$code || $code !~ qr/^[0-9a-f]{16}$/;
+ my $time = time;
+ return 1 if $self->authGetCode($id, $time) eq $code;
+ return 1 if $self->authGetCode($id, $time-3600) eq $code;
+ return 1 if $self->authGetCode($id, $time-2*3600) eq $code;
+ return _incorrectcode($self);
+}
+
+
+sub _incorrectcode {
+ my $self = shift;
+ $self->resInit;
+ $self->htmlHeader(title => mt '_formcode_title', noindex => 1);
+
+ div class => 'mainbox';
+ h1 mt '_formcode_title';
+ div class => 'warning';
+ p mt '_formcode_msg';
+ end;
+ end;
+
+ $self->htmlFooter;
+ return 0;
+}
+
+
1;