mirror of
https://github.com/webmin/webmin.git
synced 2026-06-20 03:10:30 +01:00
Support for temporary passwords which must be changed at the next login
This commit is contained in:
@@ -46,3 +46,4 @@ Updated the user interface to use the Webmin UI library.
|
||||
Fixed the display of modules granted to groups.
|
||||
Added a per-user option to opt out of forced password changes after a certain number of days.
|
||||
A human-readable description of the password restrictions regular expression can be entered, for use in error messages.
|
||||
Webmin users can now be given temporary passwords, which they are forced to change at the next login.
|
||||
|
||||
@@ -43,6 +43,7 @@ while(<PWFILE>) {
|
||||
$user{'olds'} = [ split(/\s+/, $user[7]) ];
|
||||
$user{'minsize'} = $user[8];
|
||||
$user{'nochange'} = int($user[9]);
|
||||
$user{'temppass'} = int($user[10]);
|
||||
$user{'modules'} = $acl{$user[0]};
|
||||
$user{'lang'} = $gconfig{"lang_$user[0]"};
|
||||
$user{'notabs'} = $gconfig{"notabs_$user[0]"};
|
||||
@@ -135,7 +136,8 @@ push(@times, "hours", $user{'hoursfrom'}."-".$user{'hoursto'})
|
||||
$user{'lastchange'},":",
|
||||
join(" ", @{$user{'olds'}}),":",
|
||||
$user{'minsize'},":",
|
||||
$user{'nochange'},
|
||||
$user{'nochange'},":",
|
||||
$user{'temppass'},
|
||||
"\n");
|
||||
&close_tempfile(PWFILE);
|
||||
&unlock_file($miniserv{'userfile'});
|
||||
@@ -238,7 +240,8 @@ foreach (@pwfile) {
|
||||
$user{'lastchange'},":",
|
||||
join(" ", @{$user{'olds'}}),":",
|
||||
$user{'minsize'},":",
|
||||
$user{'nochange'},
|
||||
$user{'nochange'},":",
|
||||
$user{'temppass'},
|
||||
"\n");
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -114,6 +114,10 @@ if ($passmode == 1) {
|
||||
$lockbox = &ui_checkbox("lock", 1, $text{'edit_templock'},
|
||||
$user{'pass'} =~ /^\!/ ? 1 : 0);
|
||||
}
|
||||
if ($passmode != 3 && $passmode != 4) {
|
||||
$tempbox = &ui_checkbox("temp", 1, $text{'edit_temppass'},
|
||||
$user{'temppass'});
|
||||
}
|
||||
if ($user{'lastchange'} && $miniserv{'pass_maxdays'}) {
|
||||
$daysold = int((time() - $user{'lastchange'})/(24*60*60));
|
||||
if ($miniserv{'pass_lockdays'} &&
|
||||
@@ -134,7 +138,8 @@ if ($user{'lastchange'} && $miniserv{'pass_maxdays'}) {
|
||||
}
|
||||
print &ui_table_row($text{'edit_pass'},
|
||||
&ui_select("pass_def", $passmode, \@opts)." ".
|
||||
&ui_password("pass", undef, 25).$lockbox.$expmsg);
|
||||
&ui_password("pass", undef, 25).
|
||||
($lockbox || $tempbox ? "<br>" : "").$lockbox.$tempbox.$expmsg);
|
||||
|
||||
# Real name
|
||||
print &ui_table_row($text{'edit_real'},
|
||||
|
||||
@@ -83,6 +83,7 @@ edit_rbacdeny0=RBAC only controls selected module ACLs
|
||||
edit_rbacdeny1=RBAC controls all modules and ACLs
|
||||
edit_special=Special
|
||||
edit_templock=Temporarily locked
|
||||
edit_temppass=Force change at next login
|
||||
edit_days=Allowed days of the week
|
||||
edit_alldays=Every day
|
||||
edit_seldays=Only selected days ..
|
||||
|
||||
@@ -232,8 +232,11 @@ if ($in{'pass_def'} == 0) {
|
||||
$in{'pass'} =~ /:/ && &error($text{'save_ecolon'});
|
||||
$user{'pass'} = &encrypt_password($in{'pass'});
|
||||
$user{'sync'} = 0;
|
||||
$perr = &check_password_restrictions($in{'name'}, $in{'pass'});
|
||||
$perr && &error(&text('save_epass', $perr));
|
||||
if (!$in{'temp'}) {
|
||||
# Check password quality, unless this is a temp password
|
||||
$perr = &check_password_restrictions($in{'name'}, $in{'pass'});
|
||||
$perr && &error(&text('save_epass', $perr));
|
||||
}
|
||||
}
|
||||
elsif ($in{'pass_def'} == 1) {
|
||||
# No change in password
|
||||
@@ -304,6 +307,9 @@ elsif ($in{'lock'} && $user{'pass'} !~ /^\!/ && $in{'pass_def'} <= 1) {
|
||||
$user{'pass'} = "!".$user{'pass'};
|
||||
}
|
||||
|
||||
# Check for force change
|
||||
$user{'temppass'} = $in{'temp'};
|
||||
|
||||
if ($in{'old'}) {
|
||||
# update user and all ACLs
|
||||
&modify_user($in{'old'}, \%user);
|
||||
|
||||
15
miniserv.pl
15
miniserv.pl
@@ -2944,7 +2944,7 @@ sub urlize {
|
||||
|
||||
# validate_user(username, password, host)
|
||||
# Checks if some username and password are valid. Returns the modified username,
|
||||
# the expired flag, and the non-existence flag
|
||||
# the expired / temp pass flag, and the non-existence flag
|
||||
sub validate_user
|
||||
{
|
||||
local ($user, $pass, $host) = @_;
|
||||
@@ -2978,6 +2978,10 @@ elsif ($canmode == 1) {
|
||||
# Password has expired
|
||||
return ( $user, 1, 0 );
|
||||
}
|
||||
elsif ($temppass{$user}) {
|
||||
# Temporary password - force change now
|
||||
return ( $user, 2, 0 );
|
||||
}
|
||||
}
|
||||
return ( $user, 0, 0 );
|
||||
}
|
||||
@@ -3522,13 +3526,14 @@ if ($ok && (!$expired ||
|
||||
return 0;
|
||||
}
|
||||
elsif ($ok && $expired &&
|
||||
$config{'passwd_mode'} == 2) {
|
||||
# Login was ok, but password has expired. Need
|
||||
($config{'passwd_mode'} == 2 || $expired == 2)) {
|
||||
# Login was ok, but password has expired or was temporary. Need
|
||||
# to force display of password change form.
|
||||
$validated = 1;
|
||||
$authuser = undef;
|
||||
$querystring = "&user=".&urlize($vu).
|
||||
"&pam=".$use_pam;
|
||||
"&pam=".$use_pam.
|
||||
"&expired=".$expired;
|
||||
$method = "GET";
|
||||
$queryargs = "";
|
||||
$page = $config{'password_form'};
|
||||
@@ -3928,6 +3933,7 @@ undef(%allowdays);
|
||||
undef(%allowhours);
|
||||
undef(%lastchanges);
|
||||
undef(%nochange);
|
||||
undef(%temppass);
|
||||
if ($config{'userfile'}) {
|
||||
open(USERS, $config{'userfile'});
|
||||
while(<USERS>) {
|
||||
@@ -3953,6 +3959,7 @@ if ($config{'userfile'}) {
|
||||
}
|
||||
$lastchanges{$user[0]} = $user[6];
|
||||
$nochange{$user[0]} = $user[9];
|
||||
$temppass{$user[0]} = $user[10];
|
||||
}
|
||||
close(USERS);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ if ($wuser) {
|
||||
$perr = &acl::check_password_restrictions($in{'user'}, $in{'new1'});
|
||||
$perr && &pass_error(&text('password_enewpass', $perr));
|
||||
$wuser->{'pass'} = &acl::encrypt_password($in{'new1'});
|
||||
$wuser->{'temppass'} = 0;
|
||||
&acl::modify_user($wuser->{'name'}, $wuser);
|
||||
&reload_miniserv();
|
||||
}
|
||||
|
||||
@@ -5,39 +5,45 @@
|
||||
$ENV{'MINISERV_INTERNAL'} || die "Can only be called by miniserv.pl";
|
||||
require './web-lib.pl';
|
||||
&init_config();
|
||||
require './ui-lib.pl';
|
||||
&ReadParse();
|
||||
&header(undef, undef, undef, undef, 1, 1);
|
||||
|
||||
print "<center>\n";
|
||||
print "<h3>$text{'password_expired'}</h3><p>\n";
|
||||
if ($in{'expired'} == 2) {
|
||||
print &ui_subheading($text{'password_temp'});
|
||||
}
|
||||
else {
|
||||
print &ui_subheading($text{'password_expired'});
|
||||
}
|
||||
|
||||
# Start of the form
|
||||
print "$text{'password_prefix'}\n";
|
||||
print "<form action=$gconfig{'webprefix'}/password_change.cgi method=post>\n";
|
||||
print "<input type=hidden name=user value='",&html_escape($in{'user'}),"'>\n";
|
||||
print "<input type=hidden name=pam value='",&html_escape($in{'pam'}),"'>\n";
|
||||
print &ui_form_start("$gconfig{'webprefix'}/password_change.cgi", "post");
|
||||
print &ui_hidden("user", $in{'user'});
|
||||
print &ui_hidden("pam", $in{'pam'});
|
||||
print &ui_hidden("expired", $in{'expired'});
|
||||
print &ui_table_start($text{'password_header'}, "width=50% style='width:50%'", 2);
|
||||
|
||||
print "<table border width=40%>\n";
|
||||
print "<tr $tb> <td><b>$text{'password_header'}</b></td> </tr>\n";
|
||||
print "<tr $cb> <td align=center><table cellpadding=3>\n";
|
||||
# Current username
|
||||
print &ui_table_row($text{'password_user'},
|
||||
&html_escape($in{'user'}));
|
||||
|
||||
print "<tr> <td><b>$text{'password_user'}</b></td>\n";
|
||||
print "<td><tt>",&html_escape($in{'user'}),"</tt></td> </tr>\n";
|
||||
# Old password
|
||||
print &ui_table_row($text{'password_old'},
|
||||
&ui_password("old", undef, 20));
|
||||
|
||||
print "<tr> <td><b>$text{'password_old'}</b></td>\n";
|
||||
print "<td><input name=old size=20 type=password></td> </tr>\n";
|
||||
# New password, twice
|
||||
print &ui_table_row($text{'password_new1'},
|
||||
&ui_password("new1", undef, 20));
|
||||
print &ui_table_row($text{'password_new2'},
|
||||
&ui_password("new2", undef, 20));
|
||||
|
||||
print "<tr> <td><b>$text{'password_new1'}</b></td>\n";
|
||||
print "<td><input name=new1 size=20 type=password></td> </tr>\n";
|
||||
print "<tr> <td><b>$text{'password_new2'}</b></td>\n";
|
||||
print "<td><input name=new2 size=20 type=password></td> </tr>\n";
|
||||
|
||||
print "<tr> <td colspan=2 align=center><input type=submit ",
|
||||
"value='$text{'password_ok'}'>\n";
|
||||
print "<input type=reset value='$text{'password_clear'}'><br>\n";
|
||||
print "</td> </tr>\n";
|
||||
print "</table></td></tr></table><p>\n";
|
||||
print "<hr>\n";
|
||||
print "</form></center>\n";
|
||||
# End of form
|
||||
print &ui_table_end();
|
||||
print &ui_form_end([ [ undef, $text{'password_ok'} ] ]);
|
||||
print "</center>\n";
|
||||
print "$text{'password_postfix'}\n";
|
||||
|
||||
&footer();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user