‪TYPO3CMS  9.5
PasswordHashFactory.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
25 {
33  protected static ‪$instance;
34 
45  public function get(string $hash, string $mode): ‪PasswordHashInterface
46  {
47  if ($mode !== 'FE' && $mode !== 'BE') {
48  throw new \InvalidArgumentException('Mode must be either \'FE\' or \'BE\', ' . $mode . ' given.', 1533948312);
49  }
50 
51  $registeredHashClasses = static::getRegisteredSaltedHashingMethods();
52 
53  if (empty(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['className'])
54  || !isset(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'])
55  || !is_array(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'])
56  ) {
57  throw new \LogicException(
58  'passwordHashing configuration of ' . $mode . ' broken',
59  1533949053
60  );
61  }
62  $defaultHashClassName = ‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['className'];
63  $defaultHashOptions = (array)‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'];
64 
65  foreach ($registeredHashClasses as $className) {
66  if ($className === $defaultHashClassName) {
67  $hashInstance = GeneralUtility::makeInstance($className, $defaultHashOptions);
68  } else {
69  $hashInstance = GeneralUtility::makeInstance($className);
70  }
71  if (!$hashInstance instanceof ‪PasswordHashInterface) {
72  throw new \LogicException('Class ' . $className . ' does not implement PasswordHashInterface', 1533818569);
73  }
74  if ($hashInstance->isAvailable() && $hashInstance->isValidSaltedPW($hash)) {
75  return $hashInstance;
76  }
77  }
78  // Do not add the hash to the exception to prevent information disclosure
80  'No implementation found to handle given hash. This happens if the stored hash uses a'
81  . ' mechanism not supported by current server. Follow the documentation link to fix this issue.',
82  1533818591
83  );
84  }
85 
95  public function ‪getDefaultHashInstance(string $mode): ‪PasswordHashInterface
96  {
97  if ($mode !== 'FE' && $mode !== 'BE') {
98  throw new \InvalidArgumentException('Mode must be either \'FE\' or \'BE\', ' . $mode . ' given.', 1533820041);
99  }
100 
101  if (empty(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['className'])
102  || !isset(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'])
103  || !is_array(‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'])
104  ) {
105  throw new \LogicException(
106  'passwordHashing configuration of ' . $mode . ' broken',
107  1533950622
108  );
109  }
110 
111  $defaultHashClassName = ‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['className'];
112  $defaultHashOptions = ‪$GLOBALS['TYPO3_CONF_VARS'][$mode]['passwordHashing']['options'];
113  $availableHashClasses = static::getRegisteredSaltedHashingMethods();
114 
115  if (!in_array($defaultHashClassName, $availableHashClasses, true)) {
117  'Configured default hash method ' . $defaultHashClassName . ' is not registered',
118  1533820194
119  );
120  }
121  $hashInstance = GeneralUtility::makeInstance($defaultHashClassName, $defaultHashOptions);
122  if (!$hashInstance instanceof ‪PasswordHashInterface) {
123  throw new \LogicException(
124  'Configured default hash method ' . $defaultHashClassName . ' is not an instance of PasswordHashInterface',
125  1533820281
126  );
127  }
128  if (!$hashInstance->isAvailable()) {
130  'Configured default hash method ' . $defaultHashClassName . ' is not available. If'
131  . ' the instance has just been upgraded, please log in to the standalone install tool'
132  . ' at typo3/install.php to fix this. Follow the documentation link for more details.',
133  1533822084
134  );
135  }
136  return $hashInstance;
137  }
138 
146  public static function ‪getRegisteredSaltedHashingMethods(): array
147  {
148  $saltMethods = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['availablePasswordHashAlgorithms'];
149  if (!is_array($saltMethods) || empty($saltMethods)) {
150  throw new \RuntimeException('No password hash methods configured', 1533948733);
151  }
152  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods'])) {
153  trigger_error(
154  'Registering additional hash algorithms in $GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'ext/saltedpasswords\'][\'saltMethods\']'
155  . ' has been deprecated. Extend $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'availablePasswordHashAlgorithms\'] instead',
156  E_USER_DEPRECATED
157  );
158  $configuredMethods = (array)‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods'];
159  if (!empty($configuredMethods)) {
160  $saltMethods = array_merge($saltMethods, $configuredMethods);
161  }
162  }
163  return $saltMethods;
164  }
165 
179  public static function ‪getSaltingInstance($saltedHash = '', $mode = TYPO3_MODE)
180  {
181  trigger_error(
182  'This method is obsolete and will be removed in TYPO3 v10.0. Use get() and getDefaultHashInstance() instead.',
183  E_USER_DEPRECATED
184  );
185  // Creating new instance when
186  // * no instance existing
187  // * a salted hash given to determine salted hashing method from
188  // * a NULL parameter given to reset instance back to default method
189  if (!is_object(self::$instance) || !empty($saltedHash) || $saltedHash === null) {
190  // Determine method by checking the given hash
191  if (!empty($saltedHash)) {
192  $result = ‪self::determineSaltingHashingMethod($saltedHash, $mode);
193  if (!$result) {
194  self::$instance = null;
195  }
196  } else {
198  self::$instance = GeneralUtility::makeInstance($classNameToUse);
199  }
200  }
201  return ‪self::$instance;
202  }
203 
214  public static function ‪determineSaltingHashingMethod(string $saltedHash, $mode = TYPO3_MODE): bool
215  {
216  trigger_error(
217  'This method is obsolete and will be removed in TYPO3 v10.0.',
218  E_USER_DEPRECATED
219  );
220  $registeredMethods = static::getRegisteredSaltedHashingMethods();
222  unset($registeredMethods[$defaultClassName]);
223  // place the default method first in the order
224  $registeredMethods = [$defaultClassName => $defaultClassName] + $registeredMethods;
225  $methodFound = false;
226  foreach ($registeredMethods as $method) {
227  $objectInstance = GeneralUtility::makeInstance($method);
228  if ($objectInstance instanceof ‪PasswordHashInterface && $objectInstance->‪isAvailable()) {
229  $methodFound = $objectInstance->isValidSaltedPW($saltedHash);
230  if ($methodFound) {
231  self::$instance = $objectInstance;
232  break;
233  }
234  }
235  }
236  return $methodFound;
237  }
238 
246  public static function ‪setPreferredHashingMethod(string $resource)
247  {
248  trigger_error('This method is obsolete and will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
249  self::$instance = null;
250  $objectInstance = GeneralUtility::makeInstance($resource);
251  if ($objectInstance instanceof ‪PasswordHashInterface) {
252  self::$instance = $objectInstance;
253  }
254  return ‪self::$instance;
255  }
256 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:25
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\determineSaltingHashingMethod
‪static bool determineSaltingHashingMethod(string $saltedHash, $mode=TYPO3_MODE)
Definition: PasswordHashFactory.php:213
‪TYPO3\CMS\Core\Crypto\PasswordHashing
Definition: AbstractComposedSalt.php:3
‪TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException
Definition: InvalidPasswordHashException.php:22
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\$instance
‪static PasswordHashInterface $instance
Definition: PasswordHashFactory.php:32
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\getSaltingInstance
‪static PasswordHashInterface null getSaltingInstance($saltedHash='', $mode=TYPO3_MODE)
Definition: PasswordHashFactory.php:178
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\getRegisteredSaltedHashingMethods
‪static array getRegisteredSaltedHashingMethods()
Definition: PasswordHashFactory.php:145
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\setPreferredHashingMethod
‪static PasswordHashInterface null setPreferredHashingMethod(string $resource)
Definition: PasswordHashFactory.php:245
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory\getDefaultHashInstance
‪PasswordHashInterface getDefaultHashInstance(string $mode)
Definition: PasswordHashFactory.php:94
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashInterface\isAvailable
‪bool isAvailable()
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashInterface
Definition: PasswordHashInterface.php:23
‪TYPO3\CMS\Core\Crypto\PasswordHashing\SaltedPasswordsUtility\getDefaultSaltingHashingMethod
‪static string getDefaultSaltingHashingMethod($mode=TYPO3_MODE)
Definition: SaltedPasswordsUtility.php:104