#!/usr/bin/perl

# sel_to_add.pl, distributed as part of Snortsnarf v020316.1
# Author: James Hoagland, Silicon Defense (hoagland@SiliconDefense.com)
# copyright (c) 2000 by Silicon Defense (http://www.silicondefense.com/)
# Released under GNU General Public License, see the COPYING file included
# with the distribution or http://www.silicondefense.com/software/snortsnarf/
# for details.

# sel_to_add.pl is a CGI script that accepts a SISR configuration file in
#   the field 'configfile', an ip address in 'ip', an end ('src' or 'dest')
#   in 'end', a re-create string in 'sources' suitable
#   for passing to Input::recreate_input_mods(), to produce a HTML
#   form for selecting a portion of the alerts with 'end' 'ip' in 'logs' to
#   add to a labeled alert set.

# Please send complaints, kudos, and especially improvements and bugfixes to
# hoagland@SiliconDefense.com.  As described in GNU General Public License, no
# warranty is expressed for this program.

######################################################################

# avoid needing to refer to SnortSnarf packages as SnortSnarf::*, even if
# that is where they really are:
sub BEGIN { push(@INC,map("$_/SnortSnarf",grep(-d "$_/SnortSnarf",@INC))); }

use CGI;
use Filter;
use SnortFileInput;
use Input;

require "sisr_utils.pl";

# get parameters of the invocation
$input= new CGI;
foreach (@ARGV) {  # simulate field input if running on command line
  $input->param(split('=',$_,2));
}

# print out headers
print $input->header(-header => 'text/html',-expires => '+0d');

$configfile= $input->param('configfile');
$end= $input->param('end');
$ip= $input->param('ip');
$insources= $input->param('sources');
if (defined($insources)) {
    @insources= &Input::recreate_input_mods($insources);
}
$logs= $input->param('logs');
if (defined($logs)) {
    push(@insources, SnortFileInput->new({},['all'],$Filter::true,split(',',$logs)));
}
$include= $input->param('include');

($setfile,$modpath,$defaultname)= &get_config_fields($configfile);

#@alerts= &grab_alerts_of_type($ip,$end,$include,@logs);
@alerts= &Input::grab_alerts_of_type_from_mods($ip,$end,$include,@insources);

print "<HTML><HEAD><TITLE>Add alerts with ",($end eq 'src'?'source':'destination')," $ip</TITLE></HEAD>\n";

($setfile_filename)= &filename($setfile);
print <<">>";
<BODY bgcolor="#E7DEBD">
<H1>Add alerts to a labelled set in $setfile_filename</H1>
Choose the alerts you wish to add to a labelled set and give the set name.  If the set does not already exist, it will be created.<P>
>>

&pipeline_form_start("setifempty2.pl allalertids=\$alertids | extr_alert_ids.pl $insources \$allalertids \%alerts | add_alerts_to_db_set.pl \%alerts \$setname $setfile| add_alert_set_notes_to_anns.pl \%alerts \$setname $setfile| lab_set_view.pl \$setname $setfile",$modpath);

@allalertids=();
foreach $alert (@alerts) {
    push(@allalertids,$alert->id());
}
$allalertids= join(';',@allalertids);

print <<">>";

<INPUT TYPE="checkbox" NAME="allalertids" VALUE="$allalertids" CHECKED></TD> Select all alerts<BR>
<B>-or-</B>
<TABLE BORDER=3>
    <TR>
        <TH>&nbsp;</TH>
        <TH>Alert text</TH>
        <TH>Source</TH>
    </TR>
>>

foreach $alert (@alerts) {      
    $source= $alert->source();
    $source= '(unspecified)' unless defined($source);
    $text= $alert->as_text();
    $text=~ s/\n/<br>/g;
    $id= $alert->id();
    print <<">>"
    <TR>
        <TD ALIGN=right><INPUT TYPE="checkbox" NAME="alertids" VALUE="$id" CHECKED></TD>
        <TD ALIGN=left><code>$text</code></TD>
        <TD ALIGN=CENTER>$source</TD>
    </TR>
>>
}

print <<">>";
</TABLE>
Add to set: <INPUT TYPE="text" NAME="setname" VALUE="$defaultname" SIZE="20"><INPUT TYPE="submit" VALUE="Add/Create"> in $setfile

<INPUT TYPE=hidden NAME="configfile" VALUE="$configfile">
>>

@sel= ();
push(@sel,'general') if $include =~ /g/;
push(@sel,'anomaly reports') if $include =~ /a/;
$sel= join(',',@sel);
print <<">>";

</FORM>
<P>
<BR>
Generated by <EM>$0</EM> from <EM>$insources</EM>, grabbing <EM>$end $ip</EM> and selecting <EM>{$sel}</EM>
</BODY>
</HTML>
>>

sub get_config_fields {
    my($configfile)= shift;
    open(C,"<$configfile") || die "could not open config file \"$configfile\"";
    my($setfile,$modpath,$setname);
    $setfile= $modpath= undef;
    $setname= '';
    while (<C>) {
        if (s/^set-db-loc\s*:\s*//) {
            s/\s+$//;
            $setfile= $_;
            next;
        }
        if (s/^module-path\s*:\s*//) {
            s/\s+$//;
            $modpath= $_;
            next;
        }
        if (s/^set-name-default\s*:\s*//) {
            s/\s+$//;
            $setname= $_;
        }
    }
    close C;
    defined($setfile) || die "could not find labeled set database file \"set-db-loc\" in $configfile";
    defined($modpath) || die "could not find pipeline module path \"module-path\" in $configfile";
    
    if ($setname =~ m:^/:) { # get name from file
        my $namefile= $setname;
        open(F,"<$namefile") || die "could not open $namefile (set-name-default in $configfile) to get default set name from";
        do { $_= <F> } while (defined($_) && /^#/ || /^\s*$/);
        $_= "no-setname-found-in-$namefile" unless defined($_);
        chomp;
        $setname= $_;
        close F;
        my $nextname= $setname;
        if ($nextname =~ s/(\d+)$//) { # should update count in file
            $nextname.= ($1 + 1); # update trailing number part of set name
            if (open(F,">$namefile")) {
                print F "# this is the next default set name:\n$nextname\n";
                close F;
            } else {
                warn "could not update default set name from $setname to $nextname since could not write to file $namefile";
            }
        }
    }
    return ($setfile,$modpath,$setname);
}

sub filename {
    return $_[0] =~ /([^\/]+)$/;
}

1;

# $Id: sel_to_add.pl,v 1.15 2001/10/18 21:42:54 jim Exp $
