[BUGFIX] Check default salting method first 92/26692/5
authorMarkus Klein <klein.t3@mfc-linz.at>
Wed, 8 Jan 2014 13:11:07 +0000 (14:11 +0100)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Wed, 26 Mar 2014 23:39:04 +0000 (00:39 +0100)
Prioritise default salting hashing method when determining
the salting hashing method of a given salted hash.

Fixes rare cases when the method "isValidSaltedPW()" returns TRUE
for similar salting implementations.

Resolves: #54833
Releases: 6.2
Change-Id: I58eb214f171de9f285a7818edebd925eb8164888
Reviewed-on: https://review.typo3.org/26692
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Jigal van Hemert
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
typo3/sysext/saltedpasswords/Classes/Salt/SaltFactory.php
typo3/sysext/saltedpasswords/Classes/Utility/ExtensionManagerConfigurationUtility.php
typo3/sysext/saltedpasswords/Classes/Utility/SaltedPasswordsUtility.php

index 43864a7..778ae3b 100644 (file)
@@ -50,14 +50,25 @@ class SaltFactory {
         * @return array
         */
        static public function getRegisteredSaltedHashingMethods() {
-               return array_merge(
-                       static::getDefaultSaltMethods(),
-                       (array) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods']
-               );
+               $saltMethods = static::getDefaultSaltMethods();
+               if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods'])) {
+                       $configuredMethods = (array)$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods'];
+                       if (count($configuredMethods) > 0) {
+                               if (isset($configuredMethods[0])) {
+                                       // ensure the key of the array is not numeric, but a class name
+                                       foreach ($configuredMethods as $method) {
+                                               $saltMethods[$method] = $method;
+                                       }
+                               } else {
+                                       $saltMethods = array_merge($saltMethods, $configuredMethods);
+                               }
+                       }
+               }
+               return $saltMethods;
        }
 
        /**
-        * Returns an array with default salt methods.
+        * Returns an array with default salt method class names.
         *
         * @return array
         */
