#!/usr/bin/perl
##########################################################################
# $Id: named,v 1.17 2002/03/28 05:00:00 kirk Exp $
##########################################################################
# $Log: named,v $
# Revision 1.17  2002/03/28 05:00:00  kirk
# - Implemented several bug fixes and patches that have been sent in
# - Fixed a possible root exploit using a race condition in /tmp
# - Fixed bugs 46371, 56191, 58578, 61202, 61829, 61831, 61832 from bugzilla.redhat.com
#
# Revision 1.16  1999/02/23 01:24:31  kirk
# Improved LookupIP in named/secure.
# Applied ftp-messages patch from Simon Liddington <sjl96v@ecs.soton.ac.uk>.
#
# Revision 1.15  1999/01/22 22:30:21  kirk
# Prepping for Version 1.6.1
#
# Revision 1.14  1999/01/22 22:22:04  kirk
# Prepping for Version 1.6
#
# Revision 1.13  1999/01/17 03:16:20  kirk
# Fixed named messages for BIND8.
#
# Revision 1.12  1998/11/18 19:57:24  kirk
# Prepping for Version 1.5.0
#
# Revision 1.11  1998/11/18 19:34:54  kirk
# Prepping for Version 1.5.0
#
# Revision 1.10  1998/09/09 20:08:53  kirk
# Prepping for Version 1.4.6
#
# Revision 1.9  1998/09/08 13:12:17  kirk
# Applied patch submitted by Osma Ahvenlampi <oa@spray.fi>... thanks!
#
# Revision 1.8  1998/07/30 19:44:49  kirk
# Prepping for Version 1.4.2
#
# Revision 1.7  1998/06/01 20:33:25  kirk
# Applied changes submitted by Bert de Bruijn <bob@ace.ulyssis.student.kuleuven.ac.be>...
#
# Revision 1.6  1998/05/11 13:03:30  kirk
# Applied some wonderful patches sent in by
# Luuk de Boer <luuk_de_boer@pi.net>.
#
# Revision 1.5  1998/03/19 03:12:54  kirk
# Fixed a few problems
#
# Revision 1.4  1998/03/10 06:08:52  kirk
# First working named filter...
#
# Revision 1.3  1998/02/23 01:16:58  kirk
# Getting ready for a first distribution
#
# Revision 1.2  1998/02/22 23:17:00  kirk
# Added support for 'pam' messages...
#
# Revision 1.1  1998/02/22 22:36:29  kirk
# Created named...
#
##########################################################################

########################################################
# This was written and is maintained by:
#    Kirk Bauer <kirk@kaybee.org>
#
# Please send all comments, suggestions, bug reports,
#    etc, to kirk@kaybee.org.
#
########################################################

$Debug = $ENV{'LOGWATCH_DEBUG'};
$DoLookup = $ENV{'named_ip_lookup'};
$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'};

sub LookupIP {
   my ($name, $a1, $a2,$a3,$a4,$PackedAddr,$Addr);
   $Addr = $_[0];
   ($a1,$a2,$a3,$a4) = split /\./,$Addr;
   $PackedAddr = pack('C4',$a1,$a2,$a3,$a4);
   if ($DoLookup) {
      if ($name = gethostbyaddr ($PackedAddr,2)) {
         return ($name . " (" . $Addr . ")");
      } else {
         return ($Addr);
      }
   }
   else {
      return ($Addr);
   }
}

# No sense in running if 'named' doesn't even exist on this system...
unless (( -f "/usr/sbin/named" ) or ( -f "/usr/sbin/in.named") or
	( -f "/usr/local/sbin/named") or ( -f "/usr/local/sbin/in.named" ) ) {
    exit (0);
}

if ( $Debug >= 5 ) {
    print STDERR "\n\nDEBUG: Inside Named Filter \n\n";
}

