initial commit of file from CVS for smeserver-lazy_admin_tools on Sat Sep 7 20:29:45 AEST 2024

This commit is contained in:
Trevor Batley 2024-09-07 20:29:45 +10:00
parent ab14940b94
commit 376cfcf5b4
31 changed files with 4128 additions and 2 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.rpm
*.log
*spec-20*
*.tgz

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
# Makefile for source rpm: smeserver-lazy_admin_tools
# $Id: Makefile,v 1.1 2020/10/13 09:42:02 brianr Exp $
NAME := smeserver-lazy_admin_tools
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))
ifeq ($(MAKEFILE_COMMON),)
# attept a checkout
define checkout-makefile-common
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
endef
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
endif
include $(MAKEFILE_COMMON)

View File

@ -1,3 +1,15 @@
# smeserver-lazy_admin_tools
# <img src="https://www.koozali.org/images/koozali/Logo/Png/Koozali_logo_2016.png" width="25%" vertical="auto" style="vertical-align:bottom"> smeserver-lazy_admin_tools
SMEServer Koozali developed git repo for smeserver-lazy_admin_tools smecontribs
SMEServer Koozali developed git repo for smeserver-lazy_admin_tools smecontribs
## Wiki
<br />https://wiki.koozali.org/
## Bugzilla
Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-lazy_admin_tools&product=SME%20Contribs&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
## Description
<br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
*Once it has been checked, then this comment will be deleted*
<br />

48
additional/createman Normal file
View File

@ -0,0 +1,48 @@
#!/usr/bin/perl
use Pod::Man;
my $parser = Pod::Man->new (release => $VERSION, section => 8);
#create
$parser->parse_from_file ('root/usr/sbin/lat-users', "root/usr/man/man8/lat-users.8");
$parser->parse_from_file ('root/usr/sbin/lat-procmail', "root/usr/man/man8/lat-procmail.8");
$parser->parse_from_file ('root/usr/sbin/lat-dump',"root/usr/man/man8/lat-dump.8");
$parser->parse_from_file ('root/usr/sbin/lat-domains',"root/usr/man/man8/lat-domains.8");
$parser->parse_from_file ('root/usr/sbin/lat-groups',"root/usr/man/man8/lat-groups.8");
$parser->parse_from_file ('root/usr/sbin/lat-hosts',"root/usr/man/man8/lat-hosts.8");
$parser->parse_from_file ('root/usr/sbin/lat-ibays',"root/usr/man/man8/lat-ibays.8");
$parser->parse_from_file ('root/usr/sbin/lat-pptp',"root/usr/man/man8/lat-pptp.8");
$parser->parse_from_file ('root/usr/sbin/lat-pseudonyms',"root/usr/man/man8/lat-pseudonyms.8");
$parser->parse_from_file ('root/usr/sbin/lat-quota',"root/usr/man/man8/lat-quota.8");
$parser->parse_from_file ('root/usr/sbin/lat-restore',"root/usr/man/man8/lat-restore.8");
$parser->parse_from_file ('root/usr/sbin/lat-shadow',"root/usr/man/man8/lat-shadow.8");
# compress
system("/bin/gzip","root/usr/man/man8/lat-users.8");
system("/bin/gzip","root/usr/man/man8/lat-procmail.8");
system("/bin/gzip","root/usr/man/man8/lat-dump.8");
system("/bin/gzip","root/usr/man/man8/lat-domains.8");
system("/bin/gzip","root/usr/man/man8/lat-groups.8");
system("/bin/gzip","root/usr/man/man8/lat-hosts.8");
system("/bin/gzip","root/usr/man/man8/lat-ibays.8");
system("/bin/gzip","root/usr/man/man8/lat-pptp.8");
system("/bin/gzip","root/usr/man/man8/lat-pseudonyms.8");
system("/bin/gzip","root/usr/man/man8/lat-quota.8");
system("/bin/gzip","root/usr/man/man8/lat-restore.8");
system("/bin/gzip","root/usr/man/man8/lat-shadow.8");
# delete
system("/bin/rm -f","root/usr/man/man8/lat-users.8");
system("/bin/rm -f","root/usr/man/man8/lat-procmail.8");
system("/bin/rm -f","root/usr/man/man8/lat-dump.8");
system("/bin/rm -f","root/usr/man/man8/lat-domains.8");
system("/bin/rm -f","root/usr/man/man8/lat-groups.8");
system("/bin/rm -f","root/usr/man/man8/lat-hosts.8");
system("/bin/rm -f","root/usr/man/man8/lat-ibays.8");
system("/bin/rm -f","root/usr/man/man8/lat-pptp.8");
system("/bin/rm -f","root/usr/man/man8/lat-pseudonyms.8");
system("/bin/rm -f","root/usr/man/man8/lat-quota.8");
system("/bin/rm -f","root/usr/man/man8/lat-restore.8");
system("/bin/rm -f","root/usr/man/man8/lat-shadow.8");

1
contriborbase Normal file
View File

@ -0,0 +1 @@
contribs10

View File

@ -0,0 +1,45 @@
The Lazy Administrator's Toolkit
================================
Version: 0.9.0 (2004-09-08)
The Lazy Administrator's Tools is a set of scripts designed to automate batch
tasks and admin jobs for E-Smith/SME servers (5.x/6.x).
Currently the following tools are available:
* lat-user : add/delete users
* lat-group : add/delete groups
* lat-pseudonyms : add/delete e-mail pseudonyms for individual users
* lat-ibays : add/delete ibays
* lat-quota : set the disk quota for individual users
* lat-domains : add domainnames the server
* lat-hosts : add hostnames to the server
* lat-procmail : activate or deactivate procmail for individual users
* lat-pptp : activate or deactivate VPN access for individual users
* lat-dump : create input files for the above lat-tools, based on the
configuration files of the SME servers.
INSTALLATION: 
Download the latest version of the tools from
http://www.contribs.org/contribs/mblotwijk/Contribs/lazy-admin-tools/.
Install the tools as 'root':
[root@hogwarts /]# rpm -Uvh e-smith-lazy_admin_tools-*.rpm
This installs the tools in /usr/sbin, the example files in
/usr/doc/lazy-admin-tools and the man-pages in /usr/man/man8.
USAGE:
Each tool has its own comprehensive man page. See `man lazy-admin-tools` for an
overview of the tools that have been installed.
All tools follow the same concept:
- Arguments can be specified on the command line (--comand-line), or in a file
(--input-file) for batch processing.
- If the arguments are specified on the command line, the arguments must be
between quotes (e.g. -c="foo | bar | baz")
- Most tools recognize the wildcards * and ? in the first argument
(e.g -c="foo* | bar | baz").
- See the relevant man pages for the exact usage of the various tools.
- See the various examples in /usr/doc/lazy-admin-tools for the format of the
input file.

View File

@ -0,0 +1,17 @@
# Domainname : Should contain one or more letters, numbers, periods and
# minus signs.
# Wildcards (* and ?) can only be used to delete domainnames!
# Desription : Free text description of the domain.
# I-bay : Location where the content for the website can be found.
# Must be a valid ibay-name. Otherwise the primary website
# of the server is assumed.
#
# @ Mandatory field
#
#------------------------------------------------------------------,
# Domainname@ |Description |I-bay |
#------------------------------------------------------------------'
hogwarts.net |Wizards network |Vault
azkaban.org
delete.me*
delet?.me2

View File

@ -0,0 +1,24 @@
#
# NB: Please note that the format of the arguments has been changed in
# version 0.7. An (optional) field has been inserted to allow for the
# group id (GID).
#
#
# Group name : 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 groups!
# Description : Free text description of the group.
# UID/GID : Group ID. If omitted, the first available free uid/gid will be used.
# Member1..n : Must be a valid account on the server
#
# @ Mandatory field
#
#-------------------------------------------------------------------------------------------------,
# Group name@ |Description |GID |Member1 |Member2 |Member3 | etc... |
#-------------------------------------------------------------------------------------------------'
allstaff |Mailing group for all staff |7003 |michiel | ejo | susanne| nathalie| marco
finance |Finance department | |susanne |nathalie
sales|Sales department|7004 |marco
dev | Development | | michiel | ejo
delete_me*
delet?_me2

View File

@ -0,0 +1,29 @@
# Hostname : Must contain only letters, numbers, and hyphens, and must
# start with a letter or number.
# Wildcards (* and ?) can only be used to delete hosts!
# Domainname : Must be an existing (virtual) domainname. If omitted, the
# domainname of the server is used.
# Location : Location of the server. Must be one of the follwing:
# 'Local' (on the LAN)
# 'Remote' (on the Internet)
# 'Self' (alias for the SME server)
# Visibility : 'Local' (only visible on the LAN)
# 'Global' (visible on the entire Internet).
# LocalIP : Internal IP number
# GlobalIP : Public IP number
# MacAddress : The ethernet address is optional and causes the DHCP server
# to statically bind the local IP address to the computer with
# this ethernet address.
#
# @ Mandatory field
#
#-----------------------------------------------------------------------------------------------------------,
# Hostname@ |Domainname |Location |Visibility | LocalIP |GlobalIP |MacAddress |
#-----------------------------------------------------------------------------------------------------------'
dumbledore |hogwarts.net |Self
hagrid |azkaban.org |Local |Local |192.168.209.11 | |12:34:56:78:90:AB
quaffle |quiddich.net |Remote |Global |192.168.209.22 |64.12.47.28
seeker |harry.com.uk
dobby
delete_me*
delet?_me2

View File

@ -0,0 +1,30 @@
# IbayName : Must contain only lower-case letters, numbers, hyphens, periods
# and underscores, and should start with a lower-case letter.
# Wildcards (* and ?) are only accepted to delete ibays.
# Description: Free text description of the ibay.
# Group : Must be an existing group on the server.
# User access: wr-admin-rd-group
# wr-group-rd-everyone
# wr-group-rd-group
# Pub. access: local
# local-pw
# global
# global-pw
# global-pw-remote
# none
# Password : Password for the ibay in clear-text (dangerous!).
# CGI-bin : enabled
# disabled
# UID/GID : User ID. If omitted, the first available free uid/gid will be used.
#
# @ Mandatory field
#
#--------------------------------------------------------------------------------------------------------.
# IbayName@ |Description |Group@ |UserAccess |Publ.Access |Password |CGI-bin | Uid |
#--------------------------------------------------------------------------------------------------------'
intranet |Intranet website |allstaff |wr-admin-rd-group |local | |enabled | 6001
knowledge-db|Support website |dev |wr-group-rd-everyone |global | |enabled
vault |Folder for finance |finance |wr-group-rd-group |local-pw |secret |disabled
toolbox | Usefull tools ||||||6002
delete_me*
delet?_me2

View File

@ -0,0 +1,12 @@
# users : Must be an existing account on the server.
# Wildcards (* and ?) are accepted.
# pptpaccess : Either 'on' or 'off'.
#
# @ Mandatory field
#
#-------------------------,
# User@ |PPTPaccess@ |
#-------------------------'
* | off
michiel | on
ejo | on

View File

@ -0,0 +1,20 @@
# User : Must be an existing account on the server. The wildcards * and ?
# are recognized.
# Status : Either 'enabled' or 'disabled'. Default is 'disabled'.
# DelDups : Delete duplicates. Use 'yes' or 'no'. Default is 'no'.
# LogLevel : Amount of log info. Use 'none', 'some' or 'lots'. Default is
# 'some'.
# Mode : Set 'normal' or 'geek' mode. Default is 'normal'.
#
# @ Mandatory field
#
#---------------------------------------------------,
# User@ |Status |DelDups |LogLevel |Mode |
#---------------------------------------------------'
* |enabled |yes |none |normal
class199? |disabled
michiel |enabled |yes |none |geek
marco |enabled |yes |some |normal
susanne |disabled
nathalie|disabled
ejo|enabled|||geek

