#!/usr/bin/perl -w
use strict;
use Socket;
use Time::Local;

my $distinctports=20; #Number of distinct ports scaned to count as a port scan
my $displayportsscanned=0; #When displaying Port Scans, Do we display the ports that are scanned?

my ($num,$cnt,$name);
my @filelist=(
"testlogs/messages",
"testlogs/messages.1",
"testlogs/messages.2",
"testlogs/messages.3",
"testlogs/messages.4");
my ($date_month,$date_day,$time_hour,$time_min,$time_sec);
my (%date,%chain,%action,%interface,%protocol,%sIP,%sPORT,%dIP,%dPORT);
$cnt=0;
	
my ($sec,$min,$hour,$mday,$currmon,$curryear,$wday,$yday,$isdst) = localtime(time);


	
foreach my $file (@filelist){
	open (FILE,$file)or die("can't open $file");
	print "\nAnalyzing File: $file\n";
	while(<FILE>){
		if(m/^(.+?)\s+(\d+) (\d+):(\d+):(\d+) (.+?) kernel: Packet log: (.+?) (.+?) (.+?) PROTO=(\d+?) (.+?):(\d+?) (.+?):(\d+?) .+?$/){
			$date_month=$1;
			$date_day=$2;
			$time_hour=$3;
			$time_min=$4;
			$time_sec=$5;
			$date{$cnt}=getutctime($date_month,$date_day,$time_hour,$time_min,$time_sec,$curryear,$currmon);
			#$server{$cnt}=$6
			$chain{$cnt}=$7;
			$action{$cnt}=$8;
			$interface{$cnt}=$9;
			$protocol{$cnt}=$10;
			$sIP{$cnt}=$11;
			$sPORT{$cnt}=$12;
			$dIP{$cnt}=$13;
			$dPORT{$cnt}=$14;
			$cnt++;
		}
		}
	}
	


#for (my $i=0;$i<$cnt;$i++){
#	print $date_month{$i}," ",$date_day{$i}," ",$date_time{$i}," ";
#	print $chain{$i}," ",$action{$i}," ",$interface{$i}," ",$protocol{$i}," ",$sIP{$i},":",$sPORT{$i}," ",$dIP{$i},":",$dPORT{$i},"\n";
#	}

######## Look for port scans
print "######################################## Port Scans ########################################\n";
my ($w,$ins,$ins2);
foreach my $i (retuvalues(%sIP)){
	$ins=numofi($i,%sIP);
	next if ($ins <=$distinctports);
	print "\n",$i," is suspect.\n";
	my $numofports;
	my @keysofcomp=keyswithvalue($i,%sIP);
	my %dIP_ps;
	foreach $w (@keysofcomp){
		$dIP_ps{$w}=$dIP{$w};
		}
	
	foreach $w (retuvalues(%dIP_ps)){
		my @keysofcomp_ipsubset = keyswithvalue($w,%dIP_ps);
		
		my @portsscaned = @dPORT{@keysofcomp_ipsubset};
		
		my @uniqueports = retuvalues_l(@portsscaned);
		$ins2=0;
		foreach my $k (@uniqueports){
			$ins2++;
			}
		
		
		if ($ins2 >= $distinctports){
			print "\t",$w," was scanned on $ins2 Unique Ports.\n";
			print "\t\tDate:     Pkts:$ins   \n";
			if ($displayportsscanned){
				print "\t\tPorts:  ";
				my ($qqq1,$qqq)=(0,0);
				foreach my $k (findportranges(@portsscaned)){
					if (($qqq == 0 )&&($qqq1 ==0)){
						print $k;
						$qqq=1;
						}
					elsif (($qqq == 5)&&($qqq1 == 0)){
						print "\,\t$k\n";
						$qqq=0;
						$qqq1=1;
						}
					elsif ($qqq1 == 0){
						print "\,\t$k";
						$qqq++;
						}
					elsif ($qqq == 0){
						print "\t\t\t$k";
						$qqq=1;
						}
					elsif ($qqq == 5){
						print ",\t$k\n";
						$qqq=0;
						}
					else {
						print "\,\t$k";
						$qqq++;
						}
					}
				}
			}
		else {
			print "\t",$w," was accessed but probally not port scanned.\n";
			print "\t\tDate:     Pkts:$ins   \n";
			print "\t\tPorts:  ";
			my ($qqq1,$qqq)=(0,0);
			foreach my $k (findportranges(@portsscaned)){
				if (($qqq == 0 )&&($qqq1 ==0)){
					print $k;
					$qqq=1;
					}
				elsif (($qqq == 5)&&($qqq1 == 0)){
					print "\,\t$k\n";
					$qqq=0;
					$qqq1=1;
					}
				elsif ($qqq1 == 0){
					print "\,\t$k";
					$qqq++;
					}
				elsif ($qqq == 0){
					print "\t\t\t$k";
					$qqq=1;
					}
				elsif ($qqq == 5){
					print ",\t$k\n";
					$qqq=0;
					}
				else {
					print "\,\t$k";
					$qqq++;
					}
				
				}
			print "\n";
			}
		}
		
	
	
	}



