|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) Marcus Krause (marcus#exp2009@t3sec.info) 00006 * (c) Steffen Ritter (info@rs-websystems.de) 00007 * All rights reserved 00008 * 00009 * This script is part of the TYPO3 project. The TYPO3 project is 00010 * free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * The GNU General Public License can be found at 00016 * http://www.gnu.org/copyleft/gpl.html. 00017 * A copy is found in the textfile GPL.txt and important notices to the license 00018 * from the author is found in LICENSE.txt distributed with these scripts. 00019 * 00020 * 00021 * This script is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * This copyright notice MUST APPEAR in all copies of the script! 00027 ***************************************************************/ 00028 /** 00029 * Contains authentication service class for salted hashed passwords. 00030 * 00031 * $Id: class.tx_saltedpasswords_sv1.php 9758 2010-12-05 11:25:36Z stephenking $ 00032 */ 00033 00034 00035 /** 00036 * Class implements salted-password hashes authentication service. 00037 * 00038 * @author Marcus Krause <marcus#exp2009@t3sec.info> 00039 * @author Steffen Ritter <info@rs-websystems.de> 00040 * 00041 * @since 2009-06-14 00042 * @package TYPO3 00043 * @subpackage tx_saltedpasswords 00044 */ 00045 class tx_saltedpasswords_sv1 extends tx_sv_authbase { 00046 /** 00047 * Keeps class name. 00048 * 00049 * @var string 00050 */ 00051 public $prefixId = 'tx_saltedpasswords_sv1'; 00052 00053 /** 00054 * Keeps path to this script relative to the extension directory. 00055 * 00056 * @var string 00057 */ 00058 public $scriptRelPath = 'sv1/class.tx_saltedpasswords_sv1.php'; 00059 00060 /** 00061 * Keeps extension key. 00062 * 00063 * @var string 00064 */ 00065 public $extKey = 'saltedpasswords'; 00066 00067 /** 00068 * Keeps extension configuration. 00069 * 00070 * @var mixed 00071 */ 00072 protected $extConf; 00073 00074 /** 00075 * An instance of the salted hashing method. 00076 * This member is set in the getSaltingInstance() function. 00077 * 00078 * @var tx_saltedpasswords_abstract_salts 00079 */ 00080 protected $objInstanceSaltedPW = NULL; 00081 00082 /** 00083 * Indicates whether the salted password authentication has failed. 00084 * 00085 * Prevents authentication bypass. See vulnerability report: 00086 * { @link http://bugs.typo3.org/view.php?id=13372 } 00087 * 00088 * @var boolean 00089 */ 00090 protected $authenticationFailed = FALSE; 00091 00092 /** 00093 * Checks if service is available. In case of this service we check that 00094 * following prerequesties are fulfilled: 00095 * - loginSecurityLevel of according TYPO3_MODE is set to normal 00096 * 00097 * @return boolean TRUE if service is available 00098 */ 00099 public function init() { 00100 $available = FALSE; 00101 00102 if (tx_saltedpasswords_div::isUsageEnabled()) { 00103 $available = TRUE; 00104 $this->extConf = tx_saltedpasswords_div::returnExtConf(); 00105 } 00106 00107 return $available ? parent::init() : FALSE; 00108 } 00109 00110 /** 00111 * Checks the login data with the user record data for builtin login method. 00112 * 00113 * @param array user data array 00114 * @param array login data array 00115 * @param string login security level (optional) 00116 * @return boolean TRUE if login data matched 00117 */ 00118 function compareUident(array $user, array $loginData, $security_level = 'normal') { 00119 $validPasswd = FALSE; 00120 00121 // could be merged; still here to clarify 00122 if (!strcmp(TYPO3_MODE, 'BE')) { 00123 $password = $loginData['uident_text']; 00124 } else if (!strcmp(TYPO3_MODE, 'FE')) { 00125 $password = $loginData['uident_text']; 00126 } 00127 00128 // determine method used for given salted hashed password 00129 $this->objInstanceSaltedPW = tx_saltedpasswords_salts_factory::getSaltingInstance($user['password']); 00130 00131 // existing record is in format of Salted Hash password 00132 if (is_object($this->objInstanceSaltedPW)) { 00133 $validPasswd = $this->objInstanceSaltedPW->checkPassword($password,$user['password']); 00134 00135 // record is in format of Salted Hash password but authentication failed 00136 // skip further authentication methods 00137 if (!$validPasswd) { 00138 $this->authenticationFailed = TRUE; 00139 } 00140 00141 $defaultHashingClassName = tx_saltedpasswords_div::getDefaultSaltingHashingMethod(); 00142 $skip = FALSE; 00143 00144 // test for wrong salted hashing method 00145 if ($validPasswd && !(get_class($this->objInstanceSaltedPW) == $defaultHashingClassName) || (is_subclass_of($this->objInstanceSaltedPW, $defaultHashingClassName))) { 00146 // instanciate default method class 00147 $this->objInstanceSaltedPW = tx_saltedpasswords_salts_factory::getSaltingInstance(NULL); 00148 $this->updatePassword( 00149 intval($user['uid']), 00150 array('password' => $this->objInstanceSaltedPW->getHashedPassword($password)) 00151 ); 00152 } 00153 00154 if ($validPasswd && !$skip && $this->objInstanceSaltedPW->isHashUpdateNeeded($user['password'])) { 00155 $this->updatePassword( 00156 intval($user['uid']), 00157 array('password' => $this->objInstanceSaltedPW->getHashedPassword($password)) 00158 ); 00159 } 00160 // we process also clear-text, md5 and passwords updated by Portable PHP password hashing framework 00161 } else if (!intval($this->extConf['forceSalted'])) { 00162 00163 // stored password is in deprecated salted hashing method 00164 if (t3lib_div::inList('C$,M$', substr($user['password'], 0, 2))) { 00165 00166 // instanciate default method class 00167 $this->objInstanceSaltedPW = tx_saltedpasswords_salts_factory::getSaltingInstance(substr($user['password'], 1)); 00168 00169 // md5 00170 if (!strcmp(substr($user['password'], 0, 1), 'M')) { 00171 $validPasswd = $this->objInstanceSaltedPW->checkPassword(md5($password), substr($user['password'], 1)); 00172 } else { 00173 $validPasswd = $this->objInstanceSaltedPW->checkPassword($password, substr($user['password'], 1)); 00174 } 00175 00176 // skip further authentication methods 00177 if (!$validPasswd) { 00178 $this->authenticationFailed = TRUE; 00179 } 00180 00181 // password is stored as md5 00182 } else if (preg_match('/[0-9abcdef]{32,32}/', $user['password'])) { 00183 $validPasswd = (!strcmp(md5($password), $user['password']) ? TRUE : FALSE); 00184 00185 // skip further authentication methods 00186 if (!$validPasswd) { 00187 $this->authenticationFailed = TRUE; 00188 } 00189 00190 // password is stored plain or unrecognized format 00191 } else { 00192 $validPasswd = (!strcmp($password, $user['password']) ? TRUE : FALSE); 00193 } 00194 // should we store the new format value in DB? 00195 if ($validPasswd && intval($this->extConf['updatePasswd'])) { 00196 // instanciate default method class 00197 $this->objInstanceSaltedPW = tx_saltedpasswords_salts_factory::getSaltingInstance(NULL); 00198 $this->updatePassword( 00199 intval($user['uid']), 00200 array('password' => $this->objInstanceSaltedPW->getHashedPassword($password)) 00201 ); 00202 } 00203 } 00204 00205 return $validPasswd; 00206 } 00207 00208 /** 00209 * Method adds a further authUser method. 00210 * 00211 * Will return one of following authentication status codes: 00212 * - 0 - authentication failure 00213 * - 100 - just go on. User is not authenticated but there is still no reason to stop 00214 * - 200 - the service was able to authenticate the user 00215 * 00216 * @param array Array containing FE user data of the logged user. 00217 * @return integer authentication statuscode, one of 0,100 and 200 00218 */ 00219 public function authUser(array $user) { 00220 $OK = 100; 00221 $validPasswd = FALSE; 00222 00223 if ($this->pObj->security_level == 'rsa' && t3lib_extMgm::isLoaded('rsaauth')) { 00224 require_once(t3lib_extMgm::extPath('rsaauth') . 'sv1/backends/class.tx_rsaauth_backendfactory.php'); 00225 require_once(t3lib_extMgm::extPath('rsaauth') . 'sv1/storage/class.tx_rsaauth_storagefactory.php'); 00226 00227 $backend = tx_rsaauth_backendfactory::getBackend(); 00228 $storage = tx_rsaauth_storagefactory::getStorage(); 00229 // Preprocess the password 00230 $password = $this->login['uident']; 00231 $key = $storage->get(); 00232 if ($key != NULL && substr($password, 0, 4) == 'rsa:') { 00233 // Decode password and pass to parent 00234 $decryptedPassword = $backend->decrypt($key, substr($password, 4)); 00235 $this->login['uident_text'] = $decryptedPassword; 00236 } 00237 } 00238 00239 if ($this->login['uident'] && $this->login['uname']) { 00240 if (!empty($this->login['uident_text'])) { 00241 $validPasswd = $this->compareUident( 00242 $user, 00243 $this->login 00244 ); 00245 } 00246 00247 if (!$validPasswd && (intval($this->extConf['onlyAuthService']) || $this->authenticationFailed)) { 00248 // Failed login attempt (wrong password) - no delegation to further services 00249 $this->writeLog( 00250 TYPO3_MODE . ' Authentication failed - wrong password for username \'%s\'', 00251 $this->login['uname'] 00252 ); 00253 $OK = 0; 00254 } else if(!$validPasswd) { 00255 // Failed login attempt (wrong password) 00256 $this->writeLog( 00257 "Login-attempt from %s, username '%s', password not accepted!", 00258 $this->authInfo['REMOTE_ADDR'], $this->login['uname'] 00259 ); 00260 } else if ($validPasswd && $user['lockToDomain'] && strcasecmp($user['lockToDomain'], $this->authInfo['HTTP_HOST'])) { 00261 // Lock domain didn't match, so error: 00262 $this->writeLog( 00263 "Login-attempt from %s, username '%s', locked domain '%s' did not match '%s'!", 00264 $this->authInfo['REMOTE_ADDR'], $this->login['uname'], $user['lockToDomain'], $this->authInfo['HTTP_HOST'] 00265 ); 00266 $OK = 0; 00267 } else if ($validPasswd) { 00268 $this->writeLog( 00269 TYPO3_MODE . ' Authentication successful for username \'%s\'', 00270 $this->login['uname'] 00271 ); 00272 $OK = 200; 00273 } 00274 } 00275 00276 return $OK; 00277 } 00278 00279 /** 00280 * Method updates a FE/BE user record - in this case a new password string will be set. 00281 * 00282 * @param integer $uid: uid of user record that will be updated 00283 * @param mixed $updateFields: Field values as key=>value pairs to be updated in database 00284 * @return void 00285 */ 00286 protected function updatePassword($uid, $updateFields) { 00287 if (TYPO3_MODE === 'BE') { 00288 $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 'be_users', sprintf('uid = %u', $uid), $updateFields); 00289 } else { 00290 $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 'fe_users', sprintf('uid = %u', $uid), $updateFields); 00291 } 00292 00293 t3lib_div::devLog(sprintf('Automatic password update for %s user with uid %u', TYPO3_MODE, $uid), $this->extKey, 1); 00294 } 00295 00296 /** 00297 * Writes log message. Destination log depends on the current system mode. 00298 * For FE the function writes to the admin panel log. For BE messages are 00299 * sent to the system log. If developer log is enabled, messages are also 00300 * sent there. 00301 * 00302 * This function accepts variable number of arguments and can format 00303 * parameters. The syntax is the same as for sprintf() 00304 * 00305 * @param string $message: Message to output 00306 * @return void 00307 * @see sprintf() 00308 * @see t3lib::divLog() 00309 * @see t3lib_div::sysLog() 00310 * @see t3lib_timeTrack::setTSlogMessage() 00311 */ 00312 function writeLog($message) { 00313 if (func_num_args() > 1) { 00314 $params = func_get_args(); 00315 array_shift($params); 00316 $message = vsprintf($message, $params); 00317 } 00318 00319 if (TYPO3_MODE === 'BE') { 00320 t3lib_div::sysLog($message, $this->extKey, 1); 00321 } else { 00322 $GLOBALS['TT']->setTSlogMessage($message); 00323 } 00324 00325 if (TYPO3_DLOG) { 00326 t3lib_div::devLog($message, $this->extKey, 1); 00327 } 00328 } 00329 } 00330 00331 00332 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/sv1/class.tx_saltedpasswords_sv1.php'])) { 00333 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/sv1/class.tx_saltedpasswords_sv1.php']); 00334 } 00335 ?>
1.8.0