#!/usr/bin/perl

###
# Parse text-based log files of Snort alerts, and save them
# to a file in Berkley DB format.

###
# Load necessary libraries.
require "init.pl";


###
# Initialize output alert database.
if (-e $ALERTDB) {
    die "Output alert database $ALERTDB already exists. Exiting.\n";
}
if (! tie(%ALERTDB, "DB_File", $ALERTDB)) {
    die "Could not initialize output alert database $ALERTDB:\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;
	}
    }

    # 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 Alert Report/));
    if (! /^\d\d\/\d\d\-/) {
	warn "No leading date: $_";
	next;
    }

    # Separate the line into meaningful fields.
    chop;
    ($timestamp, $name, $details) = split(/\s*\[\*\*\]\s*/);
    if ($timestamp =~ /^\s*$/) {
	warn "Timestamp empty ([**] $name [**] $details)\n";
	next;
    }
    if ($name =~ /^\s*$/) {
	warn "Alert name empty ($timestamp .. $details)\n";
	next;
    }
    if ($details =~ /^\s*$/) {
	# In some alerts these are empty.
	($src, $dst, $srchost, $srcport, $dsthost, $dstport) = ();
    } else {
	($src, $dst) = split(/ \-> /, $details);
	($srchost, $srcport) = split(/:/, $src);
	($dsthost, $dstport) = split(/:/, $dst);
	if (($srchost =~ /^\s*$/) || ($dsthost =~ /^\s*$/)) {	
	    # Hosts cannot be empty, but ports are in some alerts.
	    warn "Details corrupted ($timestamp)\n";
	    next;
	}
    }

    # Write alert to the database.
    $ALERTDB{$counter++} = $timestamp . $dbdelim . $name . $dbdelim .
	                   $srchost . $dbdelim . $srcport . $dbdelim .
                           $dsthost . $dbdelim . $dstport;
}


###
# Clean up and exit.
untie(%ALERTDB);
