[BUGFIX] Prevent saltedpasswords destroying the password
authorXavier Perseguers <xavier@typo3.org>
Wed, 10 Oct 2012 10:48:19 +0000 (12:48 +0200)
committerXavier Perseguers <xavier@typo3.org>
Tue, 16 Oct 2012 06:33:31 +0000 (08:33 +0200)
When a record is using a plain MD5 password, EXT:saltedpasswords will
destroy the password after the second successive edit.

Add check for already temporarily hashed passwords to prevent that.

Change-Id: I487cbb335616c1d378a704845d5cc96e4ad6cb62
Fixes: #41828
Releases: 4.5, 4.6, 4.7, 6.0
Reviewed-on: http://review.typo3.org/15478
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
Reviewed-by: Xavier Perseguers
Tested-by: Xavier Perseguers
typo3/sysext/saltedpasswords/Classes/Evaluation/Evaluator.php
typo3/sysext/saltedpasswords/tests/Unit/Evaluation/EvaluatorTest.php [new file with mode: 0644]

index d871d96..acdf661 100644 (file)
@@ -72,14 +72,20 @@ class Evaluator {
                if ($isEnabled) {
                        $set = FALSE;
                        $isMD5 = preg_match('/[0-9abcdef]{32,32}/', $value);
-                       $isSaltedHash = \TYPO3\CMS\Core\Utility\GeneralUtility::inList('$1$,$2$,$2a,$P$', substr($value, 0, 3));
-                       $this->objInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, $this->mode);
+                       $isDeprecatedSaltedHash = \TYPO3\CMS\Core\Utility\GeneralUtility::inList('C$,M$', substr($value, 0, 2));
+                       /** @var $objInstanceSaltedPW \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface */
+                       $objInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, $this->mode);
                        if ($isMD5) {
                                $set = TRUE;
-                               $value = 'M' . $this->objInstanceSaltedPW->getHashedPassword($value);
-                       } elseif (!$isSaltedHash) {
-                               $set = TRUE;
-                               $value = $this->objInstanceSaltedPW->getHashedPassword($value);
+                               $value = 'M' . $objInstanceSaltedPW->getHashedPassword($value);
+                       } else {
+                               // Determine method used for the (possibly) salted hashed password
+                               $tempValue = $isDeprecatedSaltedHash ? substr($value, 1) : $value;
+                               $tempObjInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($tempValue);
+                               if (!is_object($tempObjInstanceSaltedPW)) {
+                                       $set = TRUE;
+                                       $value = $objInstanceSaltedPW->getHashedPassword($value);
+                               }
                        }
                }
                return $value;
diff --git a/typo3/sysext/saltedpasswords/tests/Unit/Evaluation/EvaluatorTest.php b/typo3/sysext/saltedpasswords/tests/Unit/Evaluation/EvaluatorTest.php
new file mode 100644 (file)
index 0000000..1f4be49
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+namespace TYPO3\CMS\Saltedpasswords\Tests\Unit\Evaluation;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2009-2011 Marcus Krause <marcus#exp2009@t3sec.info>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Testcase for SaltedPasswordsUtility
+ *
+ * @author Marcus Krause <marcus#exp2009@t3sec.info>
+ * @package TYPO3
+ * @subpackage tx_saltedpasswords
+ */
+class EvaluatorTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
+
+       /**
+        * Enable backup of global and system variables
+        *
+        * @var boolean
+        */
+       protected $backupGlobals = TRUE;
+
+       /**
+        * @var \TYPO3\CMS\Saltedpasswords\Evaluation\Evaluator
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = $this->getMock('TYPO3\\CMS\\Saltedpasswords\\Evaluation\\Evaluator', array('dummy'));
+               unset($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['saltedpasswords']);
+       }
+
+       /**
+        * @test
+        */
+       public function passwordIsTurnedIntoSaltedString() {
+               $isSet = NULL;
+               $originalPassword = 'password';
+               $saltedPassword = $this->fixture->evaluateFieldValue($originalPassword, '', $isSet);
+               $this->assertTrue($isSet);
+               $this->assertNotEquals($originalPassword, $saltedPassword);
+               $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::inList('$1$,$2$,$2a,$P$', substr($saltedPassword, 0, 3)));
+       }
+
+       /**
+        * @test
+        */
+       public function md5HashIsUpdatedToTemporarySaltedString() {
+               $isSet = NULL;
+               $originalPassword = '5f4dcc3b5aa765d61d8327deb882cf99';
+               $saltedPassword = $this->fixture->evaluateFieldValue($originalPassword, '', $isSet);
+               $this->assertTrue($isSet);
+               $this->assertNotEquals($originalPassword, $saltedPassword);
+               $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($saltedPassword, 'M$'));
+       }
+
+       /**
+        * @test
+        */
+       public function temporarySaltedStringIsNotTouched() {
+               $isSet = NULL;
+               $originalPassword = 'M$P$CibIRipvLfaPlaaeH8ifu9g21BrPjp.';
+               $saltedPassword = $this->fixture->evaluateFieldValue($originalPassword, '', $isSet);
+               $this->assertFalse($isSet);
+               $this->assertSame($originalPassword, $saltedPassword);
+       }
+}
+
+
+?>
\ No newline at end of file