File: /usr/local/www/apache24/cgi-bin/easytecc4/easytecc_class.pm
package file;
BEGIN {
if(-e '/etc/sudoers'){
my $osversion = `/usr/bin/uname -K`;
chomp $osversion;
my $perl;
if($osversion >= 1300000){
$perl = '5.34';
} elsif($osversion >= 1200000){
$perl = '5.26';
} elsif($osversion >= 1003000){
$perl = '5.24';
} else {
$perl = '5.20';
}
@INC = (
"/usr/iports/lib/perl5/site_perl",
"/usr/iports/lib/perl5/amd64-freebsd-thread-multi",
"/usr/iports/lib/perl5/$perl",
"/usr/iports/lib/perl5/$perl/mach",
"/usr/iports/lib/perl5/site_perl/mach/$perl",
"/usr/local/lib/perl5/site_perl",
"/usr/local/lib/perl5/amd64-freebsd-thread-multi",
"/usr/local/lib/perl5/$perl",
"/usr/local/lib/perl5/$perl/mach",
"/usr/local/lib/perl5/site_perl/mach/$perl",
"/usr/local/www/apache24/cgi-bin/easytecc4"
);
} else {
push @INC, '/home/httpd/cgi-bin/easytecc4';
}
}
use Data::Dumper;
#use lib '/usr/local/lib/perl5/site_perl/5.16';
#use Passwd::Unix;
#$| = 1;
my $debug = 1 if(-e '/etc/easytecc'); #run logline("debug",...) only when $debug=1
#Jimmy: Log around the world
use Log::Dispatch;
use Log::Dispatch::File;
use File::Spec;
use Time::Format qw(%time %strftime);
use HTML::Entities qw(encode_entities decode_entities encode_entities_numeric);
use constant LOG_DIR => '/home/web/log';
use constant LOG_FILE => 'easytecc4.log';
our $loglevel = 'debug'; #'debug','info','notice','warning','error','critical','alert','emergency' # most reasonable is 'warning' or 'error' for production
sub dienice ($);
sub logline($$);
#
# Begin setup logging agent
#
our $log = new Log::Dispatch(
callbacks => sub {
my %h=@_;
my ($package, $filename, $line) = caller;
my $level = sprintf '%-8.8s', $h{level};
return $strftime{'%b %e %T'}." \[$$]: ".$level." => ".$h{message}."\n";
}
);
our $debug = 0;
$debug = 1 if(-e '/etc/easytecc'); #run logline("debug",...) only when $debug=1
if ($debug) {
$log->add( Log::Dispatch::File->new( name => 'logfile',
min_level => $loglevel,
mode => 'append',
filename => File::Spec->catfile(LOG_DIR, LOG_FILE),
)
);
}
#
# End setup logging agent
#
my $fb = "";
if (-e '/etc/sudoers') {
$fb = '1';
}
my %file_fb = ( '/etc/httpd/conf/httpd.conf' => '/etc/apache24/httpd.conf' );
if ($fb) {
$awstats_etc_path = '/usr/local/etc/awstats';;
}
else{
$awstats_etc_path = '/etc/awstats';
}
use Class::Builder {
file_name => { string => undef },
file_content => { arrayref => []},
file_parsed_hash => { hashref => {}},
config_hash => { hashref => {}},
lookup_hash => { hashref => {}},
lookup2_hash => { hashref => {}},
lookup_hash_domain_count => { hashref => {}},
lookup_hash_autoreply_count => { hashref => {}},
restart => { boolean => 1 },
user => { string => undef },
domain => { string => undef },
append => { boolean => undef },
};
1;
sub read_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $self = shift;
my @raw_data = ();
my $file = '';
logline("debug",'read_file1:' . $self->file_name ) if $debug;
#fbsd
if ($fb && $file_fb{$self->file_name}) {
$file = $file_fb{$self->file_name};
}
else{
$file = $self->file_name;
}
logline("debug",'$file = ' . $file ) if $debug;
if(-e $file){
open(DAT, $file) || dienice ("Could not open file: " . $file);
@raw_data=<DAT>;
close DAT;
$self->file_content(\@raw_data);
}
my %to_parse = (
'/etc/procmailrc' => '1',
'/home/spamdef/.spamproc' => '1',
'/home/spamdef/.white.lst' => '1',
'/home/spamdef/.black.lst' => '1',
'/home/spamdef/.spamd/user_prefs' => '1',
'/etc/mail/access' => '1',
'/etc/mail/virtmaps' => '1',
'/etc/mail/aliases' => '1',
'/etc/mail/mailuser' => '1',
'/etc/mail/dnsbl.hosts' => '1',
'/etc/sysconfig/clamav-milter' => '1',
'/etc/sysconfig/clamav-template' => '1',
'/etc/sysconfig/clamav-whitelist' => '1',
'/etc/httpd/conf/httpd.conf' => '1',
'/etc/php.ini' => '1',
'/home/web/cronfile' => '1',
'/usr/local/etc/easytecc/settings.conf' => '1',
'/usr/local/etc/easytecc/current.lang' => '1',
'/etc/passwd' => '1',
'/etc/mail/sendmail.cw' => '1'
);
if($to_parse{$self->file_name} || $self->file_name =~ /(\.spamproc|user_prefs|\.white\.lst|\.black\.lst)$/){
$self->parse_file;
}
# Das Filehandle zur späteren Verwendung speichern wie z.B. für Schreiben der Datei nach Validierung
easytecc3::store_file_handle($self);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
# http://www.network-science.de/ascii/ -> font 'standard'.....
sub parse_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $self = shift;
logline("debug","parse_file: ". $self->file_name) if $debug;
# _ _
# _ __ _ __ ___ ___ _ __ ___ __ _(_) |_ __ ___
# | '_ \| '__/ _ \ / __| '_ ` _ \ / _` | | | '__/ __|
# | |_) | | | (_) | (__| | | | | | (_| | | | | | (__
# | .__/|_| \___/ \___|_| |_| |_|\__,_|_|_|_| \___|
# |_|
#
#
if($self->file_name eq '/etc/procmailrc'){
my $name = '';
my $val = '';
my %procmailrc;
foreach($self->file_content){
# raus hier sobald comments oder leerzeilen beginnen
last if(/################/ || ! $_);
next if /^#/ || /^$/;
s/#.*$//;
s/\s+$//g;
s/^\s+//g;
s/'//g;
s/"//g;
s/\s+//g;
($name,$val) = split(/=/,$_,2);
$procmailrc{$name}=$val;
}
# in procmailrc ist CLEVEL='\*\*\*\*\*\*\*\*\*\*', also level = Anzahl Zeichen durch 2
$procmailrc{'CLEVEL'} = length($procmailrc{'CLEVEL'}) / 2;
logline("debug","#procmailrc CLEVEL=#" . $procmailrc{'CLEVEL'} ) if $debug;
# fr Darstellung in Formular | gegen Space ersetzen
$procmailrc{'POSTFIX'} =~ s/\|/ /g;
$self->file_parsed_hash(\%procmailrc);
}
#
# ___ _ __ __ _ _ __ ___ _ __ _ __ ___ ___
# / __| '_ \ / _` | '_ ` _ \| '_ \| '__/ _ \ / __|
# _\__ \ |_) | (_| | | | | | | |_) | | | (_) | (__
# (_)___/ .__/ \__,_|_| |_| |_| .__/|_| \___/ \___|
# |_| |_|
#
elsif($self->file_name =~ /\.spamproc$/){
my $name = '';
my $val = '';
my %spamproc;
foreach($self->file_content){
# raus hier sobald comments oder leerzeilen beginnen
last if(/################/ || ! $_);
next if /^#/ || /^$/;
s/#.*$//;
s/\s+$//g;
s/^\s+//g;
s/'//g;
s/"//g;
s/\s+//g;
($name,$val) = split(/=/,$_,2);
$spamproc{$name}=$val;
logline("debug","#$name##$spamproc{$name}#\n") if $debug;
}
# in procmailrc ist CLEVEL='\*\*\*\*\*\*\*\*\*\*', also level = Anzahl Zeichen durch 2
$spamproc{'CLEVEL'} = length($spamproc{'CLEVEL'}) / 2;
logline("debug","#procmailrc CLEVEL=#" . $spamproc{'CLEVEL'} ) if $debug;
# fr Darstellung in Formular | gegen Space ersetzen
# POSTFIX='zip|dll|pif|scr|exe|bat|vbs|com'
$spamproc{'POSTFIX'} =~ s/\|/ /g;
$self->file_parsed_hash(\%spamproc);
}
# _ _ _ _ _
# __ _| |__ (_) |_ ___ | |___| |_
# \ \ /\ / / '_ \| | __/ _ \ | / __| __|
# \ V V /| | | | | || __/_| \__ \ |_
# (_)_/\_/ |_| |_|_|\__\___(_)_|___/\__|
#
#
elsif($self->file_name =~ /\.white\.lst$/){
my %whitelist;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
##raus hier sobald comments oder leerzeilen beginnen
last if(! $_);
$whitelist{$_} = '1';
}
$self->file_parsed_hash(\%whitelist);
}
#
# _ _ _ _ _
# | |__ | | __ _ ___| | __ | |___| |_
# | '_ \| |/ _` |/ __| |/ / | / __| __|
# _| |_) | | (_| | (__| < _| \__ \ |_
# (_)_.__/|_|\__,_|\___|_|\_(_)_|___/\__|
#
#
elsif($self->file_name =~ /\.black\.lst$/){
my %blacklist;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
##raus hier sobald comments oder leerzeilen beginnen
last if(! $_);
$blacklist{$_} = '1';
}
$self->file_parsed_hash(\%blacklist);
}
# __
# _ _ ___ ___ _ __ _ __ _ __ ___ / _|___
# | | | / __|/ _ \ '__| | '_ \| '__/ _ \ |_/ __|
# | |_| \__ \ __/ | | |_) | | | __/ _\__ \
# \__,_|___/\___|_|____| .__/|_| \___|_| |___/
# |_____|_|
#
elsif($self->file_name =~ /\/user_prefs$/){
my $name = '';
my $val = '';
my %user_prefs;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
# ugly hack for sa-scores: score RDNS_NONE 10 -> score_RDNS_NONE 10
s/^score\s/score_/;
($name,$val) = split(/\s+/,$_,2);
$user_prefs{$name}=$val;
logline("debug","#$name##$user_prefs{$name}#\n") if $debug;
}
$self->file_parsed_hash(\%user_prefs);
}
#
# __ _ ___ ___ ___ ___ ___
# / _` |/ __/ __/ _ \/ __/ __|
# | (_| | (_| (_| __/\__ \__ \
# \__,_|\___\___\___||___/___/
#
#
elsif($self->file_name eq '/etc/mail/access'){
my $lhs = '';
my $rhs = '';
my %access;
foreach($self->file_content){
# Beispiele:
# cyberspammer.com 550 We don't accept mail from spammers
# okay.cyberspammer.com OK
# sendmail.org OK
# 128.32 RELAY
# spammer@aol.com REJECT
# ClientRate: 10
# ClientConn: 10
# ClientRate:83.138 0
# ClientConn:83.138 0
# GreetPause:83.138 0
# 121.42.166.135 550 We don't allow bulkmail! You are locked out! [121.42.166.135]
# Kommentare nicht parsen
next if /^#/ || /^$/;
s/\s+$//;
($lhs, $rhs) = split / /, $_;
$access{$lhs} = $rhs;
$lhs = '';
$rhs = '';
}
$self->file_parsed_hash(\%access);
}
#
# _ _
# __ _(_)_ __| |_ _ __ ___ __ _ _ __ ___
# \ \ / / | '__| __| '_ ` _ \ / _` | '_ \/ __|
# \ V /| | | | |_| | | | | | (_| | |_) \__ \
# \_/ |_|_| \__|_| |_| |_|\__,_| .__/|___/
# |_|
#
elsif($self->file_name eq '/etc/mail/virtmaps'){
my $lhs = '';
my $rhs = '';
my %virtmaps;
my %domain_count_lookup;
my %autoreply_count_lookup;
logline("debug","Creating File Object \$aliases.") if $debug;
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
foreach($self->file_content){
# Kommentare nicht parsen
next if /^#/ || /^$/;
s/\s+$//;
($lhs, $rhs) = split /\s+/, $_;
my $domain = $lhs;
$domain =~ s/^.*@(.*)$/$1/;
if(defined($virtmaps{$lhs})){
$domain_count_lookup{$domain}--;
}
$virtmaps{$lhs} = $rhs;
$domain_count_lookup{$domain}++;
logline("debug","parse /etc/mail/virtmaps domain=$domain count=" . $domain_count_lookup{$domain}) if $debug;
if ($aliases{$rhs} =~ /\/autoresponder/){
logline("debug","match aut") if $debug;
$autoreply_count_lookup{$domain}++;
}
$lhs = '';
$rhs = '';
}
$self->file_parsed_hash(\%virtmaps);
$self->lookup_hash_domain_count(\%domain_count_lookup);
$self->lookup_hash_autoreply_count(\%autoreply_count_lookup);
}
#
# _ _
# __ _| (_) __ _ ___ ___ ___
# / _` | | |/ _` / __|/ _ \/ __|
# | (_| | | | (_| \__ \ __/\__ \
# \__,_|_|_|\__,_|___/\___||___/
#
#
elsif($self->file_name eq '/etc/mail/aliases'){
my $lhs = '';
my $rhs = '';
my %aliases;
foreach($self->file_content){
# Kommentare nicht parsen
next if /^#/ || /^$/;
s/\s+$//;
($lhs, $rhs) = split /:\s*/, $_;
$aliases{$lhs} = $rhs;
$lhs = '';
$rhs = '';
}
$self->file_parsed_hash(\%aliases);
}
#
# _ _ _ _ _
# __| |_ __ ___| |__ | | | |__ ___ ___| |_ ___
# / _` | '_ \/ __| '_ \| | | '_ \ / _ \/ __| __/ __|
# | (_| | | | \__ \ |_) | |_| | | | (_) \__ \ |_\__ \
# \__,_|_| |_|___/_.__/|_(_)_| |_|\___/|___/\__|___/
#
#
elsif($self->file_name eq '/etc/mail/dnsbl.hosts'){
my ($line,$name,$val);
my (@YESdnsbl,@NOdnsbl,$entry);
my %dnsbl;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
($name,$val) = split(/\s+/,$_,2);
@YESdnsbl = split(/\s+/,$val) if($name eq "YES");
@NOdnsbl = split(/\s+/,$val) if($name eq "NO");
logline("debug","#rbl= $name $val#\n") if $debug;
}
foreach $entry (@YESdnsbl){
$dnsbl{$entry} = 1;
}
foreach $entry (@NOdnsbl){
$dnsbl{$entry} = 0;
}
$self->file_parsed_hash(\%dnsbl);
}
#
# _ _ _ _
# ___| | __ _ _ __ ___ __ ___ __ _ __ ___ (_) | |_ ___ _ __
# / __| |/ _` | '_ ` _ \ / _` \ \ / /____| '_ ` _ \| | | __/ _ \ '__|
# | (__| | (_| | | | | | | (_| |\ V /_____| | | | | | | | || __/ |
# \___|_|\__,_|_| |_| |_|\__,_| \_/ |_| |_| |_|_|_|\__\___|_|
#
#
elsif($self->file_name eq '/etc/sysconfig/clamav-milter'){
my $name = '';
my $val = '';
my %clamav_milter;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
($name,$val) = split(/=/,$_,2);
$val =~ s/^"//;
$val =~ s/"$//;
$clamav_milter{$name}=$val;
logline("debug","#$name##$clamav_milter{$name}#\n") if $debug;
}
$self->file_parsed_hash(\%clamav_milter);
}
#
# _ _ _ _
# ___| | __ _ _ __ ___ __ ___ __ | |_ ___ _ __ ___ _ __ | | __ _| |_ ___
# / __| |/ _` | '_ ` _ \ / _` \ \ / /____| __/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \
# | (__| | (_| | | | | | | (_| |\ V /_____| || __/ | | | | | |_) | | (_| | || __/
# \___|_|\__,_|_| |_| |_|\__,_| \_/ \__\___|_| |_| |_| .__/|_|\__,_|\__\___|
# |_|
#
elsif($self->file_name eq '/etc/sysconfig/clamav-template'){
my $name = '';
my $val = '';
my %clamav_template;
my $template = '';
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
if(/^Subject\:\s/){
my $line = $_;
$line =~ s/^Subject\:\s+//;
$line =~ s/\%s/{ORGSUB}/;
$clamav_template{'subject'} = $line;
}
else {
$template .= $_ . "\n";
}
logline("debug","template: #$_#$template\n") if $debug;
}
$clamav_template{'template'} = $template;
$self->file_parsed_hash(\%clamav_template);
}
#
# _ _ _ _ _ _ _
# ___| | __ _ _ __ ___ __ ___ __ __ _| |__ (_) |_ ___| (_)___| |_
# / __| |/ _` | '_ ` _ \ / _` \ \ / /___\ \ /\ / / '_ \| | __/ _ \ | / __| __|
# | (__| | (_| | | | | | | (_| |\ V /_____\ V V /| | | | | || __/ | \__ \ |_
# \___|_|\__,_|_| |_| |_|\__,_| \_/ \_/\_/ |_| |_|_|\__\___|_|_|___/\__|
#
#
elsif($self->file_name eq '/etc/sysconfig/clamav-whitelist'){
my %clamav_whitelist;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
$clamav_whitelist{$_} = '1';
logline("debug","whitelist: #$_#\n") if $debug;
}
$self->file_parsed_hash(\%clamav_whitelist);
}
#
# _ _ _ _ __
# | |__ | |_| |_ _ __ __| | ___ ___ _ __ / _|
# | '_ \| __| __| '_ \ / _` | / __/ _ \| '_ \| |_
# | | | | |_| |_| |_) | (_| || (_| (_) | | | | _|
# |_| |_|\__|\__| .__/ \__,_(_)___\___/|_| |_|_|
# |_|
#
elsif($self->file_name eq '/etc/httpd/conf/httpd.conf'){
my $ssl_enabled = '';
my $count=0;
my $vhost='';
my $ssldefine='';
my $ssl='';
my @domains = ();
my @ssl_domains = ();
my $dname = '';
my $dname_withoutwww = '';
my $ssl_dname = '';
my $droot = '';
my $ssl_droot = '';
my $ip = '';
my $ssl_ip = '';
my $port = '';
my $ssl_port = '';
my $pop = '';
my $popmax = '';
my $for = '';
my $aut = '';
my $quota = '';
my $statslink = '';
my $access_log = '';
my $error_log = '';
my %vhosts;
my %config_hash;
my @errordocs = ();
my @addtype = ();
my @scriptalias = ();
my @alias = ();
my @special = ();
my @special_ssl = ();
my @redirect = ();
my @php_admin_value = ();
my @listen_80 = ();
my @listen_ssl = ();
my $has_fastcgi = '';
my $has_suexec = '';
my @php_versions = ();
my $php = '';
my $server_php = '';
my $twig = '';
my $roundcube = '';
my $mysql = '';
my $zarafa = '';
my $serveradmin = '';
my $has_cgi_local = '';
my $custom_tag = '';
my $admin_users = '';
my $awstats = '';
my $ssl_force = '';
my $redirect_domain = '';
my $ssl_cert = '';
my $ssl_chain = '';
my $ssl_key = '';
my $serveralias = '';
my $openbasedir='';
# evtl. gibs sowas. Das nur in special rein, anstatt in Array fr einzelne Direktiven
#<Directory />
#php_admin_value safe_mode off
#</Directory>
my $directory = '';
$ssl_enabled = '1' if (-e '/etc/SSL');
$ssl_enabled = '1' if ($fb);
foreach($self->file_content){
# next if /^$/;
# ignore each line without content
next if /^\s*$/;
s/\s+$//; #trailing
s/^\s+//; #leading
chomp;
if(/^Listen\s+(83\.138\..*):80/){
push(@listen_80, $1);
}
if(/^LoadModule\s*fcgid_module/ && $fb){
$has_fastcgi = 1;
}
if(/^LoadModule\s*suexec_module/ && $fb){
$has_suexec = 1;
}
if(/^[^#]*FcgidWrapper\s/ && $has_fastcgi){
my $tmp_php = '';
if(/\/usr\/iports\/bin\/php-cgi/){
$tmp_php = '5.5';
}
elsif(/\/usr\/iports\/php([0-9]+)\/bin\/php-cgi/){
$tmp_php = join('.',split(//,$1,2));
}
elsif(/\/php([0-9]\.[0-9]+)-cgi/){
$tmp_php = $1;
}
if(/open_basedir=([^\"\s]+)[\"\s]/){
$openbasedir = $1;
}
if($vhost){
if($php eq ''){
$php = $tmp_php;
}
} else {
$server_php = $tmp_php;
}
}
if(/^\<VirtualHost\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{2,5})/i){
#z.B. <VirtualHost 83.138.64.250:80>
$vhost = 1;
$count++;
$ip = $1;
$port = $2;
}
elsif(/^SSLEngine\s+on/ && $vhost){
$ssl = '1';
$ssl_port = $port;
$ssl_ip = $ip;
push (@listen_ssl, "$ip:$port");
push (@special, "$_");
}
elsif(/^SSLCertificateFile\s+(.+)$/ && $vhost && $ssl){
$ssl_cert = $1;
push (@special, "$_");
}
elsif(/^SSLCertificateKeyFile\s+(.+)$/ && $vhost && $ssl){
$ssl_key = $1;
push (@special, "$_");
}
elsif(/^SSLCertificateChainFile\s+(.+)$/ && $vhost && $ssl){
$ssl_chain = $1;
push (@special, "$_");
}
elsif(/^\<Directory.*\/cgi-local/ && $vhost){
$has_cgi_local = '1';
}
elsif(/^\<\/Directory\>/ && $vhost && $has_cgi_local){
$has_cgi_local = '';
}
elsif($has_cgi_local){
}
elsif(/^\<Directory / && $vhost){
$directory = '1';
push (@special, $_);
}
elsif(/^\<\/Directory\>/ && $vhost){
$directory = '';
push (@special, $_);
}
elsif(/^ServerAdmin\s+(.*)\b/i && $vhost){
$serveradmin = $1;
}
elsif(/^DocumentRoot\s+(.*)\b/i && $vhost){
$droot = $1;
}
elsif(/^ServerName\s+(.*)\b/i && $vhost){
#logline("debug","Servername=$1 ssl=$ssl\n") if $debug;
$dname = $1;
$dname_withoutwww = $1;
$dname_withoutwww =~ s/^www\.//i;
}
elsif(/^ServerAlias\s+(.*)$/i && $vhost){
$serveralias = $1;
my $line = $1;
$line =~ s/\swww\.[a-z0-9\-\_\.\*]*//g;
@domains = split(" ", $line);
}
elsif(/^CustomLog\s+(.*)\s+combined$/i && $vhost && !$directory){
$access_log = $1;
}
elsif(/^ErrorLog\s+(.*)$/i && $vhost && !$directory){
$error_log = $1;
}
# Alias für Twig
elsif(/^Alias \/twig /i && $vhost){
push (@special, $_);
$twig = 1;
}
elsif(/^Alias\s+\/webmail\s+.*roundcube/i && $vhost){
$roundcube = 1;
}
elsif(/^Redirect\s+\/webmail\s+/i && $vhost){
$roundcube = 1;
}
elsif(/^Redirect\s+\/stats\s+.*awstats/i && $vhost){
#variable wird zur Zeit nicht benutzt, if dient nur dazu damit redirect nicht im Feld manuelle Einträge erscheint
$awstats = 1;
}
# Alias für mysql
elsif(/^Alias \/mysql /i && $vhost){
$mysql = 1;
}
# Alias für zarafa
elsif(/^Alias \/zarafa /i && $vhost){
$zarafa = 1;
##Alle anderen Aliase
}
elsif(/^Alias \/.*/i && $vhost && !$directory){
# @alias wird aktuell nicht verwendet, in change_vhost landen unbekannte aliase in manuelle Einträge
push (@alias, $_);
push (@special, $_);
}
elsif(/^ScriptAlias / && $vhost && !$directory){
push (@scriptalias, $_);
}
elsif(/^AddType / && $vhost && !$directory){
my ($foo,$action,$type) = split(" ", $_);
push (@addtype, "$action:$type");
}
elsif(/^ErrorDocument / && $vhost && !$directory){
my ($foo,$type,$pfad) = split(" ", $_);
push (@errordocs, "$type:$pfad");
}
elsif(/^Redirect / && $vhost && !$directory){
#my ($foo,$source,$target) = split /\s+/, $_;
#push (@redirect, "$foo $source $target");
push (@redirect, $_);
}
#elsif(/^php_admin_value / && $vhost && !$directory){
# php_admin_value open_basedir /home/httpd/docs/blubb:/tmp
# my ($foo,$key,$value) = split /\s+/, $_;
# push (@php_admin_value, "$foo $key $value");
#}
elsif(/^#POP\:/ && $vhost){
$pop = $_;
$pop =~ s/[^0-9]//g;
}
elsif(/^#FOR\:/ && $vhost){
$for = $_;
$for =~ s/[^0-9]//g;
}
elsif(/^#AUT\:/ && $vhost){
$aut = $_;
$aut =~ s/[^0-9]//g;
}
elsif(/^#POPMAX\:/ && $vhost){
$popmax = $_;
$popmax =~ s/[^0-9]//g;
}
elsif(/^#QUOT\:/ && $vhost){
$quota = $_;
$quota =~ s/[^0-9]//g;
}
elsif(/^#CUSTOM_TAG\:(.*)$/ && $vhost){
$custom_tag = $1;
}
elsif(/^#ADMIN_USERS\:(.*)$/ && $vhost){
my @admin_users = split(/[,\s]/,$1);
my $admin_user = '';
foreach $admin_user (@admin_users){
my $ftp_user = lc($admin_user );
my $got = `/usr/bin/finger -m $ftp_user 2>/dev/null`;
chomp $got;
if(length($got)){
if(length($admin_users)){
$admin_users .= ',';
}
$admin_users .= $admin_user;
}
}
}
elsif(/^RewriteRule.*\[E=REDIRECT_SCHEME:https\]$/ && $vhost){
$ssl_force = 1;
push (@special, "$_");
}
elsif(/^RewriteRule.*\[E=REDIRECT_DOMAIN:([^\]\%\{\}]+)\]$/ && $vhost){
$redirect_domain = $1;
push (@special, "$_");
}
elsif(/^RewriteRule.*%\{ENV:REDIRECT_DOMAIN\}\/([^\s]+)\s.*$/ && $vhost){
if($1 ne '$1'){
$redirect_domain .= '/' . $1;
}
push (@special, "$_");
}
elsif(!/^\<\/VirtualHost/ && $vhost && $_) {
##nur Endzeile und Kommentarzeilen nicht
push (@special, "$_");
}
# logline("debug","whatever domain=$dname domains=@domains\n") if ($debug && $dname);
if ($ssl) {
#SSLEngine on could be anywhere in vhost, so we know only after parsing the last line if ssl or non ssl
@special_ssl = @special;
@ssl_domains = @domains;
$ssl_droot = $droot;
$ssl_dname = $dname;
}
#stats vorhanden? Entweder awstats oder webalizer oder nix
if(-e "$awstats_etc_path/awstats.$dname_withoutwww.conf"){
$statslink = qq~/awstats/awstats.pl?config=$dname_withoutwww~;
}
elsif(-e "$droot/stats/index.html"){
my $relhome = $droot;
$relhome =~ s/\/home\/httpd\/docs//;
$statslink = qq~/stats/index.html~;
}
else {
undef $statslink;
}
if(/^\<\/VirtualHost/i && $vhost){
# Achtung! Evtl. gibt es vhost mit unterschiedlichen IP-Adressen
# Das wird angelegt, wenn zusätzliche IP und vhost auf neue IP abgespeichert wird.
# Wegen Propagation gibt es dann 2 vhosts. Immer den ersten vhost bei gleichen IPs nehmen.
#if($dname !~ /\.han-solo\.net$/ && not exists $vhosts{$dname}{'ip'}){
if($dname !~ /^[^\.]{1,}\.han-solo\.net$/ && not exists $vhosts{$dname}{'ip'}){
#@redirect in @special rein, weil Redirects anders geparsed werden
push @special, @redirect;
#push @special, @php_admin_value;
#logline("debug","domain=$dname ssldname=$ssl_dname ssl=$ssl ssl_port=$ssl_port\n") if $debug;
$vhosts{$dname}{'domain'} = $dname;
$vhosts{$dname}{'ssl_domain'} = $ssl_dname if $ssl;
#logline("debug","parse_file domain=$dname domains=@domains\n") if $debug;
#logline("debug","parse_file domain=$dname droot=$droot\n") if $debug;
@{$vhosts{$dname}{'domains'}} = @domains;
@{$vhosts{$dname}{'ssl_domains'}} = @ssl_domains if $ssl;
$vhosts{$dname}{'serveralias'} = $serveralias;
$vhosts{$dname}{'serveradmin'} = $serveradmin;
$vhosts{$dname}{'droot'} = $droot;
$vhosts{$dname}{'ssl_droot'} = $ssl_droot if $ssl;
$vhosts{$dname}{'pop'} = $pop;
$vhosts{$dname}{'for'} = $for;
$vhosts{$dname}{'aut'} = $aut;
$vhosts{$dname}{'quota'} = $quota;
$vhosts{$dname}{'popmax'} = $popmax;
$vhosts{$dname}{'statslink'} = $statslink;
$vhosts{$dname}{'awstats'} = $awstats;
$vhosts{$dname}{'twig'} = $twig;
$vhosts{$dname}{'roundcube'} = $roundcube;
$vhosts{$dname}{'mysql'} = $mysql;
$vhosts{$dname}{'zarafa'} = $zarafa;
$vhosts{$dname}{'ssl'} = $ssl if $ssl;
# ip nur zuweisen wenn kein SSL
$vhosts{$dname}{'ip'} = $ip unless $ssl;
$vhosts{$dname}{'port'} = $port;
$vhosts{$dname}{'ssl_ip'} = $ssl_ip if $ssl;
$vhosts{$dname}{'ssl_port'} = $ssl_port if $ssl;
$vhosts{$dname}{'access_log'} = $access_log;
$vhosts{$dname}{'error_log'} = $error_log;
$vhosts{$dname}{'custom_tag'} = $custom_tag;
$vhosts{$dname}{'admin_users'} = $admin_users;
@{$vhosts{$dname}{'errordoc'}} = @errordocs;
@{$vhosts{$dname}{'addtype'}} = @addtype;
@{$vhosts{$dname}{'scriptalias'}} = @scriptalias;
@{$vhosts{$dname}{'alias'}} = @alias;
@{$vhosts{$dname}{'special'}} = @special;
@{$vhosts{$dname}{'special_ssl'}} = @special_ssl if $ssl;
$vhosts{$dname}{'ssl_force'} = $ssl_force;
$vhosts{$dname}{'ssl_cert'} = $ssl_cert if $ssl;
$vhosts{$dname}{'ssl_key'} = $ssl_key if $ssl;
$vhosts{$dname}{'ssl_chain'} = $ssl_chain if $ssl;
$vhosts{$dname}{'redirect_domain'} = $redirect_domain;
#@{$vhosts{$dname}{'redirect'}} = @redirect;
#@{$vhosts{$dname}{'php_admin_value'}} = @php_admin_value;
if($php){
$vhosts{$dname}{'php'} = $php;
} else {
$vhosts{$dname}{'php'} = $server_php;
}
$vhosts{$dname}{'openbasedir'} = $openbasedir;
}
elsif($dname =~ /\.han-solo\.net$/){
# die Haupt-IP des Servers
$config_hash{'main_ip'} = $ip;
}
$vhost=0;
$ssl = '';
@domains=();
@ssl_domains=();
$dname='';
$dname_withoutwww = '';
$ssl_dname='';
$serveradmin = '';
$droot = '';
$ssl_droot='';
$ip = '';
$ssl_ip = '';
$port = '';
$ssl_port = '';
$pop = 0;
$popmax = 0;
$for = 0;
$aut = 0;
$quota = 0;
$statslink = '';
$directory = '';
$access_log = '';
$error_log = '';
@errordocs = ();
@addtype = ();
@scriptalias = ();
@alias = ();
@special = ();
@special_ssl = ();
@redirect = ();
@php_admin_value = ();
$twig = '';
$roundcube = '';
$mysql = '';
$zarafa = '';
$custom_tag = '';
$admin_users = '';
$awstats = '';
$php = '';
$ssl_force = '';
$redirect_domain = '';
$openbasedir = '';
}
@{$config_hash{'listen_80'}} = @listen_80 if scalar @listen_80 >=1;
@{$config_hash{'listen_ssl'}} = @listen_ssl if scalar @listen_ssl >=1;
$config_hash{'ssl_enabled'} = $ssl_enabled;
$config_hash{'server_php'} = $server_php;
$config_hash{'has_suexec'} = $has_suexec;
}
if($has_fastcgi){
if(-e '/usr/iports/bin/php-cgi'){
push @php_versions, '5.5';
}
my $php_dirs = `/bin/ls -d /usr/iports/php*`;
chomp($php_dirs);
my @php_dirs_arr = split(/\s/,$php_dirs);
my $php_bin = '';
foreach $php_bin (@php_dirs_arr){
$php_bin .= '/bin/php-cgi';
if(-e $php_bin){
my $php_version = $php_bin;
$php_version =~ s/[^0-9]*//g;
$php_version = join('.',split(//,$php_version,2));
push @php_versions, $php_version;
}
}
}
#logline("debug","php-versions: " . join(',',@php_versions));
@{$config_hash{'php_versions'}} = @php_versions if scalar @php_versions >=1;
$self->file_parsed_hash(\%vhosts);
$self->config_hash(\%config_hash);
}
#
# _ _ _
# _ __ | |__ _ __ (_)_ __ (_)
# | '_ \| '_ \| '_ \ | | '_ \| |
# | |_) | | | | |_) || | | | | |
# | .__/|_| |_| .__(_)_|_| |_|_|
# |_| |_|
#
elsif($self->file_name eq '/etc/php.ini'){
my $safe_mode = '';
my $disable_functions = '';
my $max_execution_time = '';
my $memory_limit = '';
my $log_errors = '';
my $error_log = '';
my $register_globals = '';
my $post_max_size = '';
my $include_path = '';
my $extension_dir = '';
my $file_uploads = '';
my $upload_max_filesize = '';
my $allow_url_fopen = '';
my $allow_url_include = '';
my $session_use_trans_sid = '';
my $session_cache_expire = '';
my $session_cache_limiter = '';
my $espeedboat_enable = '';
my %php_ini;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
if(/^safe_mode\s+=\s+(.*)$/){
$php_ini{'safe_mode'} = $1;
}
elsif(/^disable_functions\s+=\s+(.*)$/){
$php_ini{'disable_functions'} = $1;
}
elsif(/^max_execution_time\s+=\s+(.*)$/){
$php_ini{'max_execution_time'} = $1;
}
elsif(/^memory_limit\s+=\s+(.*)$/){
$php_ini{'memory_limit'} = $1;
}
elsif(/^log_errors\s+=\s+(.*)$/){
$php_ini{'log_errors'} = $1;
}
elsif(/^error_log\s+=\s+(.*)$/){
$php_ini{'error_log'} = $1;
}
elsif(/^register_globals\s+=\s+(.*)$/){
$php_ini{'register_globals'} = $1;
}
elsif(/^post_max_size\s+=\s+(.*)$/){
$php_ini{'post_max_size'} = $1;
}
elsif(/^include_path\s+=\s+(.*)$/){
$php_ini{'include_path'} = $1;
}
elsif(/^extension_dir\s+=\s+(.*)$/){
$php_ini{'extension_dir'} = $1;
}
elsif(/^file_uploads\s+=\s+(.*)$/){
$php_ini{'file_uploads'} = $1;
}
elsif(/^upload_max_filesize\s+=\s+(.*)$/){
$php_ini{'upload_max_filesize'} = $1;
}
elsif(/^allow_url_fopen\s+=\s+(.*)$/){
$php_ini{'allow_url_fopen'} = $1;
}
elsif(/^allow_url_include\s+=\s+(.*)$/){
$php_ini{'allow_url_include'} = $1;
}
elsif(/^session.use_trans_sid\s+=\s+(.*)$/){
$php_ini{'session_use_trans_sid'} = $1;
}
elsif(/^session.cache_expire\s+=\s+(.*)$/){
$php_ini{'session_cache_expire'} = $1;
}
elsif(/^session.cache_limiter\s+=\s+(.*)$/){
$php_ini{'session_cache_limiter'} = $1;
}
elsif(/^espeedboat.enable\s+=\s+(.*)$/){
$php_ini{'espeedboat_enable'} = $1;
}
}
$self->file_parsed_hash(\%php_ini);
}
#
# __ _ _
# ___ _ __ ___ _ __ / _(_) | ___
# / __| '__/ _ \| '_ \| |_| | |/ _ \
# | (__| | | (_) | | | | _| | | __/
# \___|_| \___/|_| |_|_| |_|_|\___|
#
#
elsif($self->file_name eq '/home/web/cronfile'){
my $count = '';
my @min = ();
my @std = ();
my @mday = ();
my @mon = ();
my @wday = ();
my @command = ();
my $reverseline = '';
my %cronjobs;
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
if(/[^#|=]/){
$count++;
($min[$count],$std[$count],$mday[$count],$mon[$count],$wday[$count],$command[$count]) = split(" ", $_, 6);
if($command[$count]){
#reverseline ermoglicht das listing von gleichen jobs mit unterschiedlichen Zeiten
$reverseline = "$command[$count]:$min[$count]:$std[$count]:$mday[$count]:$mon[$count]:$wday[$count]";
$cronjobs{$reverseline}{'job'} = $command[$count];
$cronjobs{$reverseline}{'count'} = $count;
$cronjobs{$reverseline}{'min'} = $min[$count];
$cronjobs{$reverseline}{'std'} = $std[$count];
$cronjobs{$reverseline}{'mday'} = $mday[$count];
$cronjobs{$reverseline}{'mon'} = $mon[$count];
$cronjobs{$reverseline}{'wday'} = $wday[$count];
}
}
}
$self->file_parsed_hash(\%cronjobs);
}
#
# _ _ _ __
# ___ ___| |_| |_(_)_ __ __ _ ___ ___ ___ _ __ / _|
# / __|/ _ \ __| __| | '_ \ / _` / __| / __/ _ \| '_ \| |_
# \__ \ __/ |_| |_| | | | | (_| \__ \| (_| (_) | | | | _|
# |___/\___|\__|\__|_|_| |_|\__, |___(_)___\___/|_| |_|_|
# |___/
#
elsif($self->file_name eq '/usr/local/etc/easytecc/settings.conf'){
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
}
}
#
# _ _
# ___ _ _ _ __ _ __ ___ _ __ | |_ | | __ _ _ __ __ _
# / __| | | | '__| '__/ _ \ '_ \| __| | |/ _` | '_ \ / _` |
# | (__| |_| | | | | | __/ | | | |_ _| | (_| | | | | (_| |
# \___|\__,_|_| |_| \___|_| |_|\__(_)_|\__,_|_| |_|\__, |
# |___/
#
elsif($self->file_name eq '/usr/local/etc/easytecc/current.lang'){
foreach($self->file_content){
next if /^#/ || /^$/;
s/\s+$//;
}
}
#
# _
# _ __ __ _ ___ _____ ____| |
# | '_ \ / _` / __/ __\ \ /\ / / _` |
# | |_) | (_| \__ \__ \\ V V / (_| |
# | .__/ \__,_|___/___/ \_/\_/ \__,_|
# |_|
#
elsif($self->file_name eq '/etc/passwd'){
my %passwd;
#my $pw = Passwd::Unix->new('passwd' => '/etc/passwd', 'shadow' => '/etc/passwd');
my $pw = `cat /etc/passwd`;
my @passwd = split /\n/, $pw;
my %username_lookup;
#root is skipped in foreach but user lookup for root has to work for filemanager
#$username_lookup{'0'} = 'root';
my %home_lookup;
my %domain_count_lookup;
#logline("debug","passwd=$pw\n") if $debug;
foreach my $user (@passwd) {
#next if $user =~ /^(bin|daemon|adm|lp|sync|shutdown|halt|news|uucp|operator|nobody|sysmail):/;
$user =~ m/^([\w\-_]{1,32}):(.............|\*):([0-9]{1,6}):([0-9]{1,6}):(.*):(.*):(.*)$/;
$user = $1;
# nix ohne shell, ausser mysql und web
if($user ne 'mysql' && $user ne 'web' && ($7 =~ /^\s*$/ || $7 =~ /nologin/)){
next;
}
$passwd{$user}{'passwd'} = $2;
$passwd{$user}{'uid'} = $3;
$passwd{$user}{'gid'} = $4;
$passwd{$user}{'gecos'} = $5;
$passwd{$user}{'home'} = $6;
$passwd{$user}{'shell'} = $7;
# add groups
my $groups = `/usr/bin/id -n -G $user`;
chomp($groups);
my @groups = split(/\s/,$groups);
if(scalar @groups){
$passwd{$user}{'groups'} = \@groups;
}
#logline("debug","Username: $1 passwd=$2 uid=$3 gid=$4 gecos=$5 home=$6 shell=$7 groups=$groups\n") if $debug;
# in lookup_hash rein, um User zu Domain schneller zu finden ohne immer iterieren zu mssen
$home_lookup{$passwd{$user}{'home'}} = $user;
# ebenso die uid, da stat() nur uid zurckgibt, also hash zum lookup von uid auf namen.
$username_lookup{$passwd{$user}{'uid'}} = $user;
#Anzahl der angelegten Emailuser zählen
my $domain = $passwd{$user}{'gecos'};
$domain =~ s/\s\-\sPOP$//;
$domain_count_lookup{$domain}++;
# Passwort von Mailuser in Klartext
if(-e "/usr/local/etc/easytecc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/easytecc/$user.pass");
} elsif(-e "/usr/local/etc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/$user.pass");
}
}
$self->file_parsed_hash(\%passwd);
# lookups könnte man auch mit einem hash realisieren, wird aber zu kompliziert...
# passwd dürfte die einzige Funktion sein, wo zwei lookup hashes gebraucht werden
$self->lookup_hash(\%username_lookup);
$self->lookup2_hash(\%home_lookup);
$self->lookup_hash_domain_count(\%domain_count_lookup);
}
#elsif($self->file_name eq '/etc/passwd'){
#my %passwd;
#my $pw = Passwd::Unix->new('passwd' => '/etc/passwd', 'shadow' => '/etc/passwd');
#my %username_lookup;
#my %home_lookup;
# logline("debug","passwd=$pw\n") if $debug;
# foreach $user ($pw->users) {
# next if $user =~ /^(root|bin|daemon|adm|lp|sync|shutdown|halt|news|uucp|operator|nobody|sysmail)$/;
# #logline("debug","Username: $user, Full Name: ", $pw->gecos($user), $pw->home($user), "\n") if $debug;
# $passwd{$user}{'passwd'} = $pw->passwd($user);
# $passwd{$user}{'uid'} = $pw->uid($user);
# $passwd{$user}{'gid'} = $pw->gid($user);
# $passwd{$user}{'gecos'} = $pw->gecos($user);
# $passwd{$user}{'home'} = $pw->home($user);
# $passwd{$user}{'shell'} = $pw->shell($user);
# # in lookup_hash rein, um User zu Domain schneller zu finden ohne immer iterieren zu mssen
# $home_lookup{$pw->home($user)} = $user;
# # ebenso die uid, da stat() nur uid zurckgibt, also hash zum lookup von uid auf namen.
# $username_lookup{$pw->uid($user)} = $user;
# # Passwort von Mailuser in Klartext
# $passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/$user.pass") if (-e "/usr/local/etc/$user.pass");
# }
# $self->file_parsed_hash(\%passwd);
# # lookups knnte man auch mit einem hash realisieren, wird aber zu kompliziert...
# # passwd drfte die einzige Funktion sein, wo zwei lookup hashes gebraucht werden
# $self->lookup_hash(\%username_lookup);
# $self->lookup2_hash(\%home_lookup);
#}
#
# _ _
# _ __ ___ __ _(_) |_ _ ___ ___ _ __
# | '_ ` _ \ / _` | | | | | / __|/ _ \ '__|
# | | | | | | (_| | | | |_| \__ \ __/ |
# |_| |_| |_|\__,_|_|_|\__,_|___/\___|_|
#
#
elsif($self->file_name eq '/etc/mail/mailuser'){
my %passwd;
my %domain_count_lookup;
#test@dapag.de:gYBy6qPD8MLBc:admin:vuser::/home/test@dapag.de::userdb_quota_rule=*:bytes=100M
my $pw = `cat /etc/mail/mailuser`;
chomp $pw;
my @passwd = split /\n/, $pw;
#logline("debug","pw = $pw\n") if $debug;
foreach my $line (@passwd) {
#$user =~ m/^([\w\-@\.]{1,100}):([a-zA-Z0-9]{32,32}):([\w\-]{1,100}):([\w\-]{1,100}):(.*):(.*):(.*):(.*):(.*)$/;
my ($user, $password_hash, $uid, $gid, $gecos, $home, $dummy2, $dummy3, $quota_M) = split(/:/, $line);
$quota_M =~ s/^storage=//;
my $quota = $quota_M;
$quota =~ s/M$//;
$passwd{$user}{'home'} = $home;
$passwd{$user}{'quota_M'} = $quota_M;
$passwd{$user}{'quota'} = $quota;
$passwd{$user}{'gecos'} = $gecos;
#logline("debug","Username:$user passwd=$password_hash uid=$uid gid=$gid home=$home quota=$quota\n") if $debug;
#Anzahl der angelegten Emailuser zählen
my $domain = $passwd{$user}{'gecos'};
$domain =~ s/\s\-\sPOP$//;
$domain_count_lookup{$domain}++;
#logline("debug","Username: $1 passwd=$2 uid=$3 gid=$4 gecos=$5 home=$6 shell=$7 quotarule=$8 quota=$9\n") if $debug;
# Passwort von Mailuser in Klartext
if(-e "/usr/local/etc/easytecc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/easytecc/$user.pass");
} elsif(-e "/usr/local/etc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/$user.pass");
}
}
$self->file_parsed_hash(\%passwd);
$self->lookup_hash_domain_count(\%domain_count_lookup);
}
#
# _ _ _
# _ __ ___ __ _(_) |_ __ __ _ ___ _____ ____| |
# | '_ ` _ \ / _` | | | '_ \ / _` / __/ __\ \ /\ / / _` |
# | | | | | | (_| | | | |_) | (_| \__ \__ \\ V V / (_| |
# |_| |_| |_|\__,_|_|_| .__/ \__,_|___/___/ \_/\_/ \__,_|
# |_|
#
elsif($self->file_name eq '/usr/local/etc/mailpasswd'){
my %passwd;
#my $pw = Passwd::Unix->new('passwd' => '/usr/local/etc/mailpasswd', 'shadow' => '/usr/local/etc/mailpasswd');
my $pw = `cat /usr/local/etc/mailpasswd`;
my @passwd = split /\n/, $pw;
my %username_lookup;
my %home_lookup;
my %domain_count_lookup;
#logline("debug","passwd=$pw\n") if $debug;
foreach $user (@passwd) {
next if $user =~ /^(root|bin|daemon|adm|lp|sync|shutdown|halt|news|uucp|operator|nobody|sysmail)$/;
$user =~ m/^([\w\-_]{1,32}):(.............|\*):([0-9]{1,6}):([0-9]{1,6}):(.*):(.*):(.*)$/;
$user = $1;
$passwd{$user}{'passwd'} = $2;
$passwd{$user}{'uid'} = $3;
$passwd{$user}{'gid'} = $4;
$passwd{$user}{'gecos'} = $5;
$passwd{$user}{'home'} = $6;
$passwd{$user}{'shell'} = $7;
# in lookup_hash rein, um User zu Domain schneller zu finden ohne immer iterieren zu müssen
$home_lookup{$passwd{$user}{'home'}} = $user;
# ebenso die uid, da stat() nur uid zurück gibt, also hash zum lookup von uid auf namen.
$username_lookup{$passwd{$user}{'uid'}} = $user;
#Anzahl der angelegten Emailuser zählen
my $domain = $passwd{$user}{'gecos'};
$domain =~ s/\s\-\sPOP$//;
$domain_count_lookup{$domain}++;
logline("debug","domain=$domain count=" . $domain_count_lookup{$domain}) if $debug;
# Passwort von Mailuser in Klartext
if(-e "/usr/local/etc/easytecc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/easytecc/$user.pass");
} elsif(-e "/usr/local/etc/$user.pass"){
$passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/$user.pass");
}
}
$self->file_parsed_hash(\%passwd);
# lookups könnte man auch mit einem hash realisieren, wird aber zu kompliziert...
# passwd dürfte die einzige Funktion sein, wo zwei lookup hashes gebraucht werden
$self->lookup_hash(\%username_lookup);
$self->lookup2_hash(\%home_lookup);
#wegen zu langsam: weiterer lookup hash für Domainzuordnung und Anzahl Emailuser pro Domain um Iterationen zu sparen
$self->lookup_hash_domain_count(\%domain_count_lookup);
}
#elsif($self->file_name eq '/usr/local/etc/mailpasswd'){
# my %passwd;
#
# my $pw = Passwd::Unix->new('passwd' => '/usr/local/etc/mailpasswd', 'shadow' => '/usr/local/etc/mailpasswd');
# my %username_lookup;
# my %home_lookup;
#
# #logline("debug","passwd=$pw\n") if $debug;
# foreach $user ($pw->users) {
# next if $user =~ /^(root|bin|daemon|adm|lp|sync|shutdown|halt|news|uucp|operator|nobody|sysmail)$/;
# #logline("debug","Username: $user, Full Name: ", $pw->gecos($user), $pw->home($user), "\n") if $debug;
# $passwd{$user}{'passwd'} = $pw->passwd($user);
# $passwd{$user}{'uid'} = $pw->uid($user);
# $passwd{$user}{'gid'} = $pw->gid($user);
# $passwd{$user}{'gecos'} = $pw->gecos($user);
# $passwd{$user}{'home'} = $pw->home($user);
# $passwd{$user}{'shell'} = $pw->shell($user);
# # in lookup_hash rein, um User zu Domain schneller zu finden ohne immer iterieren zu müssen
# $home_lookup{$pw->home($user)} = $user;
# # ebenso die uid, da stat() nur uid zurück gibt, also hash zum lookup von uid auf namen.
# $username_lookup{$pw->uid($user)} = $user;
# # Passwort von Mailuser in Klartext
# $passwd{$user}{'dec'} = easytecc3::decrypt("/usr/local/etc/$user.pass") if (-e "/usr/local/etc/$user.pass");
# }
#
# $self->file_parsed_hash(\%passwd);
# # lookups könnte man auch mit einem hash realisieren, wird aber zu kompliziert...
# # passwd dürfte die einzige Funktion sein, wo zwei lookup hashes gebraucht werden
# $self->lookup_hash(\%username_lookup);
# $self->lookup2_hash(\%home_lookup);
#}
#
# _ _ _
# ___ ___ _ __ __| |_ __ ___ __ _(_) | _____ __
# / __|/ _ \ '_ \ / _` | '_ ` _ \ / _` | | | / __\ \ /\ / /
# \__ \ __/ | | | (_| | | | | | | (_| | | || (__ \ V V /
# |___/\___|_| |_|\__,_|_| |_| |_|\__,_|_|_(_)___| \_/\_/
#
#
elsif($self->file_name eq '/etc/mail/sendmail.cw'){
my %sendmail_cw;
foreach($self->file_content){
next if /^#/ || /^$/ || /^[\t\s]{1,}$/;
s/\s+$//;
$sendmail_cw{$_} = '1';
}
$self->file_parsed_hash(\%sendmail_cw);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub write_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $self = shift;
logline("debug",'write_file:' . $self->file_name ) if $debug;
my $file = '';
my $file_tmp = '';
#fbsd
if ($fb && $file_fb{$self->file_name}) {
$file = $file_fb{$self->file_name};
my $dir = $file;
$dir =~ s/\/[^\/]*$//g;
my @pieces = split (/\//,$file);
$file_tmp = pop(@pieces);
$file_tmp = "/home/web/$file_tmp";
}
else{
$file = $self->file_name;
$file_tmp = $file;
}
# vor Schreiben immer prüfen ob genug Quota zur Verfügung steht
if(easytecc3::system_quota_reached()){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return('<h1>L__Fehler__L: L__Systemquotagrenze erreicht__L</h1>L__Es steht zuwenig freier Speicherplatz zur Verfügung um neue Dateien schreiben zu können.__L');
}
my $backup_error = easytecc3::backup_file($file);
if($backup_error){
logline("debug","backup error: $backup_error\n") if $debug;
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return(qq~<h1>L__Fehler__L:</h1> $backup_error~);
}
#bei httpd.conf einen Syntaxcheck machen, da Apache nach Neustart sonst abstürzt wenn z.B. bei "manuelle Einträge" Fehler drin
if($self->file_name eq '/etc/httpd/conf/httpd.conf'){
open(DAT, '> ' . $file_tmp . '.new') || die("Could not open file!");
# leere bloecke und mehr als zwei leerzeilen entfernen
my $buffer = '';
my $emptylines = 0;
my $lasttag = '';
foreach my $line($self->file_content){
chomp $line;
#logline("debug","#1##line = $line\n") if $debug;
if($line =~ m/^\s*$/){
$emptylines++;
}
else{
$emptylines = $emptylines >= 2 ? 2 : $emptylines;
while($emptylines){
if($buffer ne ''){
$buffer .= "\n";
} else {
print DAT "\n";
}
$emptylines--;
}
if($buffer ne ''){
if($line !~ m/^\s*<\/$lasttag/){
print DAT $buffer;
$buffer = '';
$lasttag = '';
} else {
$buffer = '';
$lasttag = '';
next;
}
}
if($line =~ m/^\s*<([^\/\s]+)/){
$lasttag = $1;
$buffer = $line . "\n";
} else {
print DAT $line . "\n";
$lasttag = '';
}
}
}
close DAT;
my $syntax_ok = '';
my $apache = '';
#SSL?
my $ssl = '-DSSL' if(-e '/etc/SSL');
if ($fb) {
$apache = "24_fb";
}
else{
$apache = `grep httpd_enable /etc/rc.conf`;
chomp $apache;
}
logline("debug","apache = $apache\n") if $debug;
logline("debug","file_tmp.new = $file_tmp.new\n") if $debug;
if($apache =~ /"1"/s){
$syntax_ok = `/usr/local/apache/bin/httpd -t -f /etc/httpd/conf/httpd.conf.new -DAP1 $ssl 2>&1`;
}
elsif($apache =~ /"(2|F)"/s){
$syntax_ok = `/usr/local/apache2/bin/httpd -t -f /etc/httpd/conf/httpd.conf.new -DAP2 $ssl 2>&1`;
}
elsif($apache =~ /"22"/s){
$syntax_ok = `/usr/local/apache2.2/bin/httpd -t -f /etc/httpd/conf/httpd.conf.new -DAP22 $ssl 2>&1`;
}
elsif($apache =~ /"24"/s){
$syntax_ok = `/usr/local/apache2.4/bin/httpd -t -f /etc/httpd/conf/httpd.conf.new -DAP24 $ssl 2>&1`;
}
elsif($apache eq "24_fb"){
$syntax_ok = `/usr/iports/bin/sudo /usr/iports/sbin/httpd -t -f $file_tmp.new -DAP24 $ssl 2>&1`;
}
else{
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return('L__Fehler__L: L__Unbekannte Apacheversion__L');
}
logline("debug","syntax_ok=$syntax_ok\n") if $debug;
unless( $syntax_ok =~ /Syntax OK/s ){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return('L__Fehler__L: L__Die Apache-Konfigurationsdatei konnte nicht geändert werden. Möglicherweise enthält das Feld "manuelle Einträge" ungültige Inhalte.__L<br><br>' . encode_entities($syntax_ok));
}
my $got = `cp -f $file_tmp.new $file`;
logline("debug","cp -f $file_tmp.new $file\n") if $debug;
system("$easytecc_prefix/chmod.pl 664 $file");
if ($got || -z $file){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return('L__Fehler__L: L__Die Apache-Konfigurationsdatei konnte nicht geschrieben werden. Bitte wenden Sie sich an unseren Support.__L');
}
}
elsif($self->file_name eq '/etc/mail/aliases'){
my $cat_aliases = `cat /etc/mail/aliases > /tmp/webalias.$$`;
if($self->append){
#an vorhandene Datei anhängen
open(DAT, '>> ' . "/tmp/webalias.$$") || return("/tmp/webalias.$$" . " Fehler: $!");
}
else{
# oder neu schreiben
open(DAT, '> ' . "/tmp/webalias.$$") || return("/tmp/webalias.$$" . " Fehler: $!");
}
foreach($self->file_content){
# Leerzeilen verhindern
chomp;
print DAT $_ . "\n";
}
close DAT;
my $uniq_aliases = `uniq /tmp/webalias.$$ > /tmp/webalias.$$.uniq`;
$uniq_aliases = `cat /tmp/webalias.$$.uniq > /tmp/webalias.$$`;
$uniq_aliases = `rm /tmp/webalias.$$.uniq`;
if(! -s "/tmp/webalias.$$"){
return("/tmp/webalias.$$" . " Fehler: $!");
}
if($fb){
# auf FreeBSD wird aliases über temporäre Datei mit Hilfe von /usr/sbin/vmvaliases in vorhandene aliases reingecattet
# da aliases chmod 644 admin:vuser hat. Andere Rechte nicht möglich weil sendmail sonst meckert
my $swap_aliases = `/usr/iports/bin/sudo -u admin /usr/sbin/vmvaliases $$`;
} else {
my $swap_aliases = `cat /tmp/webalias.$$ > /etc/mail/aliases`;
}
`rm /tmp/webalias.$$`;
}
elsif($self->file_name eq '/etc/mail/mailuser' && $fb){
my $cat_mailuser = `cat /etc/mail/mailuser > /tmp/mailuser.$$`;
if($self->append){
#an vorhandene Datei anhängen
open(DAT, '>> ' . "/tmp/mailuser.$$") || return("/tmp/mailuser.$$" . " Fehler: $!");
}
else{
# oder neu schreiben
open(DAT, '> ' . "/tmp/mailuser.$$") || return("/tmp/mailuser.$$" . " Fehler: $!");
}
foreach($self->file_content){
# Leerzeilen verhindern
chomp;
print DAT $_ . "\n";
}
close DAT;
if(! -s "/tmp/mailuser.$$"){
return("/tmp/mailuser.$$" . " Fehler: $!");
}
my $swap_mailuser = `sort -u /tmp/mailuser.$$ > /etc/mail/mailuser`;
$swap_mailuser = `rm /tmp/mailuser.$$`;
}
elsif($self->file_name eq '/etc/mail/virtmaps'){
my $cat_virtmaps = `cat /etc/mail/virtmaps > /tmp/virtmaps.$$`;
if($self->append){
#an vorhandene Datei anhängen
open(DAT, '>> ' . "/tmp/virtmaps.$$") || return("/tmp/virtmaps.$$" . " Fehler: $!");
}
else{
# oder neu schreiben
open(DAT, '> ' . "/tmp/virtmaps.$$") || return("/tmp/virtmaps.$$" . " Fehler: $!");
}
foreach($self->file_content){
# Leerzeilen verhindern
chomp;
print DAT $_ . "\n";
}
close DAT;
if(! -s "/tmp/virtmaps.$$"){
return("/tmp/virtmaps.$$" . " Fehler: $!");
}
my $swap_virtmaps = `uniq /tmp/virtmaps.$$ > /etc/mail/virtmaps`;
$swap_virtmaps = `rm /tmp/virtmaps.$$`;
}
elsif($self->file_name eq '/etc/mail/dnsbl.hosts' && $fb){
#gibs auf freebsd nicht mehr
}
elsif($self->file_name eq '/etc/procmailrc' && $fb){
# Unter freebsd nur Zugriff auf procmailrc über sudo web sed-wrapper wo key/values einzeln ersetzt werden
foreach(@{$self->file_content}){
$_ =~ s/[\$`&\|;]+//;
my ($key, $value) = split /=/, $_;
if(/^VIRUS=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v '$value'`;
}
elsif(/^SPAMD=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v '$value'`;
}
elsif(/^PSPAM=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v '$value'`;
}
elsif(/^CSPAM=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v '$value'`;
}
elsif(/^CLEVEL=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v "'$value'"`;
}
elsif(/^POSTFIX=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v "'$value'"`;
}
elsif(/^SUBJ_CSPAM\s*=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v "'$value'"`;
}
elsif(/^SUBJ_PSPAM\s*=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v "'$value'"`;
}
elsif(/^SUBJ_VIRUS\s*=/){
`/usr/iports/bin/sudo /usr/sbin/sed_procmail -k $key -v "'$value'"`;
}
}
}
else{
if($self->append){
#an vorhandene Datei anhängen
open(DAT, '>> ' . $file) || return($file . " Fehler: $!");
}
else{
# oder neu schreiben
open(DAT, '> ' . $file) || return($file . " Fehler: $!");
}
foreach($self->file_content){
# Leerzeilen verhindern
chomp;
print DAT $_ . "\n";
}
close DAT;
}
# Dienst neu starten
if($self->restart){
logline("debug",'restart' . $self->file_name ) if $debug;
my $service_restart = '';
my $command = '';
if ($fb) {
#erstmal gucken obs für freebsd anderes neustartkommando gibt
$service_restart = service_restart->new({command => $self->file_name . '_fb'});
if( ! $service_restart->command_exists($self->file_name . '_fb')){
# wenn nicht fallback auf normales kommando
$service_restart = service_restart->new({command => $self->file_name});
if($service_restart->command_exists($self->file_name)){
$command = $service_restart->command($self->file_name);
#system($command . " >/dev/null");
system("/bin/sh -c \"sleep 1; " . $command . "\" >/dev/null 2>&1 &");
}
}
else{
$command = $service_restart->command($self->file_name . '_fb');
#system($command . " >/dev/null");
system("/bin/sh -c \"sleep 1; " . $command . "\" >/dev/null 2>&1 &");
}
logline("debug",'restart done' . "/bin/sh -c \"sleep 1; " . $command . "\" >/dev/null 2>&1 &" ) if $debug;
#logline("debug",'restart done' . $command ) if $debug;
}
else{
$service_restart = service_restart->new({command => $self->file_name});
if($service_restart->command_exists($self->file_name)){
$command = $service_restart->command($self->file_name);
system($command . ' >/dev/null 2>&1');
}
}
}
# user_prefs muss auch auf clamspam übertragen werden
if($self->file_name =~ /\/user_prefs$/){
logline("debug",'user_prefs geändert:' . $self->file_name ) if $debug;
# default-user_prefs, dei für alle ohne eigene Einstellungen gilt
if($self->file_name =~ /\/home\/spamdef\//){
logline("debug","user_prefs=spamdef \n") if $debug;
my $tmperror = `/usr/sbin/spamconf -n spamdef 2>&1` unless $fb;
my $tmperror = `/usr/sbin/spamconf -n spamdef 2>&1` if $fb;
die "can't transfer spamconfs for user spamdef to spamd: $tmperror" if $tmperror;
}
# userspezifische user_prefs
else{
my $user = $self->user;
logline("debug","user_prefs=user " . $user ) if $debug;
my $tmperror = `/usr/sbin/spamconf -n $user 2>&1` unless $fb;
my $tmperror = `/usr/sbin/spamconf -n $user 2>&1` if $fb;
die "can't transfer spamconfs for user $user to spamd: $tmperror" if $tmperror;
}
}
# Dateien auf externen Mailserver übertragen
if( easytecc3::extern_mx() ){
logline("debug",'extern_mx' . $self->domain ) if $debug;
my %file_for_mailhost =(
'/etc/procmailrc' => 'write_proc=/etc/procmailrc',
'/home/spamdef/.black.lst' => 'lists=/home/spamdef/.black.lst,/home/spamdef/.white.lst',
'/home/spamdef/.spamproc' => 'write_proc=/home/spamdef/.spamproc',
'/home/spamdef/.white.lst' => 'lists=/home/spamdef/.black.lst,/home/spamdef/.white.lst',
'/home/spamdef/.spamd/user_prefs' => 'user_prefs=/home/spamdef/.spamd/user_prefs',
'/home/'.$self->user.'/.black.lst' => 'lists='.'/home/'.$self->user.'/.black.lst,'.'/home/'.$self->user.'/.white.lst',
'/home/'.$self->user.'/.white.lst' => 'lists='.'/home/'.$self->user.'/.black.lst,'.'/home/'.$self->user.'/.white.lst',
'/home/'.$self->user.'/.spamproc' => 'write_proc='.'/home/'.$self->user.'/.spamproc',
'/home/'.$self->user.'/.spamd/user_prefs' => 'user_prefs='.'/home/'.$self->user.'/.spamd/user_prefs',
'/home/'.$self->domain.'/.black.lst' => 'lists='.'/home/'.$self->domain.'/.black.lst,'. '/home/'.$self->user.'/.white.lst',
'/home/'.$self->domain.'/.white.lst' => 'lists='.'/home/'.$self->domain.'/.black.lst,'. '/home/'.$self->user.'/.white.lst',
'/home/'.$self->domain.'/.spamproc' => 'write_proc='.'/home/'.$self->domain.'/.spamproc',
'/home/'.$self->domain.'/.spamd/user_prefs' => 'user_prefs='.'/home/'.$self->domain.'/.spamd/user_prefs',
'/usr/local/etc/'.$self->user.'_'.$self->domain.'.aut' => 'autoreply='.'/usr/local/etc/'.$self->user.'_'.$self->domain.'.aut',
'/usr/local/etc/easytecc/'.$self->user.'_'.$self->domain.'.aut' => 'autoreply='.'/usr/local/etc/easytecc/'.$self->user.'_'.$self->domain.'.aut',
'/etc/sysconfig/clamav-milter' => 'write_clamav=milter',
'/etc/sysconfig/clamav-template' => 'write_clamav=template',
'/etc/sysconfig/clamav-whitelist' => 'write_clamav=whitelist'
);
if($file_for_mailhost{$self->file_name}){
logline("debug",'file_for_mailhost:' . $file_for_mailhost{$self->file_name} ) if $debug;
my $socket = easytecc3::make_socket();
print $socket $file_for_mailhost{$self->file_name} . "\n";
easytecc3::close_socket($socket) if $socket;
}
logline("debug","<<< Leaving ".(caller(0))[3]."(). external mail") if $debug;
return();
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub logline($$) {
my $level = shift;
my $message = shift;
chomp $message;
my ($package, $filename, $line) = caller;
my $logline = sprintf '(%5.5d)', $line;
$log->log( level => $level, message => $logline." ".$message);
}
sub dienice ($) {
# write die messages to the log before die'ing
my ($package, $filename, $line) = caller;
logline("alert","$_[0] at line $line in $filename");
die $_[0];
}
package service_restart;
use Class::Builder {
command => {
hashref => {
'/etc/mail/sendmail.cw' => '/usr/local/bin/vnewcw',
'/etc/mail/sendmail.cw.neu' => '/usr/local/bin/vnewcw',
'/etc/mail/access' => '/usr/local/bin/vnewaccess',
'/etc/mail/aliases' => '/usr/sbin/admalias',
'/etc/mail/virtmaps' => '/usr/local/bin/vnewvirtmaps',
'/etc/mail/dnsbl.hosts' => '/usr/local/bin/vnewdnsbl',
'/etc/httpd/conf/httpd.conf' => '/usr/sbin/reload_apache',
'/etc/php.ini' => '/usr/sbin/restart_apache',
'/home/web/cronfile' => '/usr/sbin/admcron',
# fbsd commandos werden mit $command . '_fb' getestet....
'/etc/httpd/conf/httpd.conf_fb' => '/usr/iports/bin/sudo /usr/sbin/reload_apache',
'/home/web/cronfile_fb' => '/usr/iports/bin/sudo /usr/sbin/webcron',
'/etc/mail/virtmaps_fb' => '/usr/iports/bin/sudo /usr/sbin/vnewvirtmaps',
'/etc/mail/access_fb' => '/usr/iports/bin/sudo /usr/sbin/vnewaccess',
'/etc/mail/aliases_fb' => '/usr/iports/bin/sudo /usr/sbin/vnewaliases',
'/etc/mail/sendmail.cw_fb' => '/usr/iports/bin/sudo /usr/sbin/restart_sendmail',
}
}
};
#'/etc/httpd/conf/httpd.conf_fb' => '/bin/sh -c \'sleep 10 ; /usr/iports/bin/sudo /usr/sbin/reload_apache \' &',
#
1;