while (defined($ThisLine = <STDIN>)) {
    if ( ($ThisLine =~ /RR negative cache entry/) or
	 ($ThisLine =~ /^ns_....: .* NS points to CNAME/) or
	 ($ThisLine =~ /^accept: connection reset by peer/) or
	 ($ThisLine =~ /^There may be a name server already running/) or
	 ($ThisLine =~ /^exiting/) or
	 ($ThisLine =~ /^NSTATS /) or
	 ($ThisLine =~ /Cleaned cache of \d+ RRs/) or
	 ($ThisLine =~ /USAGE \d+ \d+ CPU=\d+.*/) or
	 ($ThisLine =~ /^XSTATS /) or
	 ($ThisLine =~ /^Ready to answer queries/) or
	 ($ThisLine =~ /^Lame server on/) or
	 ($ThisLine =~ /^Forwarding source address is/) or
	 ($ThisLine =~ /^bad referral/) or
	 ($ThisLine =~ /^rcvd NOTIFY/) or
	 ($ThisLine =~ /^Sent NOTIFY/) or
	 ($ThisLine =~ /^ns_resp: TCP truncated/) or
	 ($ThisLine =~ /No possible A RRs/) or
	 ($ThisLine =~ /NS points to CNAME/) or
	 ($ThisLine =~ /points to a CNAME/) or
	 ($ThisLine =~ /^dangling CNAME pointer/) or
	 ($ThisLine =~ /^listening on/) or
	 ($ThisLine =~ /^unrelated additional info/) or
	 ($ThisLine =~ /^Response from unexpected source/) or
	 ($ThisLine =~ /^No root nameservers for class IN/) or
	 ($ThisLine =~ /^recvfrom: No route to host/) or
	 ($ThisLine =~ /Connection refused/) or
    ($ThisLine =~ /^zone transfer of .* to/) or
    ($ThisLine =~ /^using \d+ CPU/) or
    ($ThisLine =~ /^starting BIND/) or
    ($ThisLine =~ /^loading configuration/) or
    ($ThisLine =~ /^lame server on/) or
    ($ThisLine =~ /^command channel listening/) or
    ($ThisLine =~ /^no IPv6 interfaces found/) or
    ($ThisLine =~ /^running/) or
    ($ThisLine =~ /^exiting/) or
    ($ThisLine =~ /^no longer listening/) or
    ($ThisLine =~ /^shutting down/) or
    ($ThisLine =~ /^the default for the .* option is now/) or
	 ($ThisLine =~ /^Malformed response from/) 
	 ) {
	# Don't care about these...
    }
    elsif ( ( $ThisLine =~ /^starting\..*named/) or
            ($ThisLine =~ /^named startup succeeded/) ) {
	$StartNamed++;
    }
    elsif ( $ThisLine =~ /^reloading nameserver/ ) {
	$ReloadNamed++;
    }
    elsif ( ( $ThisLine =~ /^named shutting down/ ) or
            ( $ThisLine =~ /^named shutdown succeeded/ ) ) {
	$ShutdownNamed++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /cache zone \"(.*)\" loaded/ ) ) {
	$ZoneLoaded{"cache $Zone"}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /cache zone \"(.*)\" .* loaded/ ) ) {
	$ZoneLoaded{"cache $Zone"}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /primary zone \"(.+)\" loaded/ ) ) {
	$ZoneLoaded{$Zone}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /master zone \"(.+)\" .* loaded/ ) ) {
	$ZoneLoaded{$Zone}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /secondary zone \"(.+)\" loaded/ ) ) {
	$ZoneLoaded{"secondary $Zone"}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /slave zone \"(.+)\" .* loaded/ ) ) {
	$ZoneLoaded{"secondary $Zone"}++;
    }
    elsif ( ($Addr,$Server) = ( $ThisLine =~ /Lame server on '(.+)' \(in .+\): \[.+\]\.\d+ '(.+)':/ ) ) {
   $LameServer{"$Addr ($Server)"}++;
    }
    elsif ( ($Zone) = ( $ThisLine =~ /Zone \"(.+)\" was removed/ ) ) {
	$ZoneRemoved{$Zone}++;
    }
    elsif ( ($Host) = ( $ThisLine =~ /^([^ ]+) has CNAME and other data \(invalid\)/ ) ) {
	push @CNAMEAndOther, $Host;
    }
    elsif ( ($Way,$Host) = ( $ThisLine =~ /^([^ ]+): sendto\(\[([^ ]+)\].+\): Network is unreachable/ ) ) {
	$FullHost = LookupIP ($Host);
	$NetworkUnreachable{$Way}{$FullHost}++;
    }
    elsif ( ($Host,$Zone) = ( $ThisLine =~ /approved AXFR from \[(.+)\]\..+ for \"(.+)\"/ ) ) {
	$FullHost = LookupIP ($Host);
   $AXFR{$Zone}{$FullHost}++;
    }
    else {
	# Report any unmatched entries...
	#push @OtherList,$ThisLine;
	chomp($ThisLine);
        $OtherList{$ThisLine}++;
    }
}

if ( ( ($Detail >= 5) and (keys %ZoneLoaded) ) or
     ( ($Detail >= 5) and ($StartNamed) ) or
     ( ($Detail >= 5) and ($ReloadNamed) ) or
     ( ($Detail >= 5) and ($ShutdownNamed) ) or
     ( ($Detail >= 5) and (keys %AXFR) ) or
     ( ($Detail >= 10) and (@CNAMEAndOther) ) or
     ( ($Detail >= 10) and (keys %LameServer) ) or
     ( ($Detail >= 10) and (keys %NetworkUnreachable) ) or
     ( keys %OtherList ) 
     ) {

    print "\n\n --------------------- Named Begin ------------------------ \n";
    
    if ( ( $Detail >= 5 ) and ($StartNamed) ) {
	print "Named started: $StartNamed Time(s)\n";
    }
    if ( ( $Detail >= 5 ) and ($ReloadNamed) ) {
	print "Named reloaded: $ReloadNamed Time(s)\n";
    }
    if ( ( $Detail >= 5 ) and ($ShutdownNamed) ) {
	print "Named shutdown: $ShutdownNamed Time(s)\n";
    }
    if ( ( $Detail >= 5 ) and (keys %ZoneLoaded) ) {
	print "\nLoaded Zones:\n";
	foreach $ThisOne (sort {$a cmp $b} keys %ZoneLoaded) {
	    print "   " . $ThisOne . ": " . $ZoneLoaded{$ThisOne} . " Time(s)\n";
	}
    }
    if ( ( $Detail >= 5 ) and (keys %ZoneRemoved) ) {
	print "\nRemoved Zones:\n";
	foreach $ThisOne (sort {$a cmp $b} keys %ZoneRemoved) {
	    print "   " . $ThisOne . ": " . $ZoneRemoved{$ThisOne} . " Time(s)\n";
	}
    }

    if ( ( $Detail >= 5 ) and (keys %AXFR) ) {
	print "\nZone Transfers:\n";
	foreach $ThisOne (keys %AXFR) {
	    print "   Zone: " . $ThisOne . "\n";
       foreach $Temp (keys %{$AXFR{$ThisOne}}) {
         print "      by " . $Temp . ": " . $AXFR{$ThisOne}{$Temp} . " Time(s)\n";
	    }
	}
    }

    if ( ( $Detail >= 10 ) and (@CNAMEAndOther) ) {
	print "\nThese hosts have CNAME and other data (invalid):\n";
	foreach $ThisOne (@CNAMEAndOther) {
	    print "   " . $ThisOne . "\n";
	}
    }
    if ( ( $Detail >= 10 ) and (keys %LameServer) ) {
   print "\nThese addresses had lame server references:\n";
   foreach $ThisOne (keys %LameServer) {
       print "   " . $ThisOne . ": " . $LameServer{$ThisOne} . " Time(s)\n";
    }
      }
    if ( ( $Detail >= 10 ) and (keys %NetworkUnreachable) ) {
	print "\nNetwork is unreachable for:\n";
	foreach $ThisOne (sort {$a cmp $b} keys %NetworkUnreachable) {
	    print "   " . $ThisOne . ":\n";
	    foreach $Host (sort {$a cmp $b} keys %{$NetworkUnreachable{$ThisOne}}) {
		print "      " . $Host . ": $NetworkUnreachable{$ThisOne}{$Host} Time(s)\n";
	    } 
	}
    }
    if (keys %OtherList) {
	print "\n**Unmatched Entries**\n";
        foreach $line (sort {$a cmp $b} keys %OtherList) {
	    print "   $line: $OtherList{$line} Time(s)\n";
	}
    }
    
    print "\n\n ---------------------- Named End ------------------------- \n\n";

}
    
exit(0);
    


