#!/usr/bin/perl -w #============================================================================== # lat-users # ========= # 0.9.0 (2004-09-08) # (c)2003-2004 Altiplano bvba #============================================================================== package esmith; use strict; use esmith::db; use esmith::util; use Getopt::Long; use Pod::Usage; my %conf; tie %conf, 'esmith::config'; my %accounts; tie %accounts, 'esmith::config', '/home/e-smith/db/accounts'; my ($Hlp, $Cml, $Frc, $Inp); my $Add =0; my $Del =0; #============================================================================== # Main #============================================================================== # Analyze commandline options GetOptions ("help" => \$Hlp, "add" => \$Add, "delete" => \$Del, "force" => \$Frc, "command-line=s" => \$Cml, "input-file=s" => \$Inp); if ( $Hlp ) { &PrintPod(9); exit; } # We need one argument or the other, but not both if ((($Cml && $Inp) || (! $Cml && ! $Inp)) || ($Add + $Del != 1)) { &PrintPod(1); exit; } my @records; if ($Inp) { open(LIST,"< $Inp") || die "Can't find $Inp.\n"; @records = grep(!/(^\s*#)|(^\s*$)/,); close(LIST); } elsif ($Cml) { @records=($Cml); } else { &PrintPod(1); exit; } # Add ibays if ($Add) { # Process each ibay foreach my $record (@records) { my @fields=split(/\|/,$record); for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }} my $ibayname = $fields[0]; my $password = ""; if ($fields[5]) { $password = $fields[5] } my $uid; if ($fields[7]) { $uid = $fields[7]; } else { $uid = &FindUid;} if (&TestUid($uid)) { my %ibay; if ( $fields[1] ) { $ibay{'Name'} = $fields[1] } else { $ibay{'Name'} = $ibayname } if ( $fields[2] ) { $ibay{'Group'} = $fields[2] } else {die "We need a valid group to create '$ibayname'.\a\n";} if ( $fields[3] ) { $ibay{'UserAccess'} = $fields[3] } else { $ibay{'UserAccess'} = "wr-admin-rd-group" } if ( $fields[4] ) { $ibay{'PublicAccess'} = $fields[4] } else { $ibay{'PublicAccess'} = "local-pw" } if ( $fields[5] ) { $ibay{'PasswordSet'} = "yes" } else { $ibay{'PasswordSet'} = "no" } if ( $fields[6] ) { $ibay{'CgiBin'} = $fields[6] } else { $ibay{'CgiBin'} = "disabled" } $ibay{'Uid'} = $uid; $ibay{'Gid'} = $uid; if (&ValidArguments(\%ibay, $ibayname, $password)) { print "Creating ibay '$ibayname' (Uid:$uid).\n"; db_set(\%accounts, $ibayname, 'ibay', \%ibay); system("/sbin/e-smith/signal-event", "ibay-create", $ibayname) == 0 or die ("An error occurred while creating ibay '$ibayname'.\n"); # Set password if ($ibay{'PasswordSet'} eq 'yes') { esmith::util::setIbayPassword($ibayname, $password); } } } } } # Delete ibays if ($Del) { &ExpandWildCard; # Check for wildcards and expand if necessary foreach my $record (@records) { my @fields=split(/\|/,$record); for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }} my $ibayname = $fields[0]; my $password = ""; if ($fields[5]) { $password = $fields[5] } if ((db_get(\%accounts, $ibayname)) && (db_get_type(\%accounts, $ibayname)) eq "ibay") { my $yn = 'yes'; if (! $Frc) { print "Do you want to delete ibay '$ibayname'?\n"; print "All files in this ibay will be deleted! [yes/NO/all] "; $yn = ; if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; } } if ($yn =~ /^y/i) { print "Deleting ibay '$ibayname'.\n"; db_delete(\%accounts, $ibayname); system("/sbin/e-smith/signal-event", "ibay-delete", $ibayname) == 0 or die ("An error occurred while deleting ibay '$ibayname'.\n"); } } else { print "Can't find ibay '$ibayname'.\n\a";} } } #============================================================================== # Subroutines #============================================================================== # Find an unused Uid/Gid sub FindUid { open(ACC,"/home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts"; my @recs = grep(/Uid\|\d*/,); close(ACC); open(PWD,"/etc/passwd") || die "Can't find /etc/passwd"; my @pwds = grep(/\:\d*\:/,); close(PWD); open(GRP,"/etc/group") || die "Can't find /etc/group"; my @grps = grep(/\:\d*\:/,); close(GRP); my $newuid=db_get(\%conf, 'MinUid'); do { ++$newuid;} until ((! grep(/Uid\|$newuid\D/,@recs)) && (! grep(/\:$newuid\:/,@pwds)) && (! grep(/\:$newuid\:/,@grps))); return $newuid; } #============================================================================== # Test the uid/gid for availability and legality sub TestUid { open(ACC,"/home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts"; my @recs = grep(/Uid\|\d*/,); close(ACC); open(PWD,"/etc/passwd") || die "Can't find /etc/passwd"; my @pwds = grep(/\:\d*\:/,); close(PWD); open(GRP,"/etc/group") || die "Can't find /etc/group"; my @grps = grep(/\:\d*\:/,); close(GRP); if (! ($_[0] =~ /^\d*$/)) { print "Error: A user ID should contain only numbers.\a\n"; return 0; } elsif ( $_[0] < db_get(\%conf, 'MinUid')) { print "Error: The user ID should be greater or equal to ".&FindUid."\a\n"; return 0; } elsif ((grep(/Uid\|$_[0]\D/,@recs)) or (grep(/\:$_[0]\:/,@pwds)) or (grep(/\:$_[0]\:/,@grps))) { print "Error: The uid/gid '$_[0]' is already in use\a\n"; return 0; } else { return 1 }; } #============================================================================== # Test the various arguments for their validity sub ValidArguments { my $href = $_[0]; my $nm =$_[1]; my $pw =$_[2]; my $ret = 1; if (db_get(\%accounts, $nm)) { print "An account with the name '$nm' already exists on this server.\n\a"; $ret = 0; } if ( ! ( $nm =~ /^[a-z][a-z\-\_\d\.]*$/ )) { print "Can't create ibay '$nm'. "; print "The name contains illegal characters.\n"; print "The name should contain only lower-case letters, numbers, hyphens, periods and \n"; print "underscores, and should start with a lower-case letter.\n\a"; $ret = 0; } if (not defined(db_get(\%accounts, $href->{'Group'})) && (db_get_type(\%accounts, $href->{'Group'} ) ne "ibay" )) { print "Can't create ibay '$href->{'Name'}'. "; print "The group '".$href->{'Group'}."' does not exist.\n\a"; $ret = 0; } if ( ! ($href->{'UserAccess'} =~ /^wr-admin-rd-group$|^wr-group-rd-everyone$|^wr-group-rd-group$/)) { print "Can't create ibay '$href->{'Name'}'. "; print "User access must be either 'wr-admin-rd-group', \n'wr-group-rd-everyone' or 'wr-group-rd-group'.\n\a"; $ret = 0; } if ( ! ($href->{'PublicAccess'} =~ /^local$|^local-pw$|^global$|^global-pw$|^global-pw-remote|^none$/)) { print "Can't create ibay '$href->{'Name'}'.\n"; print "Public access must be either 'local', 'local-pw', 'global', 'global-pw', 'global-pw-remote', or 'none'.\n\a"; $ret = 0; } if ( ! ($href->{'CgiBin'} =~ /^(disabled)$|^(enabled)$/)) { print "Can't create ibay '$href->{'Name'}'. "; print "The CGI-Bin must be either 'disabled' or 'enabled'.\n\a"; $ret = 0; } return $ret; } #============================================================================== # Test for wildcards in the ibayname. If any wildecards are found, the array # @records is expanded with the ibay names that meet the conditions. sub ExpandWildCard { my $ctrec = 0; foreach my $record (@records) { my @fld=split(/\|/,$record); for (my $cnt=0; $cnt <= $#fld; ++$cnt) { for ($fld[$cnt]) { s/^\s+//; s/\s+$//; }} if ($fld[0] =~ /\*|\?/) { # Does it contain the wildcards? $fld[0] =~ s/\*/\.\*/g; # Replace * with .* to allow for grep. $fld[0] =~ s/\?/\./g; # Replace ? with . to allow for grep. open USRS, "; close(USRS); my $cu = 0; foreach my $tst (@match) { $tst =~ /\=/; $tst = $`; for (my $cnt=1; $cnt <= $#fld; ++$cnt) { $tst = $tst." | ".$fld[$cnt]; }; if ($cu == 0 ) { $records[$ctrec] = $tst; $cu =1; } else { push(@records, $tst); } } } ++$ctrec; } } #============================================================================== # Print the pod text as a help screen sub PrintPod { my ($verbose, $message) = @_; pod2usage(-verbose => $verbose, -message => $message, -exitval => 64); } #============================================================================== =pod =head1 NAME B - The lazy administrator's tool to create ibays =head1 DESCRIPTION Creates or deletes ibays on Mitel's SME servers (5.x/6.x). This tool is functionally equivalent to the 'Information bays' option in the server-manager, but can be run from the command line or called from an other script. It allows you, for example, to create an i-bay as part of an installation script, or delete i-bays on a remote machine via an ssh console. See F for the format of the input file. =head1 SYNOPSIS B -a -c "ibay | descr | group | useraccess | publicaccess | password | cgi-bin | uid" B -a -i /path/to/ibays.list B -d [-f] -c "Ibay" B -d [-f] -i /path/to/ibays.list =head1 OPTIONS The following options are supported: =over 4 =item B<-a>, B<--add> Add an ibay to the server =item B<-c 'Arguments'>, B<--command-line='Arguments'> Take arguments from the command line. See below for the various arguments that are accepted. =item B<-d>, B<--delete> Delete an ibay from the server. Wildcards (* and ?) are accepted. =item B<-f>, B<--force> Don't prompt before deleting. =item B<-h>, B<--help> Extended help for this tool =item B<-i FILE>, B<--input-file=FILE> Use the information from FILE to create or delete ibays. =back =head2 Arguments: Ibay* : Must contain only lower-case letters, numbers, hyphens, periods and underscores, and should start with a lower- case letter. Wildcards (* and ?) can only be used to delete ibays! Descr. : Free text description of the ibay. Group* : Must be an existing group on the server. UserAccess : wr-admin-rd-group (default) wr-group-rd-everyone wr-group-rd-group PublicAcc. : local (default) local-pw global global-pw global-pw-remote none Passd : Password for the ibay in clear-text (dangerous!). CGI : enabled disabled (default) uid : User ID. If omitted, the first available uid will used. * mandatory field =head1 EXAMPLES B Creates the i-bay 'library' for user group 'griffindor'. B Creates the i-bays defined in F. Please refer to F for an example of an input file. B Deletes all ibays that start with 'class'. All ibays and their files are deleted without prompting (-f). B Creates the i-bay 'library' for user group 'griffindor'. Password is 'quiddich', cgi is enabled and the group ID is set to 8003. =head1 SEE ALSO lat-group(8), lat-pseudonyms(8), lat-users(8), lat-quota(8), lat-domains(8), lat-hosts(8), lat-procmail(8), lat-pptp(8), lat-dump(8) =head1 VERSION Version 0.9.0 (2004-09-08). The latest version is hosted at B =head1 COPYRIGHT (c)2003-2004, Altiplano bvba (B). Released under the terms of the GNU license. =head1 BUGS Please report bugs to =cut #==============================================================================