Added support for SHA512 format passwords.
---- Changes since 1.540 ----
Fixed an XSS vulnerability that can be triggered if an attacker has the ability to change the real name of a Unix user.
+---- 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.
# Link to first available user
my @allulist = &list_users();
my @ulist = &list_allowed_users(\%access, \@allulist);
- return @ulist ? "num=".&urlize($ulist[0]->{'num'}) : "none";
+ return @ulist ? "user=".&urlize($ulist[0]->{'user'}) : "none";
}
elsif ($cgi eq 'edit_group.cgi') {
my @allglist = &list_groups();
my @glist = &list_allowed_groups(\%access, \@allglist);
- return @glist ? "num=".&urlize($glist[0]->{'num'}) : "none";
+ return @glist ? "group=".&urlize($glist[0]->{'group'}) : "none";
}
return undef;
}
require './user-lib.pl';
&ReadParse();
@glist = &list_groups();
-$group = $glist[$in{'num'}];
-$group || &error($text{'gdel_enum'});
+($group) = grep { $_->{'group'} eq $in{'group'} } @glist;
+$group || &error($text{'gedit_egone'});
$| = 1;
&error_setup($text{'gdel_err'});
&can_edit_group(\%access, $group) || &error($text{'gdel_egroup'});
print "$text{'gdel_done'}<p>\n";
done:
- &ui_print_footer("", $text{'index_return'});
+ &ui_print_footer("index.cgi?mode=groups", $text{'index_return'});
}
else {
# check if this is anyone's primary group
# Ask if the user is sure
print &ui_confirmation_form("delete_group.cgi",
&text('gdel_sure', $group->{'group'}),
- [ [ "num", $in{'num'} ],
- [ "group", $group->{'group'} ] ],
+ [ [ "group", $group->{'group'} ] ],
[ [ "confirmed", $text{'gdel_del'} ] ],
ui_checkbox("others", 1, $text{'gdel_dothers'},
$config{'default_other'}),
);
- &ui_print_footer("", $text{'index_return'});
+ &ui_print_footer("index.cgi?mode=groups", $text{'index_return'});
}
&ReadParse();
&lock_user_files();
@ulist = &list_users();
-$user = $ulist[$in{'num'}];
-$user || &error($text{'udel_enum'});
+($user) = grep { $_->{'user'} eq $in{'user'} } @ulist;
+$user || &error($text{'uedit_egone'});
&error_setup($text{'udel_err'});
&can_edit_user(\%access, $user) || &error($text{'udel_euser'});
$access{'udelete'} || &error($text{'udel_euser'});
}
print &ui_confirmation_form("delete_user.cgi", $msg,
- [ [ "num", $in{'num'} ],
- [ "user", $user->{'user'} ],
+ [ [ "user", $user->{'user'} ],
[ "confirmed", 1 ] ],
\@buts,
$access{'dothers'} == 1 ?
&ReadParse();
# Get group and show page header
-$n = $in{'num'};
+$n = $in{'group'};
if ($n eq "") {
$access{'gcreate'} == 1 || &error($text{'gedit_ecreate'});
&ui_print_header(undef, $text{'gedit_title2'}, "", "create_group");
}
else {
@glist = &list_groups();
- %group = %{$glist[$n]};
+ ($ginfo_hash) = grep { $_->{'group'} eq $n } @glist;
+ $ginfo_hash || &error($text{'gedit_egone'});
+ %group = %$ginfo_hash;
&can_edit_group(\%access, \%group) ||
&error($text{'gedit_eedit'});
&ui_print_header(undef, $text{'gedit_title'}, "", "edit_group");
# Start of form
print &ui_form_start("save_group.cgi", "post");
-print &ui_hidden("num", $n) if ($n ne "");
+print &ui_hidden("old", $n) if ($n ne "");
print &ui_table_start($text{'gedit_details'}, "width=100%", 2, [ "width=30%" ]);
# Group name
foreach $u (@upri) {
if (&can_edit_user(\%access, $u)) {
push(@uprilinks, "<a href='edit_user.cgi?".
- "num=$u->{'num'}'>$u->{'user'}</a>");
+ "user=$u->{'user'}'>$u->{'user'}</a>");
}
else {
push(@uprilinks, $u->{'user'});
&ReadParse();
# Show header and get the user
-$n = $in{'num'};
+$n = $in{'user'};
if ($n eq "") {
$access{'ucreate'} || &error($text{'uedit_ecreate'});
&ui_print_header(undef, $text{'uedit_title2'}, "", "create_user");
}
else {
@ulist = &list_users();
- %uinfo = %{$ulist[$n]};
+ ($uinfo_hash) = grep { $_->{'user'} eq $n } @ulist;
+ $uinfo_hash || &error($text{'uedit_egone'});
+ %uinfo = %$uinfo_hash;
&can_edit_user(\%access, \%uinfo) || &error($text{'uedit_eedit'});
&ui_print_header(undef, $text{'uedit_title'}, "", "edit_user");
}
# Start of the form
print &ui_form_start("save_user.cgi", "post");
-print &ui_hidden("num", $n) if ($n ne "");
-print &ui_hidden("old", $uinfo{'user'}) if ($n ne "");
+print &ui_hidden("old", $n) if ($n ne "");
print &ui_table_start($text{'uedit_details'}, "width=100%", 2, \@tds);
# Username
uedit_mail=Read Email
uedit_swit=Login to Usermin
uedit_ecreate=You cannot create new users
+uedit_egone=Selected user no longer exists!
uedit_eedit=You cannot edit this user
uedit_admin=Only root can change password
uedit_admchg=User must choose new password
gedit_homedirs=Home directories
gedit_allfiles=All files
gedit_ecreate=You cannot create new groups
+gedit_egone=Selected group no longer exists!
gedit_eedit=You cannot edit this group
gedit_cothers=Create group in other modules?
gedit_mothers=Modify group in other modules?
if ($in{'delete'}) {
# Redirect to deletion page
- &redirect("delete_group.cgi?num=$in{'num'}");
+ &redirect("delete_group.cgi?group=$in{'old'}");
return;
}
&lock_user_files();
@glist = &list_groups();
-if ($in{'num'} ne "") {
+if ($in{'old'} ne "") {
# get old group
- %ogroup = %{$glist[$in{'num'}]};
+ @glist = &list_groups();
+ ($ginfo_hash) = grep { $_->{'group'} eq $in{'old'} } @glist;
+ $ginfo_hash || &error($text{'gedit_egone'});
+ %ogroup = %$ginfo_hash;
$group{'group'} = $ogroup{'group'};
&can_edit_group(\%access, \%ogroup) || &error($text{'gsave_eedit'});
}
}
# Validate and save inputs
-if (!$in{'gid_def'} || $in{'num'} ne '') {
+if (!$in{'gid_def'} || $in{'old'} ne '') {
# Only do GID checks if not automatic
$in{'gid'} =~ /^[0-9]+$/ || &error(&text('gsave_egid', $in{'gid'}));
!$access{'lowgid'} || $in{'gid'} >= $access{'lowgid'} ||
return;
}
elsif ($in{'delete'}) {
- &redirect("delete_user.cgi?user=".&urlize($in{'old'}).
- "&num=".$in{'num'});
+ &redirect("delete_user.cgi?user=".&urlize($in{'old'}));
return;
}
&lock_user_files();
@ulist = &list_users();
@glist = &list_groups();
-if ($in{'num'} ne "") {
+if ($in{'old'} ne "") {
# Get old user info
- %ouser = %{$ulist[$in{'num'}]};
+ ($ouser_hash) = grep { $_->{'user'} eq $in{'old'} } @ulist;
+ $ouser_hash || &error($text{'uedit_egone'});
+ %ouser = %$ouser_hash;
if (!$access{'urename'} && $ouser{'user'} ne $user{'user'}) {
&error($text{'usave_erename'});
}
if ($ou->{'user'} eq $in{'user'});
}
}
-if (($in{'num'} eq '' || $user{'user'} ne $ouser{'user'}) &&
+if (($in{'old'} eq '' || $user{'user'} ne $ouser{'user'}) &&
$config{'alias_check'} && &foreign_check("sendmail")) {
# Check if the new username conflicts with a sendmail alias
&foreign_require("sendmail", "sendmail-lib.pl");
}
# Validate and store basic inputs
-if (!$in{'uid_def'} || $in{'num'} ne '') {
+if (!$in{'uid_def'} || $in{'old'} ne '') {
# Only do UID checks if not automatic
$in{'uid'} =~ /^\-?[0-9]+$/ || &error(&text('usave_euid', $in{'uid'}));
if (!%ouser || $ouser{'uid'} != $in{'uid'}) {
}
}
$user{'uid'} = $in{'uid'};
-if ($in{'num'} ne "" || !$in{'gidmode'}) {
+if ($in{'old'} ne "" || !$in{'gidmode'}) {
# Selecting existing group
$user{'gid'} = &my_getgrnam($in{'gid'});
if ($user{'gid'} eq "") { &error(&text('usave_egid', $in{'gid'})); }
}
if ($access{'ugroups'} ne "*") {
- if ($in{'num'} ne "") {
+ if ($in{'old'} ne "") {
# existing users can only be added to or removed from
# allowed groups
if ($ouser{'gid'} != $user{'gid'}) {
}
}
if (@match == 1) {
- &redirect("edit_group.cgi?num=".$match[0]->{'num'});
+ &redirect("edit_group.cgi?group=".$match[0]->{'group'});
}
else {
&ui_print_header(undef, $text{'search_title'}, "");
}
}
if (@match == 1) {
- &redirect("edit_user.cgi?num=".$match[0]->{'num'});
+ &redirect("edit_user.cgi?user=".$match[0]->{'user'});
}
else {
&ui_print_header(undef, $text{'search_title'}, "");
"$dis</a>";
}
else {
- return "<a href='edit_user.cgi?num=$_[0]->{'num'}'>".
+ return "<a href='edit_user.cgi?user=".&urlize($_[0]->{'user'})."'>".
"$dis</a>";
}
}
&html_escape($_[0]->{'group'})."</a>";
}
else {
- return "<a href='edit_group.cgi?num=$_[0]->{'num'}'>".
+ return "<a href='edit_group.cgi?group=".&urlize($_[0]->{'group'})."'>".
&html_escape($_[0]->{'group'})."</a>";
}
}