[TASK] Use simple file backend for core php cache
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_beuserauth.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (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 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
31 *
32 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
33 * @internal
34 */
35
36 /**
37 * TYPO3 user authentication, backend
38 * Could technically have been the same class as t3lib_userauthgroup since these two are always used together and only together.
39 * 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.
40 * This class contains the configuration of the database fields used plus some functions for the authentication process of backend users.
41 *
42 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
43 * @package TYPO3
44 * @subpackage t3lib
45 */
46 class t3lib_beUserAuth extends t3lib_userAuthGroup {
47 // Table to use for session data
48 var $session_table = 'be_sessions';
49
50 // Table in database with userdata
51 var $user_table = 'be_users';
52 // Column for login-name
53 var $username_column = 'username';
54 // Column for password
55 var $userident_column = 'password';
56 // Column for user-id
57 var $userid_column = 'uid';
58 var $lastLogin_column = 'lastlogin';
59
60 var $enablecolumns = array(
61 'rootLevel' => 1,
62 'deleted' => 'deleted',
63 'disabled' => 'disable',
64 'starttime' => 'starttime',
65 'endtime' => 'endtime'
66 );
67
68 // Formfield with login-name
69 var $formfield_uname = 'username';
70 // Formfield with password
71 var $formfield_uident = 'userident';
72 // Formfield with a unique value which is used to encrypt the password and username
73 var $formfield_chalvalue = 'challenge';
74 // Formfield with status: *'login', 'logout'
75 var $formfield_status = 'login_status';
76
77 // Decides if the writelog() function is called at login and logout
78 var $writeStdLog = 1;
79 // If the writelog() functions is called if a login-attempt has be tried without success
80 var $writeAttemptLog = 1;
81
82 // 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.
83 var $auth_timeout_field = 6000;
84 // 0 = Session-cookies. If session-cookies, the browser will stop session when the browser is closed. Else it keeps the session for $lifetime seconds.
85 var $lifetime = 0;
86 var $challengeStoredInCookie = TRUE;
87
88
89 // User Config:
90 var $uc;
91
92 // User Config Default values:
93 // The array may contain other fields for configuration. For this, see "setup" extension and "TSConfig" document (User TSconfig, "setup.[xxx]....")
94 // Reserved keys for other storage of session data:
95 // moduleData
96 // moduleSessionID
97 var $uc_default = array(
98 'interfaceSetup' => '', // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
99 'moduleData' => array(), // user-data for the modules
100 'thumbnailsByDefault' => 1,
101 'emailMeAtLogin' => 0,
102 'condensedMode' => 0,
103 'noMenuMode' => 0,
104 'startModule' => 'help_aboutmodules',
105 'hideSubmoduleIcons' => 0,
106 'helpText' => 1,
107 'titleLen' => 50,
108 'edit_wideDocument' => '0',
109 'edit_showFieldHelp' => 'icon',
110 'edit_RTE' => '1',
111 'edit_docModuleUpload' => '1',
112 'enableFlashUploader' => '1',
113 'navFrameWidth' => '', // Default is 245 pixels
114 'navFrameResizable' => 0,
115 'resizeTextareas' => 1,
116 'resizeTextareas_MaxHeight' => 500,
117 'resizeTextareas_Flexible' => 0,
118 );
119
120 /**
121 * Constructor
122 */
123 public function __construct() {
124 $this->name = self::getCookieName();
125 $this->loginType = 'BE';
126 }
127
128 /**
129 * Getter for the cookie name
130 *
131 * @static
132 * @return string returns the configured cookie name
133 */
134 public static function getCookieName() {
135 $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
136 if (empty($configuredCookieName)) {
137 $configuredCookieName = 'be_typo_user';
138 }
139 return $configuredCookieName;
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 $standardSecurityLevels = array('normal', 'challenged', 'superchallenged');
150
151 // The TYPO3 standard login service relies on $this->security_level being set
152 // to 'superchallenged' because of the password in the database is stored as md5 hash.
153 // @deprecated since 4.7
154 // These lines are here for compatibility purpose only, can be removed in 6.1.
155 // @see tx_sv_auth::processLoginData()
156 if (!empty($securityLevel) && !in_array($securityLevel, $standardSecurityLevels)) {
157 $this->security_level = $securityLevel;
158 } else {
159 $this->security_level = 'superchallenged';
160 }
161
162 parent::start();
163 }
164
165 /**
166 * If TYPO3_CONF_VARS['BE']['enabledBeUserIPLock'] is enabled and
167 * an IP-list is found in the User TSconfig objString "options.lockToIP",
168 * then make an IP comparison with REMOTE_ADDR and return the outcome (TRUE/FALSE)
169 *
170 * @return boolean TRUE, if IP address validates OK (or no check is done at all)
171 */
172 function checkLockToIP() {
173 $out = 1;
174 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['enabledBeUserIPLock']) {
175 $IPList = $this->getTSConfigVal('options.lockToIP');
176 if (trim($IPList)) {
177 $baseIP = t3lib_div::getIndpEnv('REMOTE_ADDR');
178 $out = t3lib_div::cmpIP($baseIP, $IPList);
179 }
180 }
181 return $out;
182 }
183
184 /**
185 * 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.
186 * 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.
187 * This function is called right after ->start() in fx. init.php
188 *
189 * @return void
190 */
191 function backendCheckLogin() {
192 if (!$this->user['uid']) {
193 if (!defined('TYPO3_PROCEED_IF_NO_USER') || !TYPO3_PROCEED_IF_NO_USER) {
194 t3lib_utility_Http::redirect($GLOBALS['BACK_PATH']);
195 }
196 } else { // ...and if that's the case, call these functions
197 $this->fetchGroupData();
198
199 // The groups are fetched and ready for permission checking in this initialization.
200 // Tables.php must be read before this because stuff like the modules has impact in this
201 if ($this->checkLockToIP()) {
202 if ($this->isUserAllowedToLogin()) {
203 // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
204 $this->backendSetUC();
205 // Email at login - if option set.
206 $this->emailAtLogin();
207 } else {
208 throw new RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
209 }
210 } else {
211 throw new RuntimeException('Login Error: IP locking prevented you from being authorized. Can\'t proceed, sorry.', 1294585861);
212 }
213 }
214 }
215
216 /**
217 * If the backend script is in CLI mode, it will try to load a backend user named by the CLI module name (in lowercase)
218 *
219 * @return boolean Returns TRUE if a CLI user was loaded, otherwise FALSE!
220 */
221 function checkCLIuser() {
222 // First, check if cliMode is enabled:
223 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
224 if (!$this->user['uid']) {
225 if (substr($GLOBALS['MCONF']['name'], 0, 5) == '_CLI_') {
226 $userName = strtolower($GLOBALS['MCONF']['name']);
227 $this->setBeUserByName($userName);
228 if ($this->user['uid']) {
229 if (!$this->isAdmin()) {
230 return TRUE;
231 } else {
232 fwrite(STDERR, 'ERROR: CLI backend user "' . $userName . '" was ADMIN which is not allowed!' . LF . LF);
233 exit(3);
234 }
235 } else {
236 fwrite(STDERR, 'ERROR: No backend user named "' . $userName . '" was found!' . LF . LF);
237 exit(3);
238 }
239 } else {
240 fwrite(STDERR, 'ERROR: Module name, "' . $GLOBALS['MCONF']['name'] . '", was not prefixed with "_CLI_"' . LF . LF);
241 exit(3);
242 }
243 } else {
244 fwrite(STDERR, 'ERROR: Another user was already loaded which is impossible in CLI mode!' . LF . LF);
245 exit(3);
246 }
247 }
248 }
249
250 /**
251 * Initialize the internal ->uc array for the backend user
252 * Will make the overrides if necessary, and write the UC back to the be_users record if changes has happend
253 *
254 * @return void
255 * @internal
256 */
257 function backendSetUC() {
258 // UC - user configuration is a serialized array inside the userobject
259 // If there is a saved uc we implement that instead of the default one.
260 $temp_theSavedUC = unserialize($this->user['uc']);
261 if (is_array($temp_theSavedUC)) {
262 $this->unpack_uc($temp_theSavedUC);
263 }
264 // Setting defaults if uc is empty
265 if (!is_array($this->uc)) {
266 $this->uc = array_merge(
267 $this->uc_default,
268 (array) $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
269 t3lib_div::removeDotsFromTS((array) $this->getTSConfigProp('setup.default'))
270 );
271 $this->overrideUC();
272 $U = 1;
273 }
274 // If TSconfig is updated, update the defaultUC.
275 if ($this->userTSUpdated) {
276 $this->overrideUC();
277 $U = 1;
278 }
279 // Setting default lang from be_user record.
280 if (!isset($this->uc['lang'])) {
281 $this->uc['lang'] = $this->user['lang'];
282 $U = 1;
283 }
284 // Setting the time of the first login:
285 if (!isset($this->uc['firstLoginTimeStamp'])) {
286 $this->uc['firstLoginTimeStamp'] = $GLOBALS['EXEC_TIME'];
287 $U = TRUE;
288 }
289
290 // Saving if updated.
291 if ($U) {
292 // Method from the t3lib_userauth class.
293 $this->writeUC();
294 }
295 }
296
297 /**
298 * Override: Call this function every time the uc is updated.
299 * That is 1) by reverting to default values, 2) in the setup-module, 3) userTS changes (userauthgroup)
300 *
301 * @return void
302 * @internal
303 */
304 function overrideUC() {
305 $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...
306 }
307
308 /**
309 * Clears the user[uc] and ->uc to blank strings. Then calls ->backendSetUC() to fill it again with reset contents
310 *
311 * @return void
312 * @internal
313 */
314 function resetUC() {
315 $this->user['uc'] = '';
316 $this->uc = '';
317 $this->backendSetUC();
318 }
319
320 /**
321 * Will send an email notification to warning_email_address/the login users email address when a login session is just started.
322 * Depends on various parameters whether mails are send and to whom.
323 *
324 * @return void
325 * @access private
326 */
327 private function emailAtLogin() {
328 if ($this->loginSessionStarted) {
329 // Send notify-mail
330 $subject = 'At "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"' .
331 ' from ' . t3lib_div::getIndpEnv('REMOTE_ADDR') .
332 (t3lib_div::getIndpEnv('REMOTE_HOST') ? ' (' . t3lib_div::getIndpEnv('REMOTE_HOST') . ')' : '');
333 $msg = sprintf('User "%s" logged in from %s (%s) at "%s" (%s)',
334 $this->user['username'],
335 t3lib_div::getIndpEnv('REMOTE_ADDR'),
336 t3lib_div::getIndpEnv('REMOTE_HOST'),
337 $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'],
338 t3lib_div::getIndpEnv('HTTP_HOST')
339 );
340
341 // Warning email address
342 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr']) {
343 $warn = 0;
344 $prefix = '';
345 if (intval($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode']) & 1) { // first bit: All logins
346 $warn = 1;
347 $prefix = $this->isAdmin() ? '[AdminLoginWarning]' : '[LoginWarning]';
348 }
349 if ($this->isAdmin() && (intval($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode']) & 2)) { // second bit: Only admin-logins
350 $warn = 1;
351 $prefix = '[AdminLoginWarning]';
352 }
353 if ($warn) {
354 $from = t3lib_utility_Mail::getSystemFrom();
355 /** @var $mail t3lib_mail_Message */
356 $mail = t3lib_div::makeInstance('t3lib_mail_Message');
357 $mail->setTo($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'])
358 ->setFrom($from)
359 ->setSubject($prefix . ' ' . $subject)
360 ->setBody($msg);
361 $mail->send();
362 }
363 }
364
365 // If An email should be sent to the current user, do that:
366 if ($this->uc['emailMeAtLogin'] && strstr($this->user['email'], '@')) {
367 $from = t3lib_utility_Mail::getSystemFrom();
368 /** @var $mail t3lib_mail_Message */
369 $mail = t3lib_div::makeInstance('t3lib_mail_Message');
370 $mail->setTo($this->user['email'])
371 ->setFrom($from)
372 ->setSubject($subject)
373 ->setBody($msg);
374 $mail->send();
375 }
376 }
377 }
378
379 /**
380 * Determines whether a backend user is allowed to access the backend.
381 *
382 * The conditions are:
383 * + backend user is a regular user and adminOnly is not defined
384 * + backend user is an admin user
385 * + backend user is used in CLI context and adminOnly is explicitly set to "2"
386 * + backend user is being controlled by an admin user
387 *
388 * @return boolean Whether a backend user is allowed to access the backend
389 */
390 protected function isUserAllowedToLogin() {
391 $isUserAllowedToLogin = FALSE;
392 $adminOnlyMode = $GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
393
394 // Backend user is allowed if adminOnly is not set or user is an admin:
395 if (!$adminOnlyMode || $this->isAdmin()) {
396 $isUserAllowedToLogin = TRUE;
397 // Backend user is allowed if adminOnly is set to 2 (CLI) and a CLI process is running:
398 } elseif ($adminOnlyMode == 2 && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI)) {
399 $isUserAllowedToLogin = TRUE;
400 // Backend user is allowed if an admin has switched to that user
401 } elseif ($this->user['ses_backuserid']) {
402 $backendUserId = intval($this->user['ses_backuserid']);
403 $whereAdmin = 'uid=' . $backendUserId . ' AND admin=1' . t3lib_BEfunc::BEenableFields('be_users');
404 if ($GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'be_users', $whereAdmin) > 0) {
405 $isUserAllowedToLogin = TRUE;
406 }
407 }
408
409 return $isUserAllowedToLogin;
410 }
411
412 /**
413 * Logs out the current user and clears the form protection tokens.
414 */
415 public function logoff() {
416 if (isset($GLOBALS['BE_USER'])) {
417 t3lib_formProtection_Factory::get()->clean();
418 }
419 parent::logoff();
420 }
421 }
422
423 ?>