diff --git a/administrator/components/com_installer/models/install.php b/administrator/components/com_installer/models/install.php index 539730ae91198..aacf9eef037f3 100644 --- a/administrator/components/com_installer/models/install.php +++ b/administrator/components/com_installer/models/install.php @@ -170,6 +170,29 @@ public function install() } } + // Check the package + $children = $installer->manifest->updateservers->children(); + + foreach ($children as $child) + { + $check = JInstallerHelper::isChecksumValid($package['packagefile'], (string) $child); + + switch ($check) + { + case 0: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_WRONG'), 'warning'); + break; + + case 1: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_CORRECT'), 'message'); + break; + + case 2: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_NOT_FOUND'), 'notice'); + break; + } + } + // Was the package unpacked? if (!$package || !$package['type']) { diff --git a/administrator/components/com_installer/models/update.php b/administrator/components/com_installer/models/update.php index e1bbde987e7ee..0d5d58cbd2431 100644 --- a/administrator/components/com_installer/models/update.php +++ b/administrator/components/com_installer/models/update.php @@ -361,7 +361,7 @@ public function update($uids, $minimum_stability = JUpdater::STABILITY_STABLE) $this->preparePreUpdate($update, $instance); // Install sets state and enqueues messages - $res = $this->install($update); + $res = $this->install($update, $instance->detailsurl); if ($res) { @@ -388,13 +388,14 @@ public function update($uids, $minimum_stability = JUpdater::STABILITY_STABLE) /** * Handles the actual update installation. * - * @param JUpdate $update An update definition + * @param JUpdate $update An update definition + * @param string $updateurl Update Server manifest * * @return boolean Result of install * * @since 1.6 */ - private function install($update) + private function install($update, $updateurl) { $app = JFactory::getApplication(); @@ -433,6 +434,22 @@ private function install($update) $installer = JInstaller::getInstance(); $update->set('type', $package['type']); + // Check the package + $check = JInstallerHelper::isChecksumValid($package['packagefile'], (string) $updateurl); + + switch ($check) + { + case 0: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_WRONG'), 'warning'); + break; + case 1: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_CORRECT'), 'message'); + break; + case 2: + $app->enqueueMessage(\JText::_('COM_INSTALLER_INSTALL_CHECKSUM_NOT_FOUND'), 'notice'); + break; + } + // Install the package if (!$installer->update($package['dir'])) { diff --git a/administrator/language/en-GB/en-GB.com_installer.ini b/administrator/language/en-GB/en-GB.com_installer.ini index a0e31bd8676c3..8cda873109710 100644 --- a/administrator/language/en-GB/en-GB.com_installer.ini +++ b/administrator/language/en-GB/en-GB.com_installer.ini @@ -64,6 +64,9 @@ COM_INSTALLER_HEADING_UPDATESITE_NAME_ASC="Update Site ascending" COM_INSTALLER_HEADING_UPDATESITE_NAME_DESC="Update Site descending" COM_INSTALLER_HEADING_UPDATESITEID="ID" COM_INSTALLER_INSTALL_BUTTON="Install" +COM_INSTALLER_INSTALL_CHECKSUM_CORRECT="File Checksum OK" +COM_INSTALLER_INSTALL_CHECKSUM_NOT_FOUND="There were no checksums provided in the package." +COM_INSTALLER_INSTALL_CHECKSUM_WRONG="File Checksum Failed" COM_INSTALLER_INSTALL_DIRECTORY="Install Folder" COM_INSTALLER_INSTALL_ERROR="Error installing %s" COM_INSTALLER_INSTALL_FROM_DIRECTORY="Install from Folder" diff --git a/libraries/src/Installer/InstallerHelper.php b/libraries/src/Installer/InstallerHelper.php index 7523cc69618f0..d64f598c0a42f 100644 --- a/libraries/src/Installer/InstallerHelper.php +++ b/libraries/src/Installer/InstallerHelper.php @@ -25,6 +25,30 @@ */ abstract class InstallerHelper { + /** + * Hash not validated identifier. + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + const HASH_NOT_VALIDATED = 0; + + /** + * Hash validated identifier. + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + const HASH_VALIDATED = 1; + + /** + * Hash not provided identifier. + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + const HASH_NOT_PROVIDED = 2; + /** * Downloads a package * @@ -333,4 +357,46 @@ public static function splitSql($query) return $db->splitSql($query); } + + /** + * Return the result of the checksum of a package with the SHA256/SHA384/SHA512 tags in the update server manifest + * + * @param string $packagefile Location of the package to be installed + * @param Installer $updateServerManifest Update Server manifest + * + * @return integer one if the hashes match, zero if hashes doesn't match, two if hashes not found + * + * @since __DEPLOY_VERSION__ + */ + public static function isChecksumValid($packagefile, $updateServerManifest) + { + $hashes = array("sha256", "sha384", "sha512"); + $hashOnFile = false; + + $update = new \JUpdate; + $update->loadFromXml($updateServerManifest); + + foreach ($hashes as $hash) + { + if ($update->get($hash, false)) + { + $hash_package = hash_file($hash, $packagefile); + $hash_remote = $update->$hash->_data; + + $hashOnFile = true; + + if ($hash_package !== $hash_remote) + { + return self::HASH_NOT_VALIDATED; + } + } + } + + if ($hashOnFile) + { + return self::HASH_VALIDATED; + } + + return self::HASH_NOT_PROVIDED; + } }