#!/usr/bin/perl

###
# Parse text-based log files of Snort scan reports, and save them
# to a file in Berkley DB format.

###
# Load necessary libraries.
require "init.pl";


###
# Initialize output scan database.
if (-e $SCANDB) {
    die "Output scan database $SCANDB already exists. Exiting.\n";
}
if (! tie(%SCANDB, "DB_File", $SCANDB)) {
    die "Could not initialize output scan database $SCANDB:\n$!\n";
}


###
# Process every line on STDIN or in files passed on command line.
$counter = 0;
$dbdelim = "|";
while (<>) {

    # Display a message every time a new file is being processed.
    if ($VERBOSE) {
	if ($ARGV eq "-") {
	    $infile = "STDIN";
	} else {
	    $infile = $ARGV;
	}
	if (! $PROCESSED_FILES{$infile}) {
	    warn "Processing $infile...\n";
	    $PROCESSED_FILES{$infile} = 1;
	    sleep(1);
	}
    }

    # Skip empty lines, lines with nothing but stars, and title lines.
    # Also skip lines that don't start with a date, but warn about that.
    next if ((/^\s*\**\s*$/) || (/^\s*Snort Scan Report/));
    if (! /^(May|Jun) [\d ]\d /) {
	warn "No leading date: $_";
	next;
    }

    # Separate the line into meaningful fields.
    chop;
    /^(\w\w\w [\d ]\d \d\d:\d\d:\d\d) (.*) \-\> ([^ ]*) (.*)$/;
    $timestamp = $1;
    $src = $2;
    $dst = $3;
    $details = $4;
    $details =~ s/\s+$//;
    if ($timestamp =~ /^\s*$/) {
	warn "Timestamp empty ([**] $name [**] $details)\n";
	next;
    }
    $timestamp =~ s/^May /05\//;
    $timestamp =~ s/^Jun /06\//;
    $timestamp =~ s/\/([\d ]\d) /\/$1\-/;
    $timestamp .= ".000000";
    if ($src =~ /^\s*$/) {
	warn "Source empty ($timestamp)\n";
	next;
    }
    if ($dst =~ /^\s*$/) {
	warn "Destination empty ($timestamp)\n";
	next;
    }
    ($srchost, $srcport) = split(/:/, $src);
    ($dsthost, $dstport) = split(/:/, $dst);
    if (($srchost =~ /^\s*$/) || ($dsthost =~ /^\s*$/)) {	
	# Hosts cannot be empty, but ports are in some alerts.
	warn "Source or destination host corrupted ($timestamp)\n";
	next;
    }

    # Write alert to the database.
    $SCANDB{$counter++} = $timestamp . $dbdelim . $details . $dbdelim .
	                   $srchost . $dbdelim . $srcport . $dbdelim .
                           $dsthost . $dbdelim . $dstport;
}


###
# Clean up and exit.
untie(%SCANDB);
