]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1009013 - Require a user to change their password if they log in and their curren...
authorSimon Green <sgreen@redhat.com>
Wed, 10 Sep 2014 23:45:23 +0000 (09:45 +1000)
committerSimon Green <sgreen@redhat.com>
Wed, 10 Sep 2014 23:45:23 +0000 (09:45 +1000)
r=glob, a=sgreen

Bugzilla/Auth/Verify/DB.pm
Bugzilla/Config/Auth.pm
Bugzilla/User.pm
Bugzilla/WebService/Constants.pm
template/en/default/admin/params/auth.html.tmpl
template/en/default/global/user-error.html.tmpl

index ad7f15d240b6e26221ec31a32261a2d9d6580392..28a9310c97cb047ae6bc267136fc6fb9d1947a8c 100644 (file)
@@ -56,10 +56,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
index bf5db9d97c716eae2603ad057a7aa6b7102a8c2e..78d719b15d35bc7cfafe4ae876bae4f6d22311df 100644 (file)
@@ -114,7 +114,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;
 }
 
index 58565daf90ccdaad14cdb15c144b19b2cf9fd600..acedc65f2a38d9fa49bd247eedf30b703ce86483 100644 (file)
@@ -32,7 +32,7 @@ use URI::QueryParam;
 
 use parent qw(Bugzilla::Object Exporter);
 @Bugzilla::User::EXPORT = qw(is_available_username
-    login_to_id validate_password
+    login_to_id validate_password validate_password_check
     USER_MATCH_MULTIPLE USER_MATCH_FAILED USER_MATCH_SUCCESS
     MATCH_SKIP_CONFIRM
 );
@@ -2449,29 +2449,35 @@ sub login_to_id {
 }
 
 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;
 }
 
 
@@ -3142,12 +3148,23 @@ 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.
+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
index f76f6b481429d11df1a85c30e75f6dde9aaaaecd..d612ebc7517b2d96f88fd4b20d3d92b975a8c405 100644 (file)
@@ -142,7 +142,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,
index bf8539b873ec53da3a892ee2e9bebd5b03bba637..902d2fc826bf33ff8bda10515f6891abfefe8245 100644 (file)
     "lower case letter and a number.</li>" _
     "<li>letters_numbers_specialchars - Passwords must contain at least one " _
     "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."
   }
 %]
index 48cbcad47c1f0790789c85308c9c81baa3360a73..055bde3d41613771d51e1ff06ea34e313edc2221 100644 (file)
     [% 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" %]
         <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 == "product_access_denied" %]
     [% title = "Product Access Denied" %]