Fixed #11430: Performance improvement: use $GLOBALS['EXEC_TIME'] instead of time...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_beuserauth.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for TYPO3 backend user authentication
29 *
30 * $Id$
31 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
32 *
33 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
34 * @internal
35 */
36 /**
37 * [CLASS/FUNCTION INDEX of SCRIPT]
38 *
39 *
40 *
41 * 76: class t3lib_beUserAuth extends t3lib_userAuthGroup
42 * 150: function trackBeUser($flag)
43 * 168: function checkLockToIP()
44 * 188: function backendCheckLogin()
45 * 216: function checkCLIuser()
46 * 240: function backendSetUC()
47 * 278: function overrideUC()
48 * 288: function resetUC()
49 * 301: function emailAtLogin()
50 * 353: function veriCode()
51 *
52 * TOTAL FUNCTIONS: 9
53 * (This index is automatically created/updated by the extension "extdeveval")
54 *
55 */
56
57
58
59
60
61
62
63
64
65
66 /**
67 * TYPO3 user authentication, backend
68 * Could technically have been the same class as t3lib_userauthgroup since these two are always used together and only together.
69 * t3lib_userauthgroup contains most of the functions used for checking permissions, authenticating users, setting up the user etc. This class is most interesting in terms of an API for user from outside.
70 * This class contains the configuration of the database fields used plus some functions for the authentication process of backend users.
71 *
72 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
73 * @package TYPO3
74 * @subpackage t3lib
75 */
76 class t3lib_beUserAuth extends t3lib_userAuthGroup {
77 var $session_table = 'be_sessions'; // Table to use for session data.
78 var $name = 'be_typo_user'; // Session/Cookie name
79
80 var $user_table = 'be_users'; // Table in database with userdata
81 var $username_column = 'username'; // Column for login-name
82 var $userident_column = 'password'; // Column for password
83 var $userid_column = 'uid'; // Column for user-id
84 var $lastLogin_column = 'lastlogin';
85 var $notifyHeader = 'From: TYPO3 Login notify <no_reply@no_reply.no_reply>';
86
87 var $enablecolumns = Array (
88 'rootLevel' => 1,
89 'deleted' => 'deleted',
90 'disabled' => 'disable',
91 'starttime' => 'starttime',
92 'endtime' => 'endtime'
93 );
94
95 var $formfield_uname = 'username'; // formfield with login-name
96 var $formfield_uident = 'userident'; // formfield with password
97 var $formfield_chalvalue = 'challenge'; // formfield with a unique value which is used to encrypt the password and username
98 var $formfield_status = 'login_status'; // formfield with status: *'login', 'logout'
99
100 var $writeStdLog = 1; // Decides if the writelog() function is called at login and logout
101 var $writeAttemptLog = 1; // If the writelog() functions is called if a login-attempt has be tried without success
102
103 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.
104
105 var $auth_timeout_field = 6000; // if > 0 : session-timeout in seconds. if false/<0 : no timeout. if string: The string is fieldname from the usertable where the timeout can be found.
106 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.
107 var $challengeStoredInCookie = TRUE;
108
109
110 // User Config:
111 var $uc;
112
113 // User Config Default values:
114 // The array may contain other fields for configuration. For this, see "setup" extension and "TSConfig" document (User TSconfig, "setup.[xxx]....")
115 /*
116 Reserved keys for other storage of session data:
117 moduleData
118 moduleSessionID
119 */
120 var $uc_default = Array (
121 'interfaceSetup' => '', // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
122 'moduleData' => Array(), // user-data for the modules
123 'thumbnailsByDefault' => 0,
124 'emailMeAtLogin' => 0,
125 'condensedMode' => 0,
126 'noMenuMode' => 0,
127 'startModule' => 'help_aboutmodules',
128 'hideSubmoduleIcons' => 0,
129 'helpText' => 1,
130 'titleLen' => 30,
131 'edit_wideDocument' => '0',
132 'edit_showFieldHelp' => 'icon',
133 'edit_RTE' => '1',
134 'edit_docModuleUpload' => '1',
135 'enableFlashUploader' => '1',
136 'disableCMlayers' => 0,
137 'navFrameWidth' => '', // Default is 245 pixels
138 'navFrameResizable' => 0,
139 );
140
141
142 /**
143 * Sets the security level for the Backend login
144 *
145 * @return void
146 */
147 function start() {
148 $securityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']);
149 $this->security_level = $securityLevel ? $securityLevel : 'superchallenged';
150
151 parent::start();
152 }
153
154 /**
155 * If flag is set and the extensions 'beuser_tracking' is loaded, this will insert a table row with the REQUEST_URI of current script - thus tracking the scripts the backend users uses...
156 * This function works ONLY with the "beuser_tracking" extension and is deprecated since it does nothing useful.
157 *
158 * @param boolean Activate insertion of the URL.
159 * @return void
160 * @deprecated since TYPO3 3.6
161 */
162 function trackBeUser($flag) {
163 if ($flag && t3lib_extMgm::isLoaded('beuser_tracking')) {
164 $insertFields = array(
165 'userid' => intval($this->user['uid']),
166 'tstamp' => $GLOBALS['EXEC_TIME'],
167 'script' => t3lib_div::getIndpEnv('REQUEST_URI')
168 );
169
170 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_trackbeuser', $insertFields);
171 }
172 }
173
174 /**
175 * If TYPO3_CONF_VARS['BE']['enabledBeUserIPLock'] is enabled and an IP-list is found in the User TSconfig objString "options.lockToIP", then make an IP comparison with REMOTE_ADDR and return the outcome (true/false)
176 *
177 * @return boolean True, if IP address validates OK (or no check is done at all)
178 * @access private
179 */
180 function checkLockToIP() {
181 global $TYPO3_CONF_VARS;
182 $out = 1;
183 if ($TYPO3_CONF_VARS['BE']['enabledBeUserIPLock']) {
184 $IPList = $this->getTSConfigVal('options.lockToIP');
185 if (trim($IPList)) {
186 $baseIP = t3lib_div::getIndpEnv('REMOTE_ADDR');
187 $out = t3lib_div::cmpIP($baseIP, $IPList);
188 }
189 }
190 return $out;
191 }
192
193 /**
194 * Check if user is logged in and if so, call ->fetchGroupData() to load group information and access lists of all kind, further check IP, set the ->uc array and send login-notification email if required.
195 * If no user is logged in the default behaviour is to exit with an error message, but this will happen ONLY if the constant TYPO3_PROCEED_IF_NO_USER is set true.
196 * This function is called right after ->start() in fx. init.php
197 *
198 * @return void
199 */
200 function backendCheckLogin() {
201 if (!$this->user['uid']) {
202 if (!defined('TYPO3_PROCEED_IF_NO_USER') || !TYPO3_PROCEED_IF_NO_USER) {
203 t3lib_BEfunc::typo3PrintError ('Login-error or session timed-out', 'No user logged in! Sorry, I can\'t proceed then!<br /><br />(You must have cookies enabled!)<br /><br />If your session has just timed-out, you may<br /><a href="'.t3lib_div::locationHeaderUrl(t3lib_div::getIndpEnv('TYPO3_SITE_URL').TYPO3_mainDir.'index.php'.'" target="_top">click here to re-login</a>.',0));
204 exit;
205 }
206 } else { // ...and if that's the case, call these functions
207 $this->fetchGroupData(); // The groups are fetched and ready for permission checking in this initialization. Tables.php must be read before this because stuff like the modules has impact in this
208 if ($this->checkLockToIP()) {
209 if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] || $this->isAdmin()) {
210 $this->backendSetUC(); // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
211 $this->emailAtLogin(); // email at login - if option set.
212 } else {
213 t3lib_BEfunc::typo3PrintError ('Login-error','TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.',0);
214 exit;
215 }
216 } else {
217 t3lib_BEfunc::typo3PrintError ('Login-error','IP locking prevented you from being authorized. Can\'t proceed, sorry.',0);
218 exit;
219 }
220 }
221 }
222
223 /**
224 * If the backend script is in CLI mode, it will try to load a backend user named by the CLI module name (in lowercase)
225 *
226 * @return boolean Returns true if a CLI user was loaded, otherwise false!
227 */
228 function checkCLIuser() {
229 // First, check if cliMode is enabled:
230 if (defined('TYPO3_cliMode') && TYPO3_cliMode) {
231 if (!$this->user['uid']) {
232 if (substr($GLOBALS['MCONF']['name'],0,5)=='_CLI_') {
233 $userName = strtolower($GLOBALS['MCONF']['name']);
234 $this->setBeUserByName($userName);
235 if ($this->user['uid']) {
236 if (!$this->isAdmin()) {
237 return TRUE;
238 } else die('ERROR: CLI backend user "'.$userName.'" was ADMIN which is not allowed!'.chr(10).chr(10));
239 } else die('ERROR: No backend user named "'.$userName.'" was found! [Database: '.TYPO3_db.']'.chr(10).chr(10));
240 } else die('ERROR: Module name, "'.$GLOBALS['MCONF']['name'].'", was not prefixed with "_CLI_"'.chr(10).chr(10));
241 } else die('ERROR: Another user was already loaded which is impossible in CLI mode!'.chr(10).chr(10));
242 }
243 }
244
245 /**
246 * Initialize the internal ->uc array for the backend user
247 * Will make the overrides if necessary, and write the UC back to the be_users record if changes has happend
248 *
249 * @return void
250 * @internal
251 */
252 function backendSetUC() {
253 global $TYPO3_CONF_VARS;
254
255 // UC - user configuration is a serialized array inside the userobject
256 $temp_theSavedUC=unserialize($this->user['uc']); // if there is a saved uc we implement that instead of the default one.
257 if (is_array($temp_theSavedUC)) {
258 $this->unpack_uc($temp_theSavedUC);
259 }
260 // Setting defaults if uc is empty
261 if (!is_array($this->uc)) {
262 $this->uc = array_merge($this->uc_default, (array)$TYPO3_CONF_VARS['BE']['defaultUC'], (array)$this->getTSConfigProp('setup.default')); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
263 $this->overrideUC();
264 $U=1;
265 }
266 // If TSconfig is updated, update the defaultUC.
267 if ($this->userTSUpdated) {
268 $this->overrideUC();
269 $U=1;
270 }
271 // Setting default lang from be_user record.
272 if (!isset($this->uc['lang'])) {
273 $this->uc['lang']=$this->user['lang'];
274 $U=1;
275 }
276
277 // Saving if updated.
278 if ($U) {
279 $this->writeUC(); // Method from the t3lib_userauth class.
280 }
281 }
282
283 /**
284 * Override: Call this function every time the uc is updated.
285 * That is 1) by reverting to default values, 2) in the setup-module, 3) userTS changes (userauthgroup)
286 *
287 * @return void
288 * @internal
289 */
290 function overrideUC() {
291 $this->uc = array_merge((array)$this->uc, (array)$this->getTSConfigProp('setup.override')); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
292 }
293
294 /**
295 * Clears the user[uc] and ->uc to blank strings. Then calls ->backendSetUC() to fill it again with reset contents
296 *
297 * @return void
298 * @internal
299 */
300 function resetUC() {
301 $this->user['uc']='';
302 $this->uc='';
303 $this->backendSetUC();
304 }
305
306 /**
307 * Will send an email notification to warning_email_address/the login users email address when a login session is just started.
308 * Depends on various parameters whether mails are send and to whom.
309 *
310 * @return void
311 * @access private
312 */
313 function emailAtLogin() {
314 if ($this->loginSessionStarted) {
315 // Send notify-mail
316 $subject = 'At "'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'].'"'.
317 ' from '.t3lib_div::getIndpEnv('REMOTE_ADDR').
318 (t3lib_div::getIndpEnv('REMOTE_HOST') ? ' ('.t3lib_div::getIndpEnv('REMOTE_HOST').')' : '');
319 $msg = sprintf ('User "%s" logged in from %s (%s) at "%s" (%s)',
320 $this->user['username'],
321 t3lib_div::getIndpEnv('REMOTE_ADDR'),
322 t3lib_div::getIndpEnv('REMOTE_HOST'),
323 $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'],
324 t3lib_div::getIndpEnv('HTTP_HOST')
325 );
326
327 // Warning email address
328 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr']) {
329 $warn=0;
330 $prefix='';
331 if (intval($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode']) & 1) { // first bit: All logins
332 $warn=1;
333 $prefix= $this->isAdmin() ? '[AdminLoginWarning]' : '[LoginWarning]';
334 }
335 if ($this->isAdmin() && (intval($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode']) & 2)) { // second bit: Only admin-logins
336 $warn=1;
337 $prefix='[AdminLoginWarning]';
338 }
339 if ($warn) {
340 mail($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'],
341 $prefix.' '.$subject,
342 $msg,
343 $this->notifyHeader
344 );
345 }
346 }
347
348 // If An email should be sent to the current user, do that:
349 if ($this->uc['emailMeAtLogin'] && strstr($this->user['email'],'@')) {
350 mail($this->user['email'],
351 $subject,
352 $msg,
353 $this->notifyHeader
354 );
355 }
356 }
357 }
358
359 /**
360 * VeriCode returns 10 first chars of a md5 hash of the session cookie AND the encryptionKey from TYPO3_CONF_VARS.
361 * This code is used as an alternative verification when the JavaScript interface executes cmd's to tce_db.php from eg. MSIE 5.0 because the proper referer is not passed with this browser...
362 *
363 * @return string
364 */
365 function veriCode() {
366 return substr(md5($this->id.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']),0,10);
367 }
368
369
370 /**
371 * The session_id is used to find user in the database.
372 * Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
373 * if the client is flash (e.g. from a flash application inside TYPO3 that does a server request)
374 * then don't evaluate with the hashLockClause, as the client/browser is included in this hash
375 * and thus, the flash request would be rejected
376 *
377 * @return DB result object or false on error
378 * @access private
379 */
380 protected function fetchUserSessionFromDB() {
381 if ($GLOBALS['CLIENT']['BROWSER'] == 'flash') {
382 // if on the flash client, the veri code is valid, then the user session is fetched
383 // from the DB without the hashLock clause
384 if (t3lib_div::_GP('vC') == $this->veriCode()) {
385 $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
386 '*',
387 $this->session_table.','.$this->user_table,
388 $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
389 AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
390 AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
391 '.$this->ipLockClause().'
392 '.$this->user_where_clause()
393 );
394 } else {
395 $dbres = false;
396 }
397 } else {
398 $dbres = parent::fetchUserSessionFromDB();
399 }
400 return $dbres;
401 }
402 }
403
404
405
406
407 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_beuserauth.php']) {
408 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_beuserauth.php']);
409 }
410
411 ?>