全部博文(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 } }