Commit 30d5fb8e authored by bugzilla%glob.com.au's avatar bugzilla%glob.com.au

Bug 297646: Write helper functions for Bugzilla::Token.pm

Patch by Byron Jones <bugzilla@glob.com.au> r=LpSolit,a=justdave
parent 667869ea
...@@ -32,8 +32,10 @@ package Bugzilla::Token; ...@@ -32,8 +32,10 @@ package Bugzilla::Token;
use Bugzilla::Config; use Bugzilla::Config;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::BugMail; use Bugzilla::BugMail;
use Bugzilla::Util;
use Date::Format; use Date::Format;
use Date::Parse;
# This module requires that its caller have said "require CGI.pl" to import # This module requires that its caller have said "require CGI.pl" to import
# relevant functions from that script and its companion globals.pl. # relevant functions from that script and its companion globals.pl.
...@@ -46,34 +48,15 @@ use Date::Format; ...@@ -46,34 +48,15 @@ use Date::Format;
my $maxtokenage = 3; my $maxtokenage = 3;
################################################################################ ################################################################################
# Functions # Public Functions
################################################################################ ################################################################################
sub IssueEmailChangeToken { sub IssueEmailChangeToken {
my ($userid, $old_email, $new_email) = @_; my ($userid, $old_email, $new_email) = @_;
my $dbh = Bugzilla->dbh; my ($token, $token_ts) = _create_token($userid, 'emailold', $old_email . ":" . $new_email);
my $token_ts = time();
my $issuedate = time2str("%Y-%m-%d %H:%M", $token_ts);
# Generate a unique token and insert it into the tokens table. my $newtoken = _create_token($userid, 'emailnew', $old_email . ":" . $new_email);
# We have to lock the tokens table before generating the token,
# since the database must be queried for token uniqueness.
$dbh->bz_lock_tables('tokens WRITE');
my $token = GenerateUniqueToken();
my $quotedtoken = &::SqlQuote($token);
my $quoted_emails = &::SqlQuote($old_email . ":" . $new_email);
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token ,
tokentype , eventdata )
VALUES ( $userid , '$issuedate' , $quotedtoken ,
'emailold' , $quoted_emails )");
my $newtoken = GenerateUniqueToken();
$quotedtoken = &::SqlQuote($newtoken);
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token ,
tokentype , eventdata )
VALUES ( $userid , '$issuedate' , $quotedtoken ,
'emailnew' , $quoted_emails )");
$dbh->bz_unlock_tables();
# Mail the user the token along with instructions for using it. # Mail the user the token along with instructions for using it.
...@@ -128,18 +111,7 @@ sub IssuePasswordToken { ...@@ -128,18 +111,7 @@ sub IssuePasswordToken {
ThrowUserError('too_soon_for_new_token'); ThrowUserError('too_soon_for_new_token');
}; };
my $token_ts = time(); my ($token, $token_ts) = _create_token($userid, 'password', $::ENV{'REMOTE_ADDR'});
# Generate a unique token and insert it into the tokens table.
# We have to lock the tokens table before generating the token,
# since the database must be queried for token uniqueness.
$dbh->bz_lock_tables('tokens WRITE');
my $token = GenerateUniqueToken();
my $quotedtoken = &::SqlQuote($token);
my $quotedipaddr = &::SqlQuote($::ENV{'REMOTE_ADDR'});
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token , tokentype , eventdata )
VALUES ( $userid , NOW() , $quotedtoken , 'password' , $quotedipaddr )");
$dbh->bz_unlock_tables();
# Mail the user the token along with instructions for using it. # Mail the user the token along with instructions for using it.
...@@ -160,6 +132,13 @@ sub IssuePasswordToken { ...@@ -160,6 +132,13 @@ sub IssuePasswordToken {
Bugzilla::BugMail::MessageToMTA($message); Bugzilla::BugMail::MessageToMTA($message);
} }
sub IssueSessionToken {
# Generates a random token, adds it to the tokens table, and returns
# the token to the caller.
my $data = shift;
return _create_token(Bugzilla->user->id, 'session', $data);
}
sub CleanTokenTable { sub CleanTokenTable {
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
...@@ -170,7 +149,6 @@ sub CleanTokenTable { ...@@ -170,7 +149,6 @@ sub CleanTokenTable {
$dbh->bz_unlock_tables(); $dbh->bz_unlock_tables();
} }
sub GenerateUniqueToken { sub GenerateUniqueToken {
# Generates a unique random token. Uses &GenerateRandomPassword # Generates a unique random token. Uses &GenerateRandomPassword
# for the tokens themselves and checks uniqueness by searching for # for the tokens themselves and checks uniqueness by searching for
...@@ -180,23 +158,23 @@ sub GenerateUniqueToken { ...@@ -180,23 +158,23 @@ sub GenerateUniqueToken {
my $token; my $token;
my $duplicate = 1; my $duplicate = 1;
my $tries = 0; my $tries = 0;
while ($duplicate) {
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare("SELECT userid FROM tokens WHERE token = ?");
while ($duplicate) {
++$tries; ++$tries;
if ($tries > 100) { if ($tries > 100) {
ThrowCodeError("token_generation_error"); ThrowCodeError("token_generation_error");
} }
$token = &::GenerateRandomPassword(); $token = &::GenerateRandomPassword();
&::SendSQL("SELECT userid FROM tokens WHERE token = " . &::SqlQuote($token)); $sth->execute($token);
$duplicate = &::FetchSQLData(); $duplicate = $sth->fetchrow_array;
} }
return $token; return $token;
} }
sub Cancel { sub Cancel {
# Cancels a previously issued token and notifies the system administrator. # Cancels a previously issued token and notifies the system administrator.
# This should only happen when the user accidentally makes a token request # This should only happen when the user accidentally makes a token request
...@@ -210,7 +188,8 @@ sub Cancel { ...@@ -210,7 +188,8 @@ sub Cancel {
my $quotedtoken = &::SqlQuote($token); my $quotedtoken = &::SqlQuote($token);
# Get information about the token being cancelled. # Get information about the token being cancelled.
&::SendSQL("SELECT issuedate , tokentype , eventdata , login_name , realname &::SendSQL("SELECT " . $dbh->sql_date_format('issuedate') . ",
tokentype , eventdata , login_name , realname
FROM tokens, profiles FROM tokens, profiles
WHERE tokens.userid = profiles.userid WHERE tokens.userid = profiles.userid
AND token = $quotedtoken"); AND token = $quotedtoken");
...@@ -240,9 +219,7 @@ sub Cancel { ...@@ -240,9 +219,7 @@ sub Cancel {
Bugzilla::BugMail::MessageToMTA($message); Bugzilla::BugMail::MessageToMTA($message);
# Delete the token from the database. # Delete the token from the database.
$dbh->bz_lock_tables('tokens WRITE'); DeleteToken($token);
&::SendSQL("DELETE FROM tokens WHERE token = $quotedtoken");
$dbh->bz_unlock_tables();
} }
sub DeletePasswordTokens { sub DeletePasswordTokens {
...@@ -272,5 +249,63 @@ sub HasEmailChangeToken { ...@@ -272,5 +249,63 @@ sub HasEmailChangeToken {
return $token; return $token;
} }
sub GetTokenData($) {
# Returns the userid, issuedate and eventdata for the specified token
my ($token) = @_;
return unless defined $token;
trick_taint($token);
my $dbh = Bugzilla->dbh;
return $dbh->selectrow_array(
"SELECT userid, " . $dbh->sql_date_format('issuedate') . ", eventdata
FROM tokens
WHERE token = ?", undef, $token);
}
sub DeleteToken($) {
# Deletes specified token
my ($token) = @_;
return unless defined $token;
trick_taint($token);
my $dbh = Bugzilla->dbh;
$dbh->bz_lock_tables('tokens WRITE');
$dbh->do("DELETE FROM tokens WHERE token = ?", undef, $token);
$dbh->bz_unlock_tables();
}
################################################################################
# Internal Functions
################################################################################
sub _create_token($$$) {
# Generates a unique token and inserts it into the database
# Returns the token and the token timestamp
my ($userid, $tokentype, $eventdata) = @_;
detaint_natural($userid);
trick_taint($tokentype);
trick_taint($eventdata);
my $dbh = Bugzilla->dbh;
$dbh->bz_lock_tables('tokens WRITE');
my $token = GenerateUniqueToken();
$dbh->do("INSERT INTO tokens (userid, issuedate, token, tokentype, eventdata)
VALUES (?, NOW(), ?, ?, ?)", undef, ($userid, $token, $tokentype, $eventdata));
$dbh->bz_unlock_tables();
if (wantarray) {
my (undef, $token_ts, undef) = GetTokenData($token);
$token_ts = str2time($token_ts);
return ($token, $token_ts);
} else {
return $token;
}
}
1; 1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment