mirror of
https://github.com/webmin/webmin.git
synced 2025-07-21 23:40:34 +00:00
335 lines
8.1 KiB
Perl
Executable File
335 lines
8.1 KiB
Perl
Executable File
#!/usr/local/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;
|
|
}
|
|
|