mirror of
https://github.com/webmin/webmin.git
synced 2026-06-20 03:10:30 +01:00
Add new password restriction for min days before a change is allowed
This commit is contained in:
@@ -246,7 +246,7 @@ else {
|
||||
# Password is blank
|
||||
if (!$mconfig{'empty_mode'}) {
|
||||
local $err = &useradmin::check_password_restrictions(
|
||||
"", $user);
|
||||
"", $user, $in{'new'} ? 'none' : \%ouser);
|
||||
&error($err) if ($err);
|
||||
}
|
||||
$pass = "";
|
||||
@@ -263,7 +263,8 @@ else {
|
||||
elsif ($in{'passmode'} == 3) {
|
||||
# Normal password entered - check restrictions
|
||||
local $err = &useradmin::check_password_restrictions(
|
||||
$in{'pass'}, $user);
|
||||
$in{'pass'}, $user,
|
||||
$in{'new'} ? 'none' : \%ouser);
|
||||
&error($err) if ($err);
|
||||
$pass = $pfx.&encrypt_password($in{'pass'});
|
||||
$plainpass = $in{'pass'};
|
||||
|
||||
@@ -46,7 +46,7 @@ $again =~ s/\r|\n//g;
|
||||
$pass eq $again || &errordie("Passwords don't match");
|
||||
|
||||
# Check password sanity
|
||||
$err = &useradmin::check_password_restrictions($pass, $ARGV[0]);
|
||||
$err = &useradmin::check_password_restrictions($pass, $ARGV[0], $user);
|
||||
&errordie($err) if ($err);
|
||||
|
||||
# Do the change!
|
||||
|
||||
@@ -68,7 +68,7 @@ else {
|
||||
$in{'new'} eq $in{'repeat'} || &error($text{'passwd_erepeat'});
|
||||
}
|
||||
$err = &useradmin::check_password_restrictions(
|
||||
$in{'new'}, $in{'user'});
|
||||
$in{'new'}, $in{'user'}, $user);
|
||||
&error($err) if ($err);
|
||||
|
||||
&can_edit_passwd([ $user->{'user'}, $user->{'pass'},
|
||||
|
||||
@@ -69,3 +69,5 @@ Fixed an XSS vulnerability that can be triggered if an attacker has the ability
|
||||
---- Changes since 1.550 ----
|
||||
Updated all links to users and groups to be by name instead of by index, to avoid incorrect links if the passwd or group files are changed manually or by another Webmin session.
|
||||
The faster lastlog command is now used to get the most recent login time on Linux, for display in the user list.
|
||||
---- Changes since 1.580 ----
|
||||
Added a new password restriction for the minimum number of days before a password can be changed.
|
||||
|
||||
@@ -54,6 +54,7 @@ passwd_re=Perl regexp to check password against,3,None
|
||||
passwd_same=Prevent passwords containing username?,1,1-Yes,0-No
|
||||
passwd_prog=External password-checking program,3,None
|
||||
passwd_progmode=Pass username and password to program,1,1-As input,0-As parameters
|
||||
passwd_mindays=Number of days before password change is allowed,3,None
|
||||
|
||||
line0=Before and after commands,11
|
||||
pre_command=Command to run before making changes,0
|
||||
|
||||
@@ -176,6 +176,7 @@ usave_epasswd_min=Password must be at least $1 letters long
|
||||
usave_epasswd_re=Password does not match regexp $1
|
||||
usave_epasswd_dict=Password is a dictionary word
|
||||
usave_epasswd_same=Password contains or is the same as username
|
||||
usave_epasswd_mindays=Password was changed less than $1 days ago
|
||||
usave_eothers=The user was successfully saved, but an error occured in another module : $1
|
||||
|
||||
gedit_title=Edit Group
|
||||
|
||||
@@ -282,7 +282,8 @@ if ($access{'ugroups'} ne "*") {
|
||||
if ($in{'passmode'} == 0) {
|
||||
# Password is blank
|
||||
if (!$config{'empty_mode'}) {
|
||||
local $err = &check_password_restrictions("", $user{'user'});
|
||||
local $err = &check_password_restrictions("", $user{'user'},
|
||||
$in{'old'} eq '' ? 'none' : \%ouser);
|
||||
&error($err) if ($err);
|
||||
}
|
||||
$user{'pass'} = "";
|
||||
@@ -297,7 +298,8 @@ elsif ($in{'passmode'} == 2) {
|
||||
}
|
||||
elsif ($in{'passmode'} == 3) {
|
||||
# Normal password entered - check restrictions
|
||||
local $err = &check_password_restrictions($in{'pass'}, $user{'user'});
|
||||
local $err = &check_password_restrictions($in{'pass'}, $user{'user'},
|
||||
$in{'old'} eq '' ? 'none' : \%ouser);
|
||||
&error($err) if ($err);
|
||||
$user{'pass'} = &encrypt_password($in{'pass'});
|
||||
}
|
||||
|
||||
@@ -1502,7 +1502,7 @@ foreach my $k (keys %group_properties_map) {
|
||||
}
|
||||
}
|
||||
|
||||
=head2 check_password_restrictions(pass, username)
|
||||
=head2 check_password_restrictions(pass, username, [&user-hash|"none"])
|
||||
|
||||
Returns an error message if the given password fails length and other
|
||||
checks, or undef if it is OK.
|
||||
@@ -1510,20 +1510,21 @@ checks, or undef if it is OK.
|
||||
=cut
|
||||
sub check_password_restrictions
|
||||
{
|
||||
local ($pass, $username, $uinfo) = @_;
|
||||
return &text('usave_epasswd_min', $config{'passwd_min'})
|
||||
if (length($_[0]) < $config{'passwd_min'});
|
||||
if (length($pass) < $config{'passwd_min'});
|
||||
local $re = $config{'passwd_re'};
|
||||
return &text('usave_epasswd_re', $re)
|
||||
if ($re && !eval { $_[0] =~ /^$re$/ });
|
||||
if ($re && !eval { $pass =~ /^$re$/ });
|
||||
if ($config{'passwd_same'}) {
|
||||
return &text('usave_epasswd_same') if ($_[0] =~ /\Q$_[1]\E/i);
|
||||
return &text('usave_epasswd_same') if ($pass =~ /\Q$username\E/i);
|
||||
}
|
||||
if ($config{'passwd_dict'} && $_[0] =~ /^[A-Za-z\'\-]+$/ &&
|
||||
if ($config{'passwd_dict'} && $pass =~ /^[A-Za-z\'\-]+$/ &&
|
||||
(&has_command("ispell") || &has_command("spell"))) {
|
||||
# Call spell or ispell to check for dictionary words
|
||||
local $temp = &transname();
|
||||
open(TEMP, ">$temp");
|
||||
print TEMP $_[0],"\n";
|
||||
print TEMP $pass,"\n";
|
||||
close(TEMP);
|
||||
if (&has_command("ispell")) {
|
||||
open(SPELL, "ispell -a <$temp |");
|
||||
@@ -1547,8 +1548,8 @@ if ($config{'passwd_prog'}) {
|
||||
local $out;
|
||||
if ($config{'passwd_progmode'} == 0) {
|
||||
# Run external validation program with user and password as args
|
||||
local $qu = quotemeta($_[1]);
|
||||
local $qp = quotemeta($_[0]);
|
||||
local $qu = quotemeta($username);
|
||||
local $qp = quotemeta($pass);
|
||||
$out = &backquote_command(
|
||||
"$config{'passwd_prog'} $qu $qp 2>&1 </dev/null");
|
||||
}
|
||||
@@ -1556,8 +1557,8 @@ if ($config{'passwd_prog'}) {
|
||||
# Run program with password as input on stdin
|
||||
local $temp = &transname();
|
||||
&open_tempfile(TEMP, ">$temp", 0, 1);
|
||||
&print_tempfile(TEMP, $_[1],"\n");
|
||||
&print_tempfile(TEMP, $_[0],"\n");
|
||||
&print_tempfile(TEMP, $username,"\n");
|
||||
&print_tempfile(TEMP, $pass,"\n");
|
||||
&close_tempfile(TEMP);
|
||||
$out = &backquote_command("$config{'passwd_prog'} <$temp 2>&1");
|
||||
}
|
||||
@@ -1565,6 +1566,33 @@ if ($config{'passwd_prog'}) {
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
if ($config{'passwd_mindays'} && $uinfo ne "none") {
|
||||
# Check if password was changed too recently
|
||||
if (!$uinfo) {
|
||||
($uinfo) = grep { $_->{'user'} eq $username } &list_users();
|
||||
}
|
||||
if ($uinfo) {
|
||||
local $pft = &passfiles_type();
|
||||
local $when;
|
||||
if ($pft == 1 || $pft == 6) {
|
||||
# BSD (unix time)
|
||||
$when = $uinfo->{'change'};
|
||||
}
|
||||
elsif ($pft == 2 || $pft == 5) {
|
||||
# Linux (number of days)
|
||||
$when = $uinfo->{'change'} * 24*60*60;
|
||||
}
|
||||
elsif ($pft == 4) {
|
||||
# AIX (unix time)
|
||||
$when = $uinfo->{'change'};
|
||||
}
|
||||
if ($when && time() - $when <
|
||||
$config{'passwd_mindays'}*24*60*60) {
|
||||
return &text('usave_epasswd_mindays',
|
||||
$config{'passwd_mindays'});
|
||||
}
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -1576,12 +1604,13 @@ it is OK.
|
||||
=cut
|
||||
sub check_username_restrictions
|
||||
{
|
||||
if ($config{'max_length'} && length($_[0]) > $config{'max_length'}) {
|
||||
local ($username) = @_;
|
||||
if ($config{'max_length'} && length($username) > $config{'max_length'}) {
|
||||
return &text('usave_elength', $config{'max_length'});
|
||||
}
|
||||
local $re = $config{'username_re'};
|
||||
return &text('usave_ere', $re)
|
||||
if ($re && !eval { $_[0] =~ /^$re$/ });
|
||||
if ($re && !eval { $username =~ /^$re$/ });
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user