aboutsummaryrefslogtreecommitdiffstats
path: root/config/snort-dev/bin/oinkmaster_contrib/addsid.pl
diff options
context:
space:
mode:
Diffstat (limited to 'config/snort-dev/bin/oinkmaster_contrib/addsid.pl')
-rw-r--r--config/snort-dev/bin/oinkmaster_contrib/addsid.pl382
1 files changed, 382 insertions, 0 deletions
diff --git a/config/snort-dev/bin/oinkmaster_contrib/addsid.pl b/config/snort-dev/bin/oinkmaster_contrib/addsid.pl
new file mode 100644
index 00000000..64255d22
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/addsid.pl
@@ -0,0 +1,382 @@
+#!/usr/bin/perl -w
+
+# $Id: addsid.pl,v 1.30 2005/12/31 13:42:46 andreas_o Exp $ #
+
+# Copyright (c) 2004-2006 Andreas Östling <andreaso@it.su.se>
+# 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. Neither the name of the author nor the names of its
+# contributors may be used to endorse or promote products
+# derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "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 COPYRIGHT OWNER OR
+# CONTRIBUTORS 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.
+
+
+use strict;
+
+
+sub get_next_entry($ $ $ $ $ $);
+sub parse_singleline_rule($ $ $);
+sub get_next_available_sid(@);
+
+
+# Set this to the default classtype you want to add, if missing.
+# Set to 0 or "" if you don't want to add a classtype.
+my $CLASSTYPE = "misc-attack";
+
+# If ADD_REV is set to 1, "rev: 1;" will be added to rule if it has no rev.
+# Set to 0 if you don't want to add it.
+my $ADD_REV = 1;
+
+# Minimum SID to add. Normally, the next available SID will be used,
+# unless it's below this value. Only SIDs >= 1000000 are reserved for
+# personal use.
+my $MIN_SID = 1000001;
+
+# Regexp to match the start of a multi-line rule.
+# %ACTIONS% will be replaced with content of $config{actions} later.
+my $MULTILINE_RULE_REGEXP = '^\s*#*\s*(?:%ACTIONS%)'.
+ '\s.*\\\\\s*\n$'; # ';
+
+# Regexp to match a single-line rule.
+my $SINGLELINE_RULE_REGEXP = '^\s*#*\s*(?:%ACTIONS%)'.
+ '\s.+;\s*\)\s*$'; # ';
+
+
+my $USAGE = << "RTFM";
+
+Parse *.rules in one or more directories and add "sid:<sid>;" to
+active rules that don't have any "sid" entry, starting with the next
+available SID after parsing all rules files (but $MIN_SID at minumum).
+Also, "rev:1;" is added to rules without a "rev" entry, and
+"classtype:misc-attack;" is added to rules without a "classtype" entry
+(edit options at the top of $0 if you want to change this).
+
+Usage: $0 <rulesdir> [rulesdir2, ...]
+
+RTFM
+
+
+# Start in verbose mode.
+my $verbose = 1;
+
+my (%all_sids, %active_sids, %config);
+
+my @rulesdirs = @ARGV;
+
+die($USAGE) unless ($#rulesdirs > -1);
+
+$config{rule_actions} = "alert|drop|log|pass|reject|sdrop|activate|dynamic";
+
+$SINGLELINE_RULE_REGEXP =~ s/%ACTIONS%/$config{rule_actions}/;
+$MULTILINE_RULE_REGEXP =~ s/%ACTIONS%/$config{rule_actions}/;
+
+
+# Find out the next available SID.
+my $next_sid = get_next_available_sid(@rulesdirs);
+
+# Avoid seeing possible warnings about broken rules twice.
+$verbose = 0;
+
+# Add sid/rev/classtype to active rules that don't have any.
+foreach my $dir (@rulesdirs) {
+ opendir(RULESDIR, "$dir") or die("could not open \"$dir\": $!\n");
+
+ while (my $file = readdir(RULESDIR)) {
+ next unless ($file =~ /\.rules$/);
+
+ open(OLDFILE, "$dir/$file")
+ or die("could not open \"$dir/$file\": $!\n");
+ my @file = <OLDFILE>;
+ close(OLDFILE);
+
+ open(NEWFILE, ">", "$dir/$file")
+ or die("could not open \"$dir/$file\" for writing: $!\n");
+
+ my ($single, $multi, $nonrule, $msg, $sid);
+ while (get_next_entry(\@file, \$single, \$multi, \$nonrule, \$msg, \$sid)) {
+
+ if (defined($nonrule)) {
+ print NEWFILE "$nonrule";
+ next;
+ }
+
+ $multi = $single unless (defined($multi));
+
+ # Don't care about inactive rules.
+ if ($single =~ /^\s*#/) {
+ print NEWFILE "$multi";
+ next;
+ }
+
+ my $added;
+
+ # Add SID.
+ if ($single !~ /sid\s*:\s*\d+\s*;/) {
+ $added .= "SID $next_sid,";
+ $multi =~ s/\)\s*\n/sid:$next_sid;)\n/;
+ $next_sid++;
+ }
+
+ # Add revision.
+ if ($ADD_REV && $single !~ /rev\s*:\s*\d+\s*;/) {
+ $added .= "rev,";
+ $multi =~ s/\)\s*\n/rev:1;)\n/;
+ }
+
+ # Add classtype.
+ if ($CLASSTYPE && $single !~ /classtype\s*:\s*.+\s*;/) {
+ $added .= "classtype $CLASSTYPE,";
+ $multi =~ s/\)\s*\n/classtype:$CLASSTYPE;)\n/;
+ }
+
+ if (defined($added)) {
+ $added =~ s/,$//;
+ print "Adding $added to rule \"$msg\"\n"
+ if (defined($added));
+ }
+
+ print NEWFILE "$multi";
+ }
+
+ close(NEWFILE);
+ }
+
+ closedir(RULESDIR);
+}
+
+
+
+# Read in *.rules in given directory and return highest SID.
+sub get_next_available_sid(@)
+{
+ my @dirs = @_;
+
+ foreach my $dir (@dirs) {
+ opendir(RULESDIR, "$dir") or die("could not open \"$dir\": $!\n");
+
+ # Only care about *.rules.
+ while (my $file = readdir(RULESDIR)) {
+ next unless ($file =~ /\.rules$/);
+
+ open(OLDFILE, "<$dir/$file") or die("could not open \"$dir/$file\": $!\n");
+ my @file = <OLDFILE>;
+ close(OLDFILE);
+
+ my ($single, $multi, $nonrule, $msg, $sid);
+
+ while (get_next_entry(\@file, \$single, \$multi, \$nonrule, \$msg, \$sid)) {
+ if (defined($single) && defined($sid)) {
+ $all_sids{$sid}++;
+
+ # If this is an active rule add to %active_sids and
+ # warn if it already exists.
+ if ($single =~ /^\s*alert/) {
+ print STDERR "WARNING: duplicate SID: $sid\n"
+ if (exists($active_sids{$sid}));
+ $active_sids{$sid}++
+ }
+ }
+ }
+ }
+ }
+
+ # Sort sids and use highest one + 1, unless it's below MIN_SID.
+ @_ = sort {$a <=> $b} keys(%all_sids);
+ my $sid = pop(@_);
+
+ if (!defined($sid)) {
+ $sid = $MIN_SID
+ } else {
+ $sid++;
+ }
+
+ # If it's below MIN_SID, use MIN_SID instead.
+ $sid = $MIN_SID if ($sid < $MIN_SID);
+
+ return ($sid)
+}
+
+
+
+sub get_next_entry($ $ $ $ $ $)
+{
+ my $arr_ref = shift;
+ my $single_ref = shift;
+ my $multi_ref = shift;
+ my $nonrule_ref = shift;
+ my $msg_ref = shift;
+ my $sid_ref = shift;
+
+ undef($$single_ref);
+ undef($$multi_ref);
+ undef($$nonrule_ref);
+ undef($$msg_ref);
+ undef($$sid_ref);
+
+ my $line = shift(@$arr_ref) || return(0);
+ my $disabled = 0;
+ my $broken = 0;
+
+ # Possible beginning of multi-line rule?
+ if ($line =~ /$MULTILINE_RULE_REGEXP/oi) {
+ $$single_ref = $line;
+ $$multi_ref = $line;
+
+ $disabled = 1 if ($line =~ /^\s*#/);
+
+ # Keep on reading as long as line ends with "\".
+ while (!$broken && $line =~ /\\\s*\n$/) {
+
+ # Remove trailing "\" and newline for single-line version.
+ $$single_ref =~ s/\\\s*\n//;
+
+ # If there are no more lines, this can not be a valid multi-line rule.
+ if (!($line = shift(@$arr_ref))) {
+
+ warn("\nWARNING: got EOF while parsing multi-line rule: $$multi_ref\n")
+ if ($config{verbose});
+
+ @_ = split(/\n/, $$multi_ref);
+
+ undef($$multi_ref);
+ undef($$single_ref);
+
+ # First line of broken multi-line rule will be returned as a non-rule line.
+ $$nonrule_ref = shift(@_) . "\n";
+ $$nonrule_ref =~ s/\s*\n$/\n/; # remove trailing whitespaces
+
+ # The rest is put back to the array again.
+ foreach $_ (reverse((@_))) {
+ unshift(@$arr_ref, "$_\n");
+ }
+
+ return (1); # return non-rule
+ }
+
+ # Multi-line continuation.
+ $$multi_ref .= $line;
+
+ # If there are non-comment lines in the middle of a disabled rule,
+ # mark the rule as broken to return as non-rule lines.
+ if ($line !~ /^\s*#/ && $disabled) {
+ $broken = 1;
+ } elsif ($line =~ /^\s*#/ && !$disabled) {
+ # comment line (with trailing slash) in the middle of an active rule - ignore it
+ } else {
+ $line =~ s/^\s*#*\s*//; # remove leading # in single-line version
+ $$single_ref .= $line;
+ }
+
+ } # while line ends with "\"
+
+ # Single-line version should now be a valid rule.
+ # If not, it wasn't a valid multi-line rule after all.
+ if (!$broken && parse_singleline_rule($$single_ref, $msg_ref, $sid_ref)) {
+
+ $$single_ref =~ s/^\s*//; # remove leading whitespaces
+ $$single_ref =~ s/^#+\s*/#/; # remove whitespaces next to leading #
+ $$single_ref =~ s/\s*\n$/\n/; # remove trailing whitespaces
+
+ $$multi_ref =~ s/^\s*//;
+ $$multi_ref =~ s/\s*\n$/\n/;
+ $$multi_ref =~ s/^#+\s*/#/;
+
+ return (1); # return multi
+ } else {
+ warn("\nWARNING: invalid multi-line rule: $$single_ref\n")
+ if ($config{verbose} && $$multi_ref !~ /^\s*#/);
+
+ @_ = split(/\n/, $$multi_ref);
+
+ undef($$multi_ref);
+ undef($$single_ref);
+
+ # First line of broken multi-line rule will be returned as a non-rule line.
+ $$nonrule_ref = shift(@_) . "\n";
+ $$nonrule_ref =~ s/\s*\n$/\n/; # remove trailing whitespaces
+
+ # The rest is put back to the array again.
+ foreach $_ (reverse((@_))) {
+ unshift(@$arr_ref, "$_\n");
+ }
+
+ return (1); # return non-rule
+ }
+ } elsif (parse_singleline_rule($line, $msg_ref, $sid_ref)) {
+ $$single_ref = $line;
+ $$single_ref =~ s/^\s*//;
+ $$single_ref =~ s/^#+\s*/#/;
+ $$single_ref =~ s/\s*\n$/\n/;
+
+ return (1); # return single
+ } else { # non-rule line
+
+ # Do extra check and warn if it *might* be a rule anyway,
+ # but that we just couldn't parse for some reason.
+ warn("\nWARNING: line may be a rule but it could not be parsed ".
+ "(missing sid or msg?): $line\n")
+ if ($config{verbose} && $line =~ /^\s*alert .+msg\s*:\s*".+"\s*;/);
+
+ $$nonrule_ref = $line;
+ $$nonrule_ref =~ s/\s*\n$/\n/;
+
+ return (1); # return non-rule
+ }
+}
+
+
+
+# From oinkmaster.pl except that this version
+# has been modified so that the sid is *optional*.
+sub parse_singleline_rule($ $ $)
+{
+ my $line = shift;
+ my $msg_ref = shift;
+ my $sid_ref = shift;
+
+ if ($line =~ /$SINGLELINE_RULE_REGEXP/oi) {
+
+ if ($line =~ /\bmsg\s*:\s*"(.+?)"\s*;/i) {
+ $$msg_ref = $1;
+ } else {
+ return (0);
+ }
+
+ if ($line =~ /\bsid\s*:\s*(\d+)\s*;/i) {
+ $$sid_ref = $1;
+# } else {
+# return (0);
+ }
+
+ return (1);
+ }
+
+ return (0);
+}