Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00088 require_once(t3lib_extMgm::extPath('sv').'class.tx_sv_authbase.php'); 00089 00090 00091 00092 00093 00094 00095 00096 00097 00111 class t3lib_userAuth { 00112 var $global_database = ''; // Which global database to connect to 00113 var $session_table = ''; // Table to use for session data. 00114 var $name = ''; // Session/Cookie name 00115 var $get_name = ''; // Session/GET-var name 00116 00117 var $user_table = ''; // Table in database with userdata 00118 var $username_column = ''; // Column for login-name 00119 var $userident_column = ''; // Column for password 00120 var $userid_column = ''; // Column for user-id 00121 var $lastLogin_column = ''; 00122 00123 var $enablecolumns = Array ( 00124 'rootLevel' => '', // Boolean: If true, 'AND pid=0' will be a part of the query... 00125 'disabled' => '', 00126 'starttime' => '', 00127 'endtime' => '', 00128 'deleted' => '' 00129 ); 00130 00131 var $formfield_uname = ''; // formfield with login-name 00132 var $formfield_uident = ''; // formfield with password 00133 var $formfield_chalvalue = ''; // formfield with a unique value which is used to encrypt the password and username 00134 var $formfield_status = ''; // formfield with status: *'login', 'logout'. If empty login is not verified. 00135 var $security_level = 'normal'; // sets the level of security. *'normal' = clear-text. 'challenged' = hashed password/username from form in $formfield_uident. 'superchallenged' = hashed password hashed again with username. 00136 00137 var $auth_include = ''; // this is the name of the include-file containing the login form. If not set, login CAN be anonymous. If set login IS needed. 00138 00139 var $auth_timeout_field = 0; // if > 0 : session-timeout in seconds. if string: The string is fieldname from the usertable where the timeout can be found. 00140 var $lifetime = 0; // 0 = Session-cookies. If session-cookies, the browser will stop session when the browser is closed. Else it keeps the session for $lifetime seconds. 00141 var $gc_time = 24; // GarbageCollection. Purge all session data older than $gc_time hours. 00142 var $gc_probability = 1; // Possibility (in percent) for GarbageCollection to be run. 00143 var $writeStdLog = FALSE; // Decides if the writelog() function is called at login and logout 00144 var $writeAttemptLog = FALSE; // If the writelog() functions is called if a login-attempt has be tried without success 00145 var $sendNoCacheHeaders = TRUE; // If this is set, headers is sent to assure, caching is NOT done 00146 var $getFallBack = FALSE; // If this is set, authentication is also accepted by the $_GET. Notice that the identification is NOT 128bit MD5 hash but reduced. This is done in order to minimize the size for mobile-devices, such as WAP-phones 00147 var $hash_length = 32; // The ident-hash is normally 32 characters and should be! But if you are making sites for WAP-devices og other lowbandwidth stuff, you may shorten the length. Never let this value drop below 6. A length of 6 would give you more than 16 mio possibilities. 00148 var $getMethodEnabled = FALSE; // Setting this flag true lets user-authetication happen from GET_VARS if POST_VARS are not set. Thus you may supply username/password from the URL. 00149 var $lockIP = 4; // If set, will lock the session to the users IP address (all four numbers. Reducing to 1-3 means that only first, second or third part of the IP address is used). 00150 var $lockHashKeyWords = 'useragent'; // Keyword list (commalist with no spaces!): "useragent". Each keyword indicates some information that can be included in a integer hash made to lock down usersessions. 00151 00152 var $warningEmail = ''; // warning -emailaddress: 00153 var $warningPeriod = 3600; // Period back in time (in seconds) in which number of failed logins are collected 00154 var $warningMax = 3; // The maximum accepted number of warnings before an email is sent 00155 var $checkPid = TRUE; // If set, the user-record must $checkPid_value as pid 00156 var $checkPid_value=0; // The pid, the user-record must have as page-id 00157 00158 // Internals 00159 var $id; // Internal: Will contain session_id (MD5-hash) 00160 var $cookieId; // Internal: Will contain the session_id gotten from cookie or GET method. This is used in statistics as a reliable cookie (one which is known to come from $_COOKIE). 00161 var $loginFailure = FALSE; // Indicates if an authentication was started but failed 00162 var $loginSessionStarted = FALSE; // Will be set to true if the login session is actually written during auth-check. 00163 00164 var $user; // Internal: Will contain user- AND session-data from database (joined tables) 00165 var $get_URL_ID = ''; // Internal: Will will be set to the url--ready (eg. '&login=ab7ef8d...') GET-auth-var if getFallBack is true. Should be inserted in links! 00166 00167 var $newSessionID = FALSE; // Will be set to true if a new session ID was created 00168 var $forceSetCookie = FALSE; // Will force the session cookie to be set everytime (lifetime must be 0) 00169 var $dontSetCookie = FALSE; // Will prevent the setting of the session cookie (takes precedence over forceSetCookie) 00170 var $challengeStoredInCookie = FALSE; // If set, the challenge value will be stored in a session as well so the server can check that is was not forged. 00171 var $loginType = ''; // Login type, used for services. 00172 00173 var $svConfig = array(); // "auth" services configuration array from $TYPO3_CONF_VARS['SVCONF']['auth'] 00174 var $writeDevLog = FALSE; // write messages into the devlog? 00175 00176 00177 00178 00179 00180 00181 00182 00183 00195 function start() { 00196 global $TYPO3_CONF_VARS; 00197 00198 // backend or frontend login - used for auth services 00199 $this->loginType = ($this->name=='fe_typo_user') ? 'FE' : 'BE'; 00200 00201 // set level to normal if not already set 00202 $this->security_level = $this->security_level ? $this->security_level : 'normal'; 00203 00204 // enable dev logging if set 00205 if ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['writeDevLog']) $this->writeDevLog = TRUE; 00206 if ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['writeDevLog'.$this->loginType]) $this->writeDevLog = TRUE; 00207 if (TYPO3_DLOG) $this->writeDevLog = TRUE; 00208 00209 if ($this->writeDevLog) t3lib_div::devLog('## Beginning of auth logging.', 't3lib_userAuth'); 00210 00211 // Init vars. 00212 $mode = ''; 00213 $this->newSessionID = FALSE; 00214 // $id is set to ses_id if cookie is present. Else set to false, which will start a new session 00215 $id = isset($_COOKIE[$this->name]) ? stripslashes($_COOKIE[$this->name]) : ''; 00216 $this->hash_length = t3lib_div::intInRange($this->hash_length,6,32); 00217 $this->svConfig = $TYPO3_CONF_VARS['SVCONF']['auth']; 00218 00219 00220 // If fallback to get mode.... 00221 if (!$id && $this->getFallBack && $this->get_name) { 00222 $id = isset($_GET[$this->get_name]) ? t3lib_div::_GET($this->get_name) : ''; 00223 if (strlen($id)!=$this->hash_length) $id=''; 00224 $mode='get'; 00225 } 00226 $this->cookieId = $id; 00227 00228 // If new session... 00229 if (!$id) { 00230 // New random session-$id is made 00231 $id = substr(md5(uniqid('').getmypid()),0,$this->hash_length); 00232 // New session 00233 $this->newSessionID = TRUE; 00234 } 00235 00236 // Internal var 'id' is set 00237 $this->id = $id; 00238 00239 // If fallback to get mode.... 00240 if ($mode=='get' && $this->getFallBack && $this->get_name) { 00241 $this->get_URL_ID = '&'.$this->get_name.'='.$id; 00242 } 00243 // Make certain that NO user is set initially 00244 $this->user = ''; 00245 00246 // Setting cookies 00247 // If new session and the cookie is a sessioncookie, we need to set it only once! 00248 if (($this->newSessionID || $this->forceSetCookie) && $this->lifetime==0 ) { 00249 if (!$this->dontSetCookie) { 00250 SetCookie($this->name, $id, 0, '/'); 00251 if ($this->writeDevLog) t3lib_div::devLog('Set new Cookie: '.$id, 't3lib_userAuth'); 00252 } 00253 } 00254 00255 // If it is NOT a session-cookie, we need to refresh it. 00256 if ($this->lifetime > 0) { 00257 if (!$this->dontSetCookie) { 00258 SetCookie($this->name, $id, time()+$this->lifetime, '/'); 00259 if ($this->writeDevLog) t3lib_div::devLog('Update Cookie: '.$id, 't3lib_userAuth'); 00260 } 00261 } 00262 00263 // Check to see if anyone has submitted login-information and if so register the user with the session. $this->user[uid] may be used to write log... 00264 $this->checkAuthentication(); 00265 00266 // Make certain that NO user is set initially. ->check_authentication may have set a session-record which will provide us with a user record in the next section: 00267 unset($this->user); 00268 00269 // re-read user session 00270 $this->user = $this->fetchUserSession(); 00271 00272 if ($this->writeDevLog AND is_array($this->user)) t3lib_div::devLog('User session finally read: '.t3lib_div::arrayToLogString($this->user, array($this->userid_column,$this->username_column)), 't3lib_userAuth', -1); 00273 if ($this->writeDevLog AND !is_array($this->user)) t3lib_div::devLog('No user session found.', 't3lib_userAuth', 2); 00274 00275 // Hook for alternative ways of filling the $this->user array (is used by TIMTAW extension) 00276 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['postUserLookUp'])) { 00277 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['postUserLookUp'] as $funcName) { 00278 $_params = array( 00279 'pObj' => &$this, 00280 ); 00281 t3lib_div::callUserFunction($funcName,$_params,$this); 00282 } 00283 } 00284 00285 // If any redirection (inclusion of file) then it will happen in this function 00286 $this->redirect(); 00287 00288 // Set all posible headers that could ensure that the script is not cached on the client-side 00289 if ($this->sendNoCacheHeaders) { 00290 header('Expires: 0'); 00291 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); 00292 header('Cache-Control: no-cache, must-revalidate'); 00293 header('Pragma: no-cache'); 00294 } 00295 00296 // If we're lucky we'll get to clean up old sessions.... 00297 if ((rand()%100) <= $this->gc_probability) { 00298 $this->gc(); 00299 } 00300 } 00301 00308 function checkAuthentication() { 00309 00310 // No user for now - will be searched by service below 00311 $tempuserArr = array(); 00312 $tempuser = FALSE; 00313 00314 // User is not authenticated by default 00315 $authenticated = FALSE; 00316 00317 // User want to login with passed login data (name/password) 00318 $activeLogin = FALSE; 00319 00320 // Indicates if an active authentication failed (not auto login) 00321 $this->loginFailure = FALSE; 00322 00323 if ($this->writeDevLog) t3lib_div::devLog('Login type: '.$this->loginType, 't3lib_userAuth'); 00324 00325 // The info array provide additional information for auth services 00326 $authInfo = $this->getAuthInfoArray(); 00327 00328 // Get Login/Logout data submitted by a form or params 00329 $loginData = $this->getLoginFormData(); 00330 00331 if ($this->writeDevLog) t3lib_div::devLog('Login data: '.t3lib_div::arrayToLogString($loginData), 't3lib_userAuth'); 00332 00333 00334 // active logout (eg. with "logout" button) 00335 if ($loginData['status']=='logout') { 00336 if ($this->writeStdLog) $this->writelog(255,2,0,2,'User %s logged out',Array($this->user['username'])); // Logout written to log 00337 if ($this->writeDevLog) t3lib_div::devLog('User logged out. Id: '.$this->id, 't3lib_userAuth', -1); 00338 00339 $this->logoff(); 00340 } 00341 00342 // active login (eg. with login form) 00343 if ($loginData['status']=='login') { 00344 $activeLogin = TRUE; 00345 00346 if ($this->writeDevLog) t3lib_div::devLog('Active login (eg. with login form)', 't3lib_userAuth'); 00347 00348 // check referer for submitted login values 00349 if($this->formfield_status && $loginData['uident'] && $loginData['uname']) { 00350 $httpHost = t3lib_div::getIndpEnv('TYPO3_HOST_ONLY'); 00351 if (!$this->getMethodEnabled && ($httpHost!=$authInfo['refInfo']['host'] && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer'])) { 00352 die('Error: This host address ("'.$httpHost.'") and the referer host ("'.$authInfo['refInfo']['host'].'") mismatches!<br /> 00353 It\'s possible that the environment variable HTTP_REFERER is not passed to the script because of a proxy.<br /> 00354 The site administrator can disable this check in the "All Configuration" section of the Install Tool (flag: TYPO3_CONF_VARS[SYS][doNotCheckReferer]).'); 00355 } 00356 00357 // delete old user session if any 00358 $this->logoff(); 00359 } 00360 } 00361 00362 00363 // the following code makes auto-login possible (if configured). No submitted data needed 00364 00365 // re-read user session 00366 $authInfo['userSession'] = $this->fetchUserSession(); 00367 $haveSession = is_array($authInfo['userSession']) ? TRUE : FALSE; 00368 00369 if ($this->writeDevLog AND $haveSession) t3lib_div::devLog('User session found: '.t3lib_div::arrayToLogString($authInfo['userSession'], array($this->userid_column,$this->username_column)), 't3lib_userAuth', 0); 00370 if ($this->writeDevLog) t3lib_div::devLog('SV setup: '.t3lib_div::arrayToLogString($this->svConfig['setup']), 't3lib_userAuth', 0); 00371 00372 00373 // fetch user if ... 00374 if ( $activeLogin 00375 OR (!$haveSession AND $this->svConfig['setup'][$this->loginType.'_fetchUserIfNoSession']) 00376 OR $this->svConfig['setup'][$this->loginType.'_alwaysFetchUser']) { 00377 00378 // use 'auth' service to find the user 00379 // first found user will be used 00380 $serviceChain = ''; 00381 $subType = 'getUser'.$this->loginType; 00382 while (is_object($serviceObj = t3lib_div::makeInstanceService('auth', $subType, $serviceChain))) { 00383 $serviceChain.=','.$serviceObj->getServiceKey(); 00384 $serviceObj->initAuth($subType, $loginData, $authInfo, $this); 00385 if ($row=$serviceObj->getUser()) { 00386 $tempuserArr[] = $row; 00387 00388 if ($this->writeDevLog) t3lib_div::devLog('User found: '.t3lib_div::arrayToLogString($row, array($this->userid_column,$this->username_column)), 't3lib_userAuth', 0); 00389 00390 // user found, just stop to search for more if not configured to go on 00391 if(!$this->svConfig['setup'][$this->loginType.'_fetchAllUsers']) { 00392 break; 00393 } 00394 } 00395 unset($serviceObj); 00396 } 00397 unset($serviceObj); 00398 00399 if ($this->writeDevLog AND $this->svConfig['setup'][$this->loginType.'_alwaysFetchUser']) t3lib_div::devLog($this->loginType.'_alwaysFetchUser option is enabled', 't3lib_userAuth'); 00400 if ($this->writeDevLog AND $serviceChain) t3lib_div::devLog($subType.' auth services called: '.$serviceChain, 't3lib_userAuth'); 00401 if ($this->writeDevLog AND !count($tempuserArr)) t3lib_div::devLog('No user found by services', 't3lib_userAuth'); 00402 if ($this->writeDevLog AND count($tempuserArr)) t3lib_div::devLog(count($tempuserArr).' user records found by services', 't3lib_userAuth'); 00403 } 00404 00405 00406 // If no new user was set we use the already found user session 00407 if (!count($tempuserArr) AND $haveSession) { 00408 $tempuserArr[] = $authInfo['userSession']; 00409 $tempuser = $authInfo['userSession']; 00410 // User is authenticated because we found a user session 00411 $authenticated = TRUE; 00412 00413 if ($this->writeDevLog) t3lib_div::devLog('User session used: '.t3lib_div::arrayToLogString($authInfo['userSession'], array($this->userid_column,$this->username_column)), 't3lib_userAuth'); 00414 } 00415 00416 00417 // Re-auth user when 'auth'-service option is set 00418 if ($this->svConfig['setup'][$this->loginType.'_alwaysAuthUser']) { 00419 $authenticated = FALSE; 00420 if ($this->writeDevLog) t3lib_div::devLog('alwaysAuthUser option is enabled', 't3lib_userAuth'); 00421 } 00422 00423 00424 // Authenticate the user if needed 00425 if(count($tempuserArr) AND !$authenticated) { 00426 00427 foreach($tempuserArr as $tempuser) { 00428 00429 // use 'auth' service to authenticate the user 00430 // if one service returns FALSE then authentication failed 00431 // a service might return 100 which means there's no reason to stop but the user can't be authenticated by that service 00432 00433 if ($this->writeDevLog) t3lib_div::devLog('Auth user: '.t3lib_div::arrayToLogString($tempuser), 't3lib_userAuth'); 00434 00435 $serviceChain=''; 00436 $subType = 'authUser'.$this->loginType; 00437 while (is_object($serviceObj = t3lib_div::makeInstanceService('auth', $subType, $serviceChain))) { 00438 $serviceChain.=','.$serviceObj->getServiceKey(); 00439 $serviceObj->initAuth($subType, $loginData, $authInfo, $this); 00440 if (($ret=$serviceObj->authUser($tempuser)) > 0) { 00441 00442 // if the service returns >=200 then no more checking is needed - useful for IP checking without password 00443 if (intval($ret) >= 200) { 00444 $authenticated = TRUE; 00445 break; 00446 } elseif (intval($ret) >= 100) { 00447 // Just go on. User is still not authenticated but there's no reason to stop now. 00448 } else { 00449 $authenticated = TRUE; 00450 } 00451 00452 } else { 00453 $authenticated = FALSE; 00454 break; 00455 } 00456 unset($serviceObj); 00457 } 00458 unset($serviceObj); 00459 00460 if ($this->writeDevLog AND $serviceChain) t3lib_div::devLog($subType.' auth services called: '.$serviceChain, 't3lib_userAuth'); 00461 00462 if($authenticated) { 00463 // leave foreach() because a user is authenticated 00464 break; 00465 } 00466 } 00467 } 00468 00469 00470 // If user is authenticated a valid user is in $tempuser 00471 if ($authenticated) { 00472 // reset failure flag 00473 $this->loginFailure = FALSE; 00474 00475 00476 // Insert session record if needed: 00477 if (!($haveSession AND ( 00478 $tempuser['ses_id']==$this->id OR // check if the tempuser has the current session id 00479 $tempuser['uid']==$authInfo['userSession']['ses_userid'] // check if the tempuser has the uid of the fetched session user 00480 ))) { 00481 $this->createUserSession($tempuser); 00482 00483 // The login session is started. 00484 $this->loginSessionStarted = TRUE; 00485 } 00486 00487 // User logged in - write that to the log! 00488 if ($this->writeStdLog && $activeLogin) { 00489 $this->writelog(255,1,0,1, 00490 'User %s logged in from %s (%s)', 00491 Array($tempuser[$this->username_column], t3lib_div::getIndpEnv('REMOTE_ADDR'), t3lib_div::getIndpEnv('REMOTE_HOST'))); 00492 } 00493 00494 if ($this->writeDevLog && $activeLogin) t3lib_div::devLog('User '.$tempuser[$this->username_column].' logged in from '.t3lib_div::getIndpEnv('REMOTE_ADDR').' ('.t3lib_div::getIndpEnv('REMOTE_HOST').')', 't3lib_userAuth', -1); 00495 if ($this->writeDevLog && !$activeLogin) t3lib_div::devLog('User '.$tempuser[$this->username_column].' authenticated from '.t3lib_div::getIndpEnv('REMOTE_ADDR').' ('.t3lib_div::getIndpEnv('REMOTE_HOST').')', 't3lib_userAuth', -1); 00496 00497 00498 } elseif ($activeLogin OR count($tempuserArr)) { 00499 $this->loginFailure = TRUE; 00500 00501 if ($this->writeDevLog AND !count($tempuserArr) AND $activeLogin) t3lib_div::devLog('Login failed: '.t3lib_div::arrayToLogString($loginData), 't3lib_userAuth', 2); 00502 if ($this->writeDevLog AND count($tempuserArr)) t3lib_div::devLog('Login failed: '.t3lib_div::arrayToLogString($tempuser, array($this->userid_column,$this->username_column)), 't3lib_userAuth', 2); 00503 } 00504 00505 00506 // If there were a login failure, check to see if a warning email should be sent: 00507 if ($this->loginFailure AND $activeLogin) { 00508 if ($this->writeDevLog) t3lib_div::devLog('Call checkLogFailures: '.t3lib_div::arrayToLogString(array('warningEmail'=>$this->warningEmail,'warningPeriod'=>$this->warningPeriod,'warningMax'=>$this->warningMax,)), 't3lib_userAuth', -1); 00509 00510 $this->checkLogFailures($this->warningEmail, $this->warningPeriod, $this->warningMax); 00511 } 00512 } 00513 00514 00515 00516 00517 00518 00519 00520 00521 00522 00523 00524 00525 /************************* 00526 * 00527 * User Sessions 00528 * 00529 *************************/ 00530 00531 00538 function createUserSession ($tempuser) { 00539 00540 if ($this->writeDevLog) t3lib_div::devLog('Create session ses_id = '.$this->id, 't3lib_userAuth'); 00541 00542 // delete session entry first 00543 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00544 $this->session_table, 00545 'ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).' 00546 AND ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table) 00547 ); 00548 00549 // re-create session entry 00550 $insertFields = array( 00551 'ses_id' => $this->id, 00552 'ses_name' => $this->name, 00553 'ses_iplock' => $tempuser['disableIPlock'] ? '[DISABLED]' : $this->ipLockClause_remoteIPNumber($this->lockIP), 00554 'ses_hashlock' => $this->hashLockClause_getHashInt(), 00555 'ses_userid' => $tempuser[$this->userid_column], 00556 'ses_tstamp' => $GLOBALS['EXEC_TIME'] 00557 ); 00558 $GLOBALS['TYPO3_DB']->exec_INSERTquery($this->session_table, $insertFields); 00559 00560 // Updating lastLogin_column carrying information about last login. 00561 if ($this->lastLogin_column) { 00562 $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 00563 $this->user_table, 00564 $this->userid_column.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($tempuser[$this->userid_column], $this->user_table), 00565 array($this->lastLogin_column => $GLOBALS['EXEC_TIME']) 00566 ); 00567 } 00568 } 00569 00575 function fetchUserSession() { 00576 00577 $user = ''; 00578 00579 if ($this->writeDevLog) t3lib_div::devLog('Fetch session ses_id = '.$this->id, 't3lib_userAuth'); 00580 00581 // The session_id is used to find user in the database. Two tables are joined: The session-table with user_id of the session and the usertable with its primary key 00582 $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00583 '*', 00584 $this->session_table.','.$this->user_table, 00585 $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).' 00586 AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).' 00587 AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.' 00588 '.$this->ipLockClause().' 00589 '.$this->hashLockClause().' 00590 '.$this->user_where_clause() 00591 ); 00592 00593 00594 if ($user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres)) { 00595 // A user was found 00596 if (is_string($this->auth_timeout_field)) { 00597 $timeout = intval($user[$this->auth_timeout_field]); // Get timeout-time from usertable 00598 } else { 00599 $timeout = intval($this->auth_timeout_field); // Get timeout from object 00600 } 00601 // If timeout > 0 (true) and currenttime has not exceeded the latest sessions-time plus the timeout in seconds then accept user 00602 // Option later on: We could check that last update was at least x seconds ago in order not to update twice in a row if one script redirects to another... 00603 if ($timeout>0 && ($GLOBALS['EXEC_TIME'] < ($user['ses_tstamp']+$timeout))) { 00604 $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 00605 $this->session_table, 00606 'ses_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).' 00607 AND ses_name='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table), 00608 array('ses_tstamp' => $GLOBALS['EXEC_TIME']) 00609 ); 00610 $user['ses_tstamp'] = $GLOBALS['EXEC_TIME']; // Make sure that the timestamp is also updated in the array 00611 } else { 00612 $this->logoff(); // delete any user set... 00613 } 00614 } else { 00615 $this->logoff(); // delete any user set... 00616 } 00617 return $user; 00618 } 00619 00626 function logoff() { 00627 if ($this->writeDevLog) t3lib_div::devLog('logoff: ses_id = '.$this->id, 't3lib_userAuth'); 00628 00629 // Hook for pre-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: 00630 if ( is_array( $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_feuserauth.php']['logoff_pre_processing'] ) ) { 00631 $_params = array(); 00632 foreach( $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_feuserauth.php']['logoff_pre_processing'] as $_funcRef ) { 00633 if ($_funcRef) { 00634 t3lib_div::callUserFunction($_funcRef,$_params,$this); 00635 } 00636 } 00637 } 00638 00639 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00640 $this->session_table, 00641 'ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).' 00642 AND ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table) 00643 ); 00644 00645 $this->user = ''; 00646 00647 // Hook for post-processing the logoff() method, requested and implemented by andreas.otto@dkd.de: 00648 if ( is_array( $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_feuserauth.php']['logoff_post_processing'] ) ) { 00649 $_params = array(); 00650 foreach( $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_feuserauth.php']['logoff_post_processing'] as $_funcRef ) { 00651 if ($_funcRef) { 00652 t3lib_div::callUserFunction($_funcRef,$_params,$this); 00653 } 00654 } 00655 } 00656 } 00657 00658 00659 00660 00661 00662 00663 00664 00665 00666 00667 00668 00669 00670 /************************* 00671 * 00672 * SQL Functions 00673 * 00674 *************************/ 00675 00682 function user_where_clause() { 00683 return (($this->enablecolumns['rootLevel']) ? 'AND '.$this->user_table.'.pid=0 ' : ''). 00684 (($this->enablecolumns['disabled']) ? ' AND '.$this->user_table.'.'.$this->enablecolumns['disabled'].'=0' : ''). 00685 (($this->enablecolumns['deleted']) ? ' AND '.$this->user_table.'.'.$this->enablecolumns['deleted'].'=0' : ''). 00686 (($this->enablecolumns['starttime']) ? ' AND ('.$this->user_table.'.'.$this->enablecolumns['starttime'].'<='.time().')' : ''). 00687 (($this->enablecolumns['endtime']) ? ' AND ('.$this->user_table.'.'.$this->enablecolumns['endtime'].'=0 OR '.$this->user_table.'.'.$this->enablecolumns['endtime'].'>'.time().')' : ''); 00688 } 00689 00696 function ipLockClause() { 00697 if ($this->lockIP) { 00698 $wherePart = 'AND ( 00699 '.$this->session_table.'.ses_iplock='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->ipLockClause_remoteIPNumber($this->lockIP),$this->session_table).' 00700 OR '.$this->session_table.'.ses_iplock=\'[DISABLED]\' 00701 )'; 00702 return $wherePart; 00703 } 00704 } 00705 00714 function ipLockClause_remoteIPNumber($parts) { 00715 $IP = t3lib_div::getIndpEnv('REMOTE_ADDR'); 00716 00717 if ($parts>=4) { 00718 return $IP; 00719 } else { 00720 $parts = t3lib_div::intInRange($parts,1,3); 00721 $IPparts = explode('.',$IP); 00722 for($a=4;$a>$parts;$a--) { 00723 unset($IPparts[$a-1]); 00724 } 00725 return implode('.',$IPparts); 00726 } 00727 } 00728 00735 function hashLockClause() { 00736 $wherePart = 'AND '.$this->session_table.'.ses_hashlock='.intval($this->hashLockClause_getHashInt()); 00737 return $wherePart; 00738 } 00739 00746 function hashLockClause_getHashInt() { 00747 $hashStr = ''; 00748 00749 if (t3lib_div::inList($this->lockHashKeyWords,'useragent')) $hashStr.=':'.t3lib_div::getIndpEnv('HTTP_USER_AGENT'); 00750 00751 return t3lib_div::md5int($hashStr); 00752 } 00753 00754 00755 00756 00757 00758 00759 00760 00761 00762 00763 00764 /************************* 00765 * 00766 * Session and Configuration Handling 00767 * 00768 *************************/ 00769 00778 function writeUC($variable='') { 00779 if (is_array($this->user) && $this->user[$this->userid_column]) { 00780 if (!is_array($variable)) { $variable = $this->uc; } 00781 00782 if ($this->writeDevLog) t3lib_div::devLog('writeUC: '.$this->userid_column.'='.intval($this->user[$this->userid_column]), 't3lib_userAuth'); 00783 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($this->user_table, $this->userid_column.'='.intval($this->user[$this->userid_column]), array('uc' => serialize($variable))); 00784 } 00785 } 00786 00793 function unpack_uc($theUC='') { 00794 if (!$theUC) $theUC=unserialize($this->user['uc']); 00795 if (is_array($theUC)) { 00796 $this->uc=$theUC; 00797 } 00798 } 00799 00809 function pushModuleData($module,$data,$noSave=0) { 00810 $this->uc['moduleData'][$module] = $data; 00811 $this->uc['moduleSessionID'][$module] = $this->id; 00812 if (!$noSave) $this->writeUC(); 00813 } 00814 00822 function getModuleData($module,$type='') { 00823 if ($type!='ses' || $this->uc['moduleSessionID'][$module]==$this->id) { 00824 return $this->uc['moduleData'][$module]; 00825 } 00826 } 00827 00835 function getSessionData($key) { 00836 $sesDat = unserialize($this->user['ses_data']); 00837 return $sesDat[$key]; 00838 } 00839 00848 function setAndSaveSessionData($key,$data) { 00849 $sesDat = unserialize($this->user['ses_data']); 00850 $sesDat[$key] = $data; 00851 $this->user['ses_data'] = serialize($sesDat); 00852 00853 if ($this->writeDevLog) t3lib_div::devLog('setAndSaveSessionData: ses_id = '.$this->user['ses_id'], 't3lib_userAuth'); 00854 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($this->session_table, 'ses_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->user['ses_id'], $this->session_table), array('ses_data' => $this->user['ses_data'])); 00855 } 00856 00857 00858 00859 00860 00861 00862 00863 00864 00865 00866 00867 00868 00869 /************************* 00870 * 00871 * Misc 00872 * 00873 *************************/ 00874 00881 function getLoginFormData() { 00882 $loginData=array(); 00883 if ($this->getMethodEnabled) { 00884 $loginData['status'] = t3lib_div::_GP($this->formfield_status); 00885 $loginData['uname'] = t3lib_div::_GP($this->formfield_uname); 00886 $loginData['uident'] = t3lib_div::_GP($this->formfield_uident); 00887 $loginData['chalvalue'] = t3lib_div::_GP($this->formfield_chalvalue); 00888 } else { 00889 $loginData['status'] = t3lib_div::_POST($this->formfield_status); 00890 $loginData['uname'] = t3lib_div::_POST($this->formfield_uname); 00891 $loginData['uident'] = t3lib_div::_POST($this->formfield_uident); 00892 $loginData['chalvalue'] = t3lib_div::_POST($this->formfield_chalvalue); 00893 } 00894 $loginData = $this->processLoginData($loginData); 00895 00896 return $loginData; 00897 } 00898 00908 function processLoginData($loginData, $security_level='') { 00909 global $TYPO3_CONF_VARS; 00910 00911 $loginSecurityLevel = $security_level ? $security_level : ($TYPO3_CONF_VARS[$this->loginType]['loginSecurityLevel'] ? $TYPO3_CONF_VARS[$this->loginType]['loginSecurityLevel'] : $this->security_level); 00912 00913 // Processing data according to the state it was submitted in. 00914 // ($loginSecurityLevel should reflect the security level used on the data being submitted in the login form) 00915 if ($loginSecurityLevel=='normal') { 00916 $loginData['uident_text'] = $loginData['uident']; 00917 $loginData['uident_challenged'] = (string)md5($loginData['uname'].':'.$loginData['uident'].':'.$loginData['chalvalue']); 00918 $loginData['uident_superchallenged'] = (string)md5($loginData['uname'].':'.(md5($loginData['uident'])).':'.$loginData['chalvalue']); 00919 } elseif ($loginSecurityLevel=='challenged') { 00920 $loginData['uident_text'] = ''; 00921 $loginData['uident_challenged'] = $loginData['uident']; 00922 $loginData['uident_superchallenged'] = ''; 00923 } elseif ($loginSecurityLevel=='superchallenged') { 00924 $loginData['uident_text'] = ''; 00925 $loginData['uident_challenged'] = ''; 00926 $loginData['uident_superchallenged'] = $loginData['uident']; 00927 } 00928 00929 // The password "uident" is set based on the internal security setting of TYPO3 00930 // Example: 00931 // $this->security_level for the backend must be "superchallenged" because passwords are stored as md5-hashes in the be_users table 00932 // $this->security_level for the frontend must be "normal" or "challenged" because passwords are stored as clear-text in the fe_users tables 00933 if ($this->security_level=='normal') { 00934 $loginData['uident'] = $loginData['uident_text']; 00935 } elseif ($this->security_level=='challenged') { 00936 $loginData['uident'] = $loginData['uident_challenged']; 00937 } elseif ($this->security_level=='superchallenged') { 00938 $loginData['uident'] = $loginData['uident_superchallenged']; 00939 } 00940 00941 return $loginData; 00942 } 00943 00950 function getAuthInfoArray() { 00951 $authInfo = array(); 00952 $authInfo['loginType'] = $this->loginType; 00953 $authInfo['refInfo'] = parse_url(t3lib_div::getIndpEnv('HTTP_REFERER')); 00954 $authInfo['HTTP_HOST'] = t3lib_div::getIndpEnv('HTTP_HOST'); 00955 $authInfo['REMOTE_ADDR'] = t3lib_div::getIndpEnv('REMOTE_ADDR'); 00956 $authInfo['REMOTE_HOST'] = t3lib_div::getIndpEnv('REMOTE_HOST'); 00957 $authInfo['security_level'] = $this->security_level; 00958 $authInfo['showHiddenRecords'] = $this->showHiddenRecords; 00959 // can be overidden in localconf by SVCONF: 00960 $authInfo['db_user']['table'] = $this->user_table; 00961 $authInfo['db_user']['userid_column'] = $this->userid_column; 00962 $authInfo['db_user']['username_column'] = $this->username_column; 00963 $authInfo['db_user']['userident_column'] = $this->userident_column; 00964 $authInfo['db_user']['usergroup_column'] = $this->usergroup_column; 00965 $authInfo['db_user']['enable_clause'] = $this->user_where_clause(); 00966 $authInfo['db_user']['checkPidList'] = $this->checkPid ? $this->checkPid_value : ''; 00967 $authInfo['db_user']['check_pid_clause'] = $this->checkPid ? ' AND pid IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($authInfo['db_user']['checkPidList']).')' : ''; 00968 $authInfo['db_groups']['table'] = $this->usergroup_table; 00969 return $authInfo; 00970 } 00971 00980 function compareUident($user, $loginData, $security_level='') { 00981 00982 $OK = FALSE; 00983 $security_level = $security_level ? $security_level : $this->security_level; 00984 00985 switch ($security_level) { 00986 case 'superchallenged': // If superchallenged the password in the database ($user[$this->userident_column]) must be a md5-hash of the original password. 00987 case 'challenged': 00988 00989 // Check challenge stored in cookie: 00990 if ($this->challengeStoredInCookie) { 00991 session_start(); 00992 if ($_SESSION['login_challenge'] !== $loginData['chalvalue']) { 00993 if ($this->writeDevLog) t3lib_div::devLog('PHP Session stored challenge "'.$_SESSION['login_challenge'].'" and submitted challenge "'.$loginData['chalvalue'].'" did not match, so authentication failed!', 't3lib_userAuth', 2); 00994 $this->logoff(); 00995 return FALSE; 00996 } 00997 } 00998 00999 if ((string)$loginData['uident'] === (string)md5($user[$this->username_column].':'.$user[$this->userident_column].':'.$loginData['chalvalue'])) { 01000 $OK = TRUE; 01001 }; 01002 break; 01003 default: // normal 01004 if ((string)$loginData['uident'] === (string)$user[$this->userident_column]) { 01005 $OK = TRUE; 01006 }; 01007 break; 01008 } 01009 01010 return $OK; 01011 } 01012 01019 function gc() { 01020 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 01021 $this->session_table, 01022 'ses_tstamp < '.intval(time()-($this->gc_time*60*60)).' 01023 AND ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table) 01024 ); 01025 } 01026 01033 function redirect() { 01034 if (!$this->userid && $this->auth_url) { // if no userid AND an include-document for login is given 01035 include ($this->auth_include); 01036 exit; 01037 } 01038 } 01039 01055 function writelog($type,$action,$error,$details_nr,$details,$data,$tablename,$recuid,$recpid) { 01056 } 01057 01064 function checkLogFailures() { 01065 } 01066 01077 function setBeUserByUid($uid) { 01078 $this->user = $this->getRawUserByUid($uid); 01079 } 01080 01089 function setBeUserByName($name) { 01090 $this->user = $this->getRawUserByName($name); 01091 } 01092 01100 function getRawUserByUid($uid) { 01101 $user = FALSE; 01102 $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->user_table, 'uid='.intval($uid).' '.$this->user_where_clause()); 01103 if ($dbres) { 01104 $user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres); 01105 $GLOBALS['TYPO3_DB']->sql_free_result($dbres); 01106 } 01107 return $user; 01108 } 01109 01118 function getRawUserByName($name) { 01119 $user = FALSE; 01120 $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->user_table, 'username='.$GLOBALS['TYPO3_DB']->fullQuoteStr($name, $this->user_table).' '.$this->user_where_clause()); 01121 if ($dbres) { 01122 $user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres); 01123 $GLOBALS['TYPO3_DB']->sql_free_result($dbres); 01124 } 01125 return $user; 01126 } 01127 01128 01129 01130 01131 01132 01133 01134 01135 01136 01137 01138 01139 01140 01141 01142 /************************* 01143 * 01144 * Create/update user - EXPERIMENTAL 01145 * 01146 *************************/ 01147 01157 function fetchUserRecord($dbUser, $username, $extraWhere='' ) { 01158 $user = FALSE; 01159 01160 $usernameClause = $username ? ($dbUser['username_column'].'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($username, $dbUser['table'])) : ''; 01161 01162 if ($username OR $extraWhere) { 01163 01164 // Look up the user by the username and/or extraWhere: 01165 $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 01166 '*', 01167 $dbUser['table'], 01168 $usernameClause. 01169 $dbUser['check_pid_clause']. 01170 $dbUser['enable_clause']. 01171 $extraWhere 01172 ); 01173 01174 if ($dbres) { 01175 $user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres); 01176 $GLOBALS['TYPO3_DB']->sql_free_result($dbres); 01177 } 01178 } 01179 return $user; 01180 } 01181 } 01182 01183 01184 01185 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_userauth.php']) { 01186 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_userauth.php']); 01187 } 01188 ?>