Bug 1009013 - Require a user to change their password if they log in and their current password does not meet the password complexity rules
r=glob, a=sgreen git-svn-id: svn://10.0.0.236/trunk@265566 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
2c0b45ce27
commit
d53c6de213
@ -1 +1 @@
|
|||||||
9130
|
9131
|
||||||
@ -1 +1 @@
|
|||||||
ab1b842ba2e2f9ad3774c6c415129a4e196acc57
|
b8ecdca238744552db04acb5450ce078d9760a4c
|
||||||
@ -56,10 +56,19 @@ sub check_credentials {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
# Force the user to type a longer password if it's too short.
|
# Force the user to change their password if it does not meet the current
|
||||||
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
|
# criteria. This should usually only happen if the criteria has changed.
|
||||||
return { failure => AUTH_ERROR, user_error => 'password_current_too_short',
|
if (Bugzilla->usage_mode == USAGE_MODE_BROWSER &&
|
||||||
details => { locked_user => $user } };
|
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
|
# The user's credentials are okay, so delete any outstanding
|
||||||
|
|||||||
@ -114,7 +114,14 @@ sub get_param_list {
|
|||||||
'letters_numbers_specialchars' ],
|
'letters_numbers_specialchars' ],
|
||||||
default => 'no_constraints',
|
default => 'no_constraints',
|
||||||
checker => \&check_multi
|
checker => \&check_multi
|
||||||
} );
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name => 'password_check_on_login',
|
||||||
|
type => 'b',
|
||||||
|
default => '1'
|
||||||
|
},
|
||||||
|
);
|
||||||
return @param_list;
|
return @param_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ use URI::QueryParam;
|
|||||||
|
|
||||||
use parent qw(Bugzilla::Object Exporter);
|
use parent qw(Bugzilla::Object Exporter);
|
||||||
@Bugzilla::User::EXPORT = qw(is_available_username
|
@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
|
USER_MATCH_MULTIPLE USER_MATCH_FAILED USER_MATCH_SUCCESS
|
||||||
MATCH_SKIP_CONFIRM
|
MATCH_SKIP_CONFIRM
|
||||||
);
|
);
|
||||||
@ -2449,29 +2449,35 @@ sub login_to_id {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub validate_password {
|
sub validate_password {
|
||||||
|
my $check = validate_password_check(@_);
|
||||||
|
ThrowUserError($check) if $check;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub validate_password_check {
|
||||||
my ($password, $matchpassword) = @_;
|
my ($password, $matchpassword) = @_;
|
||||||
|
|
||||||
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
|
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
|
||||||
ThrowUserError('password_too_short');
|
return 'password_too_short';
|
||||||
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
|
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
|
||||||
ThrowUserError('passwords_dont_match');
|
return 'passwords_dont_match';
|
||||||
}
|
}
|
||||||
|
|
||||||
my $complexity_level = Bugzilla->params->{password_complexity};
|
my $complexity_level = Bugzilla->params->{password_complexity};
|
||||||
if ($complexity_level eq 'letters_numbers_specialchars') {
|
if ($complexity_level eq 'letters_numbers_specialchars') {
|
||||||
ThrowUserError('password_not_complex')
|
return 'password_not_complex'
|
||||||
if ($password !~ /[[:alpha:]]/ || $password !~ /\d/ || $password !~ /[[:punct:]]/);
|
if ($password !~ /[[:alpha:]]/ || $password !~ /\d/ || $password !~ /[[:punct:]]/);
|
||||||
} elsif ($complexity_level eq 'letters_numbers') {
|
} elsif ($complexity_level eq 'letters_numbers') {
|
||||||
ThrowUserError('password_not_complex')
|
return 'password_not_complex'
|
||||||
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/ || $password !~ /\d/);
|
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/ || $password !~ /\d/);
|
||||||
} elsif ($complexity_level eq 'mixed_letters') {
|
} elsif ($complexity_level eq 'mixed_letters') {
|
||||||
ThrowUserError('password_not_complex')
|
return 'password_not_complex'
|
||||||
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/);
|
if ($password !~ /[[:lower:]]/ || $password !~ /[[:upper:]]/);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Having done these checks makes us consider the password untainted.
|
# Having done these checks makes us consider the password untainted.
|
||||||
trick_taint($_[0]);
|
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)>
|
=item C<validate_password($passwd1, $passwd2)>
|
||||||
|
|
||||||
Returns true if a password is valid (i.e. meets Bugzilla's
|
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.
|
Untaints C<$passwd1> if successful.
|
||||||
|
|
||||||
If a second password is passed in, this function also verifies that
|
If a second password is passed in, this function also verifies that
|
||||||
the two passwords match.
|
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)>
|
=item C<match_field($data, $fields, $behavior)>
|
||||||
|
|
||||||
=over
|
=over
|
||||||
|
|||||||
@ -142,7 +142,8 @@ use constant WS_ERROR_CODE => {
|
|||||||
auth_invalid_email => 302,
|
auth_invalid_email => 302,
|
||||||
extern_id_conflict => -303,
|
extern_id_conflict => -303,
|
||||||
auth_failure => 304,
|
auth_failure => 304,
|
||||||
password_current_too_short => 305,
|
password_too_short => 305,
|
||||||
|
password_not_complex => 305,
|
||||||
api_key_not_valid => 306,
|
api_key_not_valid => 306,
|
||||||
api_key_revoked => 306,
|
api_key_revoked => 306,
|
||||||
auth_invalid_token => 307,
|
auth_invalid_token => 307,
|
||||||
|
|||||||
@ -133,5 +133,11 @@
|
|||||||
"lower case letter and a number.</li>" _
|
"lower case letter and a number.</li>" _
|
||||||
"<li>letters_numbers_specialchars - Passwords must contain at least one " _
|
"<li>letters_numbers_specialchars - Passwords must contain at least one " _
|
||||||
"letter, a number and a special character.</li></ul>"
|
"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."
|
||||||
}
|
}
|
||||||
%]
|
%]
|
||||||
|
|||||||
@ -1459,18 +1459,14 @@
|
|||||||
[% title = "Passwords Don't Match" %]
|
[% title = "Passwords Don't Match" %]
|
||||||
The two passwords you entered did not 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" %]
|
[% ELSIF error == "password_too_short" %]
|
||||||
[% title = "Password Too Short" %]
|
[% title = "Password Too Short" %]
|
||||||
The password must be at least
|
The password must be at least
|
||||||
[%+ constants.USER_PASSWORD_MIN_LENGTH FILTER html %] characters long.
|
[%+ 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" %]
|
[% ELSIF error == "password_not_complex" %]
|
||||||
[% title = "Password Fails Requirements" %]
|
[% title = "Password Fails Requirements" %]
|
||||||
@ -1488,6 +1484,10 @@
|
|||||||
<li>digit</li>
|
<li>digit</li>
|
||||||
[% END %]
|
[% END %]
|
||||||
</ul>
|
</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 == "product_access_denied" %]
|
[% ELSIF error == "product_access_denied" %]
|
||||||
[% title = "Product Access Denied" %]
|
[% title = "Product Access Denied" %]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user