全部博文(1144)
分类: LINUX
2009-12-09 12:11:05
#!/usr/local/bin/perl
# make sure .qmail-user and user/.qmail contain something
# smelling valid
# Copyright 2008 Jeremy Kister.
use strict;
my %paths;
my ($y,$m,$d) = (localtime())[5,4,3];
$y += 1900;
$m++;
my $mon = sprintf('%.2d', $m);
my $day = sprintf('%.2d', $d);
my $date = $y . $mon . $day;
my(%dir,%nuked);
opendir(D, '/var/qmail/queue/mess/') || die "cannot opendir queue/mess: $!\n";
my @subdirs = (grep {!/^\./} readdir D); # conf-split
closedir D;
# trim log,
my @log;
if(open(LOG, "/export/home/misc_logs/nukedforwards")){
while(){
push @log, $_;
}
close LOG;
my $i=1;
open(LOG, ">/export/home/misc_logs/nukedforwards.tmp") || die "cannot write to nukedforwards.tmp: $!\n";
foreach my $line (reverse @log){
print LOG $line;
last if($i == 10000);
$i++;
}
close LOG;
rename("/export/home/misc_logs/nukedforwards.tmp","/export/home/misc_logs/nukedforwards")
|| die "cannot rename tmp: $!\n";
}
## end trim log
open(LOG, ">>/export/home/misc_logs/nukedforwards") || die "cannot open nukedforwards for append: $!\n";
our($opt_v,$opt_f);
use Getopt::Std;
getopts('v');
print "gathering mx authoritative data..\n";
open(A, '/var/qmail/users/assign') || die "cannot open assign: $!\n";
while(){
if(/^\+.+\-:([^:]+):\d+:\d+:([^:]+):-::$/){
next if($1 eq 'graves.com' || $1 eq 'lists.broadviewnet.net');
if((-f "$2/vpasswd") && (! -l $2)){
$paths{$1} = $2;
}
}
}
close A;
my %copy = %paths;
while(my($domain,$dir) = each %paths){
print "working on $domain -> $dir\n" if($opt_v);
if(opendir(D, $dir)){
# open vpasswd, look for .qmail inside Maildirs
if(open(V, "${dir}/vpasswd")){
my $n=0;
while(){
$n++;
if(/^([^:]+):(?:[^:]+)?:\d+:\d+:[^:]*:([^:]+):/){
my $mailbox = $1;
my $maildir = $2;
if(open(F, "$maildir/.qmail")){
my $l=0;
while(){
$l++;
next if(/^#/);
chomp;
my $code = verify($_,%copy);
unless($code == 0){
warn "Bad line in $maildir/.qmail:$l\n" if($opt_v);
print LOG "[${date}]: Bad line in $maildir/.qmail:$l\n";
}
}
close F;
}else{
unless(-d $maildir){
warn "No maildir for $mailbox\@$domain ($dir)\n" if($opt_v);
print LOG "[${date}]: No maildir for $mailbox\@$domain ($dir)\n";
}
}
}else{
warn "Invalid syntax at ${dir}/vpasswd:$n\n" if($opt_v);
print LOG "[${date}]: Invalid syntax at ${dir}/vpasswd:$n\n";
}
}
close V;
}else{
warn "cannot open ${dir}/vpasswd: $!\n" if($opt_v);
print LOG "[${date}]: cannot open ${dir}/vpasswd: $!\n";
}
foreach my $file (grep {/^\.qmail-/} readdir D){
my $tfile = $file;
$tfile =~ s/^.qmail-//;
if($tfile =~ /\./){
warn "Illegal character in ${dir}/${file}\n" if($opt_v);
print LOG "[${date}]: Illegal character in ${dir}/${file}\n";
}elsif($tfile =~ /-owner/){
next; # i know these are wrong and causing problems, but ignore for now
}
if(open(F, "${dir}/${file}")){
my $n=0;
while(){
$n++;
# should make sure .qmail-default contains >=1 valid command
next if(/^#/);
chomp;
my $code = verify($_,%copy);
if($code == 2){
warn "unlinked ${dir}/${file}\n" if($opt_v);
print LOG "[${date}]: unlinked ${dir}/${file}\n";
unlink("${dir}/${file}") || die "cannot unlink $dir/$file: $!\n";
}elsif($code != 0){
warn "Bad Config in ${dir}/${file}:$n\n" if($opt_v);
print LOG "[${date}]: Bad Config in ${dir}/${file}:$n\n";
}
}
close F;
}else{
warn "could not open ${dir}/${file}: $!\n" if($opt_v);
print LOG "[${date}]: could not open ${dir}/${file}: $!\n";
}
}
closedir D;
}else{
warn "error with $domain: $dir does not exist\n" if($opt_v);
print LOG "[${date}]: error with $domain: $dir does not exist\n";
}
}
sub verify {
my $line = shift;
my %copy = shift;
if($line =~ /^([\/\.]\S+\/)$/){
my $maildir = $1;
my $code = (-d $maildir) ? 0 : 2;
return $code;
}elsif($line =~ /\|\s*(\S+)/){
my $program = $1;
# piping to a program
unless($program =~ /vdelivermail|forward|esec.pl|ezmlm|autorespond|circuits-config|wreq|receive|openticket.pl/){
return 1;
}
if(-x $program){
return 0;
}else{
return 1;
}
}elsif($line =~ /^&?(([a-z0-9_\.\+\-\=\?\^])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,4})+)$/i){
my $addr = $1;
my($user,$d) = split(/\@/, $addr) || die "bad addr: $addr\n";
my $code=1; # assume bad, prove it's good.
if(exists($copy{$d})){
# must check if valid via .qmail-username, (vpasswd + Maildir), Maildir/.qmail, or .qmail-default
if(-f "$copy{$d}/.qmail-${user}"){
$code=0; # dont need to check it, done above.
}elsif(-f "$copy{$d}/${user}/Maildir/.qmail"){
$code=0; # dont need to check it, done above.
}elsif(-d "$copy{$d}/${user}/Maildir/"){
$code=0;
}elsif(open(F, "$copy{$d}/.qmail-default")){
my $n=0;
while(){
chop;
$n++;
if(/(\S+\/)$/){
my $default=$1;
if(-d $default){
$code=0;
}else{
warn "Invalid directory at $copy{$d}/.qmail-default:$n\n" if($opt_v);
print LOG "[${date}]: Invalid directory at $copy{$d}/.qmail-default:$n\n";
}
}
}
close F;
}
}else{
$code=0; # we dont do mail for that domain
}
return $code;
}else{
print "unknown: $line\n";
return 1; #unknown
}
}