View File

@ -0,0 +1,14 @@
# UserName : Must be an existing account on the server.
# Pseudonym1..n : Must contain only lower-case letters, numbers, hyphens,
# periods and underscores, and should start with a lower-case
# letter.
#
# @ Mandatory field
#
#-------------------------------------------------------------------------------,
# UserName@ |Pseudonym1@ |Pseudonym2 |Pseudonym3 | etc... |
#-------------------------------------------------------------------------------'
marco | sales | support |info
root | abuse | noc | security | hostmaster | sysadmin
root | www | webmaster
michiel | michiel.blotwijk

View File

@ -0,0 +1,19 @@
# UserName : Must be an existing user account on the server. The wildcards
# * and ? are recognized.
# Soft limit : Limit with grace period. Quota sizes are default in kilobytes.
# However, the suffixes "M" for megabytes and "G" for gigabytes
# are also recognized.
# Hard limit : Absolute limit. Quota sizes are default in kilobytes. However,
# the suffixes "M" for megabytes and "G" for gigabytes are also
# recognized.
#
# @ Mandatory field
#
#-------------------------------------------------------------------------------'
# User@ |Soft limit@ |Hard limit@ |
#-------------------------------------------------------------------------------'
* |500M |550M
class199? |200 |250M
michiel |5G |6G
nathalie |500000 |550000
susanne |500M |550M

View File

@ -0,0 +1,10 @@
# User : 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 users!
# EncPassword : Encrypted password in the /etc/shadow file for this user
# @ Mandatory field
#
#-------------------,
# User@ |EncPasswd@ |
#-------------------,
nathalie|gsdt42r5tdsf

View File

@ -0,0 +1,29 @@
# User : 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 users!
# FirstName : First name of the user. May contain spaces.
# LastName : Last name of the user. May contain spaces.
# Passwd : Password for the user in clear-text (dangerous!). If left
# blank, the account will remain locked.
# EmailForward: Must be one of the following: local, forward or both. Default
# is local.
# Forward Add.: Must be an working e-mail adres.
# UID/GID : User ID. If omitted, the first available free uid/gid will be used.
# Group(s) : Group name(s) to which the user should be added. If the
# group doesn't exist, it will be created.
# If more than one group name is specified, they must be
# separated by the pipe character (|)
#
# @ Mandatory field
#
#-----------------------------------------------------------------------------------------------------------------------------------------------------------------,
# User@ |FirstName@ |LastName@ |Passwd |Department |Company |Street |City |Phone |Emailfrwrd |Forward Address | UID/GID |
#-----------------------------------------------------------------------------------------------------------------------------------------------------------------'
michiel |Michiel |Blotwijk | |Development |Altiplano bvba |Muntweide 7 |B-1785 Brussegem |+32 2 305.70.76 |forward |Michiel@Altiplano.Be | 9001
marco |Marco |Blanc |secret |Sales |Altiplano bvba |Muntweide 7 |B-1785 Brussegem |+32 2 305.70.76
ejo |Ejo |Burger ||||||||| 9002
gilbert |Gilbert |Volk |||||||||| allstaff| accounting | management
nathalie|Nathalie |Butterfly
susanne |Susanne |Rodin
delete_me*
delet?_me2

0
root/usr/man/man8/.gitignore vendored Normal file
View File

272
root/usr/sbin/lat-domains Normal file
View File

@ -0,0 +1,272 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-domains
# ===========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
package esmith;
use strict;
use esmith::config;
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 %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
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*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
# Add domainnames
if ($Add) {
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $domainname = lc($fields[0]);
if ( ! db_get(\%domains, $domainname)) {
if ( &TestDomainName($domainname)) {
if (( ! db_get(\%accounts, $fields[2])) ||
(db_get_type(\%accounts, $fields[2])) ne "ibay")
{ $fields[2] = 'wwwpublic'; }
if ( ! $fields[1]) { $fields[1] = "Domainname '$domainname' for content at '$fields[2]'"; }
print "Creating domainname '$domainname'. Linked to '$fields[2]'.\n";
my %domain = ("Content", $fields[2],
"Description", $fields[1]);
db_set(\%domains, $domainname, 'domain', \%domain);
system ("/sbin/e-smith/signal-event", "domain-create", "$domainname") == 0
or die ("Error occurred while creating '$domainname'.\n");
}
}
else { print "The domainname '$domainname' already exists.\a\n"; }
}
}
# Delete domainnames
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 $domainname = lc($fields[0]);
if ((db_get(\%domains, $domainname)) &&
(db_get_type(\%domains, $domainname)) eq "domain") {
my $yn = 'yes';
if (! $Frc) {
print "Do you want to delete domainname '$domainname' [yes/NO/all]? ";
$yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Deleting '$domainname'...\n";
db_delete(\%domains, $domainname);
system ("/sbin/e-smith/signal-event", "domain-delete", "$domainname") == 0
or die ("Error occurred while deleting '$domainname'.\n");
}
}
else { print "Can't find domainname '$domainname'.\n\a";}
}
}
#==============================================================================
# Subroutines
#==============================================================================
sub TestDomainName {
my $dname = $_[0];
if ($dname =~ /^[a-z][a-z0-9-.]*[a-z0-9]$/) {
$dname = $&;
return -1;
}
else {
print "Domainname contains illegal characters ($dname).\a\n";
return 0;
}
}
#==============================================================================
# Test for wildcards in the domainname. If any wildecards are found, the array
# @records is expanded with the domainnames 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, "</home/e-smith/db/domains" or die "Can't open /home/e-smith/db/domains: $!";
my @match = grep /^$fld[0]\=domain\|/i, <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<lat-domains> - The lazy administrator's tool to manage domainnames
=head1 DESCRIPTION
Creates or deletes domainnames on Mitel's SME servers.
This tool is functionally equivalent to the 'virtual domains' 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 a large number of domain names in a batch process, or delete domain names on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.domains> for the format of the input file.
=head1 SYNOPSIS
B<lat-domains> -a -c "domain | description | i-bay"
B<lat-domains> -a -i /path/to/domains.list
B<lat-domains> -d [-f] -c "domain"
B<lat-domains> -d [-f] -i /path/to/domains.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add a domain name to the server
=item B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-d>, B<--delete>
Delete a domain name 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 the domain name(s).
See F</usr/doc/lazy-admin-tools> for an example of an input file.
=back
=head2 Arguments:
domain* : Must contain one or more letters, numbers,
periods and minus signs. Wildcards (* and ?)
can only be used to delete domainnames.
desription : Free text description of the domain.
i-bay : Location where the content for the website
can be found. Must be a valid ibay-name.
Otherwise the primary website of the server is
assumed.
* mandatory field
=head1 EXAMPLES
B<lat-domains -a -c "hogwarts.net | School of witchcraft | hogwarts">
Creates the domain name 'hogwarts.net' and links it to i-bay 'hogwarts'.
B<lat-domains -a -c "quidditch.net">
Creates the domain name 'quidditch.net' and links it to the primary website.
B<lat-domains -a -i /root/domains.list>
Creates the domain names defined in F</root/domains.list>.
Refer to F</usr/doc/lazy-admin-tools/example.domains> for an example of an input file.
B<lat-domains -d -f -c "*.net">
Deletes all '.net' domain names without prompting (-f).
=head1 SEE ALSO
lat-users(8), lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

438
root/usr/sbin/lat-dump Normal file
View File

