[Snort-users] Rules ordering question.

Williams Jon WilliamsJon at ...2134...
Thu May 2 07:35:19 EDT 2002


I had several requests off-list for this script, so I'm going to simplify
and post it back to the list.  I'm putting the perl inline since I hate
getting attachments from mailing lists :-)  It works for me using Perl
5.6.1, but it should also work with most Perl versions > 5 if you've got the
Getopt::Long package.  Of course, this is not a product of my employer,
YMMV, it is not a supported product, it carries no warranties, my employer
is not responsible for any problems it may or may not cause, and whatever
other disclaimer the rather severe lawyer standing behind my chair thinks
applies :-)

At any rate, I hope this helps.  I've tried to put in descriptive comments
in case anyone is interested in how my twisted coding style (or lack
thereof) works.

Jon
============================================================================
============== 

#!/usr/bin/perl

### Process commandline options
use Getopt::Long;

my $infile = '';
my $length = '';
my $o      = '';
my $help   = '';
GetOptions('infile=s' => \$infile,
			  'length:i' => \$length,
			  'o'        => \$o,
			  'help'     => \$help);

### Print out help info if user requested or if user is clueless
if ($help || (!$infile))
{
	print "\nUsage: $0 -i <input_file> [-length <line_length>] [-o]
[-help]\n";
	print "   where <input_file> is the Snort rules file to read\n";
	print "         <line_length> is the maximum line length to
output\n";
	print "         -o indicates the alternate rule order
pass->alert->log\n";
	print "         -help prints this help\n\n";
	exit;
} #end of if()

### Set parsing order based on -o option
@order = ('alert','pass','log') unless $o;
@order = ('pass','alert','log') if $o;

read_file($infile);

### Finally, print out the node tree
foreach $n (0..$#order)
{
	print "Printing $order[$n] rules\n" if $debug;
	print_tree($order[$n]);
} #end of foreach()

sub read_file
{
	my $file = shift();
	print "Processing $file\n" if $debug;
	open($file,"$file") || die "Can't read $file: $!\n";
	LINE:
	while(<$file>)
	{
		### Chop off newline and ignore comments and blank lines
		chomp();
		next LINE if /^#/;
		next LINE unless /^\s*(alert|log|pass)/ || $buf;

		### Stop processing this file and call read_file recursively
		###    for include lines
		if (/^\s*include\s+(.+)$/)
		{
			$include = $1;
			read_file($include);
		} #end of if()

		### Break up rule into action, header and options
      if (/\\\s*$/)
		{
			$_ =~ s/\\\s*$//g;
			$buf .= $_;
			print "buf       - $buf\n" if $debug;
			next LINE;
		} #end of if()
		elsif ($buf && /\)\s*$/)
		{
			print "Last Line: $buf\n" if $debug;
			$buf .= $_;
			$lastline = 1;
		} #end of elsif()
		if ($buf && $lastline)
		{
			print "end of buf:    $buf\n" if $debug;
			print "end of buf:    $_\n" if $debug;
			$buf =~ /^(alert|log|pass)\s+([^(]+)\((.+)/i;
			$action = $1;
			$header = $2;
			$options = $3;
		} #end of if()
		else
		{
			/^(alert|log|pass)\s+([^(]+)\((.+)/i;
			$action = $1;
			$header = $2;
			$options = $3;
		} #end of else()
		if ($seen{"$action $header"}++)
		{
			### Populate appropriate array, based on action
			###   This section is for headers that have already
been seen
			push(@{$alert{$header}},$options) if $action eq
'alert';
			push(@{$pass{$header}},$options) if $action eq
'pass';
			push(@{$log{$header}},$options) if $action eq 'log';
		} #end of if()
		else
		{
			### Populate appropriate array, based on action
			###   This section is for headers that haven't
already been seen
			push(@alert_header_array,$header) if $action eq
'alert';
			push(@pass_header_array,$header) if $action eq
'pass';
			push(@log_header_array,$header) if $action eq 'log';
			push(@{$alert{$header}},$options) if $action eq
'alert';
			push(@{$pass{$header}},$options) if $action eq
'pass';
			push(@{$log{$header}},$options) if $action eq 'log';
		} #end of else()
		$buf = '' if $buf && $lastline;
		$lastline  = '' if $lastline;
	} #end of while()
	close($file);
} #end of read_file()

sub print_tree
{
	my $aa = shift();
	### Identify which action array to display
	$arry = \@alert_header_array if $aa eq 'alert';
	$arry = \@pass_header_array if $aa eq 'pass';
	$arry = \@log_header_array if $aa eq 'log';
	
	### Get list of headers for this action type
	foreach $i (0..$#{$arry})
	{
		$header = ${$arry}[$i];
		print "$aa $header\n";
		foreach $j (0..$#{${$aa}{$header}})
		{
			$option = ${${$aa}{$header}}[$j];
			$shortoption = substr($option,0,$length) if $length;
			print "      $option\n" unless $length;
			print "      $shortoption\n" if $length;
		} #end of foreach()
	} #end of foreach()
} #end of print_tree()







More information about the Snort-users mailing list