439 lines
15 KiB
Plaintext
439 lines
15 KiB
Plaintext
|
#!/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
|
||
|
|
||
|
#==============================================================================
|