#!/usr/bin/perl
#
# $Id: File.pm,v 1.3 2004/04/12 16:09:19 bmc Exp $ 
#
# Copyright (C) 2003 Brian Caswell <bmc@shmoo.com>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#       This product includes software developed by Brian Caswell.
# 4. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=head1 NAME

Net::Snort::Parser::File - a module for handling the parsing of snort files

=head1 SYNOPSIS

use Net::Snort::Parser::File;
my (@lines) = parse_file('snort.conf');

=head1 DESCRIPTION

Net::Snort::Parser::File is a module that provides a simple mechanism for handling the include statements that snort supports.

=head1 NOTES

This module does not handle multiline statements.  It should.

=head1 AUTHOR

Brian Caswell <bmc@shmoo.com>

=head1 REPORTING BUGS

Report bugs to <bmc@shmoo.com>

=head1 THANKS

Thanks to The Honeynet Project

=head1 COPYRIGHT

Copyright (c) 2003 Brian Caswell 

=head1 AVAILABILITY

The latest version of this library is likely to be available from CPAN as well as:

http://www.shmoo.com/~bmc/software/snortconfig/

=head1 SEE ALSO

L<snort(8)>

=cut


package Net::Snort::Parser::File;
use Exporter;

use vars qw($VERSION @ISA @EXPORT);
$VERSION = (qw($Revision: 1.3 $))[1];

@ISA    = qw(Exporter);
@EXPORT = qw(parse_file);

$|++;

my $_config = "/home/bmc/snort/snort/etc/snort.conf";
my %variables;

sub parse_file {
   my ($file) = (@_);

   my (@tmp) = split (/\//, $file);
   my $filename = pop (@tmp);

   open(RULES, "<$file") || die "Can't open file $file : $! $?";
   my @lines = <RULES>;
   close(RULES);

   my (@return);

   while (@lines) {
      $_ = shift (@lines);
      chomp;
      if (/^var\s+([^\s]+)\s+(.*)\s*$/) {
         $variables{$1} = $2;
      }

      foreach my $var (keys %variables) {

         # don't care about off by default rulesets for now...
         s/^\s*(\#??\s*include\s+.*)\$$var(.*)/$1$variables{$var}$2/;

         # s/^\s*(include\s+.*)\$$var(.*)/$1$variables{$var}$2/;
      }

      if (/^\s*\#??\s*include\s+(.*)$/) {
         my $next_file = $1;
         my $off;
         $off++ if (/^\s*\#/);
         die "loop?  parsing $next_file twice" if ($seen{$next_file});
         if ($next_file !~ /^\//) {
            my (@path) = split (/\//, $file);
            pop (@path);
            push (@path, $next_file);
            $next_file = join ("/", @path);
         }
         push (@return, parse_file($next_file));
         if ($off) {
            $_ = "# include " . (split (/\//, $next_file))[-1];
         } else {
            $_ = "include " . (split (/\//, $next_file))[-1];
         }
      }
      push (@return, {file => $filename, line => $_});
   }

   return (@return);
}

sub test {
   require Snort::Parser::Rule;
   my (@lines) = parse_file($_config);
   foreach my $line (@lines) {
      $_ = $line->{'line'};
      next if (/^\s*$/);
      my $rule = Snort::Parser::Rule::parse_rule($_);
      if ($rule) {
         print "GOT RULE $line->{'file'} --- $rule->{'name'}\n";
      } else {
         next if (/^\s*#/);
         print "$_\n";
      }
   }
}

1;
