diff options
-rw-r--r-- | Bugzilla/Auth/Verify/DB.pm | 17 | ||||
-rw-r--r-- | Bugzilla/Config/Auth.pm | 9 | ||||
-rw-r--r-- | Bugzilla/User.pm | 35 | ||||
-rw-r--r-- | Bugzilla/WebService/Constants.pm | 3 | ||||
-rw-r--r-- | template/en/default/admin/params/auth.html.tmpl | 8 | ||||
-rw-r--r-- | template/en/default/global/user-error.html.tmpl | 16 |
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&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&loginname=[% locked_user.email FILTER uri %]&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&loginname=[% locked_user.email FILTER uri %]&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" %] |