sub keyswithvalue{
	my ($valtomatch,%hash)=@_;
	my @tkeys;
	my ($key,$value);
	while( ($key,$value) = each(%hash)){
		if ($value eq $valtomatch){
			push(@tkeys,$key);
			}
		}
	return @tkeys;
	}
	

sub retuvalues{
	my %orighash=@_;
	my @uvals=();
	my @vals=values(%orighash);
	my $prev="";
	@vals = sort(@vals);
	foreach my $i (@vals){
		if ($i ne $prev){
			$prev=$i;
			push(@uvals,$i);
			}
		}
	return @uvals;
	}

sub retuvalues_l{
	my @vals=@_;
	my @uvals=();
	my $prev="";
	@vals = sort(@vals);
	foreach my $i (@vals){
		if ($i ne $prev){
			$prev=$i;
			push(@uvals,$i);
			}
		}
	return @uvals;
	}

sub numofi{
	my ($valuetomatch,%hash)=@_;
	my @vals=values(%hash);
	my $cnt=0;
	foreach my $i (@vals){
		if ($i eq $valuetomatch){
			$cnt++;
			}
		}
	return $cnt;
	}

sub findportranges{
	my @list1=@_;
	my @ret;
	my @list=sort {$a <=> $b} @list1;
	my ($lowval,$prevval)=($list[0],$list[0]);
	foreach my $i (@list){
		if ($i <= $prevval+1){
			$prevval=$i;
			}
		else {
			if ($lowval eq $prevval){
				push(@ret,"$lowval");
				}
			else {
				push(@ret,"$lowval\-$prevval");
				}
			($lowval,$prevval)=($i,$i);
			}
		}
	if ($lowval eq $prevval){
		push(@ret,"$lowval");
		}
	else {
		push(@ret,"$lowval\-$prevval");
		}
	return(@ret);
	}	

sub getutctime{
	my ($month,$day,$hour,$min,$sec,$curryear,$currmon)=@_;
	my $year;
	
	if ($month eq "Jan") {$month=0;}
	elsif ($month eq "Feb") {$month=1;}
	elsif ($month eq "Mar") {$month=2;}
	elsif ($month eq "Apr") {$month=3;}
	elsif ($month eq "May") {$month=4;}
	elsif ($month eq "Jun") {$month=5;}
	elsif ($month eq "Jul") {$month=6;}
	elsif ($month eq "Aug") {$month=7;}
	elsif ($month eq "Sep") {$month=8;}
	elsif ($month eq "Oct") {$month=9;}
	elsif ($month eq "Nov") {$month=10;}
	elsif ($month eq "Dec") {$month=11;}
	
	if (($currmon==0)&&($month==11)){
		$year=$curryear-1;
		}
	else {
		$year=$curryear;
		}
	return(timelocal($sec,$min,$hour,$day,$month,$year));
	}