]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
ids-functions.pl: Use libarchive to extract archives
authorStefan Schantl <stefan.schantl@ipfire.org>
Sat, 30 Mar 2024 11:35:30 +0000 (12:35 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 30 Mar 2024 12:09:14 +0000 (12:09 +0000)
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>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
config/cfgroot/ids-functions.pl

index c29a5151f9f443ff31500bf3d80cbdaee6e0978d..3eb883aa94f558b0f9dba83c52adce21ca181f2f 100644 (file)
@@ -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);
+               });
        }
 }