Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"githubPullRequests.ignoredPullRequestBranches": [
"master"
]
}
168 changes: 93 additions & 75 deletions pulledpork.pl
Original file line number Diff line number Diff line change
Expand Up @@ -151,34 +151,34 @@ sub parse_config_file {
my ($FileConf, $Config_val) = @_;
my ($config_line, $Name, $Value);

if (!open(CONFIG, "$FileConf")) {
carp "ERROR: Config file not found : $FileConf\n";
syslogit('err|local0', "FATAL: Config file not found: $FileConf")
if $Syslogging;
exit(1);
}
open(CONFIG, "$FileConf");
while (<CONFIG>) {
$config_line = $_;
chomp($config_line);
$config_line = trim($config_line);
if (($config_line !~ /^#/) && ($config_line ne "")) {
($Name, $Value) = split(/=/, $config_line);
if ($Value =~ /,/ && $Name eq "rule_url") {
push(@{ $$Config_val{$Name} }, split(/,/, $Value));
}
elsif ($Name eq "rule_url") {
push(@{ $$Config_val{$Name} }, split(/,/, $Value))
if $Value;
}
else {
$$Config_val{$Name} = $Value;
}
open my $cfg_fh, '<', $FileConf
or do {
carp "ERROR: Config file not found : $FileConf\n";
syslogit('err|local0', "FATAL: Config file not found: $FileConf")
if $Syslogging;
exit(1);
};

while (my $line = <$cfg_fh>) {
chomp($line);
$config_line = trim($line);
next if $config_line =~ /^\s*#/ || $config_line eq "";

($Name, $Value) = split(/=/, $config_line, 2);
next unless defined $Name; # defensive

$Name = trim($Name);
$Value = defined $Value ? trim($Value) : '';

if ($Name eq 'rule_url' && $Value ne '') {
push @{ $Config_val->{$Name} }, map { trim($_) } split(/,/, $Value);
}
elsif ($Value ne '') {
$Config_val->{$Name} = $Value;
}
}

close(CONFIG);

close $cfg_fh;
}

## Help routine.. display help to stdout then exit
Expand Down Expand Up @@ -1191,7 +1191,6 @@ sub modify_state {
}
}
print "\tDone\n" if !$Quiet;
undef @sid_mod;
}

## iprep control socket!
Expand Down Expand Up @@ -1360,25 +1359,47 @@ sub rule_write {
print "Writing $file....\n" if !$Quiet;
open(WRITE, '>', "$file") || croak "Unable to write $file - $!\n";

#if ( $gid == 1 ) {
foreach my $fn (sort keys %$categories) {
print WRITE "\n\n# ----- Begin $fn Rules Category ----- #\n";
foreach my $gid (sort keys %{ $categories->{$fn} }) {
print WRITE "\n# -- Begin GID:$gid Based Rules -- #\n\n";
foreach my $sid (sort keys %{ $categories->{$fn}{$gid} }) {
next unless defined $$hashref{$gid}{$sid}{'rule'};
if ( $enonly
&& $$hashref{$gid}{$sid}{'rule'}
=~ /^\s*(alert|drop|pass)/)
{
print WRITE $$hashref{$gid}{$sid}{'rule'} . "\n";

# Prefer the stored state when deciding enabled/disabled
my $state = $$hashref{$gid}{$sid}{'state'}; # 0 = disabled/commented, 1 = enabled
my $out_rule = $$hashref{$gid}{$sid}{'rule'} || '';

# Normalise comment/uncomment based on state if it's defined
if (defined $state) {
if ($state == 0) {
# ensure rule is commented, preserve leading whitespace
# transform " alert ..." => " # alert ..."
$out_rule =~ s/^(\s*)/$1# / unless $out_rule =~ /^\s*#/;
# normalize existing forms like " # alert" -> " # alert"
$out_rule =~ s/^(\s*)#\s*/$1# /;
}
else {
# ensure rule is uncommented but preserve leading whitespace
$out_rule =~ s/^(\s*)#\s*/$1/;
}
}
elsif (!$enonly) {
print WRITE $$hashref{$gid}{$sid}{'rule'} . "\n";

# If enonly is requested, use state when available, otherwise fall back to text check
if ($enonly) {
if (defined $state) {
next if $state == 0;
}
else {
next unless $out_rule =~ /^\s*(alert|drop|pass)/i;
}
}

print WRITE $out_rule . "\n";
}
}
}

close(WRITE);
print "\tDone\n" if !$Quiet;
}
Expand Down Expand Up @@ -1602,34 +1623,10 @@ sub changelog {
## Trim it up, loves the trim!
sub trim {
my ($trimmer) = @_;
if ($trimmer) {
$trimmer =~ s/^\s*//;
$trimmer =~ s/\s*$//;
return $trimmer;
}
}

## Does it hurt when I slash you?
sub slash {
my ($operation, $string) = @_;
if ($operation == 0 && $string =~ /\/$/ && $string ne "") {
$string =~ s/\/$//;
}
elsif ($operation == 1 && $string !~ /\/$/ && $string ne "") {
$string = $string . "/";
}
return $string;
}

## Test the intermediate levels with exists to prevent unintended autovivification
sub safe_defined {
my ($h, @keys) = @_;
foreach my $k (@keys) {
return unless ref $h eq 'HASH';
return unless exists $h->{$k};
$h = $h->{$k};
}
return defined $h;
return '' unless defined $trimmer;
$trimmer =~ s/^\s+//;
$trimmer =~ s/\s+$//;
return $trimmer;
}

## uh, yeah
Expand Down Expand Up @@ -2281,7 +2278,37 @@ BEGIN
if ($NoDownload && !$grabonly) {
foreach (@base_url) {
my ($base_url, $rule_file) = split(/\|/, $_);
next if $rule_file =~ /IPBLOCKLIST/;

# Handle IP blocklist entries when running with -n (NoDownload)
if ($rule_file =~ /IPBLOCKLIST/) {
# Try the basename of the URL first (user likely placed this in $temp_path)
my $blfile = basename($base_url);
if (-f $temp_path . $blfile) {
print "\tReading IP Blocklist from $temp_path$blfile\n"
if ($Verbose && !$Quiet);
read_iplist(\%blocklist, $temp_path . $blfile);
$Process = 1;
next;
}

# Fallback: glob for plausible blocklist files placed in temp_path
my @candidates = glob("$temp_path*block*list*");
if (@candidates) {
foreach my $f (@candidates) {
print "\tReading IP Blocklist from $f\n"
if ($Verbose && !$Quiet);
read_iplist(\%blocklist, $f);
}
$Process = 1;
next;
}

carp "No IP blocklist file found in $temp_path for $base_url\n"
if $Verbose && !$Quiet;
next;
}

# existing NoDownload local rules handling follows
if ($base_url =~ /[^labs]\.snort\.org/i) {
$prefix = "VRT-";
unless ($rule_file =~ /snortrules-snapshot-\d{4,6}\.tar\.gz/)
Expand All @@ -2295,18 +2322,9 @@ BEGIN
$rule_file = "snortrules-snapshot-$Snortv.tar.gz";
}
}
croak "file $temp_path/$rule_file does not exist!\n"
unless (-f "$temp_path/$rule_file");
$prefix = "ET-"
if $base_url
=~ /(emergingthreats.net|emergingthreatspro.com)/;
$prefix = "Snort-Community-"
if $base_url =~ /snort\.org.+community/;
rule_extract($rule_file, $temp_path, $Distro,
$arch, $Snort, $Sorules, $ignore_files, $prefix, $Snortv3)
if !$grabonly;
}
}
elsif ($base_url =~ /(emergingthreats.net)/) {
$prefix = "ET-";
}

# Read our rules and stuff them into a hash
if ( ($Output || ($keep_rulefiles && $rule_file_path))
Expand Down