@ -0,0 +1,438 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-dump
# ========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
package esmith;
use strict;
use esmith::config;
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 %hosts;
tie %hosts, 'esmith::config', '/home/e-smith/db/hosts';
my %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
my %processmail;
# Really unsure of what this line does - John Bennett
tie %processmail, 'esmith::config', '/home/e-smith/db/processmail';
my ($Dump, $OutDir, $Hlp);
my $HostName = db_get(\%conf, 'SystemName');
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"dump" => \$Dump,
"output-path=s" => \$OutDir);
if ( $Hlp ) { &PrintPod(9); exit; }
if ($OutDir) {
if ( ! -d $OutDir ) { die "Error: $OutDir is not a directory\n\a"; }
}
else
{ $OutDir = "./"; }
if ($Dump) {
print "Creating input files for the lat-toolkit... ";
&ReadUsers;
&ReadPseudonyms;
&ReadProcmail;
&ReadQuota;
&ReadGroups;
&ReadPPTP;
&ReadIbays;
&ReadDomains;
&ReadHosts;
&ReadShadow;
open (REST, "> $OutDir/lat-restore");
print REST "#!/bin/bash\n";
print REST "echo 'This script was automatically created by lat-dump and will recreate all user'\n";
print REST "echo 'accounts, ibays, etc on this server.'\n";
print REST "echo 'Do you want to continue (Y/N)?'\n";
print REST "read c\n";
print REST 'if [ $c = "y" ] || [ $c = "Y" ]; then'."\n";
print REST " /usr/sbin/lat-users -a -i=$HostName.Users\n";
print REST " /usr/sbin/lat-procmail -i=$HostName.Procmail\n";
print REST " /usr/sbin/lat-quota -i=$HostName.Quota\n";
print REST " /usr/sbin/lat-groups -a -i=$HostName.Groups\n";
print REST " /usr/sbin/lat-pptp -i=$HostName.PPTP\n";
print REST " /usr/sbin/lat-ibays -a -i=$HostName.Ibays\n";
print REST " /usr/sbin/lat-domains -a -i=$HostName.Domains\n";
print REST " /usr/sbin/lat-hosts -a -i=$HostName.Hosts\n";
print REST " /usr/sbin/lat-pseudonyms -a -i=$HostName.Pseudonyms\n";
print REST " /usr/sbin/lat-shadow -a -i=$HostName.shadow\n";
print REST "else\n";
print REST " echo 'Action cancelled!'\n";
print REST "fi\n";
close(REST);
chmod 0750, "$OutDir/lat-restore";
print "\nDone!\n";
print "Use lat-restore to recreate the accounts, ibays, etc on a different server \nor on a clean install.\n";
}
else { &PrintPod(1); exit; }
#==============================================================================
# Subroutines
#==============================================================================
sub ReadShadow {
open(BACACC, "> $OutDir/$HostName.shadow");
print BACACC "#--------------------------------#\n";
print BACACC "#User |Encrypted Password |\n";
print BACACC "#--------------------------------#\n";
use esmith::ConfigDB;
use esmith::AccountsDB;
my $adb = esmith::AccountsDB->open_ro();
foreach my $user ($adb->users)
{
my %properties = $user->props;
my $key = $user->key;
# lecture shadow
open(ACC, "< /etc/shadow") || die "Can't find /etc/shadow.\a\n";
my $line = "";
while (<ACC>){
$line = $_;
if($line =~ /^$key:(.*):(.*):(.*):(.*):(.*):(.*):(.*):$/){
print BACACC $key.(' ' x (12 - length($key)));
print BACACC " |";
print BACACC $1."\n";
}
}
close(ACC);
}
}
#==============================================================================
sub ReadUsers {
my @fldinf = ("User", 12,
"FirstName", 10,
"LastName", 15,
"Password", 8,
"Dept", 15,
"Company", 15,
"Street", 15,
"City", 20,
"Phone", 16,
"EmailForward", 12,
"ForwardAddress", 30,
"Uid", 5);
&PrintDump("Users", "user", "accounts", \%accounts, @fldinf);
}
#==============================================================================
sub ReadQuota {
my @fldinf = ("User", 30,
"MaxBlocksSoftLim", 16,
"MaxBlocks", 16);
&PrintDump("Quota", "user", "accounts", \%accounts, @fldinf);
}
#==============================================================================
sub ReadDomains {
my @fldinf = ("Domain", 30,
"Description", 23,
"Content", 12);
&PrintDump("Domains", "domain", "domains", \%domains, @fldinf);
}
#==============================================================================
sub ReadIbays {
my @fldinf = ("User", 12,
"Name", 23,
"Group", 12,
"UserAccess", 20,
"PublicAccess", 12,
"Password", 8,
"CgiBin", 9,
"Uid", 5);
&PrintDump("Ibays", "ibay", "accounts", \%accounts, @fldinf);
}
#==============================================================================
sub ReadPPTP {
my @fldinf = ("PPTPAccess", 10);
open(ACC, "< /home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts.\a\n";
my @accounts = sort(grep(/\=user\|/, <ACC>));
close(ACC);
open(BACACC, "> $OutDir/$HostName.PPTP");
print BACACC "#-------------------------#\n";
print BACACC "#User |PPTP Access |\n";
print BACACC "#-------------------------#\n";
foreach (@accounts) {
$_ =~ /\=user\|/;
my $AccName = $`;
print BACACC $AccName.(' ' x (12 - length($AccName)));
my $SMEvalue = db_get_prop(\%accounts,$AccName,"PPTPAccess");
if ( ! $SMEvalue) { $SMEvalue = "off" }
print BACACC " |";
print BACACC $SMEvalue."\n";
}
close(BACACC);
}
#==============================================================================
sub ReadPseudonyms {
open(ACC, "< /home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts.\a\n";
my @accounts = sort(grep(/\=user\|/i, <ACC>));
close(ACC);
push(@accounts,"admin=user|");
open(ACC, "< /home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts.\a\n";
my @pseudonyms = grep(/\=pseudonym\|/i, <ACC>);
close(ACC);
open(BACACC, "> $OutDir/$HostName.Pseudonyms");
print BACACC "#".('-' x 78)."#\n";
print BACACC "#User |Pseudonyms".(' ' x 55)."|\n";
print BACACC "#".('-' x 78)."#\n";
foreach (@accounts) {
if ($_ =~ /\=user\|/) {
my $AccName = $`;
my $pseudolist;
foreach (@pseudonyms) {
my $psinfo = $_;
$psinfo =~ /\|Account\|/i;
my $owner = $'; chomp($owner);
if ($AccName eq $owner) {
if ($psinfo =~ /\=pseudonym\|/i) { $pseudolist .= " | ".$`; }
}
}
if ($pseudolist) {
print BACACC $AccName.(' ' x (12 - length($AccName))).$pseudolist."\n";
}
}
}
close(BACACC);
}
#==============================================================================
sub ReadGroups {
my @finfo = ("Group", 12,
"Description", 30,
"Gid", 5,
"Members", 25);
my $nm = "group";
open(ACC, "< /home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts.\a\n";
my @accounts = sort(grep(/\=group\|/, <ACC>));
close(ACC);
open(BACACC, "> $OutDir/$HostName.Groups");
my $Header= "#$finfo[0]".(' ' x ($finfo[1] - 1 - length($finfo[0])))." |";
for (my $cnt=2; $cnt<$#finfo; $cnt=$cnt+2) {
$Header .= $finfo[$cnt].(' ' x ($finfo[$cnt+1] - length($finfo[$cnt])))." |";
}
print BACACC "#".("-" x (length($Header)-2))."#\n";
print BACACC $Header."\n";
print BACACC "#".("-" x (length($Header)-2))."#\n";
foreach (@accounts) {
$_ =~ /\=group\|/;
my $AccName = $`;
print BACACC $AccName.(' ' x ($finfo[1] - length($AccName)));
my $cnt;
for ($cnt=2; $cnt<$#finfo-2; $cnt=$cnt+2) {
my $SMEvalue = db_get_prop(\%accounts,$AccName,$finfo[$cnt]);
if ( ! $SMEvalue) { $SMEvalue = " " }
print BACACC " |";
print BACACC $SMEvalue.(' ' x ($finfo[$cnt+1] - length($SMEvalue)));
}
my $members = db_get_prop(\%accounts, $AccName, $finfo[$cnt]);
$members =~ s/,/ \|/g;
print BACACC " |$members\n";
}
close(BACACC);
}
#==============================================================================
sub ReadProcmail {
my @finfo = ("User", 12,
"Status", 8,
"deldups", 7,
"loglevel", 8,
"mode", 6);
open(ACC, "< /home/e-smith/db/accounts") || die "Can't find /home/e-smith/db/accounts.\a\n";
my @accounts = sort(grep(/\=user\|/, <ACC>));
close(ACC);
open(BACACC, "> $OutDir/$HostName.Procmail");
my $Header= "#User |";
for (my $cnt=2; $cnt<$#finfo; $cnt=$cnt+2) {
$Header .= $finfo[$cnt].(' ' x ($finfo[$cnt+1] - length($finfo[$cnt])))." |";
}
print BACACC "#".("-" x (length($Header)-2))."#\n";
print BACACC $Header."\n";
print BACACC "#".("-" x (length($Header)-2))."#\n";
foreach (@accounts) {
$_ =~ /\=user\|/;
my $AccName = $`;
print BACACC $AccName.(' ' x ($finfo[1] - length($AccName)));
if (db_get_prop(\%accounts, $AccName, "EmailForward") =~ m/procmail/i)
{ print BACACC " |enabled " }
else { print BACACC " |disabled" }
for (my $cnt=4; $cnt<$#finfo; $cnt=$cnt+2) {
my $SMEvalue = db_get_prop(\%processmail, $AccName, $finfo[$cnt]);
if ( ! $SMEvalue) { $SMEvalue = " " }
print BACACC " |";
print BACACC $SMEvalue.(' ' x ($finfo[$cnt+1] - length($SMEvalue)));
}
print BACACC "\n";
}
close(BACACC);
}
#==============================================================================
sub ReadHosts {
my @finfo = ("HostType", 8,
"Visibility", 10,
"InternalIP", 15,
"ExternalIP", 15,
"MACAddress", 17);
open(ACC, "< /home/e-smith/db/hosts") || die "Can't find /home/e-smith/db/hosts.\a\n";
my @accounts = sort(grep(/\=host\|/, <ACC>));
close(ACC);
open(BACACC, "> $OutDir/$HostName.Hosts");
my $Header= "#Hosts |";
$Header .= "Domainname |";
for (my $cnt=0; $cnt<$#finfo; $cnt=$cnt+2) {
$Header .= $finfo[$cnt].(' ' x ($finfo[$cnt+1] - length($finfo[$cnt])))." |";
}
print BACACC "#".("-" x (length($Header)-2))."#\n";
print BACACC $Header."\n";
print BACACC "#".("-" x (length($Header)-2))."#\n";
foreach (@accounts) {
$_ =~ /\=host\|/;
my $AccName = $`;
$AccName =~ m/\./;
$AccName = $`;
my $Domain = $';
print BACACC $AccName.(' ' x (12 - length($AccName)))." |";
print BACACC $Domain.(' ' x (35 - length($Domain)));
for (my $cnt=0; $cnt<$#finfo; $cnt=$cnt+2) {
my $SMEvalue = db_get_prop(\%hosts,"$AccName.$Domain",$finfo[$cnt]);
if ( ! $SMEvalue) { $SMEvalue = " " }
print BACACC " |";
print BACACC $SMEvalue.(' ' x ($finfo[$cnt+1] - length($SMEvalue)));
}
print BACACC "\n";
}
close(BACACC);
}
#==============================================================================
# Print lat-info in a nice format
sub PrintDump {
my ($out, $nm, $src, $dbpointer, @finfo) = @_;
open(ACC, "< /home/e-smith/db/$src") || die "Can't find /home/e-smith/db/$src.\a\n";
my @accounts = sort(grep(/\=$nm\|/, <ACC>));
close(ACC);
open(BACACC, "> $OutDir/$HostName.$out");
my $Header= "#$finfo[0]".(' ' x ($finfo[1] - 1 - length($finfo[0])))." |";
for (my $cnt=2; $cnt<$#finfo; $cnt=$cnt+2) {
$Header .= $finfo[$cnt].(' ' x ($finfo[$cnt+1] - length($finfo[$cnt])))." |";
}
print BACACC "#".("-" x (length($Header)-2))."#\n";
print BACACC $Header."\n";
print BACACC "#".("-" x (length($Header)-2))."#\n";
foreach (@accounts) {
$_ =~ /\=$nm\|/;
my $AccName = $`;
print BACACC $AccName.(' ' x ($finfo[1] - length($AccName)));
for (my $cnt=2; $cnt<$#finfo; $cnt=$cnt+2) {
my $SMEvalue = db_get_prop($dbpointer,$AccName,$finfo[$cnt]);
if ( ! $SMEvalue) { $SMEvalue = " " }
print BACACC " |";
print BACACC $SMEvalue.(' ' x ($finfo[$cnt+1] - length($SMEvalue)));
}
print BACACC "\n";
}
close(BACACC);
}
#==============================================================================
# Print the pod text as a help screen
sub PrintPod {
my ($verbose, $message) = @_;
pod2usage(-verbose => $verbose, -message => $message, -exitval => 64);
}
#==============================================================================
=pod
=head1 NAME
B<lat-dump> - The lazy administrator's tool to extract config info
=head1 DESCRIPTION
Creates input-files for the lat-toolkit, based on the current configuration of the SME server (5.x/6.x). The information is extracted from the /home/e-smith/db/* databases.
The resulting input-files can be used to replicate user accounts, ibays, etc on a different SME server, or recreate them on a clean install. To facilitate the restoring/replicating, the lat-restore script is automatically created. This will launch the various lat-tools in the right sequence.
=head1 SYNOPSIS
B<lat-config> [options]
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-d>, B<--dump>
Create input files
=item B<-h>, B<--help>
Extended help for this tool
=item B<-o=/path/>, B<--output-dir=/path/>
Directory where the configuration files should be stored. If omitted, the current directory is used.
=back
=head1 EXAMPLES
B<lat-dump -d -o=/var/tmp>
Creates the configuration files and writes them to /var/tmp.
=head1 SEE ALSO
lat-users(8), lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(8), lat-domains(8), lat-hosts(8), lat-procmail(8), lat-pptp(8)
=head1 VERSION
Version 0.9.0 (2004-09-08). The latest version is hosted at B<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

423
root/usr/sbin/lat-groups Normal file
View File

@ -0,0 +1,423 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-groups
# ==========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
package esmith;
use strict;
use esmith::db;
use esmith::util;
use Pod::Usage;
use Getopt::Long;
my %conf;
tie %conf, 'esmith::config';
my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
my ($Hlp, $Cml, $Frc, $Inp, $Noa);
my $Add =0;
my $Del =0;
my $Rem =0;
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"add" => \$Add,
"delete" => \$Del,
"force" => \$Frc,
"no-admin", => \$Noa,
"remove-user" => \$Rem,
"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 && $Rem) || (! $Cml && ! $Inp && ! $Rem)) ||
($Add + $Del + $Rem != 1))
{ &PrintPod(1); exit; }
my @records;
if ($Inp) {
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
# Add groups
if ($Add) {
# Process each group
foreach my $record (@records) {
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $groupname = $fields[0];
# We need a valid group name
if ( ! &TestName($fields[0])) { exit; }
# Create the group, if needed
if ( ! db_get(\%accounts, $groupname)) {
# Find a usable GID
my $gid;
if ($fields[2]) { $gid = $fields[2]; }
else { $gid = &FindUid;}
if (&TestUid($gid)) {
my %group = ("Description", $fields[1],
"Uid",$gid,
"Gid",$gid,
"Members","");
print "Creating group '$fields[0]' (GID:$gid).\n";
db_set(\%accounts, $groupname, 'group', \%group);
system("/sbin/e-smith/signal-event", "group-create", $groupname) == 0
or die ("An error occurred while creating group $groupname.\n\a");
}
}
# Add the members to the group, if they are valid accounts
if ( db_get_type(\%accounts, $groupname) eq "group" ) {
for (my $cnt=3; $cnt < @fields; ++$cnt ) {
# Check if this user exists on the server
if (((db_get(\%accounts, $fields[$cnt])) &&
(db_get_type(\%accounts, $fields[$cnt])) eq "user") ||
($fields[$cnt] eq 'admin')) {
# Is she already a member of this group?
my $members = db_get_prop(\%accounts, $groupname, 'Members');
if (! $members) { $members="" }
if (! ($members =~ m/\b$fields[$cnt]\b/)) {
# Append the new member to the list and update the group
if (length($members) > 0) { $members=$members.",";}
$members = $members."$fields[$cnt]";
print "Adding user '$fields[$cnt]' to group '$fields[0]'.\n";
db_set_prop(\%accounts, $groupname, 'Members', $members);
system("/sbin/e-smith/signal-event", "group-modify", $groupname) == 0
or die ("An error occurred while updating group $groupname.\n\a");
}
}
else { print "User '$fields[$cnt]' doesn't exist on this server.\n\a"; }
}
}
else { print "Error: '$groupname' is not a valid group name on this system.\a\n"; }
# Remove 'admin' and 'www' from /etc/group if we don't want them.
if ($Noa) {
system("/usr/bin/gpasswd -d www $groupname > /dev/null");
system("/usr/bin/gpasswd -d admin $groupname > /dev/null");
}
}
}
# Delete groups
if ($Del) {
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each group
foreach my $record (@records) {
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $groupname = $fields[0];
# Silly, but if 'www' and 'admin' aren't member of this group an error message will be shown :-/
system("/usr/bin/gpasswd -a www $groupname > /dev/null");
system("/usr/bin/gpasswd -a admin $groupname > /dev/null");
if ((db_get_type(\%accounts, $groupname)) &&
(db_get_type(\%accounts, $groupname)) eq 'group')
{
my $yn = 'yes';
if (! $Frc) {
print "Delete group '$groupname' [yes/NO/all]? "; $yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Deleting group '$groupname'.\n";
db_delete(\%accounts, $groupname);
system("/sbin/e-smith/signal-event", "group-delete", $groupname);
}
}
else { print "Group '$groupname' doesn't exist on this server.\n\a"; }
}
}
# Remove users from group
if ($Rem) {
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each group
foreach my $record (@records) {
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $groupname = $fields[0];
if ( db_get(\%accounts, $groupname)) {
# Remove the members from the group
for (my $cnt=1; $cnt < @fields; ++$cnt ) {
my $members = db_get_prop(\%accounts, $groupname, 'Members');
if (! $members) { $members="" }
my $yn = 'yes';
if (! $Frc) {
print "Remove user '$fields[$cnt]' from group '$groupname' [yes/NO/all]? "; $yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Removing member '$fields[$cnt]' from group '$fields[0]'.\n";
$members =~ s/$fields[$cnt]//;
$members =~ s/,,/,/ ;
$members =~ s/(^,)|(,$)//;
db_set_prop(\%accounts, $groupname, 'Members', $members);
system("/sbin/e-smith/signal-event", "group-modify", $groupname) == 0
or die ("An error occurred while updating group $groupname.\n\a");
}
}
}
else { print "The group '$groupname' does not exist on this server.\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*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
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 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(/Gid\|\d*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
close(GRP);
if (! ($_[0] =~ /^\d*$/)) {
print "Error: A group ID should contain only numbers.\a\n";
exit;
}
elsif ( $_[0] < db_get(\%conf, 'MinUid')) {
print "Error: The group ID should be greater or equal to ".&FindUid.".\a\n";
exit;
}
elsif ((grep(/Gid\|$_[0]\D/,@recs)) or
(grep(/\:$_[0]\:/,@pwds)) or
(grep(/\:$_[0]\:/,@grps))) {
print "Error: The gid '$_[0]' is already in use\a\n";
exit;
}
else { return 1 };
}
#==============================================================================
# Test name for illegal characters
sub TestName {
if ( $_[0] =~ /^[a-z][a-z\-\_\d]*$/ ) {
return -1;
}
else {
print "The group name '$_[0]' contains illegal characters.\n";
print "The name should contain only lower-case letters, numbers, hyphens and\n";
print "underscores, and should start with a lower-case letter.\n\a";
return 0;
}
}
#==============================================================================
# Test for wildcards in the groupname. If any wildecards are found, the array
# @records is expanded with the groupnames 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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=group\|/i, <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<lat-groups> - The lazy administrator's tool to create groups and to add members to it.
=head1 DESCRIPTION
Creates or deletes groups on Mitel's or SME Servers (5.x/6.x/7.x).
This tool is functionally equivalent to the 'groups' 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 add a large number of accounts to a group, or delete groups on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.groups> for the format of the input file.
=head1 SYNOPSIS
B<lat-groups> -a [-n] -c "group | descr. | gid | user1| user2"
B<lat-groups> -a [-n] -i /path/to/groups.list
B<lat-groups> -r [-f] -c "group | user1 | user2"
B<lat-groups> -d [-f] -c "group"
B<lat-groups> -d [-f] -i /path/to/groups.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add a group to the server, or add users to an existing group.
=item B<-c "Arguments">, B<--command-line="Aruments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-d>, B<--delete>
Delete a group 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 F<FILE> to create or delete the group(s).
See F</usr/doc/lazy-admin-tools> for an example of an input file.
=item B<-n>, B<--no-admin>
Do not add 'admin' and 'www' as users to this group. Remove them if they are already member of this group.
Default behaviour on SME is to add both users to any group, thus limiting the number of groups on the server to 28.
Note, however, that SME is very persistent with this 'feature'. Each time you add or remove a user via the
server-manager, both 'admin' and 'www' are added again.
=item B<-r>, B<--remove-users>
Remove users from this group. Wildcards (* and ?) are accepted for the groupname.
=back
=head2 Arguments:
group* : 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 groups.
descr. : Free-text description of the group
gid : Group ID. If omitted, a suitable gid will be generated.
member(s) : Username of a member of the group. Must be an
existing account on the server.
* mandatory field
=head1 EXAMPLES
B<lat-groups -a -c "hogwarts | School of Witchcraft | | harry | hermione">
Creates group 'hogwarts' with users 'harry' and 'hermione'.
B<lat-groups -a -i /root/griffindor.list>
Creates the groups defined in /root/griffindor.list.
Refer to /usr/doc/lazy-admin-tools/example.groups for an example of an input file.
B<lat-groups -a -n -i /root/griffindor.list>
Creates the groups defined in /root/griffindor.list.
The users 'admin' and 'www' are *not* added to the group.
B<lat-groups -d -f -c "class*">
Deletes all groups whose name start with 'class'.
All groups are deleted without prompting (-f).
B<lat-groups -r -f -c " * | admin | www">
Removes users 'admin' and 'www' from all groups on the system.
Don't prompt before removing.
B<lat-groups -a -c "quidditch | Different ball game | 7005">
Creates group 'quidditch' with group ID 7005.
=head1 SEE ALSO
lat-users(8), lat-pseudonyms(8), lat-ibays(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

422
root/usr/sbin/lat-hosts Normal file
View File

@ -0,0 +1,422 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-hosts
# =========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
package esmith;
use strict;
use esmith::config;
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 %hosts;
tie %hosts, 'esmith::config', '/home/e-smith/db/hosts';
my %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
my ($Hlp, $Cml, $Frc, $Inp);
my $Add =0;
my $Del =0;
#==============================================================================
# Main
#==============================================================================
sub performCreateLocalHostEntry ($$$$$$$);
# 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*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
if ($Add) {
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
performCreateLocalHostEntry ($fields[0], # HostName
$fields[1], # DomainName
$fields[2], # Location
$fields[3], # Visibility
$fields[4], # Local IP
$fields[5], # Global IP
$fields[6]); # Mac Address
}
}
if ($Del) {
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
if (! $fields[1] ) { $fields[1] = db_get(\%conf, 'DomainName') }
my $FullHostName = lc($fields[0]).".".lc($fields[1]);
if ((db_get(\%hosts, $FullHostName)) &&
(db_get_type(\%hosts, $FullHostName)) eq "host") {
my $yn = 'yes';
if (! $Frc) {
print "Do you want to delete host '$FullHostName' [yes/NO/all]? ";
$yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Deleting '$FullHostName'...\n";
db_delete(\%hosts, $FullHostName);
system ("/sbin/e-smith/signal-event", "host-delete", "$FullHostName") == 0
or die ("Error occurred while deleting '$FullHostName'.\n");
}
}
else { print "Can't find host '$FullHostName'.\n\a";}
}
}
#==============================================================================
# Subroutines
#==============================================================================
# Create local host
sub performCreateLocalHostEntry ($$$$$$$)
{
my $REGEXPMACAddress = '([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f]){5})';
my $REGEXPIPAddress = '(self|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})';
my $REGEXPHostname = '([a-z0-9][a-z0-9-]*)';
my ($q) = @_;
my ($HostName, $DomainName, $Location, $Visibility, $InternalIP, $ExternalIP, $MACAddress) = @_;
my %hostProperties;
#------------------------------------------------------------
# Validate parameters and untaint them
#------------------------------------------------------------
# Hostname
$HostName = lc($HostName);
if ($HostName =~ /^$REGEXPHostname$/) {
$HostName = $1;
}
else {
print "Bad hostname ($HostName).\a\n";
return;
}
if (length $HostName > 32) {
print "Hostname too long.\a\n";
return;
}
# Domainname
if (! $DomainName) { $DomainName = db_get(\%conf, 'DomainName') }
$DomainName = lc($DomainName);
if ((! db_get(\%domains, $DomainName)) &&
( db_get(\%conf, 'DomainName') ne $DomainName)) {
print "\nThe domainname '$DomainName' is not hosted on this server.\a\n";
return;
}
if ($DomainName =~ /^([a-z0-9\-\.]+)$/) {
$DomainName = $1;
}
else {
print "Unexpected characters in '$DomainName'.\a\n";
return;
}
print "\nCreating $HostName.$DomainName...\n";
# Location
if (! $Location) { $Location = "Self" }
if ( $Location =~ /(local)|(remote)|(self)/i ) {
$Location = ucfirst lc $Location;
}
else { $Location = "Self" }
# Visibility
if ( ! $Visibility ) {
$Visibility = "Local";
$ExternalIP = "";
}
if ( $Visibility =~ /(local)|(global)/i ) {
$Visibility = ucfirst lc $Visibility;
}
else { $Visibility = "Local" }
if ($Visibility eq "Local") { $ExternalIP = "" }
# Internal IP address
if (! $InternalIP) { $InternalIP = ''; }
if ($Location eq 'Self') { $InternalIP = '' }
elsif ($InternalIP =~ /^$REGEXPIPAddress$/ ) { $InternalIP = $1; }
else {
print "Error: IP Address '$InternalIP' is invalid. Did not create hostname.\a\n";
return;
}
# MAC address
if (( ! $MACAddress ) || ($Location ne "Local")) { $MACAddress = "" }
if ( length($MACAddress) == 0 )
{
# They don't want one
}
elsif ($MACAddress =~ /^$REGEXPMACAddress$/i )
{
$MACAddress = $1;
}
else
{
print "Invalid Mac Address \n";
return;
}
# External IP
if ( ! $ExternalIP ) { $ExternalIP = "" }
if ($Visibility eq 'Global') # Wants externally visible - needs external IP
{
if ( length ($ExternalIP) == 0 )
{
print "Error: You did not enter a Global IP value for '$HostName'.\a\n";
return;
}
elsif ($ExternalIP =~ /^$REGEXPIPAddress$/ )
{
$ExternalIP = $1;
}
else
{
print "Error: IP Address '$ExternalIP' is invalid. Did not create hostname.\a\n";
return;
}
}
else # Wants internally visible - optional external IP
{
if ( length ($ExternalIP) == 0 )
{
# They didn't specify one
}
elsif ($ExternalIP =~ /^$REGEXPIPAddress$/ )
{
$ExternalIP = $1;
}
else
{
print "Error: IP Address '$ExternalIP' is invalid. Did not create hostname.\a\n";
return;
}
}
#------------------------------------------------------------
# Looks good. Find out if this entry has been taken
#------------------------------------------------------------
my $fullHostName = join (".", $HostName, $DomainName);
if (defined (db_get(\%hosts, $fullHostName)) )
{
print "HostName '$fullHostName' already exists. \n";
return;
}
#------------------------------------------------------------
# Host entry is available! Update hosts database.
#------------------------------------------------------------
print "HostName : $HostName\n";
print "DomainName : $DomainName\n";
print "Location : $Location\n";
print "Visibility : $Visibility\n";
print "Local IP : $InternalIP\n";
print "Global IP : $ExternalIP\n";
print "Mac Address : $MACAddress\n";
$hostProperties{'Visibility'} = $Visibility;
$hostProperties{'HostType'} = $Location;
$hostProperties{'InternalIP'} = $InternalIP;
$hostProperties{'ExternalIP'} = $ExternalIP;
$hostProperties{'MACAddress'} = $MACAddress;
db_set(\%hosts, $fullHostName, 'host', \%hostProperties);
#------------------------------------------------------------
# Signal the create-host event.
#------------------------------------------------------------
system ("/sbin/e-smith/signal-event", "host-create", "$HostName") == 0
or die ("Error occurred while creating hostname.\n");
}
#==============================================================================
# Test for wildcards in the hostname. If any wildecards are found, the array
# @records is expanded with the hostnames 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.
if (! $fld[1]) { $fld[1] = db_get(\%conf, 'DomainName'); }
open USRS, "</home/e-smith/db/hosts" or die "Can't open /home/e-smith/db/hosts: $!";
my @match = grep /^$fld[0]\.$fld[1]=host\|/i, <USRS>;
close(USRS);
my $cu = 0;
foreach my $tst (@match) {
$tst =~ /\.$fld[1]\=/; $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<lat-hosts> - The lazy administrator's tool to manage hostnames
=head1 DESCRIPTION
Creates or deletes hosnames on Mitel's SME servers.
This tool is functionally equivalent to the 'Hostnames and addresses' 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 a large number of hostnames in a batch process, or delete hostnames on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.hosts> for the format of the input file.
=head1 SYNOPSIS
B<lat-hosts> -a -c "host| domain| loc. | visib. | loc.ip | glob.ip | mac"
B<lat-hosts> -a -i /path/to/hosts.list
B<lat-hosts> -d [-f] -c "Host | Domain"
B<lat-hosts> -d [-f] -i /path/to/hosts.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add a host name 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 a hostname 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 F<FILE> to create or delete the hostname(s).
=back
=head2 Arguments:
host* : Must contain only letters, numbers, and hyphens,
and must start with a letter or number. Wildcards
(* and ?) can only be used to delete hostnames.
domain : Must be an existing (virtual) domain name. If
omitted, the primary site is assumed.
loc. : Location of the server:
'Local' (on the LAN)
'Remote' (on the Internet)
'Self' (alias for the SME server)
visib. : 'Local' (only visible on the LAN)
'Global' (visible on the entire Internet).
loc.ip : Internal IP number
glob.ip : Public IP number
mac : The ethernet address is optional and causes the
DHCP server to statically bind the local IP address
to the computer with this ethernet address.
* mandatory field
=head1 EXAMPLES
B<lat-hosts -a -c "ntp | hogwarts.net | self | local">
Creates host name 'ntp.hogwarts.net' on the SME server. The host name will be visible only on the LAN.
B<lat-hosts -a -i /root/hosts.list>
Creates the host names defined in F</root/hosts.list>. Refer to F</usr/doc/lazy-admin-tools/example.hosts> for an example of an input file.
B<lat-hosts -d -f -c "ftp*">
Deletes all host names that start with 'ftp'. The host names will be deleted without prompting (-f).
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(8), lat-domains(8), lat-users(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

370
root/usr/sbin/lat-ibays Normal file
View File

@ -0,0 +1,370 @@
#!/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*$)/,<LIST>);
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 = <STDIN>;
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*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
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*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=ibay\|/i, <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<lat-ibays> - 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</usr/doc/lazy-admin-tools/example.ibays> for the format of the input file.
=head1 SYNOPSIS
B<lat-ibays> -a -c "ibay | descr | group | useraccess | publicaccess | password | cgi-bin | uid"
B<lat-ibays> -a -i /path/to/ibays.list
B<lat-ibays> -d [-f] -c "Ibay"
B<lat-ibays> -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<lat-ibays -a -c "library | Hogwarts' library | griffindor">
Creates the i-bay 'library' for user group 'griffindor'.
B<lat-ibays -a -i "/root/ibays.list">
Creates the i-bays defined in F</root/ibays.list>.
Please refer to F</usr/doc/lazy-admin-tools/example.users> for an example of an input file.
B<lat-ibays -d -f -c "class*">
Deletes all ibays that start with 'class'. All ibays and their files are deleted without prompting (-f).
B<lat-ibays -a -c "library | Hogwarts' library | griffindor | wr-group-rd-group | local-pw | quidditch | enabled | 8003">
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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

277
root/usr/sbin/lat-pptp Normal file
View File

@ -0,0 +1,277 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-pptp
# ========
# 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, $Inp);
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"command-line=s" => \$Cml,
"input-file=s" => \$Inp);
if ( $Hlp ) { &PrintPod(9); exit; }
# What (major) SME version are we running on?
db_get_prop(\%conf, "sysconfig", "ReleaseVersion");
my $MVer = db_get_prop(\%conf, "sysconfig", "ReleaseVersion");
$MVer=substr($MVer,0,1);
# We need one argument or the other, but not both
if (($Cml && $Inp) || (! $Cml && ! $Inp))
{ &PrintPod(1); exit; }
# Check if pptp is active
if (db_get_prop(\%conf, "pptpd", "status") ne "enabled") {
print "PPTP was not activated on your server. Please activate it by increasing the\n";
print "number of PPTP clients in the server-manager (Security / Remote Access).\n\a";
exit;
}
my @records;
if ($Inp) {
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $username = $fields[0];
if ( @fields >= 2) { # Both arguments must be given
if ((db_get(\%accounts, $username)) &&
(db_get_type(\%accounts, $username) eq "user")) {
# Deactivate PPTP
if ($fields[1] =~ /off/i ) {
print "Deactivating VPN access for user '$username'.\n";
SWITCH: {
($MVer=="5") && do {
db_set_prop(\%accounts, $username, 'PPTPAccess', "off");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="6") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "no");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="7") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "no");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="8") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "no");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="9") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "no");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
}
}
# Activate PPTP
elsif ($fields[1] =~ /on/i ) {
print "Activating VPN access for user '$username'.\n";
SWITCH: {
($MVer=="5") && do {
db_set_prop(\%accounts, $username, 'PPTPAccess', "on");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="6") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "yes");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="7") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "yes");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="8") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "yes");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
($MVer=="9") && do {
db_set_prop(\%accounts, $username, 'VPNClientAccess', "yes");
system("/sbin/e-smith/signal-event", "remoteaccess-update", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
last SWITCH;
};
}
}
else { print "Unknown argument '$fields[1]' for user $username"; }
}
else { print "User '$username' doesn't exist on this server.\n\a"; }
}
else { print "We need at least a user name and its VPN access status ('on' or 'off').\n\a"; }
}
#==============================================================================
# Subroutines
#==============================================================================
# Test for wildcards in the username. If any wildecards are found, the array
# @records is expanded with the user 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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=user\|/i, <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<lat-pptp> - The lazy administrator\'s tool to (de)activate pptp access
=head1 DESCRIPTION
PPTP access is by default deactivated on Mitel's SME servers (5.x/6.x).
Once activated in the server-manager pannel, you still need to grant or deny
VPN access to individual users. With lat-pptp you can enable or disable VPN
access on a per-user basis.
In SME 5.6 there is no functional equivalent for lat-pptp in the server-manager.
In SME 6.0 you can find this setting under Collaboration/Users.
See F</usr/doc/lazy-admin-tools/example.pptp> for the format of the input file.
=head1 SYNOPSIS
B<lat-pptp> -c "user | pptpaccess"
B<lat-pptp> -a -i /path/to/pptp.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-h>, B<--help>
Extended help for this tool
=item B<-i FILE>, B<--input-file=FILE>
Use the information from FILE to activaet pptp
=back
=head2 Arguments:
users* : Must be an existing account on the server.
Wildcards (* and ?) are accepted.
pptpaccess : Either 'on' or 'off'. Default is 'off'.
* mandatory field
=head1 EXAMPLES
B<lat-pptp -c "harry | on">
Activates pptp for user 'harry'.
B<lat-pptp -c "* | off">
Dectivates pptp for all users on the server.
B<lat-pptp -i /root/pptp.list>
Sets pptp access for the users as defined in F</root/pptp.list>.
Refer to F</usr/doc/lazy-admin-tools/example.users> for an example of an input file.
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

250
root/usr/sbin/lat-procmail Normal file
View File

@ -0,0 +1,250 @@
#!/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 %processmail;
tie %processmail, 'esmith::config', '/home/e-smith/db/processmail';
my ($Hlp, $Cml, $Inp);
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"command-line=s" => \$Cml,
"input-file=s" => \$Inp);
if ( $Hlp ) { &PrintPod(9); exit; }
# Check for e-smith-user-panel
my $UPanel=`rpm -qa | grep -c "smeserver-userpanel"`;
my $MSorting=`rpm -qa | grep -c "smeserver-mailsorting"`;
if ( $UPanel < 1 || $MSorting < 1) {
print "\nThis tool requires the smeserver-userpanel and smeserver-mailsorting contribution.\n";
print "Please download them with yum from smecontribs repo and configure them first.\n\n\a";
exit;
}
# We need one argument or the other, but not both
if (($Cml && $Inp) || (! $Cml && ! $Inp))
{ &PrintPod(1); exit; }
my @records;
if ($Inp) {
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $username = $fields[0];
if ( @fields >= 2) { # The first two arguments are manadatory.
my $enabled = 0; if ($fields[1] =~ /^e/i) { $enabled=-1 }
my %user = ("deldups", $fields[2],
"loglevel", $fields[3],
"mode", $fields[4]);
if ( $fields[2] ) { $user{'deldups'} = $fields[2] } else { $user{'deldups'} = "no" }
if ( $fields[3] ) { $user{'loglevel'} = $fields[3] } else { $user{'loglevel'} = "some" }
if ( $fields[4] ) { $user{'mode'} = $fields[4] } else { $user{'mode'} = "normal" }
if ((db_get(\%accounts, $username)) &&
(db_get_type(\%accounts, $username) eq "user")) {
if ($enabled) {
if (&ValidArguments(\%user, $username)) {
print "Activating procmail for user '$username'.\n";
db_set(\%processmail, $username, 'settings', \%user);
db_set_prop(\%accounts, $username, 'EmailForward', 'procmail');
system("/sbin/e-smith/signal-event", "email-update-quick", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
}
}
else {
print "Deactivating procmail for user '$username'.\n";
db_delete(\%processmail, $username, 'settings', \%user);
db_set_prop(\%accounts, $username, 'EmailForward', 'local');
system("/sbin/e-smith/signal-event", "email-update-quick", $username) == 0
or die ("An error occurred while updating account '$username'.\n");
}
}
else { print "User '$username' doesn't exist on this server.\n\a"; }
}
else { print "We need at least a user name and its status ('enabled' or 'disabled').\n\a"; }
}
#==============================================================================
# Subroutines
#==============================================================================
# Test the various arguments for their validity
sub ValidArguments {
my $href = $_[0];
my $nm = $_[1];
my $ret = 1;
if ( ! ($href->{'deldups'} =~ /^[yn]/i )) {
print "Can't activate procmail for user '$nm'.\n";
print "The 'delete duplicates' argument must be either 'yes' or 'no'.\n\a";
$ret = 0;
}
if ( ! ($href->{'loglevel'} =~ /^[nsl]/i )) {
print "Can't activate procmail for user '$nm'.\n";
print "The 'loglevel' argument must be either 'none', 'some' or 'lots'.\n\a";
$ret = 0;
}
if ( ! ($href->{'mode'} =~ /^[ng]/i )) {
print "Can't activate procmail for user '$nm'.\n";
print "The 'mode' argument must be either 'normal' or 'geek'.\n\a";
$ret = 0;
}
return $ret;
}
#==============================================================================
# Test for wildcards in the username. If any wildecards are found, the array
# @records is expanded with the user 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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=user\|/i, <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<lat-procmail> - The lazy administrator's tool to (de)activate procmail for individual users
=head1 DESCRIPTION
Activates or deactivates procmail for individual users on Mitel's SME servers.
This tool is primarily intended to activate B<SpamAssassin> system-wide, but can also be used for other purposes.
It requires smeserver-userpanel and smeserver-mailsorting.
See F</usr/doc/lazy-admin-tools/example.procmail> for the format of the input file.
=head1 SYNOPSIS
B<lat-procmail> -c "user| status| deldups| loglevel| mode"
B<lat-procmail> -i /path/to/users.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-h>, B<--help>
Extended help for this tool
=item B<-i FILE>, B<--input-file=FILE>
Use the information from F<FILE> to (de)activate procmail for individual users.
See F</usr/doc/lazy-admin-tools> for an example of an input file.
=back
=head2 Arguments:
user* : Must be an existing account on the server.
Wildcards (* and ?) are accepted.
status : Either 'enabled' or 'disabled'.
Default is 'disabled'.
deldups : Delete duplicates. Use 'yes' or 'no'.
Default is 'no'.
loglevel : Amount of log info. Use 'none', 'some' or 'lots'.
Default is 'some'.
mode : Set 'normal' or 'geek' mode. Default is 'normal'.
* mandatory field
=head1 EXAMPLES
B<lat-procmail -c "harry | enabled | yes | lots | geek">
Activates procmail for user 'harry', deletes duplicate mails with extensive logging and activates geek-mode.
B<lat-procmail -i /root/procmail.list >
Activates procmail for the users defined in F</root/procmail.list>.
Refer to F</usr/doc/lazy-admin-tools/example.users> for an example of an input file.
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(8), lat-domains(8), lat-hosts(8), lat-users(8), lat-pptp(8), lat-dump(8)
=head1 VERSION
Version 0.9.0 (2004-09-08). The latest version is hosted at B<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

View File

@ -0,0 +1,229 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-pseudonyms
# ==============
# 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 %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
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*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
if (((db_get(\%accounts, $fields[0])) && (db_get_type(\%accounts, $fields[0]) eq "user" )) ||
((db_get(\%accounts, $fields[0])) && (db_get_type(\%accounts, $fields[0]) eq "group")) ||
($fields[0] eq 'admin')) {
if (@fields == 1 )
{ print "We need at least one pseudonym for user '$fields[0]' to perform this action.\n\a"; }
for (my $count=1; $count<@fields;++$count) {
# Add pseudonyms
if ($Add) {
if ( ! db_get(\%accounts, $fields[$count])) {
if ( &TestName($fields[$count])) {
print "Creating pseudonym '$fields[$count]' for user $fields[0]...\n";
db_set(\%accounts, $fields[$count], 'pseudonym', {"Account", $fields[0]});
system("/sbin/e-smith/signal-event", "pseudonym-create", $fields[$count], $fields[0]) == 0
or die("An error occurred while creating pseudonym '$fields[$count]'.\n\a");
}
}
else { print "Pseudonym '$fields[$count]'already exists.\n\a"; }
}
# Delete pseudonyms
if ($Del) {
if ((db_get(\%accounts, $fields[$count])) &&
(db_get_type(\%accounts, $fields[$count]) eq "pseudonym")) {
my $yn = 'yes';
if (! $Frc) {
print "Do you want to delete pseudonym '$fields[$count]' [yes/NO/all]? ";
$yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Deleting pseudonym '$fields[$count]'.\n";
db_delete(\%accounts, $fields[$count], 'pseudonym', {"Account", $fields[0]});
system("/sbin/e-smith/signal-event", "pseudonym-delete", $fields[$count], $fields[0]) == 0
or die("An error occurred while deleting pseudonym '$fields[$count]'.\n\a");
}
}
else { print "Pseudonym '$fields[$count]' does not exist on this server.\n\a"; }
}
}
}
else { print "There is no user or group with the name '$fields[0]' on this server.\a\n"; }
}
#==============================================================================
# Subroutines
#==============================================================================
# Test name for illegal characters
sub TestName {
if ( $_[0] =~ /^[a-z][a-z\-\_\d\.]*$/ ) {
return -1;
}
elsif ( $_[0] =~ /^[a-z][a-z\-\_\d\.]*\@([a-z\-\_\d\.]*)$/ ) {
print "Trying to create a pseudonym specific for $1 domain,\n";
print "checking if domain is configured for this server... \n";
if (((db_get(\%domains, $1)) && (db_get_type(\%domains, $1) eq "domain" )) ){
print "yes, it exists, go on!!\n";
return -1
}
}
else {
print "The pseudonym '$_[0]' contains illegal characters. The name should ";
print "contain only\nlower-case letters, numbers, hyphens, periods ";
print "and underscores, and should\nstart with a lower-case letter.\n\a";
return 0;
}
}
#==============================================================================
# Print the pod text as a help screen
sub PrintPod {
my ($verbose, $message) = @_;
pod2usage(-verbose => $verbose, -message => $message, -exitval => 64);
}
#==============================================================================
=pod
=head1 NAME
B<lat-pseudonyms> - The lazy administrator's tool to add pseudonyms
=head1 DESCRIPTION
Adds or deletes e-mail pseudonyms to existing user or group accounts on Mitel's SME servers (5.x/6.x).
This tool is functionally equivalent to the 'Pseudonyms' 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 a large number of e-mail aliases in a batch process, or delete the standard pseudonyms on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.pseudonyms> for the format of the input file.
=head1 SYNOPSIS
B<lat-pseudonyms> -a -c "username | pseudonym1 | pseudonym2"
B<lat-pseudonyms> -a -i /path/to/quota.list
B<lat-pseudonyms> -d [-f] -c "user | pseudonym"
B<lat-pseudonyms> -d [-f] -i /path/to/quota.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add a pseudonym to a user or group.
=item B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-d>, B<--delete>
Delete a pseudonym from the server
=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 the pseudonyms.
=back
=head2 Arguments:
user* : Must be a valid user or group on the server.
pseudonym* : Must contain only lower-case letters, numbers,
hyphens, arobase, periods and underscores, and should
start with a lower-case letter.
* mandatory field
=head1 EXAMPLES
B<lat-pseudonyms -a -c "harry | wizard | seeker |potter@existinglocaldomain.com">
Creates the pseudonyms 'wizard', 'seeker' and 'potter@existinglocaldomain.com' for user 'harry'.
B<lat-pseudonyms -a -i /root/pseudonyms.list>
Creates the pseudonyms defined in F</root/pseudonyms.list>. Refer to F</usr/doc/lazy-admin-tools/example.users> for an example of an input file.
B<lat-pseudonyms -d -f -c "harry | wizard | seeker">
Deletes pseudonyms 'wizard' and 'seeker' from user 'harry'. The pseudonyms are deleted without prompting (-f).
=head1 SEE ALSO
lat-group(8), lat-users(8), lat-ibays(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

208
root/usr/sbin/lat-quota Normal file
View File

@ -0,0 +1,208 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-quota
# =========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
package esmith;
use strict;
use esmith::db;
use Getopt::Long;
use Pod::Usage;
my %conf;
my %accounts;
tie %conf, 'esmith::config';
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
my ($Hlp, $Cml, $Inp);
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"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))
{ &PrintPod(1); exit; }
my @records;
if ($Inp) {
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
&ExpandWildCard; # Check for wildcards and expand if necessary
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
if ( @fields == 3) # All three arguments must be given
{
my $Soft = &CalculateKB($fields[1]);
my $Hard = &CalculateKB($fields[2]);
if ((db_get(\%accounts, $fields[0])) &&
(db_get_type(\%accounts, $fields[0]) eq "user"))
{
print "Setting quota for user $fields[0] ($fields[1]/$fields[2])\n";
db_set_prop(\%accounts, $fields[0], "MaxBlocksSoftLim", $Soft);
db_set_prop(\%accounts, $fields[0], "MaxBlocks", $Hard);
system("/sbin/e-smith/signal-event", "user-modify", $fields[0]) == 0
or die ("Error occurred while updating quota values for user $fields[0].\n");
}
else { print "User $fields[0] does not exist on this server.\n"; }
}
else { print "Illegal number of arguments for user $fields[0]\n\a";}
}
#==============================================================================
# Subroutines
#==============================================================================
# Convert from Gigabytes or Megabytes to true Kilobytes
sub CalculateKB {
if ( $_[0] =~ m/M$|G$/ ) {
if ($& eq "M") { return $`*1024 }
if ($& eq "G") { return $`*1024*1024 }
}
else { return $_[0]; }
}
#==============================================================================
# Test for wildcards in the username. If any wildecards are found, the array
# @records is expanded with the user 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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=user\|/i, <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<lat-quota> - The lazy administrator's tool to set user quota
=head1 DESCRIPTION
Sets the disk quota for individual users on Mitel's SME servers (5.x/6.x).
This tool is functionally equivalent to the 'Quota management' 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 set the disk quota for a large number of accounts in a batch process or on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.quota> for the format of the input file.
=head1 SYNOPSIS
B<lat-quota> -c "user | softlimit | hardlimit"
B<lat-quota> -i /path/to/quota.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-h>, B<--help>
Extended help for this tool
=item B<-i FILE>, B<--input-file=FILE>
Use the information from F<FILE> to set the disk quota for individual users.
=back
=head2 Arguments:
user* : Must be an existing user name. Wildcards (* and ?)
are accepted.
softlimit* : Limit with grace period in kilobytes, unless
followed by M (megabytes) or G (gigabytes).
hardlimit* : Absolute limit in kilobytes, unless followed by
M (megabytes) or G (gigabytes).
* mandatory field
=head1 EXAMPLES
B<lat-quota -c "harry | 800M | 1G">
Sets the quota for user 'harry' to 800 MByte (soft limit) and 1 GByte (hard limit).
B<lat-quota -i /root/quota.list>
Sets the quota for the users defined in F</root/quota.list>.
Refer to F</usr/doc/lazy-admin-tools/example.quota> for an example of an input file.
B<lat-quota -c "* | 100M | 120M">
Sets the qquota for all users to 100M / 120M.
B<lat-quota -c "hermione | 0 | 0">
Turns off quota for user 'hermione'.
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-users(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

48
root/usr/sbin/lat-restore Normal file
View File

@ -0,0 +1,48 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-restore
# ===========
# 0.9.0 (2004-09-08)
# (c)2003-2004 Altiplano bvba
#==============================================================================
use Pod::Usage;
=pod
=head1 NAME
B<lat-restore> - The lazy administrator's tool to replicate a server configuration.
=head1 DESCRIPTION
Launches all lat-tools in the correct sequence using the config files created
by lat-dump. This allows you recreate all user accounts, groups, ibays etc with
the same uid/gid on an other server or to restore a corrupted server.
lat-restore is automatically created by lat-dump and can be edited to meet your
needs
=head1 SYNOPSIS
B<lat-restore>
=head1 SEE ALSO
lat-users(8), lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(8), lat-domains(8), lat-hosts(8), lat-procmail(8), lat-pptp(8)
=head1 VERSION
Version 0.9.0 (2004-09-08). The latest version is hosted at B<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

247
root/usr/sbin/lat-shadow Normal file
View File

@ -0,0 +1,247 @@
#!/usr/bin/perl -w
#==============================================================================
# lat-shadow
# =========
# 0.0.1 (2012-11-10)
# (copyleft)2012 Jean-Philippe Pialasse, inspired by Altiplano bvba
#==============================================================================
package esmith;
use strict;
#use Cwd;
use esmith::db;
use esmith::util;
use Getopt::Long;
use Pod::Usage;
use POSIX;
use constant DATETIME => strftime("%Y-%m-%d_%H-%M-%S", localtime);
my %conf;
tie %conf, 'esmith::config';
my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
my ($Hlp, $Cml, $Frc, $Inp, $Pwf);
my $Add =0;
my $passwlist="./passwords.new";
my $shadowfile="./shadow_tmp"; # copy of shadow file to read
my $newshadow="/etc/shadow"; # shadow file in place
my $original_cp="./shadow_before_" . DATETIME; # copy in case
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"add" => \$Add,
"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))
)
{ &PrintPod(1); exit; }
my @records;
if ($Inp) {
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
# Add accounts
if ($Add) {
getcwd;
die("change current directory, can not work in /etc/") unless getcwd ne "/etc";
# make a copy of shadow file in current directory
system("cp -f $newshadow $original_cp");
system("cp -f $newshadow $shadowfile");
#Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $username = $fields[0];
if ( @fields >= 1) {
if ( &TestName($username) )# if username is with legal characters
{
if ( db_get_type(\%accounts, $username) eq "user" )
{
my $PasswordSet=db_get_prop(\%accounts, $username,'PasswordSet');
my $password = $fields[1];
# checkif present in shadow and password is empty (!!) ( if not forced)
print $username ." : " ;#." ". $password . " " .$PasswordSet . "\n";
open(SHADOWFILE,"$shadowfile") || die;
open(SHADOWNEW,">$newshadow") || die;
flock(SHADOWFILE,1)||die;
flock(SHADOWNEW,2)||die;
while(<SHADOWFILE>) {
if(m/^$username:!!:/ ) { # one of our users no password set
#print $_ ;
s/^$username:(!!):(.*):(.*):(.*):(.*):(.*):(.*):$/$username:$password:$2:$3:$4:$5:$6:$7:/i;
#print $_ ;
(print SHADOWNEW $_) or die "can not write $newshadow: $!";
$PasswordSet="no";
print "password set.\n";
}
elsif (m/^$username:/ ) { # one of our users if there is already a pass set
#print $_ ;
if ($Frc) { # if we force
s/^$username:(.*):(.*):(.*):(.*):(.*):(.*):(.*):$/$username:$password:$2:$3:$4:$5:$6:$7:/i;
#print $_ ;
(print SHADOWNEW $_) or die "can not write $newshadow: $!";
$PasswordSet="yes";
print "password set.\n";
}
else { # if force not set
print "$username has already a password, you need to force.\n";
(print SHADOWNEW $_) or die "can not write $newshadow: $!";
}
}
else # not a user we want to change
{
(print SHADOWNEW $_) or die "can not write $newshadow: $!";
}
}
close(SHADOWFILE)or die "can not close $shadowfile";
close(SHADOWNEW) or die "can not close $newshadow";
system("cp -f $newshadow $shadowfile");
# Set password
#esmith::util::setUserPassword($username, $fields[3]);
db_set_prop(\%accounts, $username, 'PasswordSet', $PasswordSet);
# if success set db accounts to say password is set
}
else { print "'$username' is not present in db or is not set as user.\a\n"; }
}
else { print "'$username' contain illegal characters.\a\n"; }
}
else { print "Please provide at least an account username and encrypted password to transfert.\n\a";}
}
system("rm -f $shadowfile ");
}
#==============================================================================
# Test name for illegal characters and length
sub TestName {
if ( ! $_[0] =~ /^[a-z][a-z\-\d]*$/ ) {
print "The name '$_[0]' contains illegal characters.\n";
print "User names should contain only lower-case letters, ";
print "numbers, hyphens or periods\n";
print "and should start with a lower-case letter.\n\a";
return 0;
}
if ( length($_[0]) > 31 ) {
print "The name '$_[0]' is too long. The maximum is 31 characters.\n";
return 0;
}
return -1;
}
#==============================================================================
# Print the pod text as a help screen
sub PrintPod {
my ($verbose, $message) = @_;
pod2usage(-verbose => $verbose, -message => $message, -exitval => 64);
}
#==============================================================================
=pod
=head1 NAME
B<lat-shadow> - The lazy administrator's tool to transfer crypted password from a box to another
=head1 DESCRIPTION
Transfer an user encrypted password fom one SME box shadow file to another box shadow file on SME servers (7.x/8.x).
This tool is functionally equivalent some python script that allow this kind of manipulation. This could be used when the adminsitrator do not know the plain apssword of its users and want to migrate a SME box.
It can be run from the command line or called from an other script.
It allows you, for example, to tranfert all your users password after creating them with lat-users and dump files obtains from the older box.
See F</usr/doc/lazy-admin-tools/example.shadow> for the format of the input file.
=head1 SYNOPSIS
B<lat-shadow> -a -c "username | encryptedPassword"
B<lat-shadow> -a [-f] -i /path/to/password.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add the encrypted passwords for user account to the server.
=item
B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-f>, B<--force>
Force update if password is not empty in the shadow file on the SME box
=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 the user accounts.
See F</usr/doc/lazy-admin-tools> for an example of an input file.
=back
=head2 Arguments:
user* - 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 users.
password* - Encrypted Password for the user from the /etc/shadow file
* mandatory field
=head1 EXAMPLES
B<lat-shadow -a -c "harry | fdasf57ertg73sdf">
Update empty password field in /etc/shadow for user 'harry' from the command line, with password entered.
B<lat-shadow -a -i /root/shadow.list>
Uses the arguments specified in F</root/shadow.list> to update user shadow encrypted password.
Please refer to F</usr/doc/lazy-admin-tools/example.shadow> for an example of an input file.
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

447
root/usr/sbin/lat-users Normal file
View File

@ -0,0 +1,447 @@
#!/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, $Pwf);
my $Add =0;
my $Del =0;
my $Kaa =0;
my $passwlist="./passwords.new";
#==============================================================================
# Main
#==============================================================================
# Analyze commandline options
GetOptions ("help" => \$Hlp,
"add" => \$Add,
"delete" => \$Del,
"force" => \$Frc,
"nickname" => \$Kaa,
"passwords" => \$Pwf,
"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*$)/,<LIST>);
close(LIST); }
elsif ($Cml) { @records=($Cml); }
else { &PrintPod(1); exit; }
# Add accounts
if ($Add) {
# Process each user
foreach my $record (@records)
{
my @fields=split(/\|/,$record);
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
my $username = $fields[0];
if ( @fields >= 1) {
if ( &TestName($username))
{
my $uid;
if ($fields[11]) { $uid = $fields[11]; }
else { $uid = &FindUid;}
if (&TestUid($uid)) {
my %user = ("FirstName", $fields[1],
"LastName", $fields[2],
"PasswordSet", "no",
"Uid",$uid,
"Dept", $fields[4],
"Company", $fields[5],
"Shell", "/usr/bin/rssh",
"VPNClientAccess","no",
"Street", $fields[6],
"City", $fields[7],
"Phone", $fields[8],
"EmailForward", $fields[9],
"ForwardAddress", $fields[10]);
if ( ! $user{'FirstName'} ) { $user{"FirstName"} = $username; }
if ( ! $user{'LastName' } ) { $user{"LastName"} = $username; }
if ( ! $user{'EmailForward'} ) { $user{"EmailForward"} = "local"; }
if ( ! $user{'EmailForward'} =~/^(local)$|^(forward)$|^(both)$/)
{ $user{"EmailForward"} = "local"; }
# Create or update account
if ( ! db_get(\%accounts, $username)) {
print "Creating user account for $username (Uid:$uid).\n";
db_set(\%accounts, $username, 'user', \%user);
system("/sbin/e-smith/signal-event", "user-create", $username) == 0
or die ("An error occurred while creating account '$username'.\n");
}
else {
print "Updating user account $username.\n";
foreach my $value (keys %user) {
if ( ! $user{$value} ) { $user{$value} = "" }
if ($user{$value} eq "" )
{ $user{$value} = db_get_prop(\%accounts, $username, $value) }
$user{"PasswordSet"} = db_get_prop(\%accounts, $username, "PasswordSet");
$user{"Uid"} = db_get_prop(\%accounts, $username, "Uid");
}
db_set(\%accounts, $username, 'user', \%user);
system("/sbin/e-smith/signal-event", "user-modify", $username) == 0
or die ("An error occurred while modifying account '$username'.\n");
}
# Set password
if ((! $fields[3]) && ($Pwf)) { $fields[3] = &RandomPassword($username);}
if ($fields[3]) {
esmith::util::setUserPassword($username, $fields[3]);
db_set_prop(\%accounts, $username, 'PasswordSet', 'yes');
}
# Should we assign the user to a group?
if ( @fields > 11) {
for (my $cntgrps=12; $cntgrps < @fields; $cntgrps++) {
system("/usr/sbin/lat-groups -a -c='$fields[$cntgrps]|$fields[$cntgrps]||$username'");
}
}
if ($Kaa) {
print "creating SME default pseudonyms\a\n";
$user{"FirstName"} = lc($user{"FirstName"}) ;
$user{"LastName"} = lc($user{"LastName"});
system("/usr/sbin/lat-pseudonyms -a -c='$username|".$user{"FirstName"}.".".$user{"LastName"}."|".$user{"FirstName"}."_".$user{"LastName"}."'");
}
}
}
else { print "User '$username' is not a correct username.\a\n"; }
}
else { print "Please provide at least an account name and the first and last name of the user.\n\a";}
}
}
# Delete accounts
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 $username = $fields[0];
if ((db_get(\%accounts, $username)) && (db_get_type(\%accounts, $username) eq "user")) {
my $yn = 'yes';
my $userdir = `cat /etc/passwd|grep "^$username:"|cut -d":" -f6|tr -d '\n'`;
#print "user folder: '$userdir'\n";
if ( $userdir eq "/home/e-smith/files/users/$username" )
{
if (! $Frc) {
print "Do you want to delete user '$username'?\n";
print "All files belonging to this user account will be deleted! [yes/NO/all] ";
$yn = <STDIN>;
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
}
if ($yn =~ /^y/i) {
print "Deleting user account '$username'.\n";
db_delete(\%accounts, $username);
system("/sbin/e-smith/signal-event", "user-delete", $username);
}
}
else { print "'$username' is not a regular SME user with its home in /home/e-smith/files/users/, can not remove it\n\a";}
}
else { print "Can't find user '$username'.\n\a";}
}
}
#==============================================================================
# Subroutines
#==============================================================================
# Find a 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*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
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*/,<ACC>);
close(ACC);
open(PWD,"/etc/passwd") || die "Can't find /etc/passwd";
my @pwds = grep(/\:\d*\:/,<PWD>);
close(PWD);
open(GRP,"/etc/group") || die "Can't find /etc/group";
my @grps = grep(/\:\d*\:/,<GRP>);
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 name for illegal characters and length
sub TestName {
if ( ! $_[0] =~ /^[a-z][a-z\-\d]*$/ ) {
print "The name '$_[0]' contains illegal characters.\n";
print "User names should contain only lower-case letters, ";
print "numbers, hyphens or periods\n";
print "and should start with a lower-case letter.\n\a";
return 0;
}
if ( length($_[0]) > 31 ) {
print "The name '$_[0]' is too long. The maximum is 31 characters.\n";
return 0;
}
return -1;
}
#==============================================================================
# Create a random password
sub RandomPassword {
my $password;
my $_rand;
my $password_length = 8;
my @chars = split(" ",
"a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
, . ; - & ! ?");
srand;
$_rand = int(rand 62);
for (my $i=0; $i <= $password_length-1 ;$i++) {
$password .= $chars[$_rand];
$_rand = int(rand 69);
}
open(PWD, ">> $passwlist") or die "Can't create or open $passwlist.\n";
print PWD "Username: $_[0]\nPassword: $password\n\n";
close(PWD);
return $password;
}
#==============================================================================
# Test for wildcards in the username. If any wildecards are found, the array
# @records is expanded with the user 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, "</home/e-smith/db/accounts" or die "Can't open /home/e-smith/db/accounts: $!";
my @match = grep /^$fld[0]\=user\|/i, <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<lat-users> - The lazy administrator's tool to add user accounts
=head1 DESCRIPTION
Creates or deletes user accounts on Mitel's SME servers (5.x/6.x).
This tool is functionally equivalent to the 'User accounts' 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 a large number of accounts in a batch process, or delete accounts on a remote machine via an ssh console.
See F</usr/doc/lazy-admin-tools/example.users> for the format of the input file.
=head1 SYNOPSIS
B<lat-tools> -a [-p] -c "user | first | last | password | department | company | street | city | tel | forward | email | uid | group1 [| group..]"
B<lat-users> -a [-p] -i /path/to/users.list
B<lat-users> -d [-f] -c "user"
B<lat-users> -d [-f] -i /path/to/users.list
=head1 OPTIONS
The following options are supported:
=over 4
=item B<-a>, B<--add>
Add a user account to the server.
=item
B<-c "Arguments">, B<--command-line="Arguments">
Take arguments from the command line.
See the 'Arguments' section below for the various arguments that are accepted.
=item B<-d>, B<--delete>
Delete a user account 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 the user accounts.
See F</usr/doc/lazy-admin-tools> for an example of an input file.
=item B<-p>, B<--passwords>
Generate random passwords for the users and write them to F<./passwords.new>. If a password was supplied, this option will be ignored.
=item B<-n>, B<--nickname>
Generate standard pseudonyms for the user: firstname_lastname and firstname.lastname.
=back
=head2 Arguments:
user* - 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 users.
first* - First name
last* - Last name
password - Password for the user (in clear-text!)
department - Department
company - Company
street - Street name and number
city - Zip & City
tel - Telephone number
forward - E-mail delivery: 'local', 'forward' or 'both'
email - Forwarding e-mail adres
uid - User ID. If omitted, a suitable uid will be generated.
group(s) - Group name(s) to which the user should be added. If the
group doesn't exist, it will be created.
* mandatory field
=head1 EXAMPLES
B<lat-users -a -c "harry | Harry | Potter | Quidditch">
Creates user 'harry' from the command line, with password 'Quidditch'.
B<lat-users -a -i /root/users.list>
Uses the arguments specified in F</root/users.list> to create user accounts.
Please refer to F</usr/doc/lazy-admin-tools/example.users> for an example of an input file.
B<lat-users -d -f -c "user*">
Deletes all user accounts that start with 'user'. All users and their files will be deleted without prompting (-f).
B<lat-users -a -p -i /root/users.list>
Creates user accounts as defined in F</root/users.list> and generates a random password for each user.
The names and passwords are written to F<./passwords.new>.
B<lat-users -a -c "ron | Ron | Weasley ||||||||| 6005">
Creates user 'ron' with user ID 6005. All other fields (company, departments, etc.) are left empty.
B<lat-users -a -c "ron | Ron | Weasley |||||||||| quiddich | dada ">
Creates user 'ron' and assigns him to groups quiddich and dada. If any of these groups doesn't exist, it will be created.
B<lat-users -a -n -c "ron | Ron | Weasley |||||||||| quiddich | dada ">
Creates user 'ron' and assigns him to groups quiddich and dada. If any of these groups doesn't exist, it will be created.
Also create pseudonyms ron_weasley and ron.weasley associated with user ron if available, else produces an alert.
=head1 SEE ALSO
lat-group(8), lat-pseudonyms(8), lat-ibays(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<http://www.contribs.org/contribs/mblotwijk/>
=head1 COPYRIGHT
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
=head1 BUGS
Please report bugs to <Bugs@Altiplano.Be>
=cut
#==============================================================================

View File

@ -0,0 +1,160 @@
# $Id: smeserver-lazy_admin_tools.spec,v 1.3 2021/06/06 04:44:20 jpp Exp $
# Authority: unnilennium
# Name: Jean-Philippe Pialasse
Summary: Lazy Admin's Tools is a set of scripts to automate admin tasks
%define name smeserver-lazy_admin_tools
%define version 1.1
%define release 7%{?dist}
Name: %{name}
Version: %{version}
Release: %{release}
Source: %{name}-%{version}.tar.xz
License: GPL
Group: Networking/Tools
BuildRoot: /var/tmp/%{name}-%{version}-buildroot
BuildArchitectures: noarch
Requires: e-smith-base
Requires: SMEServer >= 8.0
Obsoletes: e-smith-lazy_admin_tools
BuildRequires: e-smith-devtools >= 1.13.1-03
%description
The Lazy Administrator's Tools is a set of scripts designed to automate
batch tasks and jobs for E-Smith/SME servers.
* lat-user : add/delete users
* lat-group : add/delete groups
* lat pseudonyms : add/delete e-mail pseudonyms for individual users
* lat-ibays : add/delete ibays
* lat-quota : set the disk quota for individual users
* lat-domains : add domainnames the server
* lat-hosts : add hostnames to the server
* lat-procmail : activate or deactivate procmail for individual users
* lat-pptp : activate or deactivate pptp access for individual users
* lat-dump : create input files for the above lat-tools, based on the
configuration files of the SME servers.
* lat-shadow : add users' encrypted password in /etc/shadow file
See man lat-tools for general help on the usage of the toolkit, or run the
command with the --help switch to get specific help.
%changelog
* Sat Sep 07 2024 cvs2git.sh aka Brian Read <brianr@koozali.org> 1.1-7.sme
- Roll up patches and move to git repo [SME: 12338]
* Sat Sep 07 2024 BogusDateBot
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
by assuming the date is correct and changing the weekday.
* Sun Jun 06 2021 Jean-Philippe Pialasse <tests@pialasse.com> 1.1-6.sme
- add update event to prevent yum to ask for a reboot [SME: 11033]
* Tue Oct 13 2020 Brian Read <brianr@bjsystems.co.uk> 1.1-5.sme
- Initial import in SME10 tree [SME: 11033]
* Mon Mar 7 2016 JP Pialasse <tests@pialasse.com> 1.1-4.sme
- fix error in lat pseudonym, missing character [SME: 5423]
* Tue Feb 9 2016 stephane de Labrusse <stephdl@de-labrusse.fr> 1.1-3.sme
- Roll new rpm for sme9
- Bug 8503, 8500, 7731, 7706 are imported but not tested
* Tue Jul 29 2014 JP PIALASSE tests@pialasse.com 1.1.-3.sme
- fix lat-users delete too long due to groups [SME: 8503]
* Mon Jul 28 2014 JP PIALASSE tests@pialasse.com 1.1.-2.sme
- fix user not being deleted [SME: 8500]
- fix shadow activating user with blank password [SME: 7731]
- NFR added pseudonyms with @ [SME: 7706]
- note: lat-restore now do lat-pseudonyms later after lat-domains for pseudonyms with @ verification.
* Wed Jun 26 2013 JP PIALASSE tests@pialasse.com 1.1.-1.sme
- fix manual [SME: 7702]
* Wed Jun 26 2013 JP PIALASSE tests@pialasse.com 1.0-10.sme
- fix doc in lat-procmail [SME: 7707]
- fix lat-shadow issue [SME: 7709]
- patch7
- patch8
* Wed Jun 26 2013 JP PIALASSE tests@pialasse.com 1.1.-1.sme
- fix manual [SME: 7702]
* Tue Jun 25 2013 JP PIALASSE tests@pialasse.com 1.0-9.sme
- updated patch4 and applied this time
- patch5 to correct lat-user -n option errors
- patch6 to update manual
- also to check for mailsorting contrib in procmail lat
* Mon Jun 24 2013 JP PIALASSE tests@pialasse.com 1.0-6.sme
- fixed Can't enable procmail [SME: 7139]
- fixed Error during creation of pptp access with lazy admin tools [SME: 7695]
- patch4
* Mon May 13 2013 JP PIALASSE tests@pialasse.com 1.0-5.sme
- fixed lat-procmail [SME: 7139]
- fixed removing user with home dir not in /home/e-smith/files/users/ [SME: 7162]
- create basic SME pseudonyms using option -n for nicknames [SME: 7284]
- patch3
* Sat Feb 02 2013 JP PIALASSE tests@pialasse.com 1.0-4.sme
- fixed empty Gid property creation on user update bug [SME: 7192]
- added lat-shadow binary [SME: 7137]
- patch1 and patch2
* Sat Feb 02 2013 JP PIALASSE tests@pialasse.com 1.0-3.sme
- fixed warning on empty group creation/update bug [SME: 7202]
- fixed uid changed on user update bug [SME: 7196]
- fixed warning on user creation/update bug [SME: 7192]
- patch0
* Sat Feb 02 2013 JP PIALASSE tests@pialasse.com 1.0-2.sme
- binary are not executable [SME: 7138]
* Sat May 26 2012 JP PIALASSE tests@pialasse.com 1.0-1.sme
- Initial version
%prep
%setup
#%patch3 -p1
#%patch4 -p1
#%patch5 -p1
#%patch6 -p1
#%patch7 -p1
#%patch8 -p1
#%patch0 -p1
#%patch1 -p1
#%patch2 -p1
#%patch3 -p1
#%patch4 -p1
#%patch5 -p1
#%patch6 -p1
mkdir -p root/etc/e-smith/events/smeserver-lazy_admin_tools-update
%build
perl createman
%install
rm -rf $RPM_BUILD_ROOT
(cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
rm -f e-smith-%{version}-filelist
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
--file '/usr/sbin/lat-domains' 'attr(755,root,root)' \
--file '/usr/sbin/lat-dump' 'attr(755,root,root)' \
--file /usr/sbin/lat-groups 'attr(755,root,root)' \
--file /usr/sbin/lat-hosts 'attr(755,root,root)' \
--file /usr/sbin/lat-ibays 'attr(755,root,root)' \
--file /usr/sbin/lat-pptp 'attr(755,root,root)' \
--file /usr/sbin/lat-procmail 'attr(755,root,root)' \
--file /usr/sbin/lat-pseudonyms 'attr(755,root,root)' \
--file /usr/sbin/lat-quota 'attr(755,root,root)' \
--file /usr/sbin/lat-restore 'attr(755,root,root)' \
--file /usr/sbin/lat-users 'attr(755,root,root)' \
--file /usr/sbin/lat-shadow 'attr(755,root,root)' \
> %{name}-%{version}-filelist
%clean
rm -rf $RPM_BUILD_ROOT
%files -f %{name}-%{version}-filelist
%defattr(-,root,root)