From 8564f82412de9183210e8db7e37afa6066453d4d Mon Sep 17 00:00:00 2001
From: robiscool
Date: Tue, 8 Sep 2009 03:15:14 -0700
Subject: snort-dev, replace snort2c with spoink, replace snort-mysql with
barnyard2, add rule perl scrips, update Gsnort GUI, fix dboot-up issues
---
config/snort-dev/bin/barnyard2 | Bin 0 -> 641791 bytes
.../bin/oinkmaster_contrib/README.contrib | 84 ++
config/snort-dev/bin/oinkmaster_contrib/addmsg.pl | 299 ++++++
config/snort-dev/bin/oinkmaster_contrib/addsid.pl | 382 +++++++
.../bin/oinkmaster_contrib/create-sidmap.pl | 280 ++++++
.../snort-dev/bin/oinkmaster_contrib/makesidex.pl | 261 +++++
config/snort-dev/bin/oinkmaster_contrib/oinkgui.pl | 1046 ++++++++++++++++++++
config/snort-dev/bin/snort2c | Bin 0 -> 13508 bytes
.../pfsense_rules/pfsense_rules.tar.gz.md5 | 1 +
.../pfsense_rules/rules/pfsense-voip.rules | 11 +
config/snort-dev/snort.inc | 98 +-
config/snort-dev/snort.xml | 297 ++++++
config/snort-dev/snort_advanced.xml | 180 ++++
config/snort-dev/snort_alerts.php | 122 +++
config/snort-dev/snort_blocked.php | 143 +++
config/snort-dev/snort_check_for_rule_updates.php | 125 +++
config/snort-dev/snort_define_servers.xml | 364 +++++++
config/snort-dev/snort_download_rules.php | 672 +++++++++++++
config/snort-dev/snort_dynamic_ip_reload.php | 46 +
config/snort-dev/snort_rules.php | 511 ++++++++++
config/snort-dev/snort_rules_edit.php | 207 ++++
config/snort-dev/snort_rulesets.php | 167 ++++
config/snort-dev/snort_threshold.xml | 129 +++
config/snort-dev/snort_whitelist.xml | 129 +++
config/snort-dev/snort_xmlrpc_sync.php | 114 +++
25 files changed, 5658 insertions(+), 10 deletions(-)
create mode 100644 config/snort-dev/bin/barnyard2
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/README.contrib
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/addmsg.pl
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/addsid.pl
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/create-sidmap.pl
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/makesidex.pl
create mode 100644 config/snort-dev/bin/oinkmaster_contrib/oinkgui.pl
create mode 100644 config/snort-dev/bin/snort2c
create mode 100644 config/snort-dev/pfsense_rules/pfsense_rules.tar.gz.md5
create mode 100644 config/snort-dev/pfsense_rules/rules/pfsense-voip.rules
create mode 100644 config/snort-dev/snort.xml
create mode 100644 config/snort-dev/snort_advanced.xml
create mode 100644 config/snort-dev/snort_alerts.php
create mode 100644 config/snort-dev/snort_blocked.php
create mode 100644 config/snort-dev/snort_check_for_rule_updates.php
create mode 100644 config/snort-dev/snort_define_servers.xml
create mode 100644 config/snort-dev/snort_download_rules.php
create mode 100644 config/snort-dev/snort_dynamic_ip_reload.php
create mode 100644 config/snort-dev/snort_rules.php
create mode 100644 config/snort-dev/snort_rules_edit.php
create mode 100644 config/snort-dev/snort_rulesets.php
create mode 100644 config/snort-dev/snort_threshold.xml
create mode 100644 config/snort-dev/snort_whitelist.xml
create mode 100644 config/snort-dev/snort_xmlrpc_sync.php
(limited to 'config/snort-dev')
diff --git a/config/snort-dev/bin/barnyard2 b/config/snort-dev/bin/barnyard2
new file mode 100644
index 00000000..b942e87f
Binary files /dev/null and b/config/snort-dev/bin/barnyard2 differ
diff --git a/config/snort-dev/bin/oinkmaster_contrib/README.contrib b/config/snort-dev/bin/oinkmaster_contrib/README.contrib
new file mode 100644
index 00000000..6923fa26
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/README.contrib
@@ -0,0 +1,84 @@
+# $Id: README.contrib,v 1.21 2005/10/18 10:41:20 andreas_o Exp $ #
+
+-------------------------------------------------------------------------------
+* oinkgui.pl by Andreas Östling
+
+ A graphical front-end to Oinkmaster written in Perl/Tk.
+ See README.gui for complete documentation.
+-------------------------------------------------------------------------------
+
+
+
+-------------------------------------------------------------------------------
+* addsid.pl by Andreas Östling
+
+ A script that parses *.rules in all specified directories and adds a
+ SID to (active) rules that don't have any. (Actually, rev and classtype
+ are also added if missing, unless you edit addsid.pl and tune this.) The
+ script first looks for the current highest SID (even in inactive rules)
+ and starts at the next one, unless this value is below MIN_SID (defined
+ inside addsid.pl). By default, this value is set to 1000001 since this
+ is the lowest SID assigned for local usage. Handles multi-line rules.
+-------------------------------------------------------------------------------
+
+
+
+-------------------------------------------------------------------------------
+* create-sidmap.pl by Andreas Östling
+
+ A script that parses all active rules in *.rules in all specified
+ directories and creates a SID map. (Like Snort's regen-sidmap, but this
+ one handles multi-line rules.) Result goes to standard output which can
+ be redirected to a sid-msg.map file.
+-------------------------------------------------------------------------------
+
+
+
+-------------------------------------------------------------------------------
+* makesidex.pl, originally by Jerry Applebaum but later rewritten by
+ Andreas Östling to handle multi-line rules and
+ multiple rules directories.
+
+ It reads *.rules in all specified directories, looks for all disabled
+ rules and prints a "disablesid # " line for each disabled rule.
+ The output can be appended to oinkmaster.conf.
+ Useful to new Oinkmaster users.
+-------------------------------------------------------------------------------
+
+
+
+-------------------------------------------------------------------------------
+* addmsg.pl by Andreas Östling :
+
+ A script that will parse your oinkmaster.conf for
+ localsid/enablesid/disablesid lines and add their rule message as a #comment.
+ If your oinkmaster.conf looks like this before addmsg.pl has been run:
+
+ disablesid 286
+ disablesid 287
+ disablesid 288
+
+ It will look something like this afterward:
+
+ disablesid 286 # POP3 EXPLOIT x86 bsd overflow
+ disablesid 287 # POP3 EXPLOIT x86 bsd overflow
+ disablesid 288 # POP3 EXPLOIT x86 linux overflow
+
+ addmsg.pl will not touch lines that already has a comment in them.
+ It's not able to handle SID lists when written like this:
+ disablesid 1,2,3, ...
+ But it should handle them if written like this:
+ disablesid \
+ 1, \
+ 2, \
+ 3
+
+ The new config file will be printed to standard output, so you
+ probably want to redirect the output to a file, for example:
+
+ ./addmsg.pl oinkmaster.conf rules/ > oinkmaster.conf.new
+
+ If oinkmaster.conf.new looks ok, simply rename it to oinkmaster.conf.
+ Do NOT redirect to the same file you read from, as this will destroy
+ that file.
+-------------------------------------------------------------------------------
diff --git a/config/snort-dev/bin/oinkmaster_contrib/addmsg.pl b/config/snort-dev/bin/oinkmaster_contrib/addmsg.pl
new file mode 100644
index 00000000..e5866d6f
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/addmsg.pl
@@ -0,0 +1,299 @@
+#!/usr/bin/perl -w
+
+# $Id: addmsg.pl,v 1.19 2005/12/31 13:42:46 andreas_o Exp $ #
+
+# Copyright (c) 2004-2006 Andreas Östling
+# 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($ $ $);
+
+
+my $USAGE = << "RTFM";
+
+Parse Oinkmaster configuration file and add the rule's "msg" string as a
+#comment for each disablesid/enablesid line.
+
+Usage: $0 [rulesdir2, ...]
+
+The new config file will be printed to standard output, so you
+probably want to redirect the output to a new file (*NOT* the same
+file you used as input, because that will destroy the file!).
+For example:
+
+$0 /etc/oinkmaster.conf /etc/rules/ > oinkmaster.conf.new
+
+If oinkmaster.conf.new looks ok, simply rename it to /etc/oinkmaster.conf.
+
+RTFM
+
+
+# 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 $config = shift || die($USAGE);
+
+my @rulesdirs = @ARGV;
+die($USAGE) unless ($#rulesdirs > -1);
+
+my $verbose = 1;
+my (%sidmsgmap, %config);
+
+$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}/;
+
+
+
+# Read in oinkmaster.conf.
+open(CONFIG, "<" , "$config") or die("could not open \"$config\" for reading: $!\n");
+my @config = ;
+close(CONFIG);
+
+
+# Read in *.rules in all rulesdirs and create %sidmsgmap ($sidmsgmap{sid} = msg).
+foreach my $rulesdir (@rulesdirs) {
+ opendir(RULESDIR, "$rulesdir") or die("could not open \"$rulesdir\": $!\n");
+
+ while (my $file = readdir(RULESDIR)) {
+ next unless ($file =~ /\.rules$/);
+
+ open(FILE, "<", "$rulesdir/$file") or die("could not open \"$rulesdir/$file\": $!\n");
+ my @file = ;
+ close(FILE);
+
+ my ($single, $multi, $nonrule, $msg, $sid);
+
+ while (get_next_entry(\@file, \$single, \$multi, \$nonrule, \$msg, \$sid)) {
+ $sidmsgmap{$sid} = $msg
+ if (defined($single));
+ }
+ }
+}
+
+
+# Print new oinkmaster.conf.
+while ($_ = shift(@config)) {
+ if (/^\s*(?:disable|enable|local)sid\s+(\d+)\s*$/ || /^\s*(\d+)\s*,\s*\\$/ || /^\s*(\d+)\s*$/) {
+ my $sid = $1;
+ my $is_multiline = 0;
+ chomp;
+
+ if (/\\$/) {
+ $is_multiline = 1;
+ s/\\$//;
+ }
+
+ $_ = sprintf("%-25s", $_);
+ if (exists($sidmsgmap{$sid})) {
+ print "$_ # $sidmsgmap{$sid}";
+ } else {
+ print "$_";
+ }
+ print " \\" if ($is_multiline);
+ print "\n";
+ } else {
+ print;
+ }
+}
+
+
+
+# From oinkmaster.pl.
+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.
+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);
+}
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
+# 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:;" 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 [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 = ;
+ 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 = ;
+ 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);
+}
diff --git a/config/snort-dev/bin/oinkmaster_contrib/create-sidmap.pl b/config/snort-dev/bin/oinkmaster_contrib/create-sidmap.pl
new file mode 100644
index 00000000..e1ce12ab
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/create-sidmap.pl
@@ -0,0 +1,280 @@
+#!/usr/bin/perl -w
+
+# $Id: create-sidmap.pl,v 1.21 2005/12/31 13:42:46 andreas_o Exp $ #
+
+# Copyright (c) 2004-2006 Andreas Östling
+# 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($ $ $);
+
+# Files to ignore.
+my %skipfiles = (
+ 'deleted.rules' => 1,
+);
+
+# 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 active rules in *.rules in one or more directories and create a SID
+map. Result is sent to standard output, which can be redirected to a
+sid-msg.map file.
+
+Usage: $0 [rulesdir2, ...]
+
+RTFM
+
+my $verbose = 1;
+
+my (%sidmap, %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}/;
+
+
+# Read in all rules from each rules file (*.rules) in each rules dir.
+# into %sidmap.
+foreach my $rulesdir (@rulesdirs) {
+ opendir(RULESDIR, "$rulesdir") or die("could not open \"$rulesdir\": $!\n");
+
+ while (my $file = readdir(RULESDIR)) {
+ next unless ($file =~ /\.rules$/);
+ next if ($skipfiles{$file});
+
+ open(FILE, "$rulesdir/$file") or die("could not open \"$rulesdir/$file\": $!\n");
+ my @file = ;
+ close(FILE);
+
+ my ($single, $multi, $nonrule, $msg, $sid);
+
+ while (get_next_entry(\@file, \$single, \$multi, \$nonrule, \$msg, \$sid)) {
+ if (defined($single)) {
+
+ warn("WARNING: duplicate SID: $sid (discarding old)\n")
+ if (exists($sidmap{$sid}));
+
+ $sidmap{$sid} = "$sid || $msg";
+
+ # Print all references. Borrowed from Brian Caswell's regen-sidmap script.
+ my $ref = $single;
+ while ($ref =~ s/(.*)reference\s*:\s*([^\;]+)(.*)$/$1 $3/) {
+ $sidmap{$sid} .= " || $2"
+ }
+
+ $sidmap{$sid} .= "\n";
+ }
+ }
+ }
+}
+
+# Print results.
+foreach my $sid (sort { $a <=> $b } keys(%sidmap)) {
+ print "$sidmap{$sid}";
+}
+
+
+
+# Same as in oinkmaster.pl.
+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
+ }
+}
+
+
+
+# Same as in oinkmaster.pl.
+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);
+}
diff --git a/config/snort-dev/bin/oinkmaster_contrib/makesidex.pl b/config/snort-dev/bin/oinkmaster_contrib/makesidex.pl
new file mode 100644
index 00000000..80354735
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/makesidex.pl
@@ -0,0 +1,261 @@
+#!/usr/bin/perl -w
+
+# $Id: makesidex.pl,v 1.11 2005/12/31 13:42:46 andreas_o Exp $ #
+
+# Copyright (c) 2004-2006 Andreas Östling
+# 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($ $ $);
+
+
+# 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 look for all rules that are
+disabled (i.e. begin with "#") and print "disablesid # " to
+standard output for all those rules. This output can be redirected to a
+file, which will be understood by Oinkmaster.
+
+Usage: $0 [rulesdir2, ...]
+
+RTFM
+
+my $verbose = 1;
+
+my (%disabled, %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}/;
+
+foreach my $rulesdir (@rulesdirs) {
+ opendir(RULESDIR, "$rulesdir") or die("could not open \"$rulesdir\": $!\n");
+
+ while (my $file = readdir(RULESDIR)) {
+ next unless ($file =~ /\.rules$/);
+
+ open(FILE, "$rulesdir/$file") or die("could not open \"$rulesdir/$file\": $!\n");
+ my @file = ;
+ close(FILE);
+
+ my ($single, $multi, $nonrule, $msg, $sid);
+
+ while (get_next_entry(\@file, \$single, \$multi, \$nonrule, \$msg, \$sid)) {
+ $single = $multi if (defined($multi));
+ $disabled{$sid} = $msg
+ if (defined($single) && $single =~ /^\s*#/);
+ }
+ }
+}
+
+# Print results.
+foreach my $sid (sort { $a <=> $b } keys(%disabled)) {
+ printf("%-25s # %s\n", "disablesid $sid", $disabled{$sid});
+}
+
+
+
+# Same as in oinkmaster.pl.
+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
+ }
+}
+
+
+
+# Same as in oinkmaster.pl.
+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);
+}
diff --git a/config/snort-dev/bin/oinkmaster_contrib/oinkgui.pl b/config/snort-dev/bin/oinkmaster_contrib/oinkgui.pl
new file mode 100644
index 00000000..4e96f7db
--- /dev/null
+++ b/config/snort-dev/bin/oinkmaster_contrib/oinkgui.pl
@@ -0,0 +1,1046 @@
+#!/usr/bin/perl -w
+
+# $Id: oinkgui.pl,v 1.52 2005/12/31 13:42:46 andreas_o Exp $ #
+
+# Copyright (c) 2004-2006 Andreas Östling
+# 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 5.006001;
+
+use strict;
+use File::Spec;
+use Tk;
+use Tk::Balloon;
+use Tk::BrowseEntry;
+use Tk::FileSelect;
+use Tk::NoteBook;
+use Tk::ROText;
+
+use constant CSIDL_DRIVES => 17;
+
+sub update_rules();
+sub clear_messages();
+sub create_cmdline($);
+sub fileDialog($ $ $ $);
+sub load_config();
+sub save_config();
+sub save_messages();
+sub update_file_label_color($ $ $);
+sub create_fileSelectFrame($ $ $ $ $ $);
+sub create_checkbutton($ $ $);
+sub create_radiobutton($ $ $);
+sub create_actionbutton($ $ $);
+sub execute_oinkmaster(@);
+sub logmsg($ $);
+
+
+my $version = 'Oinkmaster GUI v1.1';
+
+my @oinkmaster_conf = qw(
+ /etc/oinkmaster.conf
+ /usr/local/etc/oinkmaster.conf
+);
+
+# List of URLs that will show up in the URL BrowseEntry.
+my @urls = qw(
+ http://www.bleedingsnort.com/bleeding.rules.tar.gz
+ http://www.snort.org/pub-bin/downloads.cgi/Download/comm_rules/Community-Rules.tar.gz
+ http://www.snort.org/pub-bin/oinkmaster.cgi//snortrules-snapshot-CURRENT.tar.gz
+ http://www.snort.org/pub-bin/oinkmaster.cgi//snortrules-snapshot-2.3.tar.gz
+);
+
+my %color = (
+ background => 'Bisque3',
+ button => 'Bisque2',
+ label => 'Bisque1',
+ notebook_bg => 'Bisque2',
+ notebook_inact => 'Bisque3',
+ file_label_ok => '#00e000',
+ file_label_not_ok => 'red',
+ out_frame_fg => 'white',
+ out_frame_bg => 'black',
+ entry_bg => 'white',
+ button_active => 'white',
+ button_bg => 'Bisque4',
+);
+
+my %config = (
+ animate => 1,
+ careful => 0,
+ enable_all => 0,
+ check_removed => 0,
+ output_mode => 'normal',
+ diff_mode => 'detailed',
+ perl => $^X,
+ oinkmaster => "",
+ oinkmaster_conf => "",
+ outdir => "",
+ url => "",
+ varfile => "",
+ backupdir => "",
+ editor => "",
+);
+
+my %help = (
+
+ # File locations.
+ oinkscript => 'Location of the executable Oinkmaster script (oinkmaster.pl).',
+ oinkconf => 'The Oinkmaster configuration file to use.',
+ outdir => 'Where to put the new rules. This should be the directory where you '.
+ 'store your current rules.',
+
+ url => 'Alternate location of rules archive to download/copy. '.
+ 'Leave empty to use the location set in oinkmaster.conf.',
+ varfile => 'Variables that exist in downloaded snort.conf but not in '.
+ 'this file will be added to it. Leave empty to skip.',
+ backupdir => 'Directory to put tarball of old rules before overwriting them. '.
+ 'Leave empty to skip backup.',
+ editor => 'Full path to editor to execute when pressing the "edit" button '.
+ '(wordpad is recommended on Windows). ',
+
+ # Checkbuttons.
+ careful => 'In careful mode, Oinkmaster will just check for changes, '.
+ 'not update anything.',
+ enable => 'Some rules may be commented out by default (for a reason!). '.
+ 'This option will make Oinkmaster enable those.',
+ removed => 'Check for rules files that exist in the output directory but not '.
+ 'in the downloaded rules archive.',
+
+ # Action buttons.
+ clear => 'Clear current output messages.',
+ save => 'Save current output messages to file.',
+ exit => 'Exit the GUI.',
+ update => 'Execute Oinkmaster to update the rules.',
+ test => 'Test current Oinkmaster configuration. ' .
+ 'If there are no fatal errors, you are ready to update the rules.',
+ version => 'Request version information from Oinkmaster.',
+);
+
+
+my $gui_config_file = "";
+my $use_fileop = 0;
+
+
+#### MAIN ####
+
+select STDERR;
+$| = 1;
+select STDOUT;
+$| = 1;
+
+# Find out if can use Win32::FileOp.
+if ($^O eq 'MSWin32') {
+ BEGIN { $^W = 0 }
+ $use_fileop = 1 if (eval "require Win32::FileOp");
+}
+
+# Find out which oinkmaster.pl file to default to.
+foreach my $dir (File::Spec->path()) {
+ my $file = "$dir/oinkmaster";
+ if (-f "$file" && (-x "$file" || $^O eq 'MSWin32')) {
+ $config{oinkmaster} = $file;
+ last;
+ } elsif (-f "$file.pl" && (-x "$file" || $^O eq 'MSWin32')) {
+ $config{oinkmaster} = "$file.pl";
+ last;
+ }
+}
+
+# Find out which oinkmaster config file to default to.
+foreach my $file (@oinkmaster_conf) {
+ if (-e "$file") {
+ $config{oinkmaster_conf} = $file;
+ last;
+ }
+}
+
+# Find out where the GUI config file is (it's not required).
+if ($ENV{HOME}) {
+ $gui_config_file = "$ENV{HOME}/.oinkguirc"
+} elsif ($ENV{HOMEDRIVE} && $ENV{HOMEPATH}) {
+ $gui_config_file = "$ENV{HOMEDRIVE}$ENV{HOMEPATH}\\.oinkguirc";
+}
+
+
+# Create main window.
+my $main = MainWindow->new(
+ -background => "$color{background}",
+ -title => "$version",
+);
+
+
+# Create scrolled frame with output messages.
+my $out_frame = $main->Scrolled('ROText',
+ -setgrid => 'true',
+ -scrollbars => 'e',
+ -background => $color{out_frame_bg},
+ -foreground => $color{out_frame_fg},
+);
+
+
+my $help_label = $main->Label(
+ -relief => 'groove',
+ -background => "$color{label}",
+);
+
+my $balloon = $main->Balloon(
+ -statusbar => $help_label,
+);
+
+
+# Create notebook.
+my $notebook = $main->NoteBook(
+ -ipadx => 6,
+ -ipady => 6,
+ -background => $color{notebook_bg},
+ -inactivebackground => $color{notebook_inact},
+ -backpagecolor => $color{background},
+);
+
+
+# Create tab with required files/dirs.
+my $req_tab = $notebook->add("required",
+ -label => "Required files and directories",
+ -underline => 0,
+);
+
+$req_tab->configure(-bg => "$color{notebook_inact}");
+
+
+# Create frame with oinkmaster.pl location.
+my $filetypes = [
+ ['Oinkmaster script', 'oinkmaster.pl'],
+ ['All files', '*' ]
+];
+
+my $oinkscript_frame =
+ create_fileSelectFrame($req_tab, "oinkmaster.pl", 'EXECFILE',
+ \$config{oinkmaster}, 'NOEDIT', $filetypes);
+
+$balloon->attach($oinkscript_frame, -statusmsg => $help{oinkscript});
+
+
+# Create frame with oinkmaster.conf location.
+$filetypes = [
+ ['configuration files', '.conf'],
+ ['All files', '*' ]
+];
+
+my $oinkconf_frame =
+ create_fileSelectFrame($req_tab, "oinkmaster.conf", 'ROFILE',
+ \$config{oinkmaster_conf}, 'EDIT', $filetypes);
+
+$balloon->attach($oinkconf_frame, -statusmsg => $help{oinkconf});
+
+
+# Create frame with output directory.
+my $outdir_frame =
+ create_fileSelectFrame($req_tab, "output directory", 'WRDIR',
+ \$config{outdir}, 'NOEDIT', undef);
+
+$balloon->attach($outdir_frame, -statusmsg => $help{outdir});
+
+
+
+# Create tab with optional files/dirs.
+my $opt_tab = $notebook->add("optional",
+ -label => "Optional files and directories",
+ -underline => 0,
+);
+
+$opt_tab->configure(-bg => "$color{notebook_inact}");
+
+# Create frame with alternate URL location.
+$filetypes = [
+ ['compressed tar files', '.tar.gz']
+];
+
+my $url_frame =
+ create_fileSelectFrame($opt_tab, "Alternate URL", 'URL',
+ \$config{url}, 'NOEDIT', $filetypes);
+
+$balloon->attach($url_frame, -statusmsg => $help{url});
+
+
+# Create frame with variable file.
+$filetypes = [
+ ['Snort configuration files', ['.conf', '.config']],
+ ['All files', '*' ]
+];
+
+my $varfile_frame =
+ create_fileSelectFrame($opt_tab, "Variable file", 'WRFILE',
+ \$config{varfile}, 'EDIT', $filetypes);
+
+$balloon->attach($varfile_frame, -statusmsg => $help{varfile});
+
+
+# Create frame with backup dir location.
+my $backupdir_frame =
+ create_fileSelectFrame($opt_tab, "Backup directory", 'WRDIR',
+ \$config{backupdir}, 'NOEDIT', undef);
+
+$balloon->attach($backupdir_frame, -statusmsg => $help{backupdir});
+
+
+# Create frame with editor location.
+$filetypes = [
+ ['executable files', ['.exe']],
+ ['All files', '*' ]
+];
+
+my $editor_frame =
+ create_fileSelectFrame($opt_tab, "Editor", 'EXECFILE',
+ \$config{editor}, 'NOEDIT', $filetypes);
+
+$balloon->attach($editor_frame, -statusmsg => $help{editor});
+
+
+
+$notebook->pack(
+ -expand => 'no',
+ -fill => 'x',
+ -padx => '5',
+ -pady => '5',
+ -side => 'top'
+);
+
+
+# Create the frame to the left.
+my $left_frame = $main->Frame(
+ -background => "$color{label}",
+ -border => '2',
+)->pack(
+ -side => 'left',
+ -fill => 'y',
+);
+
+
+# Create "GUI settings" label.
+$left_frame->Label(
+ -text => "GUI settings:",
+ -background => "$color{label}",
+)->pack(
+ -side => 'top',
+ -fill => 'x',
+);
+
+
+create_actionbutton($left_frame, "Load saved settings", \&load_config);
+create_actionbutton($left_frame, "Save current settings", \&save_config);
+
+
+# Create "options" label at the top of the left frame.
+$left_frame->Label(
+ -text => "Options:",
+ -background => "$color{label}",
+)->pack(-side => 'top',
+ -fill => 'x',
+);
+
+
+# Create checkbuttons in the left frame.
+$balloon->attach(
+ create_checkbutton($left_frame, "Careful mode", \$config{careful}),
+ -statusmsg => $help{careful}
+);
+
+$balloon->attach(
+ create_checkbutton($left_frame, "Enable all", \$config{enable_all}),
+ -statusmsg => $help{enable}
+);
+
+$balloon->attach(
+ create_checkbutton($left_frame, "Check for removed files", \$config{check_removed}),
+ -statusmsg => $help{removed}
+);
+
+
+# Create "mode" label.
+$left_frame->Label(
+ -text => "Output mode:",
+ -background => "$color{label}",
+)->pack(
+ -side => 'top',
+ -fill => 'x',
+);
+
+# Create mode radiobuttons in the left frame.
+create_radiobutton($left_frame, "super-quiet", \$config{output_mode});
+create_radiobutton($left_frame, "quiet", \$config{output_mode});
+create_radiobutton($left_frame, "normal", \$config{output_mode});
+create_radiobutton($left_frame, "verbose", \$config{output_mode});
+
+# Create "Diff mode" label.
+$left_frame->Label(
+ -text => "Diff mode:",
+ -background => "$color{label}",
+)->pack(
+ -side => 'top',
+ -fill => 'x',
+);
+
+create_radiobutton($left_frame, "detailed", \$config{diff_mode});
+create_radiobutton($left_frame, "summarized", \$config{diff_mode});
+create_radiobutton($left_frame, "remove common", \$config{diff_mode});
+
+
+# Create "activity messages" label.
+$main->Label(
+ -text => "Output messages:",
+ -width => '130',
+ -background => "$color{label}",
+)->pack(
+ -side => 'top',
+ -fill => 'x',
+);
+
+
+
+# Pack output frame.
+$out_frame->pack(
+ -expand => 'yes',
+ -fill => 'both',
+);
+
+
+# Pack help label below output window.
+$help_label->pack(
+ -fill => 'x',
+);
+
+
+# Create "actions" label.
+$left_frame->Label(
+ -text => "Actions:",
+ -background => "$color{label}",
+)->pack(
+ -side => 'top',
+ -fill => 'x',
+);
+
+
+# Create action buttons.
+
+$balloon->attach(
+ create_actionbutton($left_frame, "Update rules!", \&update_rules),
+ -statusmsg => $help{update}
+);
+
+$balloon->attach(
+ create_actionbutton($left_frame, "Clear output messages", \&clear_messages),
+ -statusmsg => $help{clear}
+);
+
+$balloon->attach(
+ create_actionbutton($left_frame, "Save output messages", \&save_messages),
+ -statusmsg => $help{save}
+);
+
+$balloon->attach(
+ create_actionbutton($left_frame, "Exit", \&exit),
+ -statusmsg => $help{exit}
+);
+
+
+
+# Make the mousewheel scroll the output window. Taken from Mastering Perl/Tk.
+if ($^O eq 'MSWin32') {
+ $out_frame->bind('' =>
+ [ sub { $_[0]->yview('scroll', -($_[1] / 120) * 3, 'units')},
+ Ev('D') ]
+ );
+} else {
+ $out_frame->bind('<4>' => sub {
+ $_[0]->yview('scroll', -3, 'units') unless $Tk::strictMotif;
+ });
+
+ $out_frame->bind('<5>' => sub {
+ $_[0]->yview('scroll', +3, 'units') unless $Tk::strictMotif;
+ });
+}
+
+
+
+# Now the fun begins.
+if ($config{animate}) {
+ foreach (split(//, "Welcome to $version")) {
+ logmsg("$_", 'MISC');
+ $out_frame->after(5);
+ }
+} else {
+ logmsg("Welcome to $version", 'MISC');
+}
+
+logmsg("\n\n", 'MISC');
+
+# Load gui settings into %config.
+load_config();
+
+
+# Warn if any required file/directory is not set.
+logmsg("No oinkmaster.pl set, please select one above!\n\n", 'ERROR')
+ if ($config{oinkmaster} !~ /\S/);
+
+logmsg("No oinkmaster configuration file set, please select one above!\n\n", 'ERROR')
+ if ($config{oinkmaster_conf} !~ /\S/);
+
+logmsg("Output directory is not set, please select one above!\n\n", 'ERROR')
+ if ($config{outdir} !~ /\S/);
+
+
+MainLoop;
+
+
+
+#### END ####
+
+
+
+sub fileDialog($ $ $ $)
+{
+ my $var_ref = shift;
+ my $title = shift;
+ my $type = shift;
+ my $filetypes = shift;
+ my $dirname;
+
+ if ($type eq 'WRDIR') {
+ if ($use_fileop) {
+ $dirname = Win32::FileOp::BrowseForFolder("title", CSIDL_DRIVES);
+ } else {
+ my $fs = $main->FileSelect();
+ $fs->configure(-verify => ['-d', '-w'], -title => $title);
+ $dirname = $fs->Show;
+ }
+ $$var_ref = $dirname if ($dirname);
+ } elsif ($type eq 'EXECFILE' || $type eq 'ROFILE' || $type eq 'WRFILE' || $type eq 'URL') {
+ my $filename = $main->getOpenFile(-title => $title, -filetypes => $filetypes);
+ $$var_ref = $filename if ($filename);
+ } elsif ($type eq 'SAVEFILE') {
+ my $filename = $main->getSaveFile(-title => $title, -filetypes => $filetypes);
+ $$var_ref = $filename if ($filename);
+ } else {
+ logmsg("Unknown type ($type)\n", 'ERROR');
+ }
+}
+
+
+
+sub update_file_label_color($ $ $)
+{
+ my $label = shift;
+ my $filename = shift;
+ my $type = shift;
+
+ $filename =~ s/^\s+//;
+ $filename =~ s/\s+$//;
+
+ unless ($filename) {
+ $label->configure(-background => $color{file_label_not_ok});
+ return (1);
+ }
+
+ if ($type eq "URL") {
+ if ($filename =~ /^(?:http|ftp|scp):\/\/.+\.tar\.gz$/) {
+ $label->configure(-background => $color{file_label_ok});
+ } elsif ($filename =~ /^(?:file:\/\/)*(.+\.tar\.gz)$/) {
+ my $file = $1;
+ if (-f "$file" && -r "$file") {
+ $label->configure(-background => $color{file_label_ok});
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } elsif ($type eq "ROFILE") {
+ if (-f "$filename" && -r "$filename") {
+ $label->configure(-background => $color{file_label_ok});
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } elsif ($type eq "EXECFILE") {
+ if (-f "$filename" && (-x "$filename" || $^O eq 'MSWin32')) {
+ $label->configure(-background => $color{file_label_ok});
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } elsif ($type eq "WRFILE") {
+ if (-f "$filename" && -w "$filename") {
+ $label->configure(-background => $color{file_label_ok});
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } elsif ($type eq "WRDIR") {
+ if (-d "$filename" && -w "$filename") {
+ $label->configure(-background => $color{file_label_ok});
+ } else {
+ $label->configure(-background => $color{file_label_not_ok});
+ }
+ } else {
+ print STDERR "incorrect type ($type)\n";
+ exit;
+ }
+
+ return (1);
+}
+
+
+
+sub create_checkbutton($ $ $)
+{
+ my $frame = shift;
+ my $name = shift;
+ my $var_ref = shift;
+
+ my $button = $frame->Checkbutton(
+ -text => $name,
+ -background => $color{button},
+ -activebackground => $color{button_active},
+ -highlightbackground => $color{button_bg},
+ -variable => $var_ref,
+ -relief => 'raise',
+ -anchor => 'w',
+ )->pack(
+ -fill => 'x',
+ -side => 'top',
+ -pady => '1',
+ );
+
+ return ($button);
+}
+
+
+
+sub create_actionbutton($ $ $)
+{
+ my $frame = shift;
+ my $name = shift;
+ my $func_ref = shift;
+
+ my $button = $frame->Button(
+ -text => $name,
+ -command => sub {
+ &$func_ref;
+ $out_frame->focus;
+ },
+ -background => $color{button},
+ -activebackground => $color{button_active},
+ -highlightbackground => $color{button_bg},
+ )->pack(
+ -fill => 'x',
+ );
+
+ return ($button);
+}
+
+
+
+sub create_radiobutton($ $ $)
+{
+ my $frame = shift;
+ my $name = shift;
+ my $mode_ref = shift;
+
+ my $button = $frame->Radiobutton(
+ -text => $name,
+ -highlightbackground => $color{button_bg},
+ -background => $color{button},
+ -activebackground => $color{button_active},
+ -variable => $mode_ref,
+ -relief => 'raised',
+ -anchor => 'w',
+ -value => $name,
+ )->pack(
+ -side => 'top',
+ -pady => '1',
+ -fill => 'x',
+ );
+
+ return ($button);
+}
+
+
+
+# Create