Index: t3lib/config_default.php =================================================================== --- t3lib/config_default.php (revision 5368) +++ t3lib/config_default.php (working copy) @@ -192,7 +192,7 @@ 'lockSSL' => 0, // Int. 0,1,2,3: If set (1,2,3), the backend can only be operated from an ssl-encrypted connection (https). Set to 2 you will be redirected to the https admin-url supposed to be the http-url, but with https scheme instead. If set to 3, only the login is forced to SSL, then the user switches back to non-SSL-mode 'lockSSLPort' => 0, // Integer. Use a non-standard HTTPS port for lockSSL. Set this value if you use lockSSL and the HTTPS port of your webserver is not 443. 'enabledBeUserIPLock' => 1, // Boolean. If set, the User/Group TSconfig option 'option.lockToIP' is enabled. - 'loginSecurityLevel' => '', // String. Keywords that determines the security level of login to the backend. "normal" means the password from the login form is sent in clear-text, "challenged" means the password is not sent but hashed with some other values, "superchallenged" (default) means the password is first hashed before being hashed with the challenge values again (means the password is stored as a hashed string in the database also). DO NOT CHANGE this value manually; without an alternative authentication service it will only prevent logins in TYPO3 since the "superchallenged" method is hardcoded in the default authentication system. + 'loginSecurityLevel' => '', // String. Keywords that determines the security level of login to the backend. "normal" means the password from the login form is sent in clear-text, "challenged" means the password is not sent but hashed with some other values, "superchallenged" (default) means the password is first hashed before being hashed with the challenge values again (means the password is stored as a hashed string in the database also), "rsa" uses RSA password encryption (only if the rsaauth extension is installed). DO NOT CHANGE this value manually; without an alternative authentication service it will only prevent logins in TYPO3 since the "superchallenged" method is hardcoded in the default authentication system. 'adminOnly' => 0, // Int. If set (>=1), the only "admin" users can log in to the backend. If "<=-1" then the backend is totally shut down! For maintenance purposes. 'disable_exec_function' => 0, // Boolean. Don't use exec() function (except for ImageMagick which is disabled by [GFX][im]=0). If set, all fileoperations are done by the default PHP-functions. This is nescessary under Windows! On Unix the system commands by exec() can be used, unless this is disabled. 'usePHPFileFunctions' => 1, // Boolean. If set, all fileoperations are done by the default PHP-functions. Default on Unix is using the system commands by exec(). You need to set this flag under safe_mode. @@ -287,7 +287,7 @@ 'addRootLineFields' => '', // Comma-list of fields from the 'pages'-table. These fields are added to the select query for fields in the rootline. 'checkFeUserPid' => 1, // Boolean. If set, the pid of fe_user logins must be sent in the form as the field 'pid' and then the user must be located in the pid. If you unset this, you should change the fe_users.username eval-flag 'uniqueInPid' to 'unique' in $TCA. This will do: $TCA['fe_users']['columns']['username']['config']['eval']= 'nospace,lower,required,unique'; 'lockIP' => 2, // Integer (0-4). If >0, fe_users are locked to (a part of) their REMOTE_ADDR IP for their session. Enhances security but may throw off users that may change IP during their session (in which case you can lower it to 2 or 3). The integer indicates how many parts of the IP address to include in the check. Reducing to 1-3 means that only first, second or third part of the IP address is used. 4 is the FULL IP address and recommended. 0 (zero) disables checking of course. - 'loginSecurityLevel' => '', // See description for TYPO3_CONF_VARS[BE][loginSecurityLevel]. Default state for frontend is "normal". Alternative authentication services can implement higher levels if preferred. + 'loginSecurityLevel' => '', // See description for TYPO3_CONF_VARS[BE][loginSecurityLevel]. Default state for frontend is "normal". Alternative authentication services can implement higher levels if preferred. For example, "rsa" level uses RSA password encryption (only if the rsaauth extension is installed) 'lifetime' => 0, // Integer, positive. If >0, the cookie of FE users will have a lifetime of the number of seconds this value indicates. Otherwise it will be a session cookie (deleted when browser is shut down). Setting this value to 604800 will result in automatic login of FE users during a whole week, 86400 will keep the FE users logged in for a day. 'permalogin' => 2, // Integer. -1: Permanent login for FE users disabled. 0: By default permalogin is disabled for FE users but can be enabled by a form control in the login form. 1: Permanent login is by default enabled but can be disabled by a form control in the login form. // 2: Permanent login is forced to be enabled. // In any case, permanent login is only possible if TYPO3_CONF_VARS[FE][lifetime] lifetime is > 0. 'maxSessionDataSize' => 10000, // Integer. Setting the maximum size (bytes) of frontend session data stored in the table fe_session_data. Set to zero (0) means no limit, but this is not recommended since it also disables a check that session data is stored only if a confirmed cookie is set. Index: t3lib/class.t3lib_beuserauth.php =================================================================== --- t3lib/class.t3lib_beuserauth.php (revision 5368) +++ t3lib/class.t3lib_beuserauth.php (working copy) @@ -96,7 +96,6 @@ var $formfield_uident = 'userident'; // formfield with password var $formfield_chalvalue = 'challenge'; // formfield with a unique value which is used to encrypt the password and username var $formfield_status = 'login_status'; // formfield with status: *'login', 'logout' - var $security_level = 'superchallenged'; // sets the level of security. *'normal' = clear-text. 'challenged' = hashed password/username from form in $formfield_uident. 'superchallenged' = hashed password hashed again with username. var $writeStdLog = 1; // Decides if the writelog() function is called at login and logout var $writeAttemptLog = 1; // If the writelog() functions is called if a login-attempt has be tried without success @@ -140,6 +139,18 @@ /** + * Sets the security level for the Backend login + * + * @return void + */ + function start() { + $securityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']); + $this->security_level = $securityLevel ? $securityLevel : 'superchallenged'; + + parent::start(); + } + + /** * 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... * This function works ONLY with the "beuser_tracking" extension and is deprecated since it does nothing useful. * Index: t3lib/class.t3lib_userauth.php =================================================================== --- t3lib/class.t3lib_userauth.php (revision 5368) +++ t3lib/class.t3lib_userauth.php (working copy) @@ -199,7 +199,13 @@ $this->loginType = ($this->name=='fe_typo_user') ? 'FE' : 'BE'; // set level to normal if not already set - $this->security_level = $this->security_level ? $this->security_level : 'normal'; + if (!$this->security_level) { + // Notice: cannot use TYPO3_MODE here because BE user can be logged in and operate inside FE! + $this->security_level = trim($TYPO3_CONF_VARS[$this->loginType]['loginSecurityLevel']); + if (!$this->security_level) { + $this->security_level = 'normal'; + } + } // enable dev logging if set if ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['writeDevLog']) $this->writeDevLog = TRUE; @@ -332,6 +338,7 @@ if ((rand()%100) <= $this->gc_probability) { $this->gc(); } + } /** Index: typo3/index.php =================================================================== --- typo3/index.php (revision 5368) +++ typo3/index.php (working copy) @@ -119,6 +119,9 @@ * @return void */ function init() { + // We need a PHP session session for most login levels + session_start(); + $this->redirect_url = t3lib_div::_GP('redirect_url'); $this->GPinterface = t3lib_div::_GP('interface'); @@ -171,11 +174,9 @@ $TBE_TEMPLATE->bodyTagAdditions = ' onload="startUp();"'; $TBE_TEMPLATE->moduleTemplate = $TBE_TEMPLATE->getHtmlTemplate('templates/login.html'); - // Set JavaScript for creating a MD5 hash of the password: $TBE_TEMPLATE->JScode.= $this->getJScode(); - // Checking, if we should make a redirect. // Might set JavaScript in the header to close window. $this->checkRedirect(); @@ -204,15 +205,8 @@ // Add login form: $this->content.=$this->wrapLoginForm($loginForm); - // Create a random challenge string - $challenge = $this->getChallenge(); - - // Save challenge value in session data (thanks to Bernhard Kraft for providing code): - session_start(); - $_SESSION['login_challenge'] = $challenge; - // Add hidden fields and end the page - $this->content.= $this->getHiddenFields($challenge); + $this->content .= $this->getHiddenFields(); $this->content.= $TBE_TEMPLATE->endPage(); } @@ -226,13 +220,6 @@ echo $this->content; } - - - - - - - /***************************** * * Various functions @@ -355,7 +342,7 @@ if ($BE_USER->user['uid'] && ($this->commandLI || $this->loginRefresh || !$this->interfaceSelector)) { // If no cookie has been set previously we tell people that this is a problem. This assumes that a cookie-setting script (like this one) has been hit at least once prior to this instance. - if (!$_COOKIE[$BE_USER->name]) { + if (!$_COOKIE[$BE_USER->name]) { if ($this->commandLI=='setCookie') { // we tried it a second time but still no cookie // 26/4 2005: This does not work anymore, because the saving of challenge values in $_SESSION means the system will act as if the password was wrong. @@ -367,10 +354,10 @@ } } - if ($redirectToURL = (string)$BE_USER->getTSConfigVal('auth.BE.redirectToURL')) { + if (($redirectToURL = (string)$BE_USER->getTSConfigVal('auth.BE.redirectToURL'))) { $this->redirectToURL = $redirectToURL; $this->GPinterface = ''; - } + } // store interface $BE_USER->uc['interfaceSetup'] = $this->GPinterface; @@ -589,103 +576,86 @@ function startForm() { $output = ''; - if ($this->loginSecurityLevel == 'challenged') { - $output.= ' -
- '; - } elseif ($this->loginSecurityLevel == 'normal') { - $output.= ' - - '; - } else { // if ($this->loginSecurityLevel == 'superchallenged') { - $output.= ' - - '; + // The form defaults to 'no login'. This prevents plain + // text logins to the Backend. The 'sv' extension changes the form to + // use superchallenged method and rsaauth extension makes rsa authetication. + $form = ''; + + // Call hooks. If they do not return anything, we fail to login + if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginFormHook'])) { + foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginFormHook'] as $function) { + $params = array(); + $formCode = t3lib_div::callUserFunction($function, $params, $this); + if ($formCode) { + $form = $formCode; + break; + } + } } - $output.= ' - - '; + $output .= $form . + '' . + '' . + '' . + '' . + $this->interfaceSelector_hidden . $this->addFields_hidden; return $output; } /** - * Output some hidden fields at the end of the login form + * Outputs an empty string. This function is obsolete and kept for the + * compatibility only. * - * @param string The challenge string to be included in the output + * @param string $unused Unused * @return string HTML output */ - function getHiddenFields($challenge) { - $output = ' - - - - - '.$this->interfaceSelector_hidden.' - '.$this->addFields_hidden.' - '; - - return $output; + function getHiddenFields($unused = '') { + return ''; } /** - * Set JavaScript for creating a MD5 hash of the password + * Creates JavaScript for the login form * * @return string JavaScript code */ function getJScode() { - global $TBE_TEMPLATE; - - $JScode = ' - - '.$TBE_TEMPLATE->wrapScriptTags(' - function doChallengeResponse(superchallenged) { // - password = document.loginform.p_field.value; - if (password) { - if (superchallenged) { - password = MD5(password); // this makes it superchallenged!! - } - str = document.loginform.username.value+":"+password+":"+document.loginform.challenge.value; - document.loginform.userident.value = MD5(str); - document.loginform.p_field.value = ""; - return true; - } + $JSCode = ''; + if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginScriptHook'])) { + foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginScriptHook'] as $function) { + $params = array(); + $JSCode = t3lib_div::callUserFunction($function, $params, $this); + if ($JSCode) { + break; } + } + } + $JSCode .= $GLOBALS['TBE_TEMPLATE']->wrapScriptTags(' + function startUp() { + // If the login screen is shown in the login_frameset window for re-login, then try to get the username of the current/former login from opening windows main frame: + if (parent.opener && parent.opener.TS && parent.opener.TS.username && document.loginform && document.loginform.username) { + document.loginform.username.value = parent.opener.TS.username; + } - function startUp() { - // If the login screen is shown in the login_frameset window for re-login, then try to get the username of the current/former login from opening windows main frame: - if (parent.opener && parent.opener.TS && parent.opener.TS.username && document.loginform && document.loginform.username) { - document.loginform.username.value = parent.opener.TS.username; - } + // Wait a few millisecons before calling checkFocus(). This might be necessary because some browsers need some time to auto-fill in the form fields + window.setTimeout("checkFocus()", 50); + } - // Wait a few millisecons before calling checkFocus(). This might be necessary because some browsers need some time to auto-fill in the form fields - window.setTimeout("checkFocus()", 50); + // This moves focus to the right input field: + function checkFocus() { + // If for some reason there already is a username in the username form field, move focus to the password field: + if (document.loginform.username && document.loginform.username.value == "") { + document.loginform.username.focus(); + } else if (document.loginform.p_field && document.loginform.p_field.type!="hidden") { + document.loginform.p_field.focus(); } - - // This moves focus to the right input field: - function checkFocus() { - // If for some reason there already is a username in the username form field, move focus to the password field: - if (document.loginform.username && document.loginform.username.value == "") { - document.loginform.username.focus(); - } else if (document.loginform.p_field && document.loginform.p_field.type!="hidden") { - document.loginform.p_field.focus(); - } - } + } '); - return $JScode; + return $JSCode; } - - /** - * Create a random challenge string - * - * @return string Challenge value - */ - function getChallenge() { - $challenge = md5(uniqid('').getmypid()); - return $challenge; - } } Index: typo3/sysext/sv/ext_localconf.php =================================================================== --- typo3/sysext/sv/ext_localconf.php (revision 5368) +++ typo3/sysext/sv/ext_localconf.php (working copy) @@ -23,4 +23,8 @@ ) ); +// Add hooks to the backend login form +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginFormHook'][$_EXTKEY] = 'EXT:' . $_EXTKEY . '/class.tx_sv_loginformhook.php:tx_sv_loginformhook->getLoginFormTag'; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginScriptHook'][$_EXTKEY] = 'EXT:' . $_EXTKEY . '/class.tx_sv_loginformhook.php:tx_sv_loginformhook->getLoginScripts'; + ?> \ No newline at end of file Index: typo3/sysext/sv/class.tx_sv_loginformhook.php =================================================================== --- typo3/sysext/sv/class.tx_sv_loginformhook.php (revision 0) +++ typo3/sysext/sv/class.tx_sv_loginformhook.php (revision 0) @@ -0,0 +1,122 @@ + +* All rights reserved +* +* This script is part of the TYPO3 project. The TYPO3 project is +* free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* The GNU General Public License can be found at +* http://www.gnu.org/copyleft/gpl.html. +* +* This script is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* This copyright notice MUST APPEAR in all copies of the script! +***************************************************************/ + +/** + * [CLASS/FUNCTION INDEX of SCRIPT] + * + * $Id: $ + */ + + +/** + * This class contains a BE login form hook. It adds all necessary JavaScript + * for the superchallenged authentication. + * + * @author Dmitry Dulepov + * @package TYPO3 + * @subpackage tx_sv + */ +class tx_sv_loginformhook { + + /** + * Provides form code for the superchallenged authentication. + * + * @param array $params Parameters to the script + * @param SC_index $pObj Calling object + * @return string The code for the login form + */ + public function getLoginFormTag(array $params, SC_index &$pObj) { + // Get the code according to the login level + switch ($pObj->loginSecurityLevel) { + case 'challenged': + case 'superchallenged': + $_SESSION['login_challenge'] = $this->getChallenge(); + $content = '' . + ''; + break; + case 'normal': + $content = ''; + break; + default: + // No code for unknown level! + $content = ''; + } + + return $content; + } + + /** + * Provides form code for the superchallenged authentication. + * + * @param array $params Parameters to the script + * @param SC_index $pObj Calling object + * @return string The code for the login form + */ + public function getLoginScripts(array $params, SC_index &$pObj) { + $content = ''; + + if ($pObj->loginSecurityLevel == 'superchallenged' || + $pObj->loginSecurityLevel == 'challenged') { + $content = ' + + ' . $GLOBALS['TBE_TEMPLATE']->wrapScriptTags(' + function doChallengeResponse(superchallenged) { // + password = document.loginform.p_field.value; + if (password) { + if (superchallenged) { + password = MD5(password); // this makes it superchallenged!! + } + str = document.loginform.username.value+":"+password+":"+document.loginform.challenge.value; + document.loginform.userident.value = MD5(str); + document.loginform.p_field.value = ""; + return true; + } + } + '); + } + + return $content; + } + + + /** + * Create a random challenge string + * + * @return string Challenge value + */ + protected function getChallenge() { + $challenge = md5(uniqid('') . getmypid()); + return $challenge; + } + +} + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sv/class.tx_sv_loginformhook.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sv/class.tx_sv_loginformhook.php']); +} + +?> \ No newline at end of file