Commit ece3a7ec authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 332598: Move ValidatePassword() and DBNameToIdAndCheck() from globals.pl…

Bug 332598: Move ValidatePassword() and DBNameToIdAndCheck() from globals.pl into User.pm - Patch by Frédéric Buclin <LpSolit@gmail.com> r=mkanat a=myk
parent 46c78a8c
...@@ -178,16 +178,16 @@ sub ProcessOneBug { ...@@ -178,16 +178,16 @@ sub ProcessOneBug {
# At this point, we don't care if there are duplicates in these arrays. # At this point, we don't care if there are duplicates in these arrays.
my $changer = $forced->{'changer'}; my $changer = $forced->{'changer'};
if ($forced->{'owner'}) { if ($forced->{'owner'}) {
push (@assignees, &::DBNameToIdAndCheck($forced->{'owner'})); push (@assignees, login_to_id($forced->{'owner'}, THROW_ERROR));
} }
if ($forced->{'qacontact'}) { if ($forced->{'qacontact'}) {
push (@qa_contacts, &::DBNameToIdAndCheck($forced->{'qacontact'})); push (@qa_contacts, login_to_id($forced->{'qacontact'}, THROW_ERROR));
} }
if ($forced->{'cc'}) { if ($forced->{'cc'}) {
foreach my $cc (@{$forced->{'cc'}}) { foreach my $cc (@{$forced->{'cc'}}) {
push(@ccs, &::DBNameToIdAndCheck($cc)); push(@ccs, login_to_id($cc, THROW_ERROR));
} }
} }
......
...@@ -44,6 +44,9 @@ use base qw(Exporter); ...@@ -44,6 +44,9 @@ use base qw(Exporter);
AUTH_LOGINFAILED AUTH_LOGINFAILED
AUTH_DISABLED AUTH_DISABLED
USER_PASSWORD_MIN_LENGTH
USER_PASSWORD_MAX_LENGTH
LOGIN_OPTIONAL LOGIN_OPTIONAL
LOGIN_NORMAL LOGIN_NORMAL
LOGIN_REQUIRED LOGIN_REQUIRED
...@@ -71,6 +74,7 @@ use base qw(Exporter); ...@@ -71,6 +74,7 @@ use base qw(Exporter);
COMMENT_COLS COMMENT_COLS
UNLOCK_ABORT UNLOCK_ABORT
THROW_ERROR
RELATIONSHIPS RELATIONSHIPS
REL_ASSIGNEE REL_QA REL_REPORTER REL_CC REL_VOTER REL_ASSIGNEE REL_QA REL_REPORTER REL_CC REL_VOTER
...@@ -141,6 +145,10 @@ use constant AUTH_ERROR => 2; ...@@ -141,6 +145,10 @@ use constant AUTH_ERROR => 2;
use constant AUTH_LOGINFAILED => 3; use constant AUTH_LOGINFAILED => 3;
use constant AUTH_DISABLED => 4; use constant AUTH_DISABLED => 4;
# The minimum and maximum lengths a password must have.
use constant USER_PASSWORD_MIN_LENGTH => 3;
use constant USER_PASSWORD_MAX_LENGTH => 16;
use constant LOGIN_OPTIONAL => 0; use constant LOGIN_OPTIONAL => 0;
use constant LOGIN_NORMAL => 1; use constant LOGIN_NORMAL => 1;
use constant LOGIN_REQUIRED => 2; use constant LOGIN_REQUIRED => 2;
...@@ -192,6 +200,10 @@ use constant COMMENT_COLS => 80; ...@@ -192,6 +200,10 @@ use constant COMMENT_COLS => 80;
# because of error # because of error
use constant UNLOCK_ABORT => 1; use constant UNLOCK_ABORT => 1;
# Determine whether a validation routine should return 0 or throw
# an error when the validation fails.
use constant THROW_ERROR => 1;
use constant REL_ASSIGNEE => 0; use constant REL_ASSIGNEE => 0;
use constant REL_QA => 1; use constant REL_QA => 1;
use constant REL_REPORTER => 2; use constant REL_REPORTER => 2;
......
...@@ -239,7 +239,7 @@ sub init { ...@@ -239,7 +239,7 @@ sub init {
foreach my $name (split(',', $email)) { foreach my $name (split(',', $email)) {
$name = trim($name); $name = trim($name);
if ($name) { if ($name) {
&::DBNameToIdAndCheck($name); login_to_id($name, THROW_ERROR);
} }
} }
} }
...@@ -550,7 +550,7 @@ sub init { ...@@ -550,7 +550,7 @@ sub init {
my $table = "longdescs_$chartid"; my $table = "longdescs_$chartid";
push(@supptables, "INNER JOIN longdescs AS $table " . push(@supptables, "INNER JOIN longdescs AS $table " .
"ON $table.bug_id = bugs.bug_id"); "ON $table.bug_id = bugs.bug_id");
my $id = &::DBNameToIdAndCheck($v); my $id = login_to_id($v, THROW_ERROR);
$term = "$table.who = $id"; $term = "$table.who = $id";
}, },
"^long_?desc,changedbefore" => sub { "^long_?desc,changedbefore" => sub {
...@@ -691,7 +691,7 @@ sub init { ...@@ -691,7 +691,7 @@ sub init {
my $table = "longdescs_$chartid"; my $table = "longdescs_$chartid";
push(@supptables, "INNER JOIN longdescs AS $table " . push(@supptables, "INNER JOIN longdescs AS $table " .
"ON $table.bug_id = bugs.bug_id"); "ON $table.bug_id = bugs.bug_id");
my $id = &::DBNameToIdAndCheck($v); my $id = login_to_id($v, THROW_ERROR);
$term = "(($table.who = $id"; $term = "(($table.who = $id";
$term .= ") AND ($table.work_time <> 0))"; $term .= ") AND ($table.work_time <> 0))";
}, },
...@@ -805,7 +805,7 @@ sub init { ...@@ -805,7 +805,7 @@ sub init {
$f =~ m/^attachments\.(.*)$/; $f =~ m/^attachments\.(.*)$/;
my $field = $1; my $field = $1;
if ($t eq "changedby") { if ($t eq "changedby") {
$v = &::DBNameToIdAndCheck($v); $v = login_to_id($v, THROW_ERROR);
$q = &::SqlQuote($v); $q = &::SqlQuote($v);
$field = "submitter_id"; $field = "submitter_id";
$t = "equals"; $t = "equals";
...@@ -1126,7 +1126,7 @@ sub init { ...@@ -1126,7 +1126,7 @@ sub init {
if (!$fieldid) { if (!$fieldid) {
ThrowCodeError("invalid_field_name", {field => $f}); ThrowCodeError("invalid_field_name", {field => $f});
} }
my $id = &::DBNameToIdAndCheck($v); my $id = login_to_id($v, THROW_ERROR);
push(@supptables, "LEFT JOIN bugs_activity AS $table " . push(@supptables, "LEFT JOIN bugs_activity AS $table " .
"ON $table.bug_id = bugs.bug_id " . "ON $table.bug_id = bugs.bug_id " .
"AND $table.fieldid = $fieldid " . "AND $table.fieldid = $fieldid " .
......
...@@ -48,7 +48,7 @@ use Bugzilla::Classification; ...@@ -48,7 +48,7 @@ use Bugzilla::Classification;
use base qw(Exporter); use base qw(Exporter);
@Bugzilla::User::EXPORT = qw(insert_new_user is_available_username @Bugzilla::User::EXPORT = qw(insert_new_user is_available_username
login_to_id login_to_id validate_password
UserInGroup UserInGroup
USER_MATCH_MULTIPLE USER_MATCH_FAILED USER_MATCH_SUCCESS USER_MATCH_MULTIPLE USER_MATCH_FAILED USER_MATCH_SUCCESS
MATCH_SKIP_CONFIRM MATCH_SKIP_CONFIRM
...@@ -1360,7 +1360,7 @@ sub is_available_username { ...@@ -1360,7 +1360,7 @@ sub is_available_username {
} }
sub login_to_id { sub login_to_id {
my ($login) = (@_); my ($login, $throw_error) = @_;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
# $login will only be used by the following SELECT statement, so it's safe. # $login will only be used by the following SELECT statement, so it's safe.
trick_taint($login); trick_taint($login);
...@@ -1369,11 +1369,26 @@ sub login_to_id { ...@@ -1369,11 +1369,26 @@ sub login_to_id {
undef, $login); undef, $login);
if ($user_id) { if ($user_id) {
return $user_id; return $user_id;
} elsif ($throw_error) {
ThrowUserError('invalid_username', { name => $login });
} else { } else {
return 0; return 0;
} }
} }
sub validate_password {
my ($password, $matchpassword) = @_;
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
ThrowUserError('password_too_short');
} elsif (length($password) > USER_PASSWORD_MAX_LENGTH) {
ThrowUserError('password_too_long');
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
ThrowUserError('passwords_dont_match');
}
return 1;
}
sub UserInGroup { sub UserInGroup {
return exists Bugzilla->user->groups->{$_[0]} ? 1 : 0; return exists Bugzilla->user->groups->{$_[0]} ? 1 : 0;
} }
...@@ -1774,13 +1789,15 @@ Params: $username (scalar, string) - The full login name of the username ...@@ -1774,13 +1789,15 @@ Params: $username (scalar, string) - The full login name of the username
can change his username to $username. (That is, this function can change his username to $username. (That is, this function
will return a boolean true value). will return a boolean true value).
=item C<login_to_id($login)> =item C<login_to_id($login, $throw_error)>
Takes a login name of a Bugzilla user and changes that into a numeric Takes a login name of a Bugzilla user and changes that into a numeric
ID for that user. This ID can then be passed to Bugzilla::User::new to ID for that user. This ID can then be passed to Bugzilla::User::new to
create a new user. create a new user.
If no valid user exists with that login name, then the function will return 0. If no valid user exists with that login name, then the function returns 0.
However, if $throw_error is set, the function will throw a user error
instead of returning.
This function can also be used when you want to just find out the userid This function can also be used when you want to just find out the userid
of a user, but you don't want the full weight of Bugzilla::User. of a user, but you don't want the full weight of Bugzilla::User.
...@@ -1788,6 +1805,14 @@ of a user, but you don't want the full weight of Bugzilla::User. ...@@ -1788,6 +1805,14 @@ of a user, but you don't want the full weight of Bugzilla::User.
However, consider using a Bugzilla::User object instead of this function However, consider using a Bugzilla::User object instead of this function
if you need more information about the user than just their ID. if you need more information about the user than just their ID.
=item C<validate_password($passwd1, $passwd2)>
Returns true if a password is valid (i.e. meets Bugzilla's
requirements for length and content), else returns false.
If a second password is passed in, this function also verifies that
the two passwords match.
=item C<UserInGroup($groupname)> =item C<UserInGroup($groupname)>
Takes a name of a group, and returns 1 if a user is in the group, 0 otherwise. Takes a name of a group, and returns 1 if a user is in the group, 0 otherwise.
......
...@@ -209,7 +209,7 @@ if ($action eq 'search') { ...@@ -209,7 +209,7 @@ if ($action eq 'search') {
|| ThrowUserError('illegal_email_address', {addr => $login}); || ThrowUserError('illegal_email_address', {addr => $login});
is_available_username($login) is_available_username($login)
|| ThrowUserError('account_exists', {email => $login}); || ThrowUserError('account_exists', {email => $login});
ValidatePassword($password); validate_password($password);
# Login and password are validated now, and realname and disabledtext # Login and password are validated now, and realname and disabledtext
# are allowed to contain anything # are allowed to contain anything
...@@ -296,7 +296,7 @@ if ($action eq 'search') { ...@@ -296,7 +296,7 @@ if ($action eq 'search') {
} }
if ($password) { if ($password) {
# Validate, then trick_taint. # Validate, then trick_taint.
ValidatePassword($password) if $password; validate_password($password) if $password;
trick_taint($password); trick_taint($password);
push(@changedFields, 'cryptpassword'); push(@changedFields, 'cryptpassword');
push(@values, bz_crypt($password)); push(@values, bz_crypt($password));
......
...@@ -204,22 +204,6 @@ sub AnyDefaultGroups { ...@@ -204,22 +204,6 @@ sub AnyDefaultGroups {
return $::CachedAnyDefaultGroups; return $::CachedAnyDefaultGroups;
} }
sub ValidatePassword {
# Determines whether or not a password is valid (i.e. meets Bugzilla's
# requirements for length and content).
# If a second password is passed in, this function also verifies that
# the two passwords match.
my ($password, $matchpassword) = @_;
if (length($password) < 3) {
ThrowUserError("password_too_short");
} elsif (length($password) > 16) {
ThrowUserError("password_too_long");
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
ThrowUserError("passwords_dont_match");
}
}
sub DBID_to_name { sub DBID_to_name {
my ($id) = (@_); my ($id) = (@_);
return "__UNKNOWN__" if !defined $id; return "__UNKNOWN__" if !defined $id;
...@@ -242,16 +226,6 @@ sub DBID_to_name { ...@@ -242,16 +226,6 @@ sub DBID_to_name {
return $::cachedNameArray{$id}; return $::cachedNameArray{$id};
} }
sub DBNameToIdAndCheck {
my ($name) = (@_);
my $result = login_to_id($name);
if ($result > 0) {
return $result;
}
ThrowUserError("invalid_username", { name => $name });
}
sub get_product_id { sub get_product_id {
my ($prod) = @_; my ($prod) = @_;
PushGlobalSQLState(); PushGlobalSQLState();
......
...@@ -155,7 +155,7 @@ if (!UserInGroup("editbugs") || $cgi->param('assigned_to') eq "") { ...@@ -155,7 +155,7 @@ if (!UserInGroup("editbugs") || $cgi->param('assigned_to') eq "") {
$cgi->param(-name => 'assigned_to', -value => $initialowner); $cgi->param(-name => 'assigned_to', -value => $initialowner);
} else { } else {
$cgi->param(-name => 'assigned_to', $cgi->param(-name => 'assigned_to',
-value => DBNameToIdAndCheck(trim($cgi->param('assigned_to')))); -value => login_to_id(trim($cgi->param('assigned_to')), THROW_ERROR));
} }
my @bug_fields = ("version", "rep_platform", my @bug_fields = ("version", "rep_platform",
...@@ -182,7 +182,7 @@ if (Param("useqacontact")) { ...@@ -182,7 +182,7 @@ if (Param("useqacontact")) {
WHERE id = ?}, WHERE id = ?},
undef, $component_id); undef, $component_id);
} else { } else {
$qa_contact = DBNameToIdAndCheck(trim($cgi->param('qa_contact'))); $qa_contact = login_to_id(trim($cgi->param('qa_contact')), THROW_ERROR);
} }
if ($qa_contact) { if ($qa_contact) {
...@@ -267,7 +267,7 @@ my %ccids; ...@@ -267,7 +267,7 @@ my %ccids;
if (defined $cgi->param('cc')) { if (defined $cgi->param('cc')) {
foreach my $person ($cgi->param('cc')) { foreach my $person ($cgi->param('cc')) {
next unless $person; next unless $person;
my $ccid = DBNameToIdAndCheck($person); my $ccid = login_to_id($person, THROW_ERROR);
if ($ccid && !$ccids{$ccid}) { if ($ccid && !$ccids{$ccid}) {
$ccids{$ccid} = 1; $ccids{$ccid} = 1;
} }
......
...@@ -1050,7 +1050,7 @@ if (defined $cgi->param('newcc') ...@@ -1050,7 +1050,7 @@ if (defined $cgi->param('newcc')
if ($cc_add) { if ($cc_add) {
$cc_add =~ s/[\s,]+/ /g; # Change all delimiters to a single space $cc_add =~ s/[\s,]+/ /g; # Change all delimiters to a single space
foreach my $person ( split(" ", $cc_add) ) { foreach my $person ( split(" ", $cc_add) ) {
my $pid = DBNameToIdAndCheck($person); my $pid = login_to_id($person, THROW_ERROR);
$cc_add{$pid} = $person; $cc_add{$pid} = $person;
} }
} }
...@@ -1060,7 +1060,7 @@ if (defined $cgi->param('newcc') ...@@ -1060,7 +1060,7 @@ if (defined $cgi->param('newcc')
if ($cc_remove) { if ($cc_remove) {
$cc_remove =~ s/[\s,]+/ /g; # Change all delimiters to a single space $cc_remove =~ s/[\s,]+/ /g; # Change all delimiters to a single space
foreach my $person ( split(" ", $cc_remove) ) { foreach my $person ( split(" ", $cc_remove) ) {
my $pid = DBNameToIdAndCheck($person); my $pid = login_to_id($person, THROW_ERROR);
$cc_remove{$pid} = $person; $cc_remove{$pid} = $person;
} }
} }
...@@ -1087,7 +1087,7 @@ if (defined $cgi->param('qa_contact') ...@@ -1087,7 +1087,7 @@ if (defined $cgi->param('qa_contact')
my $name = trim($cgi->param('qa_contact')); my $name = trim($cgi->param('qa_contact'));
# The QA contact cannot be deleted from show_bug.cgi for a single bug! # The QA contact cannot be deleted from show_bug.cgi for a single bug!
if ($name ne $cgi->param('dontchange')) { if ($name ne $cgi->param('dontchange')) {
$qacontact = DBNameToIdAndCheck($name) if ($name ne ""); $qacontact = login_to_id($name, THROW_ERROR) if ($name ne "");
if ($qacontact && Param("strict_isolation")) { if ($qacontact && Param("strict_isolation")) {
$usercache{$qacontact} ||= Bugzilla::User->new($qacontact); $usercache{$qacontact} ||= Bugzilla::User->new($qacontact);
my $qa_user = $usercache{$qacontact}; my $qa_user = $usercache{$qacontact};
...@@ -1172,7 +1172,7 @@ SWITCH: for ($cgi->param('knob')) { ...@@ -1172,7 +1172,7 @@ SWITCH: for ($cgi->param('knob')) {
DoComma(); DoComma();
if (defined $cgi->param('assigned_to') if (defined $cgi->param('assigned_to')
&& trim($cgi->param('assigned_to')) ne "") { && trim($cgi->param('assigned_to')) ne "") {
$assignee = DBNameToIdAndCheck(trim($cgi->param('assigned_to'))); $assignee = login_to_id(trim($cgi->param('assigned_to')), THROW_ERROR);
if (Param("strict_isolation")) { if (Param("strict_isolation")) {
$usercache{$assignee} ||= Bugzilla::User->new($assignee); $usercache{$assignee} ||= Bugzilla::User->new($assignee);
my $assign_user = $usercache{$assignee}; my $assign_user = $usercache{$assignee};
......
...@@ -1022,13 +1022,13 @@ ...@@ -1022,13 +1022,13 @@
[% ELSIF error == "password_too_long" %] [% ELSIF error == "password_too_long" %]
[% title = "Password Too Long" %] [% title = "Password Too Long" %]
The password is more than 16 characters long. It must be no more than The password must be no more than
16 characters. [%+ constants.USER_PASSWORD_MAX_LENGTH FILTER html %] characters long.
[% ELSIF error == "password_too_short" %] [% ELSIF error == "password_too_short" %]
[% title = "Password Too Short" %] [% title = "Password Too Short" %]
The password is less than three characters long. It must be at least The password must be at least
three characters. [%+ constants.USER_PASSWORD_MIN_LENGTH FILTER html %] characters long.
[% ELSIF error == "patch_too_large" %] [% ELSIF error == "patch_too_large" %]
[% title = "File Too Large" %] [% title = "File Too Large" %]
......
...@@ -68,7 +68,7 @@ if ($cgi->param('t')) { ...@@ -68,7 +68,7 @@ if ($cgi->param('t')) {
# Make sure the token contains only valid characters in the right amount. # Make sure the token contains only valid characters in the right amount.
# Validate password will throw an error if token is invalid # Validate password will throw an error if token is invalid
ValidatePassword($::token); validate_password($::token);
trick_taint($::token); # Only used in placeholders trick_taint($::token); # Only used in placeholders
Bugzilla::Token::CleanTokenTable(); Bugzilla::Token::CleanTokenTable();
...@@ -128,7 +128,7 @@ if ( $::action eq 'chgpw' ) { ...@@ -128,7 +128,7 @@ if ( $::action eq 'chgpw' ) {
&& defined $cgi->param('matchpassword') && defined $cgi->param('matchpassword')
|| ThrowUserError("require_new_password"); || ThrowUserError("require_new_password");
ValidatePassword($cgi->param('password'), $cgi->param('matchpassword')); validate_password($cgi->param('password'), $cgi->param('matchpassword'));
} }
################################################################################ ################################################################################
......
...@@ -96,7 +96,7 @@ sub SaveAccount { ...@@ -96,7 +96,7 @@ sub SaveAccount {
{ {
$cgi->param('new_password1') $cgi->param('new_password1')
|| ThrowUserError("new_password_missing"); || ThrowUserError("new_password_missing");
ValidatePassword($pwd1, $pwd2); validate_password($pwd1, $pwd2);
if ($cgi->param('Bugzilla_password') ne $pwd1) { if ($cgi->param('Bugzilla_password') ne $pwd1) {
my $cryptedpassword = bz_crypt($pwd1); my $cryptedpassword = bz_crypt($pwd1);
...@@ -313,7 +313,7 @@ sub SaveEmail { ...@@ -313,7 +313,7 @@ sub SaveEmail {
my @new_watch_names = split(/[,\s]+/, $cgi->param('watchedusers')); my @new_watch_names = split(/[,\s]+/, $cgi->param('watchedusers'));
my %new_watch_ids; my %new_watch_ids;
foreach my $username (@new_watch_names) { foreach my $username (@new_watch_names) {
my $watched_userid = DBNameToIdAndCheck(trim($username)); my $watched_userid = login_to_id(trim($username), THROW_ERROR);
$new_watch_ids{$watched_userid} = 1; $new_watch_ids{$watched_userid} = 1;
} }
my ($removed, $added) = diff_arrays($old_watch_ids, [keys %new_watch_ids]); my ($removed, $added) = diff_arrays($old_watch_ids, [keys %new_watch_ids]);
......
...@@ -29,6 +29,7 @@ use lib "."; ...@@ -29,6 +29,7 @@ use lib ".";
use Bugzilla; use Bugzilla;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Bug; use Bugzilla::Bug;
use Bugzilla::User;
require "globals.pl"; require "globals.pl";
...@@ -119,7 +120,7 @@ sub show_user { ...@@ -119,7 +120,7 @@ sub show_user {
$bug_id ||= ""; $bug_id ||= "";
my $name = $cgi->param('user') || $user->login; my $name = $cgi->param('user') || $user->login;
my $who = DBNameToIdAndCheck($name); my $who = login_to_id($name, THROW_ERROR);
my $userid = $user->id; my $userid = $user->id;
my $canedit = (Param('usevotes') && $userid == $who) ? 1 : 0; my $canedit = (Param('usevotes') && $userid == $who) ? 1 : 0;
......
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