Current File : //usr/share/webmin/useradmin/gbatch_exec.cgi |
#!/usr/bin/perl
# Execute create/modify/delete group commands in a batch file
require './user-lib.pl';
$access{'batch'} || &error($text{'gbatch_ecannot'});
if ($ENV{'REQUEST_METHOD'} eq 'GET') {
&ReadParse();
}
else {
&ReadParseMime();
}
if ($in{'source'} == 0) {
$data = $in{'file'};
$data =~ /\S/ || &error($text{'batch_efile'});
}
elsif ($in{'source'} == 1) {
open(LOCAL, "<$in{'local'}") || &error($text{'batch_elocal'});
while(<LOCAL>) {
$data .= $_;
}
close(LOCAL);
}
elsif ($in{'source'} == 2) {
$data = $in{'text'};
$data =~ /\S/ || &error($text{'batch_etext'});
}
&ui_print_unbuffered_header(undef, $text{'gbatch_title'}, "");
# Force defaults for save options
$in{'chgid'} = 1 if (!$access{'chgid'});
# Work out a good base GID for new groups
&build_group_used(\%gused, \%gtaken);
$newgid = int($config{'base_gid'} > $access{'lowgid'} ?
$config{'base_gid'} : $access{'lowgid'});
# Process the file
&batch_start() if ($in{'batch'});
&lock_user_files();
$lnum = $created = $modified = $deleted = 0;
print "<pre>\n";
$pft = &passfiles_type();
foreach $line (split(/[\r\n]+/, $data)) {
$lnum++;
$line =~ s/^\s*#.*$//;
next if ($line !~ /\S/);
local @line = split(/:/, $line, -1);
local %group;
if ($line[0] eq 'create') {
# Creating a new group
# Validate line
if (!$line[1]) {
print &text('batch_eline', $lnum),"\n";
next;
}
if (@line != 5) {
print &text('batch_elen', $lnum, 5),"\n";
next;
}
if ($line[1] !~ /^[^:\t]+$/) {
print &text('gbatch_egroupname', $lnum),"\n";
next;
}
$group{'group'} = $line[1];
if ($gtaken{$group{'group'}}) {
print &text('gbatch_egroup', $lnum,
$group{'group'}),"\n";
next;
}
if ($line[3] !~ /^\d+$/) {
# make up a GID
while($gused{$newgid}) {
$newgid++;
}
$group{'gid'} = $newgid;
}
else {
# use the given UID
if ($gused{$line[3]} && !$access{'gmultiple'}) {
print &text('gbatch_ecaccess', $lnum,
$text{'gsave_egidused2'}),"\n";
next;
}
$group{'gid'} = $line[3];
}
$gused{$group{'gid'}}++;
$group{'members'} = $line[4];
# Check access control restrictions
if (!$access{'gcreate'}) {
print &text('gbatch_ecaccess', $lnum,
$text{'gsave_ecreate'});
next;
}
local $ch = &check_group(\%group);
if ($ch) {
print &text('gbatch_ecaccess', $lnum, $ch),"\n";
next;
}
if ($line[2] eq '') {
# No password needed
$group{'pass'} = '';
$group{'passmode'} = 0;
}
else {
# Normal password
$group{'pass'} = &encrypt_password($line[2]);
$group{'passmode'} = 3;
$group{'plainpass'} = $line[2];
}
# Run the before command
&set_user_envs(\%group, 'CREATE_GROUP');
$merr = &making_changes();
&error(&text('gsave_emaking', "<tt>$merr</tt>"))
if (defined($merr));
# Create the group!
&create_group(\%group);
# All done
&made_changes();
# Call other modules, ignoring any failures
$error_must_die = 1;
eval {
&other_modules("useradmin_create_group", \%group)
if ($access{'cothers'} == 1 && $in{'others'} ||
$access{'cothers'} == 0);
};
$other_err = $@;
$error_must_die = 0;
print "<b>",&text('gbatch_created', $group{'group'}),"</b>\n";
print "<b><i>",&text('batch_eother', $other_err),"</i></b>\n"
if ($other_err);
$created++;
}
elsif ($line[0] eq 'delete') {
# Deleting an existing group
if (@line != 2) {
print &text('batch_elen', $lnum, 2),"\n";
next;
}
local @glist = &list_groups();
local ($group) = grep { $_->{'group'} eq $line[1] } @glist;
if (!$group) {
print &text('gbatch_enogroup', $lnum, $line[1]),"\n";
next;
}
# Check if deletion is allowed
if (!&can_edit_group(\%access, $group)) {
print &text('gbatch_edaccess', $lnum,
$text{'gdel_egroup'}),"\n";
next;
}
if (!$config{'delete_root'} && $group->{'gid'} <= 10) {
print &text('gbatch_edaccess', $lnum,
$text{'gdel_egroup'}),"\n";
next;
}
# Check if has primary members
local $prim;
foreach $u (&list_users()) {
if ($u->{'gid'} == $group->{'gid'}) {
$prim = $u;
last;
}
}
if ($prim) {
print &text('gbatch_eprimary', $lnum,
$prim->{'user'}),"\n";
next;
}
# Run the before command
&set_user_envs($group, 'DELETE_GROUP');
$merr = &making_changes();
&error(&text('usave_emaking', "<tt>$merr</tt>"))
if (defined($merr));
# Delete from other modules, ignoring errors
$error_must_die = 1;
eval {
&other_modules("useradmin_delete_group", $group)
if ($access{'dothers'} == 1 && $in{'others'} ||
$access{'dothers'} == 0);
};
$other_err = $@;
$error_must_die = 0;
# Delete the user entry
&delete_group($group);
&made_changes();
print "<b>",&text('gbatch_deleted',$group->{'group'}),"</b>\n";
print "<b><i>",&text('batch_eother', $other_err),"</i></b>\n"
if ($other_err);
$deleted++;
}
elsif ($line[0] eq 'modify') {
# Modifying an existing group
if (@line != 6) {
print &text('batch_elen', $lnum, 6),"\n";
next;
}
local @glist = &list_groups();
local ($group) = grep { $_->{'group'} eq $line[1] } @glist;
if (!$group) {
print &text('gbatch_enogroup', $lnum, $line[1]),"\n";
next;
}
%oldgroup = %group = %$group;
$user{'olduser'} = $user->{'user'};
if (!&can_edit_group(\%access, \%group)) {
print &text('gbatch_emaccess', $lnum,
$text{'gsave_eedit'}),"\n";
next;
}
# Update supplied fields
if ($line[2] ne '') {
if (!$access{'grename'}) {
print &text('gbatch_erename',
$lnum, $line[1]),"\n";
}
$group{'group'} = $line[2];
}
if ($line[3] ne '') {
# New normal password
$group{'pass'} = &encrypt_password($line[3]);
$group{'passmode'} = 3;
$group{'plainpass'} = $line[3];
}
else {
# No change
$group{'passmode'} = 4;
}
$group{'gid'} = $line[4] if ($line[4] ne '');
if ($line[5] =~ /^\s+$/ || $line[5] eq 'NONE') {
# No members
$group{'members'} = '';
}
elsif ($line[5]) {
$group{'members'} = $line[5];
}
# Check access control restrictions
local $ch = &check_group(\%group, \%oldgroup);
if ($ch) {
print &text('gbatch_emaccess', $lnum, $ch),"\n";
next;
}
# Run the before command
&set_user_envs(\%group, 'MODIFY_GROUP');
$merr = &making_changes();
&error(&text('usave_emaking', "<tt>$merr</tt>"))
if (defined($merr));
# Change GIDs
if ($oldgroup{'gid'} != $group{'gid'} && $in{'chgid'}) {
if ($in{'chgid'} == 1) {
# Do all the home directories of members
&change_all_home_groups(
$oldgroup{'gid'}, $group{'gid'},
[ split(/,/, $group{'members'}) ]);
}
else {
# Do all files in this group from the root dir
&recursive_change("/", -1, $oldgroup{'gid'},
-1, $group{'gid'});
}
}
# Actually modify the group
&modify_group(\%oldgroup, \%group);
&made_changes();
# Modify in other modules, ignoring errors
$error_must_die = 1;
eval {
&other_modules("groupadmin_modify_group",
\%group, \%oldgroup)
if ($access{'mothers'} == 1 && $in{'others'} ||
$access{'mothers'} == 0);
};
$error_must_die = 0;
$other_err = $@;
print "<b>",&text('batch_modified',$oldgroup{'group'}),"</b>\n";
print "<b><i>",&text('batch_eother', $other_err),"</i></b>\n"
if ($other_err);
$modified++;
}
else {
print &text('batch_eaction', $lnum, $line[0]),"\n";
next;
}
}
print "</pre>\n";
&batch_end() if ($in{'batch'});
&unlock_user_files();
&webmin_log("gbatch", undef, $in{'source'} == 1 ? $in{'local'} : undef,
{ 'created' => $created, 'modified' => $modified,
'deleted' => $deleted, 'lnum' => $lnum } );
&ui_print_footer("gbatch_form.cgi", $text{'batch_return'},
"index.cgi?mode=groups", $text{'index_return'});
# check_group(\%group, [\%oldgroup])
# Check access control restrictions for a group
sub check_group
{
# check if gid is within range
if ($access{'lowgid'} && $_[0]->{'gid'} < $access{'lowgid'}) {
return &text('usave_elowgid', $access{'lowuid'});
}
if ($access{'hiuid'} && $_[0]->{'uid'} > $access{'hiuid'}) {
return &text('usave_ehiuid', $access{'hiuid'});
}
if ($_[1] && !$access{'ggid'} && $_[1]->{'gid'} != $_[0]->{'gid'}) {
return $text{'gsave_eggid'};
}
return undef;
}