summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2015-03-26 04:56:02 +0100
committerByron Jones <glob@mozilla.com>2015-03-26 04:56:02 +0100
commitd4a53a6c7bce28a66ff0dc70def2469692f8444c (patch)
tree59e8e8cf8f6c4fee8acee84e4d3f57e404227b7c
parent48c23b11f2fc9d7f9a0666e58e77b8a03eb94dbb (diff)
downloadbugzilla-d4a53a6c7bce28a66ff0dc70def2469692f8444c.tar.gz
bugzilla-d4a53a6c7bce28a66ff0dc70def2469692f8444c.tar.xz
Bug 1147550: Minimum password length handler not trusted by password change
-rw-r--r--Bugzilla/Auth/Verify/DB.pm17
-rw-r--r--Bugzilla/Config/Auth.pm9
-rw-r--r--Bugzilla/User.pm35
-rw-r--r--Bugzilla/WebService/Constants.pm3
-rw-r--r--template/en/default/admin/params/auth.html.tmpl8
-rw-r--r--template/en/default/global/user-error.html.tmpl16
6 files changed, 64 insertions, 24 deletions
diff --git a/Bugzilla/Auth/Verify/DB.pm b/Bugzilla/Auth/Verify/DB.pm
index 2840b4ab8..aaa1b6c87 100644
--- a/Bugzilla/Auth/Verify/DB.pm
+++ b/Bugzilla/Auth/Verify/DB.pm
@@ -74,10 +74,19 @@ sub check_credentials {
};
}
- # Force the user to type a longer password if it's too short.
- if (length($password) < USER_PASSWORD_MIN_LENGTH) {
- return { failure => AUTH_ERROR, user_error => 'password_current_too_short',
- details => { locked_user => $user } };
+ # Force the user to change their password if it does not meet the current
+ # criteria. This should usually only happen if the criteria has changed.
+ if (Bugzilla->usage_mode == USAGE_MODE_BROWSER &&
+ Bugzilla->params->{password_check_on_login})
+ {
+ my $check = validate_password_check($password);
+ if ($check) {
+ return {
+ failure => AUTH_ERROR,
+ user_error => $check,
+ details => { locked_user => $user }
+ }
+ }
}
# The user's credentials are okay, so delete any outstanding
diff --git a/Bugzilla/Config/Auth.pm b/Bugzilla/Config/Auth.pm
index d70c1f81e..f87126713 100644
--- a/Bugzilla/Config/Auth.pm
+++ b/Bugzilla/Config/Auth.pm
@@ -136,7 +136,14 @@ sub get_param_list {
'letters_numbers_specialchars' ],
default => 'no_constraints',
checker => \&check_multi
- } );
+ },
+
+ {
+ name => 'password_check_on_login',
+ type => 'b',
+ default => '1'
+ },
+ );
return @param_list;
}
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index 20cc061dd..d9adec4c7 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -63,7 +63,7 @@ use URI::QueryParam;
use base qw(Bugzilla::Object Exporter);
@Bugzilla::User::EXPORT = qw(is_available_username
- login_to_id user_id_to_login validate_password
+ login_to_id user_id_to_login validate_password validate_password_check
USER_MATCH_MULTIPLE USER_MATCH_FAILED USER_MATCH_SUCCESS
MATCH_SKIP_CONFIRM
);
@@ -2376,29 +2376,35 @@ sub user_id_to_login {
}
sub validate_password {
+ my $check = validate_password_check(@_);
+ ThrowUserError($check) if $check;
+ return 1;
+}
+
+sub validate_password_check {
my ($password, $matchpassword) = @_;
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
- ThrowUserError('password_too_short');
+ return 'password_too_short';
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
- ThrowUserError('passwords_dont_match');
+ return 'passwords_dont_match';
}
-
+
my $complexity_level = Bugzilla->params->{password_complexity};
if ($complexity_level eq 'letters_numbers_specialchars') {
- ThrowUserError('password_not_complex')
+ return 'password_not_complex'
if ($password !~ /[[:alpha:]]/ || $password !~ /\d/ || $password !~ /[[:punct:]]/);
} elsif ($complexity_level eq 'letters_numbers') {
- ThrowUserError('password_not_complex')
+ return 'password_not_complex'
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/ || $password !~ /\d/);
} elsif ($complexity_level eq 'mixed_letters') {
- ThrowUserError('password_not_complex')
+ return 'password_not_complex'
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/);
}
# Having done these checks makes us consider the password untainted.
trick_taint($_[0]);
- return 1;
+ return;
}
@@ -3023,12 +3029,23 @@ we return an empty string.
=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.
+requirements for length and content), else throws an error.
Untaints C<$passwd1> if successful.
If a second password is passed in, this function also verifies that
the two passwords match.
+=item C<validate_password_check($passwd1, $passwd2)>
+
+This sub routine is similair to C<validate_password>, except that it allows
+the calling code to handle its own errors.
+
+Returns undef and untaints C<$passwd1> if a password is valid (i.e. meets
+Bugzilla's requirements for length and content), else returns the error.
+
+If a second password is passed in, this function also verifies that
+the two passwords match.
+
=item C<match_field($data, $fields, $behavior)>
=over
diff --git a/Bugzilla/WebService/Constants.pm b/Bugzilla/WebService/Constants.pm
index 4678d468d..a8d2f1db2 100644
--- a/Bugzilla/WebService/Constants.pm
+++ b/Bugzilla/WebService/Constants.pm
@@ -150,7 +150,8 @@ use constant WS_ERROR_CODE => {
auth_invalid_email => 302,
extern_id_conflict => -303,
auth_failure => 304,
- password_current_too_short => 305,
+ password_too_short => 305,
+ password_not_complex => 305,
api_key_not_valid => 306,
api_key_revoked => 306,
auth_invalid_token => 307,
diff --git a/template/en/default/admin/params/auth.html.tmpl b/template/en/default/admin/params/auth.html.tmpl
index 7a8d34791..85d707706 100644
--- a/template/en/default/admin/params/auth.html.tmpl
+++ b/template/en/default/admin/params/auth.html.tmpl
@@ -143,5 +143,11 @@
"lower case letter and a number.</li>" _
"<li>letters_numbers_specialchars - Passwords must contain at least one " _
"UPPER or one lower case letter, a number and a special character.</li></ul>"
- }
+ },
+
+ password_check_on_login =>
+ "If set, $terms.Bugzilla will check that the password meets the current " _
+ "complexity rules and minimum length requirements when the user logs " _
+ "into the $terms.Bugzilla web interface. If it doesn't, the user would " _
+ "not be able to log in, and recieve a message to reset their password."
%]
diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl
index 938c4d44d..250ab0e1d 100644
--- a/template/en/default/global/user-error.html.tmpl
+++ b/template/en/default/global/user-error.html.tmpl
@@ -1412,18 +1412,14 @@
[% title = "Passwords Don't Match" %]
The two passwords you entered did not match.
- [% ELSIF error == "password_current_too_short" %]
- [% title = "New Password Required" %]
- Your password is currently less than
- [%+ constants.USER_PASSWORD_MIN_LENGTH FILTER html %] characters long,
- which is the new minimum length required for passwords.
- You must <a href="token.cgi?a=reqpw&amp;loginname=[% locked_user.email FILTER uri %]">
- request a new password</a> in order to log in again.
-
[% ELSIF error == "password_too_short" %]
[% title = "Password Too Short" %]
The password must be at least
[%+ constants.USER_PASSWORD_MIN_LENGTH FILTER html %] characters long.
+ [% IF locked_user %]
+ You must <a href="token.cgi?a=reqpw&amp;loginname=[% locked_user.email FILTER uri %]&amp;token=[% issue_hash_token(['reqpw']) FILTER uri %]">
+ request a new password</a> in order to log in again.
+ [% END %]
[% ELSIF error == "password_not_complex" %]
[% title = "Password Fails Requirements" %]
@@ -1441,6 +1437,10 @@
<li>digit</li>
[% END %]
</ul>
+ [% IF locked_user %]
+ You must <a href="token.cgi?a=reqpw&amp;loginname=[% locked_user.email FILTER uri %]&amp;token=[% issue_hash_token(['reqpw']) FILTER uri %]">
+ request a new password</a> in order to log in again.
+ [% END %]
[% ELSIF error == "password_not_complex" %]
[% title = "Password Fails Requirements" %]