The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#/usr/bin/perl -wT
use 5.006;
use strict;
use warnings;
use HTTPD::ADS;
use IO::Socket::UNIX;
use HTTPD::Log::Filter;
use Compress::Zlib;

#do not run this as root, I specifically split root-privileged code into another module.
#you MUST run this as your Postgresql database username
BEGIN {
  use CGI::Carp qw(cluck  carpout);
  my $logfile="/tmp/LogReader.log";
  die "cannot open log file $logfile for write" if (-e $logfile && ! (-w $logfile));
  open(LOG, ">>$logfile") or die "carp could not open log";
  carpout(\*LOG);
}


our $VERSION = '0.02';

#daemon process waits for events to come in, then puts them in database and analyzes and takes action

my $IDSDatabase="wwwads";
my $IDSDataUser="";
my $IDSDataPassword="";
my $line;

my $gz;
my $loopcount;
my $bytesread;
my $rv;
my %args;
my $apacheids = HTTPD::ADS->new (
				 IDSDataUser => $IDSDataUser,
				 IDSDataPassword   => $IDSDataPassword,
				 IDSDatabase => $IDSDatabase,
				 IDSTimeWindowSize => 7801920
				);
my $logfilter= HTTPD::Log::Filter->new(
				       format              => 'ELF',
				       capture => [ qw(
    host
    ident
    authexclude
    date
    request
    status
    bytes
    referer
    agent
)]);

my $linenumber=0;
my $filename;

#foreach $loopcount ('33'..'86') {
#    $filename = "/var/log/httpd/inside.slavelucy.com-access_log.$loopcount.gz";
foreach $loopcount ('1'..'15') {
  $filename = "/var/log/httpd/www.maturebelles.com-access_log.$loopcount".($loopcount > 1?".gz":"");

  $gz = gzopen($filename, "rb") || die "could not open log file";
  print "$linenumber lines\n";
  print "process $filename\n ";
  for ($bytesread=$gz->gzreadline($line),$linenumber=0; $bytesread > 0; $bytesread=$gz->gzreadline($line),$linenumber++) {
    $rv=$logfilter->filter($line);
    if (!defined $rv) {
      my $time = scalar localtime;
      carp "$time: Invalid log format  in $filename at line $linenumber $!  \n";
      next ;
    }
    
    
    #1st is to put the event in the  database.
    # then can decide what to do  about it.
    # One may think access to protected page w/o specifying username is innocent. Maybe. but it could
    # be that someone trys and then failing to get in launches a brute force attack. So while blank
    # username on its own might be innocent it could be counted with failed login attempts
    # as grounds for "termination with extreme prejuidice" of some hacker
    # or blackholing his ip anyway. But you need data on which to make a decision.
    next unless ($logfilter->status >= 400 && $logfilter->status < 500);
    $apacheids->event_recorder(
			       #				   ip => gethostbyname($logfilter->host),
			       ip => $logfilter->host,
			       request => $logfilter->request,
			       status =>$logfilter->status,
			       referer =>$logfilter->referer,
			       user =>$logfilter->authexclude,
			       time =>$logfilter->date
			      );
    print "$linenumber completed\r";
  }
  ;
}


1;
__END__



=head1 AUTHOR

  Dana Hudes, E<lt>dhudes@networkengineer.bizE<gt>

=head1 SEE ALSO

  L<perl>.

=cut