@@ -74,23 +85,23 @@ class SaltFactory {
         * Obtains a salting hashing method instance.
         *
         * This function will return an instance of a class that implements
-        * \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt
+        * \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface
         *
         * Use parameter NULL to reset the factory!
         *
-        * @param string $saltedHash (optional) Salted hashed password to determine the type of used method from or NULL to reset the factory
-        * @param string $mode (optional) The TYPO3 mode (FE or BE) saltedpasswords shall be used for
-        * @return \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface An instance of salting hashing method object
+        * @param string|NULL $saltedHash Salted hashed password to determine the type of used method from or NULL to reset to the default type
+        * @param string $mode The TYPO3 mode (FE or BE) saltedpasswords shall be used for
+        * @return SaltInterface An instance of salting hash method class
         */
        static public function getSaltingInstance($saltedHash = '', $mode = TYPO3_MODE) {
                // Creating new instance when
                // * no instance existing
                // * a salted hash given to determine salted hashing method from
                // * a NULL parameter given to reset instance back to default method
-               if (!is_object(self::$instance) || !empty($saltedHash) || is_NULL($saltedHash)) {
+               if (!is_object(self::$instance) || !empty($saltedHash) || $saltedHash === NULL) {
                        // Determine method by checking the given hash
                        if (!empty($saltedHash)) {
-                               $result = self::determineSaltingHashingMethod($saltedHash);
+                               $result = self::determineSaltingHashingMethod($saltedHash, $mode);
                                if (!$result) {
                                        self::$instance = NULL;
                                }
@@ -109,14 +120,20 @@ class SaltFactory {
         * Method implicitly sets the instance of the found method object in the class property when found.
         *
         * @param string $saltedHash
+        * @param string $mode (optional) The TYPO3 mode (FE or BE) saltedpasswords shall be used for
         * @return boolean TRUE, if salting hashing method has been found, otherwise FALSE
         */
-       static public function determineSaltingHashingMethod($saltedHash) {
-               $methodFound = FALSE;
+       static public function determineSaltingHashingMethod($saltedHash, $mode = TYPO3_MODE) {
                $registeredMethods = static::getRegisteredSaltedHashingMethods();
+               $defaultClassName = \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::getDefaultSaltingHashingMethod($mode);
+               $defaultReference = $registeredMethods[$defaultClassName];
+               unset($registeredMethods[$defaultClassName]);
+               // place the default method first in the order
+               $registeredMethods = array($defaultClassName => $defaultReference) + $registeredMethods;
+               $methodFound = FALSE;
                foreach ($registeredMethods as $method) {
                        $objectInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($method);
-                       if ($objectInstance instanceof \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface) {
+                       if ($objectInstance instanceof SaltInterface) {
                                $methodFound = $objectInstance->isValidSaltedPW($saltedHash);
                                if ($methodFound) {
                                        self::$instance = $objectInstance;
index ab6679e..f2d5042 100644 (file)
@@ -26,6 +26,7 @@ namespace TYPO3\CMS\Saltedpasswords\Utility;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Core\Messaging\FlashMessage;
 
 /**
  * class providing configuration checks for saltedpasswords.
@@ -38,7 +39,7 @@ class ExtensionManagerConfigurationUtility {
        /**
         * @var integer
         */
-       protected $errorType = \TYPO3\CMS\Core\Messaging\FlashMessage::OK;
+       protected $errorType = FlashMessage::OK;
 
        /**
         * @var string
@@ -56,6 +57,11 @@ class ExtensionManagerConfigurationUtility {
        protected $problems = array();
 
        /**
+        * @var array
+        */
+       protected $extConf = array();
+
+       /**
         * Set the error level if no higher level
         * is set already
         *
@@ -65,28 +71,28 @@ class ExtensionManagerConfigurationUtility {
        private function setErrorLevel($level) {
                switch ($level) {
                        case 'error':
-                               $this->errorType = \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR;
+                               $this->errorType = FlashMessage::ERROR;
                                $this->header = 'Errors found in your configuration';
                                $this->preText = 'SaltedPasswords will not work until these problems have been resolved:<br />';
                                break;
                        case 'warning':
-                               if ($this->errorType < \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR) {
-                                       $this->errorType = \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING;
+                               if ($this->errorType < FlashMessage::ERROR) {
+                                       $this->errorType = FlashMessage::WARNING;
                                        $this->header = 'Warnings about your configuration';
                                        $this->preText = 'SaltedPasswords might behave different than expected:<br />';
                                }
                                break;
                        case 'info':
-                               if ($this->errorType < \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING) {
-                                       $this->errorType = \TYPO3\CMS\Core\Messaging\FlashMessage::INFO;
+                               if ($this->errorType < FlashMessage::WARNING) {
+                                       $this->errorType = FlashMessage::INFO;
                                        $this->header = 'Additional information';
                                        $this->preText = '<br />';
                                }
                                break;
                        case 'ok':
                                // TODO: Remove INFO condition as it has lower importance
-                               if ($this->errorType < \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING && $this->errorType != \TYPO3\CMS\Core\Messaging\FlashMessage::INFO) {
-                                       $this->errorType = \TYPO3\CMS\Core\Messaging\FlashMessage::OK;
+                               if ($this->errorType < FlashMessage::WARNING && $this->errorType != FlashMessage::INFO) {
+                                       $this->errorType = FlashMessage::OK;
                                        $this->header = 'No errors were found';
                                        $this->preText = 'SaltedPasswords has been configured correctly and works as expected.<br />';
                                }
@@ -107,7 +113,7 @@ class ExtensionManagerConfigurationUtility {
        <li>###PROBLEMS###</li>
 </ul>';
                        $message = str_replace('###PROBLEMS###', implode('<br />&nbsp;</li><li>', $this->problems), $message);
-                       if ($this->errorType > \TYPO3\CMS\Core\Messaging\FlashMessage::OK) {
+                       if ($this->errorType > FlashMessage::OK) {
                                $message .= '<br />
 Note, that a wrong configuration might have impact on the security of
 your TYPO3 installation and the usability of the backend.';
@@ -145,7 +151,7 @@ your TYPO3 installation and the usability of the backend.';
                $this->init();
                $extConf = $this->extConf['BE'];
                // The backend is called over SSL
-               $SSL = ($GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] > 0 ? TRUE : FALSE) && $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'] != 'superchallenged';
+               $SSL = $GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] > 0 && $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'] != 'superchallenged';
                $rsaAuthLoaded = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('rsaauth');
                // SSL configured?
                if ($SSL) {
@@ -227,7 +233,8 @@ It is not possible to set "updatePasswd" and "forceSalted" at the same time.
 Please disable either one of them.';
                }
                // Check if the configured hash-method is available on system
-               if (!($instance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, 'BE') || !$instance->isAvailable())) {
+               $instance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, 'BE');
+               if ($instance === NULL || !$instance->isAvailable()) {
                        $this->setErrorLevel('error');
                        $problems[] = 'The selected method for hashing your salted passwords is not available on this
 system! Please check your configuration.';
@@ -262,6 +269,7 @@ system! Please check your configuration.';
        public function checkConfigurationFrontend(array $params, $pObj) {
                $this->init();
                $extConf = $this->extConf['FE'];
+               $problems = array();
                if ($extConf['enabled']) {
                        // Inform the user if securityLevel in FE is challenged or blank --> extension won't work
                        if (!\TYPO3\CMS\Core\Utility\GeneralUtility::inList('normal,rsa', $GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel'])) {
index 5fec69b..c00467d 100644 (file)
@@ -40,6 +40,7 @@ class SaltedPasswordsUtility {
         * Keeps this extension's key.
         */
        const EXTKEY = 'saltedpasswords';
+
        /**
         * Calculates number of backend users, who have no saltedpasswords
         * protection.
@@ -87,8 +88,8 @@ class SaltedPasswordsUtility {
         */
        public function feloginForgotPasswordHook(array &$params, \TYPO3\CMS\Felogin\Controller\FrontendLoginController $pObj) {
                if (self::isUsageEnabled('FE')) {
-                       $this->objInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance();
-                       $params['newPassword'] = $this->objInstanceSaltedPW->getHashedPassword($params['newPassword']);
+                       $objInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance();
+                       $params['newPassword'] = $objInstanceSaltedPW->getHashedPassword($params['newPassword']);
                }
        }