#!/usr/bin/perl -w use strict; ############################################################################### # checklocaldomains, a script for Cpanel servers # Checks that local domains are really local and warns owners # (and optionally users) if they aren't. # First public release: 08/JAN/2005 # (c) Juan R. Pozo - jrpozo@conclase.net - http://html.conclase.net/cp/scripts/ ############################################################################### ############################################################################### # Copyright (c) 2005, Juan R. Pozo # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # - The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ############################################################################### ############################################################################### my $path = '/root/scripts/checklocaldomains'; my $debug = 1; # rootonly: # 1 = notify root only # 0 = notify root, resellers and optionally users my $rootonly = 1; ############################################################################### my %islocal = (); my %notlocal = (); my %ip = (); my $adminemail = 'root'; my %nameservers = (); my $hostname = `hostname`; $hostname =~ s/\s+//; open(CONF, ') { if (/^ADDR (\d+\.\d+\.\d+\.\d+)/) { $islocal{$1} = 1; } elsif (/^CONTACTEMAIL (\S+)/) { $adminemail = $1; } elsif (/^NS\d? (\S+)/i) { $nameservers{root} .= "$1\n"; } } close(CONF); $nameservers{root} =~ s/\s+$//gm; print "adminemail = $adminemail\n" if $debug; open(IPS, ') { if (/^(\d+\.\d+\.\d+\.\d+)$/) { $islocal{$1} = 1; } } close(IPS); print 'Local IPs: ' . join(', ', keys %islocal) . "\n" if $debug; my @resolvers = (); open(RES, "<$path/resolver") and do { while () { if (/^\s*(\d+\.\d+\.\d+\.\d+)\s*$/) { push @resolvers, '@' . $1; } } close(RES); }; die('Not resolvers found') unless @resolvers; print 'Resolvers: ', join(', ', @resolvers), "\n" if $debug; my %notify = (); my $notifyall = 0; if (-e "<$path/notify.all") { $notifyall = 1; } else { open(NOT, "<$path/notify") and do { while () { next if /^\s*#/; if (/^(\S+)/) { $notify{$1} = 1; } } close(NOT); }; } if ($debug) { if ($notifyall) { print "Notify all users? Yes\n"; } elsif (scalar keys %notify) { print 'Notify users of: ' . join(', ', keys %notify) . "\n"; } else { print "Notify users of: no resellers\n"; } } my %ignore = (); open(IGN, "<$path/ignore") and do { while () { next if /^\s*#/; s/\s+//; $ignore{$_} = 1; } close(IGN); }; print "Resolving IPs, please wait, this will take a while...\n" if $debug; my ($numres, $r) = (scalar @resolvers, 0); open(LD, ') { s/\s+$//; next unless /^[a-z0-9-.]+$/i; next if $ignore{$_}; my $ip; do { $ip = `dig +short $_ $resolvers[$r]`; $r = 0 if ++$r == $numres; } while ($ip =~ /^;;/); $ip =~ s/\s+$//; $ip = 'N/A' if $ip eq ''; if ($debug > 1) { print "dig +short $_ $resolvers[$r]\n"; print "$_ -> $ip\n"; } unless ($islocal{$ip}) { $notlocal{$_} = 1; $ip{$_} = $ip; } sleep(1); } close(LD); unless (scalar keys %notlocal) { print "None of the local domains point to external IPs\n"; exit; } print 'Non local domains: ' . join(', ', keys %notlocal) . "\n" if $debug; my %email = (); my %owner = (); open(TUO, ') { if (/^([^:]+): (\S+)/) { $owner{$1} = $2; my $homedir = (getpwnam($1))[7]; if (-r "$homedir/.contactemail") { $email{$1} = `head "$homedir/.contactemail" -n 1`; $email{$1} =~ s/\s+//; } } } close(TUO); my %user = (); open(UD, ') { if (/^([^:]+): (\S+)/) { $user{$1} = $2; } } close(UD); my $ownertemplate = ''; open(TMPL, "<$path/owner.template") or die($!); while () { $ownertemplate .= $_; } close(TMPL); my $usertemplate = ''; open(TMPL, "<$path/user.template") or die($!); while () { $usertemplate .= $_; } close(TMPL); my %suspended = (); opendir(SUSP, '/var/cpanel/suspended/') and do { my @susp = grep { !/^\./ } readdir(SUSP); closedir(SUSP); foreach (@susp) { $suspended{$_} = 1; } }; print 'Suspended users: ', join(', ', keys %suspended), "\n" if $debug; open(NS, ') { if (/^([^:]+):(\S+)/) { my @ns = split(/,/, $2); if (not defined($ns[0])) { $nameservers{$1} = $nameservers{root}; } else { $nameservers{$1} = join("\n", grep { $_ ne '' } @ns); } } } close(NS); foreach my $domain (sort keys %notlocal) { # Domain user unless (exists($user{$domain})) { $user{$domain} = 'unknown user'; } my $user = $user{$domain}; # Domain user email unless (exists($email{$user})) { $email{$user} = "missingemail\@$hostname"; } if ($email{$user} eq '') { $email{$user} = "missingemail\@$hostname"; } my $useremail = $email{$user}; # Domain reseller unless (exists($owner{$user})) { $owner{$user} = 'root'; } my $owner = $owner{$user}; # Domain reseller email unless (exists($email{$owner})) { $email{$owner} = $adminemail; } if ($email{$owner} eq '') { $email{$owner} = $adminemail; } my $owneremail = $email{$owner}; # Reseller's nameservers unless (exists($nameservers{$owner})) { $nameservers{$owner} = $nameservers{root}; } # If account is suspended, don't send any warning next if $suspended{$user}; if ($debug) { print "Notifying $domain\n"; print " - owner = \"$owner{$user{$domain}}\" <$email{$owner{$user{$domain}}}>\n"; print " - user = \"$user{$domain}\" <$email{$user{$domain}}>\n"; print " - ip = $ip{$domain}\n"; } # Compose message for admin/reseller my $message = $ownertemplate; $message =~ s/\[DOMAIN\]/$domain/g; $message =~ s/\[IP\]/$ip{$domain}/g; $message =~ s/\[HOSTNAME\]/$hostname/g; $message =~ s/\[ADMIN\]/$adminemail/g; $message =~ s/\[NAMESERVERS\]/$nameservers{$owner}/g; if ($rootonly) { $message =~ s/\[OWNER\]/$adminemail/g; $message =~ s/\[USER\]/$adminemail/g; } else { $message =~ s/\[OWNER\]/$owneremail/g; $message =~ s/\[USER\]/$useremail/g; } if ($debug > 2) { print $message, "---\n\n"; } elsif ($debug) { print "* Owner notified\n\n"; } else { open(MAIL, '|/usr/sbin/sendmail -t') or die($!); print MAIL $message; close(MAIL); } # If users are not to be notified, skip rest next unless ($notifyall || $notify{$owner}); # Compose message for user $message = $usertemplate; $message =~ s/\[DOMAIN\]/$domain/g; $message =~ s/\[IP\]/$ip{$domain}/g; $message =~ s/\[HOSTNAME\]/$hostname/g; $message =~ s/\[ADMIN\]/$adminemail/g; $message =~ s/\[NAMESERVERS\]/$nameservers{$owner}/g; if ($rootonly) { $message =~ s/\[OWNER\]/$adminemail/g; $message =~ s/\[USER\]/$adminemail/g; } else { $message =~ s/\[OWNER\]/$owneremail/g; $message =~ s/\[USER\]/$useremail/g; } if ($debug > 2) { print $message, "---\n\n"; } elsif ($debug) { print "* User notified\n\n"; } else { open(MAIL, '|/usr/sbin/sendmail -t') or die($!); print MAIL $message; close(MAIL); } }