This gives us a lot of benefits:
* Speed up the extraction process * More supported archive types due the power of libarchive * Support of passphrase protected archives
It also fixes a problem with non extracted files next to a zero sized file inside an archive.
Fixes #13632.
Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- config/cfgroot/ids-functions.pl | 56 +++++++++++---------------------- 1 file changed, 18 insertions(+), 38 deletions(-)
diff --git a/config/cfgroot/ids-functions.pl b/config/cfgroot/ids-functions.pl index c29a5151f..3eb883aa9 100644 --- a/config/cfgroot/ids-functions.pl +++ b/config/cfgroot/ids-functions.pl @@ -30,7 +30,7 @@ require "${General::swroot}/network-functions.pl"; require "${General::swroot}/suricata/ruleset-sources";
# Load perl module to deal with Archives. -use Archive::Tar; +use Archive::Peek::Libarchive;
# Load perl module to deal with files and path. use File::Basename; @@ -515,9 +515,6 @@ sub downloadruleset ($) { sub extractruleset ($) { my ($provider) = @_;
- # Disable chown functionality when uncompressing files. - $Archive::Tar::CHOWN = "0"; - # Get full path and downloaded rulesfile for the given provider. my $tarball = &_get_dl_rulesfile($provider);
@@ -547,13 +544,11 @@ sub extractruleset ($) {
} elsif ( $type eq "archive") { # Initialize the tar module. - my $tar = Archive::Tar->new($tarball); - - # Get the filelist inside the tarball. - my @packed_files = $tar->list_files; + my $tar = Archive::Peek::Libarchive->new(filename => $tarball);
- # Loop through the filelist. - foreach my $packed_file (@packed_files) { + # Loop through the archive + $tar->iterate( sub { + my ($packed_file, $content) = @_; my $destination;
# Splitt the packed file into chunks. @@ -572,13 +567,13 @@ sub extractruleset ($) { # Handle rules files. } elsif ($file =~ m/.rules$/) { # Skip rule files which are not located in the rules directory or archive root. - next unless(($packed_file =~ /^rules//) || ($packed_file =~ /^$provider-rules//) || ($packed_file !~ ///)); + return unless(($packed_file =~ /^rules//) || ($packed_file =~ /^$provider-rules//) || ($packed_file !~ ///));
# Skip deleted.rules. # # Mostly they have been taken out for correctness or performance reasons and therfore # it is not a great idea to enable any of them. - next if($file =~ m/deleted.rules$/); + return if($file =~ m/deleted.rules$/);
my $rulesfilename;
@@ -615,39 +610,24 @@ sub extractruleset ($) { $destination = "$tmp_rules_directory/$rulesfilename"; } else { # Skip all other files. - next; + return; }
# Check if the destination file exists. unless(-e "$destination") { - # Extract the file to the temporary directory. - $tar->extract_file("$packed_file", "$destination"); + # Open filehandle to write the content to a new file. + open(FILE, ">", "$destination") or die "Could not open $destination. $!\n"; } else { - # Generate temporary file name, located in the temporary rules directory and a suffix of ".tmp". - my $tmp = File::Temp->new( SUFFIX => ".tmp", DIR => "$tmp_rules_directory", UNLINK => 0 ); - my $tmpfile = $tmp->filename(); - - # Extract the file to the new temporary file name. - $tar->extract_file("$packed_file", "$tmpfile"); - - # Open the the existing file. - open(DESTFILE, ">>", "$destination") or die "Could not open $destination. $!\n"; - open(TMPFILE, "<", "$tmpfile") or die "Could not open $tmpfile. $!\n"; - - # Loop through the content of the temporary file. - while (<TMPFILE>) { - # Append the content line by line to the destination file. - print DESTFILE "$_"; - } + # Open filehandle to append the content to the existing file. + open(FILE, ">>", "$destination") or die "Could not open $destination. $!\n"; + }
- # Close the file handles. - close(TMPFILE); - close(DESTFILE); + # Write the extracted file content to the filehandle. + print FILE "$content" if ($content);
- # Remove the temporary file. - unlink("$tmpfile"); - } - } + # Close the file handle. + close(FILE); + }); } }