summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
authorlpsolit%gmail.com <>2006-08-20 03:11:59 +0200
committerlpsolit%gmail.com <>2006-08-20 03:11:59 +0200
commit59285f71c6ed0d4db7d4b0455902130a2d7c83bd (patch)
tree49e2e47a53bb4ac31c10d3225b5e0a66edc5c126 /Bugzilla
parent9dfdfd787ff4c0afac28b66e67082712ec2a3d92 (diff)
downloadbugzilla-59285f71c6ed0d4db7d4b0455902130a2d7c83bd.tar.gz
bugzilla-59285f71c6ed0d4db7d4b0455902130a2d7c83bd.tar.xz
Bug 87795: Creating an account should send token and wait for confirmation (prevent user account abuse) - Patch by Frédéric Buclin <LpSolit@gmail.com> r=mkanat r=bkor a=myk
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/BugMail.pm14
-rw-r--r--Bugzilla/Constants.pm5
-rw-r--r--Bugzilla/DB/Schema.pm2
-rw-r--r--Bugzilla/Install/DB.pm3
-rw-r--r--Bugzilla/Token.pm62
-rw-r--r--Bugzilla/User.pm31
6 files changed, 71 insertions, 46 deletions
diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm
index 07ebf226b..35b05d231 100644
--- a/Bugzilla/BugMail.pm
+++ b/Bugzilla/BugMail.pm
@@ -654,20 +654,6 @@ sub sendMail {
return 1;
}
-# Send the login name and password of the newly created account to the user.
-sub MailPassword {
- my ($login, $password) = (@_);
- my $template = Bugzilla->template;
- my $vars = {
- mailaddress => $login . Bugzilla->params->{'emailsuffix'},
- login => $login,
- password => $password };
- my $msg;
- $template->process("email/password.txt.tmpl", $vars, \$msg)
- || ThrowTemplateError($template->error());
- MessageToMTA($msg);
-}
-
# Get bug comments for the given period and format them to be used in emails.
sub get_comments_by_bug {
my ($id, $start, $end) = @_;
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 9493ea400..2d6c2f561 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -120,6 +120,8 @@ use File::Basename;
DB_MODULE
ROOT_USER
ON_WINDOWS
+
+ MAX_TOKEN_AGE
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -295,6 +297,9 @@ use constant SENDMAIL_EXE => '/usr/lib/sendmail.exe';
use constant FIELD_TYPE_UNKNOWN => 0;
use constant FIELD_TYPE_FREETEXT => 1;
+# The maximum number of days a token will remain valid.
+use constant MAX_TOKEN_AGE => 3;
+
# States that are considered to be "open" for bugs.
use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED',
'UNCONFIRMED');
diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 50785c5b7..1888c76c0 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -715,7 +715,7 @@ use constant ABSTRACT_SCHEMA => {
# for these changes.
tokens => {
FIELDS => [
- userid => {TYPE => 'INT3', NOTNULL => 1} ,
+ userid => {TYPE => 'INT3'},
issuedate => {TYPE => 'DATETIME', NOTNULL => 1} ,
token => {TYPE => 'varchar(16)', NOTNULL => 1,
PRIMARYKEY => 1},
diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm
index a4ab54260..d34a11f24 100644
--- a/Bugzilla/Install/DB.pm
+++ b/Bugzilla/Install/DB.pm
@@ -471,6 +471,9 @@ sub update_table_definitions {
$dbh->bz_alter_column('keyworddefs', 'id',
{TYPE => 'SMALLSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+ # 2006-08-19 LpSolit@gmail.com - Bug 87795
+ $dbh->bz_alter_column('tokens', 'userid', {TYPE => 'INT3'});
+
################################################################
# New --TABLE-- changes should go *** A B O V E *** this point #
################################################################
diff --git a/Bugzilla/Token.pm b/Bugzilla/Token.pm
index 447d27507..6dd8baa6e 100644
--- a/Bugzilla/Token.pm
+++ b/Bugzilla/Token.pm
@@ -29,6 +29,7 @@ use strict;
# Bundle the functions in this file together into the "Bugzilla::Token" package.
package Bugzilla::Token;
+use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Mailer;
use Bugzilla::Util;
@@ -37,15 +38,45 @@ use Date::Format;
use Date::Parse;
################################################################################
-# Constants
+# Public Functions
################################################################################
-# The maximum number of days a token will remain valid.
-use constant MAX_TOKEN_AGE => 3;
+# Creates and sends a token to create a new user account.
+# It assumes that the login has the correct format and is not already in use.
+sub issue_new_user_account_token {
+ my $login_name = shift;
+ my $dbh = Bugzilla->dbh;
+ my $template = Bugzilla->template;
+ my $vars = {};
-################################################################################
-# Public Functions
-################################################################################
+ # Is there already a pending request for this login name? If yes, do not throw
+ # an error because the user may have lost his email with the token inside.
+ # But to prevent using this way to mailbomb an email address, make sure
+ # the last request is at least 10 minutes old before sending a new email.
+ trick_taint($login_name);
+
+ my $pending_requests =
+ $dbh->selectrow_array('SELECT COUNT(*)
+ FROM tokens
+ WHERE tokentype = ?
+ AND ' . $dbh->sql_istrcmp('eventdata', '?') . '
+ AND issuedate > NOW() - ' . $dbh->sql_interval(10, 'MINUTE'),
+ undef, ('account', $login_name));
+
+ ThrowUserError('too_soon_for_new_token', {'type' => 'account'}) if $pending_requests;
+
+ my ($token, $token_ts) = _create_token(undef, 'account', $login_name);
+
+ $vars->{'email'} = $login_name . Bugzilla->params->{'emailsuffix'};
+ $vars->{'token_ts'} = $token_ts;
+ $vars->{'token'} = $token;
+
+ my $message;
+ $template->process('account/email/request-new.txt.tmpl', $vars, \$message)
+ || ThrowTemplateError($template->error());
+
+ MessageToMTA($message);
+}
sub IssueEmailChangeToken {
my ($userid, $old_email, $new_email) = @_;
@@ -106,7 +137,7 @@ sub IssuePasswordToken {
WHERE ' . $dbh->sql_istrcmp('login_name', '?'),
undef, ('password', $loginname));
- ThrowUserError('too_soon_for_new_token') if $too_soon;
+ ThrowUserError('too_soon_for_new_token', {'type' => 'password'}) if $too_soon;
my ($token, $token_ts) = _create_token($userid, 'password', $::ENV{'REMOTE_ADDR'});
@@ -177,26 +208,25 @@ sub GenerateUniqueToken {
sub Cancel {
my ($token, $cancelaction, $vars) = @_;
my $dbh = Bugzilla->dbh;
+ my $template = Bugzilla->template;
$vars ||= {};
# Get information about the token being cancelled.
trick_taint($token);
- my ($issuedate, $tokentype, $eventdata, $loginname, $realname) =
+ my ($issuedate, $tokentype, $eventdata, $loginname) =
$dbh->selectrow_array('SELECT ' . $dbh->sql_date_format('issuedate') . ',
- tokentype, eventdata, login_name, realname
+ tokentype, eventdata, login_name
FROM tokens
- INNER JOIN profiles
+ LEFT JOIN profiles
ON tokens.userid = profiles.userid
WHERE token = ?',
undef, $token);
- # Get the email address of the Bugzilla maintainer.
- my $maintainer = Bugzilla->params->{'maintainer'};
-
- my $template = Bugzilla->template;
-
+ # If we are cancelling the creation of a new user account, then there
+ # is no entry in the 'profiles' table.
+ $loginname ||= $eventdata;
$vars->{'emailaddress'} = $loginname . Bugzilla->params->{'emailsuffix'};
- $vars->{'maintainer'} = $maintainer;
+ $vars->{'maintainer'} = Bugzilla->params->{'maintainer'};
$vars->{'remoteaddress'} = $::ENV{'REMOTE_ADDR'};
$vars->{'token'} = $token;
$vars->{'tokentype'} = $tokentype;
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index 12c680f78..54d84020f 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -1355,9 +1355,8 @@ sub insert_new_user {
VALUES (?, ?, NOW(), ?, NOW())',
undef, ($user->id, $who, $creation_date_fieldid));
- # Return the password to the calling code so it can be included
- # in an email sent to the user.
- return $password;
+ # Return the newly created user account.
+ return $user;
}
sub is_available_username {
@@ -1377,15 +1376,18 @@ sub is_available_username {
# was unsafe and required weird escaping; using substring to pull out
# the new/old email addresses and sql_position() to find the delimiter (':')
# is cleaner/safer
- my $sth = $dbh->prepare(
- "SELECT eventdata FROM tokens WHERE tokentype = 'emailold'
- AND SUBSTRING(eventdata, 1, ("
- . $dbh->sql_position(q{':'}, 'eventdata') . "- 1)) = ?
- OR SUBSTRING(eventdata, ("
- . $dbh->sql_position(q{':'}, 'eventdata') . "+ 1)) = ?");
- $sth->execute($username, $username);
-
- if (my ($eventdata) = $sth->fetchrow_array()) {
+ my $eventdata = $dbh->selectrow_array(
+ "SELECT eventdata
+ FROM tokens
+ WHERE (tokentype = 'emailold'
+ AND SUBSTRING(eventdata, 1, (" .
+ $dbh->sql_position(q{':'}, 'eventdata') . "- 1)) = ?)
+ OR (tokentype = 'emailnew'
+ AND SUBSTRING(eventdata, (" .
+ $dbh->sql_position(q{':'}, 'eventdata') . "+ 1)) = ?)",
+ undef, ($username, $username));
+
+ if ($eventdata) {
# Allow thru owner of token
if($old_username && ($eventdata eq "$old_username:$username")) {
return 1;
@@ -1459,7 +1461,7 @@ Bugzilla::User - Object for a Bugzilla user
$user->get_selectable_classifications;
# Class Functions
- $password = insert_new_user($username, $realname, $password, $disabledtext);
+ $user = insert_new_user($username, $realname, $password, $disabledtext);
=head1 DESCRIPTION
@@ -1815,8 +1817,7 @@ Params: $username (scalar, string) - The login name for the new user.
be sent depending on the user's
email preferences.
-Returns: The password for this user, in plain text, so it can be included
- in an e-mail sent to the user.
+Returns: The Bugzilla::User object representing the new user account.
=item C<is_available_username>