diff --git a/core/tar-itop.class.inc.php b/core/tar-itop.class.inc.php new file mode 100644 index 000000000..bf46a15d5 --- /dev/null +++ b/core/tar-itop.class.inc.php @@ -0,0 +1,130 @@ + + +require_once(APPROOT.'lib/archivetar/tar.php'); + +/** + * Class ITopArchiveTar + * Custom Combodo code added to the {@link ArchiveTar} class + */ +class ITopArchiveTar extends ArchiveTar +{ + /** + * @param string $p_message + */ + public function _error($p_message) + { + IssueLog::Error($p_message); + } + + /** + * @param string $p_message + */ + public function _warning($p_message) + { + IssueLog::Warning($p_message); + } + + /** + * @param string $p_filename + * @return bool + */ + public function _writeLongHeader($p_filename) + { + $v_uid = sprintf("%07s", 0); + $v_gid = sprintf("%07s", 0); + $v_perms = sprintf("%07s", 0); + $v_size = sprintf("%'011s", DecOct(strlen($p_filename))); + $v_mtime = sprintf("%011s", 0); + $v_typeflag = 'L'; + $v_linkname = ''; + $v_magic = 'ustar '; + $v_version = ' '; + $v_uname = ''; + $v_gname = ''; + $v_devmajor = ''; + $v_devminor = ''; + $v_prefix = ''; + $v_binary_data_first = pack( + "a100a8a8a8a12a12", + '././@LongLink', + $v_perms, + $v_uid, + $v_gid, + $v_size, + $v_mtime + ); + $v_binary_data_last = pack( + "a1a100a6a2a32a32a8a8a155a12", + $v_typeflag, + $v_linkname, + $v_magic, + $v_version, + $v_uname, + $v_gname, + $v_devmajor, + $v_devminor, + $v_prefix, + '' + ); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i = 0; $i < 148; $i++) { + $v_checksum += ord(substr($v_binary_data_first, $i, 1)); + } + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i = 148; $i < 156; $i++) { + $v_checksum += ord(' '); + } + // ..... Last part of the header + for ($i = 156, $j = 0; $i < 512; $i++, $j++) { + $v_checksum += ord(substr($v_binary_data_last, $j, 1)); + } + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%06s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + // ----- Write the filename as content of the block + $i = 0; + while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + return true; + } + + // This is overloaded too but private... + // private function _maliciousFilename($file) + + public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) + { + // This method is modified, but cannot overload it here as it calls the \ArchiveTar::_pathReduction private method + return parent::_addFile($p_filename, $p_header, $p_add_dir, $p_remove_dir, $v_stored_filename); + } +} \ No newline at end of file diff --git a/lib/archivetar/README.md b/lib/archivetar/README.md new file mode 100644 index 000000000..cc80d64c3 --- /dev/null +++ b/lib/archivetar/README.md @@ -0,0 +1,10 @@ +https://github.com/combodo-itop-libs/Archive_Tar +Forked from https://github.com/pear/Archive_Tar + +Base version : a modified v1.4.4 (https://github.com/pear/Archive_Tar/blob/1.4.4/Archive/Tar.php) + +Combodo modifications are inside those comments : +```php +// --- START COMBODO modification +// --- END COMBODO modification +``` diff --git a/setup/tar.php b/lib/archivetar/tar.php similarity index 99% rename from setup/tar.php rename to lib/archivetar/tar.php index ac3e67f7e..050c22cfa 100644 --- a/setup/tar.php +++ b/lib/archivetar/tar.php @@ -680,7 +680,7 @@ class ArchiveTar */ public function _error($p_message) { - IssueLog::Error($p_message); + $this->error_object = $this->raiseError($p_message); } /** @@ -688,7 +688,7 @@ class ArchiveTar */ public function _warning($p_message) { - IssueLog::Warning($p_message); + $this->error_object = $this->raiseError($p_message); } /** @@ -1209,6 +1209,10 @@ class ArchiveTar return false; } + // --- START COMBODO modification + // (see commit 2706ebf6) + // read/write files with a bigger buffer to increase drastically performances + // to still get a valid archive, last bytes are still read/write using a 512 byte buffer $iLen = 1024*1024; while (($v_buffer = fread($v_file, $iLen)) != '') { $iBufferLen = strlen("$v_buffer"); @@ -1224,6 +1228,7 @@ class ArchiveTar $v_binary_data = pack($sPack, "$v_buffer"); $this->_writeBlock($v_binary_data); } + // --- END COMBODO modification fclose($v_file); } else { @@ -1518,28 +1523,34 @@ class ArchiveTar */ public function _writeLongHeader($p_filename) { - $v_uid = sprintf("%07s", 0); - $v_gid = sprintf("%07s", 0); - $v_perms = sprintf("%07s", 0); - $v_size = sprintf("%'011s", DecOct(strlen($p_filename))); - $v_mtime = sprintf("%011s", 0); + $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); + $v_typeflag = 'L'; + $v_linkname = ''; - $v_magic = 'ustar '; - $v_version = ' '; + + $v_magic = ''; + + $v_version = ''; + $v_uname = ''; + $v_gname = ''; + $v_devmajor = ''; + $v_devminor = ''; + $v_prefix = ''; + $v_binary_data_first = pack( "a100a8a8a8a12a12", '././@LongLink', - $v_perms, - $v_uid, - $v_gid, + 0, + 0, + 0, $v_size, - $v_mtime + 0 ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", @@ -1722,6 +1733,7 @@ class ArchiveTar if (strpos($file, 'phar://') === 0) { return true; } + if (strpos($file, '/../') !== false) { return true; } diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index ac71952c0..1eeb0254b 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -16,7 +16,7 @@ // You should have received a copy of the GNU Affero General Public License // along with iTop. If not, see -require_once('tar.php'); +require_once(APPROOT.'core/tar-itop.class.inc.php'); interface BackupArchive { @@ -308,7 +308,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the " { $this->LogInfo("Creating backup: '$sTargetFile.tar.gz'"); - $oArchive = new ArchiveTar($sTargetFile.'.tar.gz'); + $oArchive = new ITopArchiveTar($sTargetFile.'.tar.gz'); $sTmpFolder = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax()); $aFiles = $this->PrepareFilesToBackup($sSourceConfigFile, $sTmpFolder); @@ -710,18 +710,14 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the " class TarGzArchive implements BackupArchive { - /* - * @var ArchiveTar - */ + /** @var \ITopArchiveTar $oArchive */ protected $oArchive; - /* - * string[] - */ + /** @var string[] $aFiles */ protected $aFiles = null; public function __construct($sFile) { - $this->oArchive = new ArchiveTar($sFile); + $this->oArchive = new ITopArchiveTar($sFile); } /**