[!!!][TASK] Remove login security levels super-/challenged 76/39576/10
authorMarkus Klein <markus.klein@typo3.org>
Fri, 15 May 2015 23:19:59 +0000 (01:19 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 20 May 2015 10:42:19 +0000 (12:42 +0200)
* Remove (super)challenged login security levels
* Make loginSecurityLevel 'normal' the new default
* Change Backend login JS to use real submit event
* Refine hook usage of LoginController
* Remove unused code in ext:sv

Note:
OpenId login is broken due to hidden, but required, password field.
This will be resolved with the new Backend login API. #66669

Resolves: #66997
Releases: master
Change-Id: I280783588aabc78bc9bd9d1c7ee12e67bac9ed63
Reviewed-on: http://review.typo3.org/39576
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
26 files changed:
typo3/sysext/backend/Classes/AjaxLoginHandler.php
typo3/sysext/backend/Classes/AjaxRequestHandler.php
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/Controller/LoginController.php
typo3/sysext/backend/Classes/FrontendBackendUserAuthentication.php
typo3/sysext/backend/Resources/Public/JavaScript/Login.js
typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js
typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php
typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-66997-RemoveSuper-challengedPasswordSecurity.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Authentication/FrontendUserAuthentication.php
typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php
typo3/sysext/rsaauth/Classes/Hook/LoginFormHook.php
typo3/sysext/rsaauth/Documentation/Introduction/Index.rst
typo3/sysext/rsaauth/Resources/Public/JavaScript/BackendLoginFormRsaEncryption.js
typo3/sysext/rsaauth/ext_localconf.php
typo3/sysext/saltedpasswords/Classes/Utility/ExtensionManagerConfigurationUtility.php
typo3/sysext/saltedpasswords/Classes/Utility/SaltedPasswordsUtility.php
typo3/sysext/saltedpasswords/Documentation/Installation/Index.rst
typo3/sysext/sv/Classes/AbstractAuthenticationService.php
typo3/sysext/sv/Classes/AuthenticationService.php
typo3/sysext/sv/Classes/LoginFormHook.php [deleted file]
typo3/sysext/sv/Tests/Unit/AuthenticationServiceTest.php
typo3/sysext/sv/ext_localconf.php
typo3/sysext/workspaces/Classes/Controller/PreviewController.php

index 1266c0f..536f264 100644 (file)
@@ -123,19 +123,4 @@ class AjaxLoginHandler {
                }
        }
 
-       /**
-        * Gets a MD5 challenge.
-        *
-        * @param array $parameters Parameters (not used)
-        * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $parent The calling parent AJAX object
-        * @return void
-        */
-       public function getChallenge(array $parameters, \TYPO3\CMS\Core\Http\AjaxRequestHandler $parent) {
-               session_start();
-               $_SESSION['login_challenge'] = md5(uniqid('', TRUE) . getmypid());
-               session_commit();
-               $parent->addContent('challenge', $_SESSION['login_challenge']);
-               $parent->setContentFormat('json');
-       }
-
 }
index c4fa586..96bac65 100644 (file)
@@ -57,7 +57,6 @@ class AjaxRequestHandler implements RequestHandlerInterface {
                        'BackendLogin::logout',
                        'BackendLogin::refreshLogin',
                        'BackendLogin::isTimedOut',
-                       'BackendLogin::getChallenge',
                        'BackendLogin::getRsaPublicKey',
                );
 
index c59d06e..9e3af2e 100644 (file)
@@ -558,19 +558,13 @@ class BackendController {
                if (!$GLOBALS['BE_USER']->check('modules', $pageModule)) {
                        $pageModule = '';
                }
-               // Determine security level from conf vars and default to super challenged
-               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) {
-                       $this->loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'];
-               } else {
-                       $this->loginSecurityLevel = 'superchallenged';
-               }
                $t3Configuration = array(
                        'siteUrl' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL'),
                        'PATH_typo3' => $pathTYPO3,
                        'PATH_typo3_enc' => rawurlencode($pathTYPO3),
                        'username' => htmlspecialchars($GLOBALS['BE_USER']->user['username']),
                        'uniqueID' => GeneralUtility::shortMD5(uniqid('', TRUE)),
-                       'securityLevel' => $this->loginSecurityLevel,
+                       'securityLevel' => trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal',
                        'TYPO3_mainDir' => TYPO3_mainDir,
                        'pageModule' => $pageModule,
                        'inWorkspace' => $GLOBALS['BE_USER']->workspace !== 0,
index 2a6bd3b..a2b3146 100644 (file)
@@ -15,7 +15,6 @@ namespace TYPO3\CMS\Backend\Controller;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\Utility\IconUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Database\DatabaseConnection;
 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
@@ -23,6 +22,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Lang\LanguageService;
 
@@ -134,12 +134,14 @@ class LoginController {
        public $addFields_hidden = '';
 
        /**
-        * Sets the level of security. *'normal' = clear-text. 'challenged' = hashed
-        * password/username from form in $formfield_uident. 'superchallenged' = hashed password hashed again with username.
+        * Sets the level of security
+        *
+        * 'normal' = clear-text
+        * password/username from form in $formfield_uident.
         *
         * @var string
         */
-       public $loginSecurityLevel = 'superchallenged';
+       public $loginSecurityLevel = 'normal';
 
        /**
         * Constructor
@@ -171,9 +173,7 @@ class LoginController {
                // Value of "Login" button. If set, the login button was pressed.
                $this->commandLI = GeneralUtility::_GP('commandLI');
                // Sets the level of security from conf vars
-               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) {
-                       $this->loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'];
-               }
+               $this->loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal';
                // Try to get the preferred browser language
                $preferredBrowserLanguage = $this->getLanguageService()->csConvObj->getPreferredClientLanguage(GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
                // If we found a $preferredBrowserLanguage and it is not the default language and no be_user is logged in
@@ -257,7 +257,6 @@ class LoginController {
                }
 
                // Logo
-               $logo = '';
                if (!empty($extConf['loginLogo'])) {
                        $logo = $extConf['loginLogo'];
                } elseif (!empty($GLOBALS['TBE_STYLES']['logo_login'])) {
@@ -306,8 +305,7 @@ class LoginController {
                ));
 
                // Starting page:
-               $this->content .= $this->getDocumentTemplate()->startPage('TYPO3 CMS Login: ' .
-                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], FALSE);
+               $this->content .= $this->getDocumentTemplate()->startPage('TYPO3 CMS Login: ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], FALSE);
                // Add Content:
                $this->content .= $view->render();
                $this->content .= $this->getDocumentTemplate()->endPage();
@@ -330,7 +328,8 @@ class LoginController {
        /**
         * Checking, if we should perform some sort of redirection OR closing of windows.
         *
-        * @return void
+        * @throws \RuntimeException
+        * @throws \UnexpectedValueException
         */
        public function checkRedirect() {
                /*
@@ -455,7 +454,7 @@ class LoginController {
        protected function getSystemNews() {
                $systemNewsTable = 'sys_news';
                $systemNews = array();
-               $systemNewsRecords = $this->getDatabaseConntection()->exec_SELECTgetRows('title, content, crdate', $systemNewsTable, '1=1' . BackendUtility::BEenableFields($systemNewsTable) . BackendUtility::deleteClause($systemNewsTable), '', 'crdate DESC');
+               $systemNewsRecords = $this->getDatabaseConnection()->exec_SELECTgetRows('title, content, crdate', $systemNewsTable, '1=1' . BackendUtility::BEenableFields($systemNewsTable) . BackendUtility::deleteClause($systemNewsTable), '', 'crdate DESC');
                foreach ($systemNewsRecords as $systemNewsRecord) {
                        $systemNews[] = array(
                                'date' => date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $systemNewsRecord['crdate']),
@@ -472,12 +471,7 @@ class LoginController {
         * @return string Opening form tag string
         */
        public function startForm() {
-               $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 authentication.
-               $form = '<form action="index.php" method="post" name="loginform" ' . 'onsubmit="alert(\'No authentication methods available. Please, contact your TYPO3 administrator.\');return false">';
-               // Call hooks. If they do not return anything, we fail to login
+               $form = '<form action="index.php" id="typo3-login-form" method="post" name="loginform">';
                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();
@@ -488,12 +482,11 @@ class LoginController {
                                }
                        }
                }
-               $output .= $form . '<input type="hidden" name="login_status" value="login" />' .
+               return $form . '<input type="hidden" name="login_status" value="login" />' .
                        '<input type="hidden" id="t3-field-userident" class="t3js-login-userident-field" name="userident" value="" />' .
                        '<input type="hidden" name="redirect_url" value="' . htmlspecialchars($this->redirectToURL) . '" />' .
                        '<input type="hidden" name="loginRefresh" value="' . htmlspecialchars($this->loginRefresh) . '" />' .
                        $this->interfaceSelector_hidden . $this->addFields_hidden;
-               return $output;
        }
 
        /**
@@ -522,32 +515,22 @@ class LoginController {
        }
 
        /**
-        * Creates JavaScript for the login form
-        *
-        * @return string JavaScript code
-        * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
-        */
-       public function getJScode() {
-               GeneralUtility::logDeprecatedFunction();
-       }
-
-       /**
         * Checks if login credentials are currently submitted
         *
         * @return bool
         */
        protected function isLoginInProgress() {
                $username = GeneralUtility::_GP('username');
-               return !(empty($username) && empty($this->commandLI));
+               return !empty($username) || !empty($this->commandLI);
        }
 
        /**
         * Get the ObjectManager
         *
-        * @return \TYPO3\CMS\Extbase\Object\ObjectManager
+        * @return ObjectManager
         */
        protected function getObjectManager() {
-               return GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
+               return GeneralUtility::makeInstance(ObjectManager::class);
        }
 
        /**
@@ -586,7 +569,7 @@ class LoginController {
        /**
         * @return DatabaseConnection
         */
-       protected function getDatabaseConntection() {
+       protected function getDatabaseConnection() {
                return $GLOBALS['TYPO3_DB'];
        }
 
index e38874a..ddd4a0b 100644 (file)
@@ -41,13 +41,6 @@ class FrontendBackendUserAuthentication extends \TYPO3\CMS\Core\Authentication\B
        public $formfield_uident = '';
 
        /**
-        * Form field with a unique value which is used to encrypt the password and username.
-        *
-        * @var string
-        */
-       public $formfield_chalvalue = '';
-
-       /**
         * Decides if the writelog() function is called at login and logout.
         *
         * @var bool
index e7949fb..d09a587 100755 (executable)
@@ -17,6 +17,7 @@
 define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable', 'bootstrap'], function($) {
        var BackendLogin = {
                options: {
+                       loginForm: '#typo3-login-form',
                        interfaceField: '.t3js-login-interface-field',
                        interfaceSection: '.t3js-login-interface-section',
                        usernameField: '.t3js-login-username-field',
@@ -31,7 +32,8 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
                        errorNoCookies: '.t3js-login-error-nocookies',
                        formFields: '.t3js-login-formfields',
                        switchOpenIdSelector: '.t3js-login-switch-to-openid',
-                       switchDefaultSelector: '.t3js-login-switch-to-default'
+                       switchDefaultSelector: '.t3js-login-switch-to-default',
+                       submitHandler: null
                }
        },
        options = BackendLogin.options;
@@ -57,8 +59,8 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
                } else if (ev.modifiers) {
                        shift_status = !!(ev.modifiers & 4);
                }
-               return (((which >= 65 && which <= 90) && !shift_status) ||
-                       ((which >= 97 && which <= 122) && shift_status));
+               return (which >= 65 && which <= 90 && !shift_status)
+                       || (which >= 97 && which <= 122 && shift_status);
        };
 
        /**
@@ -112,6 +114,32 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
        };
 
        /**
+        * Pass on to registered submit handler
+        *
+        * @param event
+        */
+       BackendLogin.handleSubmit = function(event) {
+               "use strict";
+
+               BackendLogin.showLoginProcess();
+
+               if (BackendLogin.options.submitHandler) {
+                       BackendLogin.options.submitHandler(event);
+               }
+       };
+
+       /**
+        * Reset user password field to prevent it from being submitted
+        */
+       BackendLogin.resetPassword = function() {
+               "use strict";
+
+               var $passwordField = $(BackendLogin.options.passwordField);
+               $(BackendLogin.options.useridentField).val($passwordField.val());
+               $passwordField.val('');
+       };
+
+       /**
         * Store a login type in a cookie to save it for future visits
         * Login type means whether you login by username/password or OpenID
         */
@@ -164,11 +192,7 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
         * To prevent its unintented use when typing the password, the user is warned when Capslock is on
         */
        BackendLogin.showCapsLockWarning = function($alertIconElement, event) {
-               if (BackendLogin.isCapslockEnabled(event) === true) {
-                       $alertIconElement.removeClass('hidden');
-               } else {
-                       $alertIconElement.addClass('hidden');
-               }
+               $alertIconElement.toggleClass('hidden', !BackendLogin.isCapslockEnabled(event));
        };
 
        /**
@@ -218,11 +242,14 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
         * Registers listeners for the Login Interface (e.g. to toggle OpenID and Default login)
         */
        BackendLogin.initializeEvents = function() {
-               $(document).on('click', options.switchOpenIdSelector, BackendLogin.switchToOpenId);
-               $(document).on('click', options.switchDefaultSelector, BackendLogin.switchToDefault);
-               $(document).on('click', options.submitButton, BackendLogin.showLoginProcess);
+               // register default submit handler
+               BackendLogin.options.submitHandler = BackendLogin.resetPassword;
+
+               $(options.switchOpenIdSelector).on('click', BackendLogin.switchToOpenId);
+               $(options.switchDefaultSelector).on('click', BackendLogin.switchToDefault);
+               $(options.loginForm).on('submit', BackendLogin.handleSubmit);
 
-                       // The Interface selector is not always present, so this check is needed
+               // The Interface selector is not always present, so this check is needed
                if ($(options.interfaceField).length > 0) {
                        $(document).on('change blur', options.interfaceField, BackendLogin.interfaceSelectorChanged);
                }
@@ -274,4 +301,4 @@ define('TYPO3/CMS/Backend/Login', ['jquery', 'TYPO3/CMS/Backend/jquery.clearable
                TYPO3.BackendLogin = BackendLogin;
                return BackendLogin;
        }();
-});
\ No newline at end of file
+});
index fc484b4..2846cdb 100644 (file)
@@ -200,8 +200,7 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) {
                                        $('<input />', {type: 'password', name: 'p_field', autofocus: 'autofocus', class: 'form-control', placeholder: TYPO3.LLL.core.refresh_login_password})
                                ),
                                $('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}),
-                               $('<input />', {type: 'hidden', name: 'userident'}),
-                               $('<input />', {type: 'hidden', name: 'challenge'})
+                               $('<input />', {type: 'hidden', name: 'userident'})
                        )
                );
                LoginRefresh.$loginForm.find('.modal-footer').append(
@@ -303,22 +302,6 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) {
                e.preventDefault();
 
                switch (TYPO3.configuration.securityLevel) {
-                       case 'superchallenged':
-                       case 'challenged':
-                               $.ajax({
-                                       url: TYPO3.settings.ajaxUrls['BackendLogin::getChallenge'],
-                                       method: 'GET',
-                                       data: {
-                                               skipSessionUpdate: 1
-                                       },
-                                       success: function(response) {
-                                               if (response.challenge) {
-                                                       LoginRefresh.$loginForm.find('input[name=challenge]').val(response.challenge);
-                                                       LoginRefresh.submitForm();
-                                               }
-                                       }
-                               });
-                               break;
                        case 'rsa':
                                $.ajax({
                                        url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'],
@@ -344,9 +327,7 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) {
         */
        LoginRefresh.submitForm = function(parameters) {
                var $form = LoginRefresh.$loginForm.find('form'),
-                       $usernameField = $form.find('input[name=username]'),
                        $passwordField = $form.find('input[name=p_field]'),
-                       $challengeField = $form.find('input[name=challenge]'),
                        $useridentField = $form.find('input[name=userident]'),
                        passwordFieldValue = $passwordField.val();
 
@@ -356,14 +337,7 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) {
                        return;
                }
 
-               if (TYPO3.configuration.securityLevel === 'superchallenged') {
-                       $passwordField.val(MD5(passwordFieldValue));
-               }
-
-               if (TYPO3.configuration.securityLevel === 'superchallenged' || TYPO3.configuration.securityLevel === 'challenged') {
-                       $challengeField.val(parameters.challenge);
-                       $useridentField.val(MD5($usernameField.val() + ':' + passwordFieldValue + ':' + parameters.challenge));
-               } else if (TYPO3.configuration.securityLevel === 'rsa') {
+               if (TYPO3.configuration.securityLevel === 'rsa') {
                        var rsa = new RSAKey();
                        rsa.setPublic(parameters.publicKeyModulus, parameters.exponent);
                        var encryptedPassword = rsa.encrypt(passwordFieldValue);
index 2878a46..05a76b7 100644 (file)
@@ -128,12 +128,6 @@ abstract class AbstractUserAuthentication {
        public $formfield_uident = '';
 
        /**
-        * Form field with a unique value which is used to encrypt the password and username
-        * @var string
-        */
-       public $formfield_chalvalue = '';
-
-       /**
         * Form field with status: *'login', 'logout'. If empty login is not verified.
         * @var string
         */
@@ -315,13 +309,6 @@ abstract class AbstractUserAuthentication {
        protected $cookieWasSetOnCurrentRequest = FALSE;
 
        /**
-        * If set, the challenge value will be stored in a session as well,
-        * so the server can check that is was not forged.
-        * @var bool
-        */
-       public $challengeStoredInCookie = FALSE;
-
-       /**
         * Login type, used for services.
         * @var string
         */
@@ -1271,12 +1258,10 @@ abstract class AbstractUserAuthentication {
                        $loginData['status'] = GeneralUtility::_GP($this->formfield_status);
                        $loginData['uname'] = GeneralUtility::_GP($this->formfield_uname);
                        $loginData['uident'] = GeneralUtility::_GP($this->formfield_uident);
-                       $loginData['chalvalue'] = GeneralUtility::_GP($this->formfield_chalvalue);
                } else {
                        $loginData['status'] = GeneralUtility::_POST($this->formfield_status);
                        $loginData['uname'] = GeneralUtility::_POST($this->formfield_uname);
                        $loginData['uident'] = GeneralUtility::_POST($this->formfield_uident);
-                       $loginData['chalvalue'] = GeneralUtility::_POST($this->formfield_chalvalue);
                }
                // Only process the login data if a login is requested
                if ($loginData['status'] === 'login') {
@@ -1296,9 +1281,7 @@ abstract class AbstractUserAuthentication {
         * @internal
         */
        public function processLoginData($loginData, $passwordTransmissionStrategy = '') {
-               $loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS'][$this->loginType]['loginSecurityLevel']
-                       ? trim($GLOBALS['TYPO3_CONF_VARS'][$this->loginType]['loginSecurityLevel'])
-                       : 'normal';
+               $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS'][$this->loginType]['loginSecurityLevel']) ?: 'normal';
                $passwordTransmissionStrategy = $passwordTransmissionStrategy ?: $loginSecurityLevel;
                if ($this->writeDevLog) {
                        GeneralUtility::devLog('Login data before processing: ' . GeneralUtility::arrayToLogString($loginData), \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::class);
@@ -1373,34 +1356,7 @@ abstract class AbstractUserAuthentication {
         * @return bool TRUE if login data matched
         */
        public function compareUident($user, $loginData, $passwordCompareStrategy = '') {
-               $OK = FALSE;
-               switch ($passwordCompareStrategy) {
-                       case 'superchallenged':
-
-                       case 'challenged':
-                               // Check challenge stored in cookie:
-                               if ($this->challengeStoredInCookie) {
-                                       session_start();
-                                       if ($_SESSION['login_challenge'] !== $loginData['chalvalue']) {
-                                               if ($this->writeDevLog) {
-                                                       GeneralUtility::devLog('PHP Session stored challenge "' . $_SESSION['login_challenge'] . '" and submitted challenge "' . $loginData['chalvalue'] . '" did not match, so authentication failed!', \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::class, 2);
-                                               }
-                                               $this->logoff();
-                                               return FALSE;
-                                       }
-                               }
-                               $compareStrategyHash = md5($user[$this->username_column] . ':' . $user[$this->userident_column] . ':' . $loginData['chalvalue']);
-                               if ((string)$loginData[('uident_' . $passwordCompareStrategy)] === $compareStrategyHash) {
-                                       $OK = TRUE;
-                               }
-                               break;
-                       default:
-                               // normal
-                               if ((string)$loginData['uident_text'] === (string)$user[$this->userident_column]) {
-                                       $OK = TRUE;
-                               }
-               }
-               return $OK;
+               return (string)$loginData['uident_text'] === (string)$user[$this->userident_column];
        }
 
        /**
index c4a1381..76584d3 100644 (file)
@@ -244,12 +244,6 @@ class BackendUserAuthentication extends \TYPO3\CMS\Core\Authentication\AbstractU
        public $formfield_uident = 'userident';
 
        /**
-        * Form field with a unique value which is used to encrypt the password and username
-        * @var string
-        */
-       public $formfield_chalvalue = 'challenge';
-
-       /**
         * Form field with status: *'login', 'logout'
         * @var string
         */
@@ -276,11 +270,6 @@ class BackendUserAuthentication extends \TYPO3\CMS\Core\Authentication\AbstractU
        public $auth_timeout_field = 6000;
 
        /**
-        * @var bool
-        */
-       public $challengeStoredInCookie = TRUE;
-
-       /**
         * @var int
         */
        public $firstMainGroup = 0;
index 18c1c83..675064b 100644 (file)
@@ -331,7 +331,7 @@ return array(
                'lockHashKeyWords' => 'useragent',                              // Keyword list (Strings comma separated). Currently only "useragent"; If set, then the BE user session is locked to the value of HTTP_USER_AGENT. This lowers the risk of session hi-jacking. However in some cases (like during development) you might need to switch the user agent while keeping the session. In this case you can disable that feature (e.g. with a blank string).
                'cookieDomain' => '',                                                   // Same as <a href="#SYS-cookieDomain">$TYPO3_CONF_VARS['SYS']['cookieDomain']</a> but only for BE cookies. If empty, $TYPO3_CONF_VARS['SYS']['cookieDomain'] value will be used.
                'cookieName' => 'be_typo_user',                                 // String: Set the name for the cookie used for the back-end user session
-               '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.
+               '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, "rsa" uses RSA password encryption (only if the rsaauth extension is installed).
                'showRefreshLoginPopup' => FALSE,                               // Boolean: If set, the Ajax relogin will show a real popup window for relogin after the count down. Some auth services need this as they add custom validation to the login form. If it's not set, the Ajax relogin will show an inline relogin window.
                'adminOnly' => 0,                                                               // <p>Integer (-1, 0, 1, 2)</p><dl><dt>-1</dt><dd>total shutdown for maintenance purposes</dd><dt>0</dt><dd>normal operation, everyone can login (default)</dd><dt>1</dt><dd>only admins can login</dd><dt>2</dt><dd>only admins and regular CLI users can login</dd></dl>
                'disable_exec_function' => FALSE,                               // Boolean: Don't use exec() function (except for ImageMagick which is disabled by <a href="#GFX-im">[GFX][im]</a>=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.
@@ -711,11 +711,6 @@ return array(
                                // Needs to be unprotected
                                'csrfTokenCheck' => FALSE
                        ),
-                       'BackendLogin::getChallenge' => array(
-                               'callbackMethod' => \TYPO3\CMS\Backend\AjaxLoginHandler::class . '->getChallenge',
-                               // Needs to be unprotected
-                               'csrfTokenCheck' => FALSE
-                       ),
                        'ExtDirect::getAPI' => array(
                                'callbackMethod' => \TYPO3\CMS\Core\ExtDirect\ExtDirectApi::class . '->getAPI',
                                // No need to be CSRF protected
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-66997-RemoveSuper-challengedPasswordSecurity.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-66997-RemoveSuper-challengedPasswordSecurity.rst
new file mode 100644 (file)
index 0000000..6abcfcc
--- /dev/null
@@ -0,0 +1,46 @@
+=============================================================
+Breaking: #66997 - Remove super-/challenged password security
+=============================================================
+
+Description
+===========
+
+TYPO3 CMS supports four possibilities how passwords can be sent from the browser to the server:
+
+- "normal": Plain text
+- "challenged": md5 hashed
+- "superchallenged": md5 hashed
+- "rsa": asymmetric encryption
+
+Since TYPO3 CMS 6.2 the password transmission is protected by the rsaauth-extension by default ("rsa"),
+which renders the old protection mechanisms "superchallenged" and "challenged" useless.
+
+If the Backend login is accessed via HTTPS protocol, the "rsa" protection is redundant and can be disabled in general.
+
+The super-/challenged options are removed, as "rsa" and "normal" are sufficient.
+If rsaauth was not installed the default has been "superchallenged". The new default is "normal" now.
+
+
+Impact
+======
+
+If an installation has rsaauth disabled, the password transfer is now **Plain Text**.
+
+Any code relying on or checking for the "superchallenged" or "challenged" option
+of ``[BE][loginSecurityLevel]`` or ``[FE][loginSecurityLevel]``, will not work as expected.
+
+
+Affected Installations
+======================
+
+Any installation having set ``[BE][loginSecurityLevel]`` or ``[FE][loginSecurityLevel]`` to an empty string or to either of "superchallenged" or "challenged".
+
+
+Migration
+=========
+
+Make sure you access the Backend via HTTPS or install the rsaauth system extension.
+
+Also refer to the `TYPO3 Security Guide`_
+
+.. _TYPO3 Security Guide: http://docs.typo3.org/typo3cms/SecurityGuide/GuidelinesAdministrators/EncryptedCommunication/Index.html
index 1e53e43..63b2745 100644 (file)
@@ -141,7 +141,6 @@ class FrontendUserAuthentication extends AbstractUserAuthentication {
                );
                $this->formfield_uname = 'user';
                $this->formfield_uident = 'pass';
-               $this->formfield_chalvalue = 'challenge';
                $this->formfield_status = 'logintype';
                $this->auth_timeout_field = 6000;
                $this->sendNoCacheHeaders = FALSE;
index ae66bbb..02fded0 100644 (file)
@@ -134,28 +134,20 @@ class SilentConfigurationUpgradeService {
         * @return void
         */
        protected function configureBackendLoginSecurity() {
+               $rsaauthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
                try {
                        $currentLoginSecurityLevelValue = $this->configurationManager->getLocalConfigurationValueByPath('BE/loginSecurityLevel');
-                       if (ExtensionManagementUtility::isLoaded('rsaauth')
-                               && $currentLoginSecurityLevelValue !== 'rsa'
-                       ) {
+                       if ($rsaauthLoaded && $currentLoginSecurityLevelValue !== 'rsa') {
                                $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
                                $this->throwRedirectException();
-                       } elseif (!ExtensionManagementUtility::isLoaded('rsaauth')
-                               && $currentLoginSecurityLevelValue !== 'normal'
-                       ) {
+                       } elseif (!$rsaauthLoaded && $currentLoginSecurityLevelValue !== 'normal') {
                                $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
                                $this->throwRedirectException();
                        }
                } catch (\RuntimeException $e) {
                        // If an exception is thrown, the value is not set in LocalConfiguration
-                       if (ExtensionManagementUtility::isLoaded('rsaauth')) {
-                               $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
-                               $this->throwRedirectException();
-                       } elseif (!ExtensionManagementUtility::isLoaded('rsaauth')) {
-                               $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
-                               $this->throwRedirectException();
-                       }
+                       $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', $rsaauthLoaded ? 'rsa' : 'normal');
+                       $this->throwRedirectException();
                }
        }
 
index b062bf3..b20fa98 100644 (file)
@@ -13,6 +13,9 @@ namespace TYPO3\CMS\Rsaauth\Hook;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Backend\Controller\LoginController;
+use TYPO3\CMS\Backend\Template\DocumentTemplate;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 
 /**
  * This class provides a hook to the login form to add extra javascript code
@@ -24,34 +27,35 @@ namespace TYPO3\CMS\Rsaauth\Hook;
 class LoginFormHook {
 
        /**
-        * Adds RSA-specific JavaScript and returns a form tag
+        * Adds RSA-specific JavaScript
         *
         * @param array $params
-        * @param \TYPO3\CMS\Backend\Controller\LoginController $pObj
-        * @return string|NULL Form tag or NULL if security level is not rsa
+        * @param LoginController $pObj
+        * @return string|NULL Dummy JS or NULL if security level is not rsa
         */
-       public function getLoginFormTag(array $params, \TYPO3\CMS\Backend\Controller\LoginController &$pObj) {
-               $form = NULL;
-               if ($pObj->loginSecurityLevel === 'rsa') {
-                       /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
-                       $pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
-                       $javascriptPath = '../' . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/';
-                       $files = array(
-                               'jsbn/jsbn.js',
-                               'jsbn/prng4.js',
-                               'jsbn/rng.js',
-                               'jsbn/rsa.js',
-                               'jsbn/base64.js'
-                       );
-                       foreach ($files as $file) {
-                               $pageRenderer->addJsFile($javascriptPath . $file);
-                       }
-
-                       $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption');
+       public function getLoginFormJS(array $params, LoginController $pObj) {
+               if ($pObj->loginSecurityLevel !== 'rsa') {
+                       return NULL;
+               }
+               $javascriptPath = '../' . ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/';
+               $files = array(
+                       'jsbn/jsbn.js',
+                       'jsbn/prng4.js',
+                       'jsbn/rng.js',
+                       'jsbn/rsa.js',
+                       'jsbn/base64.js'
+               );
 
-                       return '<form action="index.php" id="typo3-login-form" method="post" name="loginform">';
+               /** @var DocumentTemplate $doc */
+               $doc = $GLOBALS['TBE_TEMPLATE'];
+               $pageRenderer = $doc->getPageRenderer();
+               foreach ($files as $file) {
+                       $pageRenderer->addJsFile($javascriptPath . $file);
                }
-               return $form;
+
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption');
+
+               return '// no content';
        }
 
 }
index 4f49655..6d476e1 100644 (file)
@@ -18,13 +18,10 @@ Introduction
 What does it do?
 ^^^^^^^^^^^^^^^^
 
-This extension adds encrypted authentication for Frontend and Backend
-logins to TYPO3. It is safer than plain text Frontend authentication
-or superchallenged Backend authentication because it uses one time
-generated public and private key pair. The password is encrypted with a
-new public key each time before it is transferred over the network.
-Next the password is decrypted on the server using one time generated
-private key.
+This extension adds encrypted authentication for Frontend and Backend logins to TYPO3.
+It is safer than plain text authentication because it uses a one time generated public and private key pair.
+The password is encrypted with a new public key each time before it is transferred over the network.
+Next the password is decrypted on the server using one time generated private key.
 
 Frontend RSA authentication works with the system extension
 :code:`felogin` only.
index 8785a15..4fd4a63 100644 (file)
@@ -29,15 +29,19 @@ define('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', ['jquery', 'TYPO3/CMS/
                typo3PasswordField: false,
 
                /**
+                * Remember if we fetched the RSA key already
+                */
+               fetchedRsaKey: false,
+
+               /**
                 * Replace event handler of submit button
                 */
                initialize: function() {
                        this.userPasswordField = BackendLogin.options.passwordField;
                        this.typo3PasswordField = BackendLogin.options.useridentField;
+                       this.loginForm = BackendLogin.options.loginForm;
 
-                       $(document).off('click', BackendLogin.options.submitButton, BackendLogin.showLoginProcess);
-                       $(document).on('click', BackendLogin.options.submitButton, this.handleFormSubmitRequest);
-                       return this;
+                       BackendLogin.options.submitHandler = this.handleFormSubmitRequest;
                },
 
                /**
@@ -46,16 +50,24 @@ define('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', ['jquery', 'TYPO3/CMS/
                 * @param event
                 */
                handleFormSubmitRequest: function(event) {
-                       event.preventDefault();
+                       if (!RsaBackendLogin.fetchedRsaKey) {
+                               RsaBackendLogin.fetchedRsaKey = true;
 
-                       BackendLogin.showLoginProcess();
+                               event.preventDefault();
 
-                       $.ajax({
-                               url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'],
-                               data: {'skipSessionUpdate': 1},
-                               success: RsaBackendLogin.handlePublicKeyResponse,
-                               dataType: 'json'
-                       });
+                               BackendLogin.showLoginProcess();
+
+                               $.ajax({
+                                       url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'],
+                                       data: {'skipSessionUpdate': 1},
+                                       success: RsaBackendLogin.handlePublicKeyResponse,
+                                       dataType: 'json'
+                               });
+                       } else {
+                               // we come here again when the submit is triggered below
+                               // reset the variable to fetch a new key for next attempt
+                               RsaBackendLogin.fetchedRsaKey = false;
+                       }
                },
 
                /**
@@ -64,19 +76,11 @@ define('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', ['jquery', 'TYPO3/CMS/
                 * @param publicKey Ajax response object
                 */
                handlePublicKeyResponse: function(publicKey) {
-                       if (publicKey.publicKeyModulus && publicKey.exponent) {
-                               RsaBackendLogin.encryptPasswordAndSubmitForm(publicKey);
-                       } else {
+                       if (!publicKey.publicKeyModulus || !publicKey.exponent) {
                                alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
+                               return;
                        }
-               },
 
-               /**
-                * Uses the public key with the RSA library to encrypt the password.
-                *
-                * @param publicKey
-                */
-               encryptPasswordAndSubmitForm: function(publicKey) {
                        var rsa = new RSAKey();
                        rsa.setPublic(publicKey.publicKeyModulus, publicKey.exponent);
                        var encryptedPassword = rsa.encrypt($(RsaBackendLogin.userPasswordField).val());
@@ -85,7 +89,7 @@ define('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', ['jquery', 'TYPO3/CMS/
                        $(RsaBackendLogin.userPasswordField).val('');
                        $(RsaBackendLogin.typo3PasswordField).val('rsa:' + hex2b64(encryptedPassword));
 
-                       var $formElement = $('form:first');
+                       var $formElement = $(RsaBackendLogin.loginForm);
 
                        // Create a hidden input field to fake pressing the submit button
                        $formElement.append('<input type="hidden" name="commandLI" value="Submit">');
@@ -94,5 +98,6 @@ define('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', ['jquery', 'TYPO3/CMS/
                        $formElement.trigger('submit');
                }
        };
+
        RsaBackendLogin.initialize();
 });
index 63a4742..e5b66ab 100644 (file)
@@ -18,7 +18,7 @@ defined('TYPO3_MODE') or die();
 ));
 
 // Add a hook to the BE login form
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginFormHook']['rsaauth'] = \TYPO3\CMS\Rsaauth\Hook\LoginFormHook::class . '->getLoginFormTag';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginScriptHook']['rsaauth'] = \TYPO3\CMS\Rsaauth\Hook\LoginFormHook::class . '->getLoginFormJS';
 // Add hook for user setup module
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['setupScriptHook']['rsaauth'] = \TYPO3\CMS\Rsaauth\Hook\UserSetupHook::class . '->getLoginScripts';
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['modifyUserDataBeforeSave']['rsaauth'] = \TYPO3\CMS\Rsaauth\Hook\UserSetupHook::class . '->decryptPassword';
@@ -34,7 +34,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['displ
 );
 
 // eID for FrontendLoginRsaPublicKey
-$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['FrontendLoginRsaPublicKey'] =
-       'EXT:rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php';
+$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['FrontendLoginRsaPublicKey'] = 'EXT:rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php';
 
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructPostProcess'][] = \TYPO3\CMS\Rsaauth\Hook\BackendHookForAjaxLogin::class . '->addRsaJsLibraries';
index af2cb42..a9d51b5 100644 (file)
@@ -168,17 +168,15 @@ class ExtensionManagerConfigurationUtility {
                $this->init();
                $extConf = $this->extConf['BE'];
                // The backend is called over SSL
-               $isBackendCalledOverSsl = (
-                       (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] > 0
-                       && $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'] !== 'superchallenged'
-               );
+               $isBackendCalledOverSsl = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] > 0;
                $rsaAuthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
                // SSL configured?
                if ($isBackendCalledOverSsl) {
                        $this->setErrorLevel('ok');
                        $problems[] = 'The backend is configured to use SaltedPasswords over SSL.';
                } elseif ($rsaAuthLoaded) {
-                       if (trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) === 'rsa') {
+                       $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal';
+                       if ($loginSecurityLevel === 'rsa') {
                                if ($this->isRsaAuthBackendAvailable()) {
                                        $this->setErrorLevel('ok');
                                        $problems[] = 'The backend is configured to use SaltedPasswords with RSA authentication.';
@@ -293,8 +291,8 @@ class ExtensionManagerConfigurationUtility {
                $extConf = $this->extConf['FE'];
                $problems = array();
                if ($extConf['enabled']) {
-                       // Inform the user if securityLevel in FE is challenged or blank --> extension won't work
-                       if (!GeneralUtility::inList('normal,rsa', $GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel'])) {
+                       $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel']) ?: 'normal';
+                       if (!GeneralUtility::inList('normal,rsa', $loginSecurityLevel)) {
                                $this->setErrorLevel('info');
                                $problems[] = '<strong>IMPORTANT:</strong><br />
                                        Frontend requirements for SaltedPasswords are not met, therefore the
@@ -302,16 +300,14 @@ class ExtensionManagerConfigurationUtility {
                                        usage:<br />
                                        <ul>
                                                <li>Install the "rsaauth" extension and use the Install Tool to set the
-                                                       Login Security Level for the frontend to "rsa"
+                                                       Login Security Level for the frontend to "rsa".
                                                        ($TYPO3_CONF_VARS[\'FE\'][\'loginSecurityLevel\'])</li>
 
                                                <li>Alternatively, use the Install Tool to set the Login Security Level
-                                                       for the frontend to "normal"
+                                                       for the frontend to "normal".
                                                        ($TYPO3_CONF_VARS[\'FE\'][\'loginSecurityLevel\'])</li>
-                                       </ul>
-                                       <br />
-                                       Make sure that the Login Security Level is not set to "" or "challenged"!';
-                       } elseif (trim($GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel']) === 'rsa') {
+                                       </ul>';
+                       } elseif ($loginSecurityLevel === 'rsa') {
                                if (ExtensionManagementUtility::isLoaded('rsaauth')) {
                                        if ($this->isRsaAuthBackendAvailable()) {
                                                $this->setErrorLevel('ok');
index c8684a6..75612ad 100644 (file)
@@ -13,6 +13,7 @@ namespace TYPO3\CMS\Saltedpasswords\Utility;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * General library class.
@@ -120,11 +121,11 @@ class SaltedPasswordsUtility {
        static public function isUsageEnabled($mode = TYPO3_MODE) {
                // Login Security Level Recognition
                $extConf = self::returnExtConf($mode);
-               $securityLevel = $GLOBALS['TYPO3_CONF_VARS'][$mode]['loginSecurityLevel'];
-               if ($mode == 'BE') {
+               $securityLevel = trim($GLOBALS['TYPO3_CONF_VARS'][$mode]['loginSecurityLevel']) ?: 'normal';
+               if ($mode === 'BE') {
                        return TRUE;
-               } elseif ($mode == 'FE' && $extConf['enabled']) {
-                       return \TYPO3\CMS\Core\Utility\GeneralUtility::inList('normal,rsa', $securityLevel);
+               } elseif ($mode === 'FE' && $extConf['enabled']) {
+                       return GeneralUtility::inList('normal,rsa', $securityLevel);
                }
                return FALSE;
        }
index ade8f50..edd5761 100644 (file)
@@ -20,10 +20,7 @@ Installing the extension
 
 Install the extension in the Extension Manager!
 
-As TYPO3 by default uses a superchallenged method for authentication
-but Salted user password hashes requires plain-text passwords on
-server side (outlined in previous chapter), you need to change that.
-So please open the  **TYPO3 install tool** . Depending on which TYPO3
+Please open the  **TYPO3 install tool** . Depending on which TYPO3
 mode (FE or BE) you like to use salted user password hashes for,
 please change the according "**loginSecurityLevel**" configuration
 variable! A valid setting for working salted user password hashes are
@@ -36,12 +33,10 @@ variable! A valid setting for working salted user password hashes are
   channel)
 
 Now return back to the Extension manager and again open the extension
-configuration for system extension "Salted user password
-hashes" (saltedpasswords)!
+configuration for system extension "Salted user password hashes" (saltedpasswords)!
 
 Depending on which TYPO3 mode (FE or BE) you like to use salted user
-password hashes for, activate the according **checkbox** "**Enable
-FE**" or "**Enable BE**"!
+password hashes for, activate the according **checkbox** "**Enable FE**" or "**Enable BE**"!
 
 Additionally, you might want to change the hashing method. See
 previous chapter for an explanation on when to use which method.
index 4cdf92d..5d807af 100644 (file)
@@ -110,16 +110,6 @@ class AbstractAuthenticationService extends AbstractService {
         * @return bool TRUE if login data matched
         */
        public function compareUident(array $user, array $loginData, $passwordCompareStrategy = '') {
-               if ($this->authInfo['loginType'] === 'BE') {
-                       // Challenge is only stored in session during BE login with the superchallenged login type.
-                       // In the frontend context the challenge is never stored in the session.
-                       if ($passwordCompareStrategy !== 'superchallenged') {
-                               $this->pObj->challengeStoredInCookie = FALSE;
-                       }
-                       // The TYPO3 standard login service relies on $passwordCompareStrategy being set
-                       // to 'superchallenged' because of the password in the database is stored as md5 hash
-                       $passwordCompareStrategy = 'superchallenged';
-               }
                return $this->pObj->compareUident($user, $loginData, $passwordCompareStrategy);
        }
 
index eee657a..43577b8 100644 (file)
@@ -32,28 +32,9 @@ class AuthenticationService extends AbstractAuthenticationService {
         * @return bool
         */
        public function processLoginData(array &$loginData, $passwordTransmissionStrategy) {
-               $isProcessed = TRUE;
-               // Processing data according to the state it was submitted in.
-               switch ($passwordTransmissionStrategy) {
-                       case 'normal':
-                               $loginData['uident_text'] = $loginData['uident'];
-                               break;
-                       case 'challenged':
-                               $loginData['uident_text'] = '';
-                               $loginData['uident_challenged'] = $loginData['uident'];
-                               $loginData['uident_superchallenged'] = '';
-                               break;
-                       case 'superchallenged':
-                               $loginData['uident_text'] = '';
-                               $loginData['uident_challenged'] = '';
-                               $loginData['uident_superchallenged'] = $loginData['uident'];
-                               break;
-                       default:
-                               $isProcessed = FALSE;
-               }
-               if (!empty($loginData['uident_text'])) {
-                       $loginData['uident_challenged'] = (string)md5(($loginData['uname'] . ':' . $loginData['uident_text'] . ':' . $loginData['chalvalue']));
-                       $loginData['uident_superchallenged'] = (string)md5(($loginData['uname'] . ':' . md5($loginData['uident_text']) . ':' . $loginData['chalvalue']));
+               $isProcessed = FALSE;
+               if ($passwordTransmissionStrategy === 'normal') {
+                       $loginData['uident_text'] = $loginData['uident'];
                        $isProcessed = TRUE;
                }
                return $isProcessed;
@@ -65,24 +46,27 @@ class AuthenticationService extends AbstractAuthenticationService {
         * @return mixed User array or FALSE
         */
        public function getUser() {
-               $user = FALSE;
-               if ($this->login['status'] === 'login') {
-                       if ($this->login['uident']) {
-                               $user = $this->fetchUserRecord($this->login['uname']);
-                               if (!is_array($user)) {
-                                       // Failed login attempt (no username found)
-                                       $this->writelog(255, 3, 3, 2, 'Login-attempt from %s (%s), username \'%s\' not found!!', array($this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']));
-                                       // Logout written to log
-                                       GeneralUtility::sysLog(sprintf('Login-attempt from %s (%s), username \'%s\' not found!', $this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']), 'Core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
-                               } else {
-                                       if ($this->writeDevLog) {
-                                               GeneralUtility::devLog('User found: ' . GeneralUtility::arrayToLogString($user, array($this->db_user['userid_column'], $this->db_user['username_column'])), AuthenticationService::class);
-                                       }
-                               }
-                       } else {
-                               // Failed Login attempt (no password given)
-                               $this->writelog(255, 3, 3, 2, 'Login-attempt from %s (%s) for username \'%s\' with an empty password!', array($this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']));
-                               GeneralUtility::sysLog(sprintf('Login-attempt from %s (%s), for username \'%s\' with an empty password!', $this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']), 'Core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
+               if ($this->login['status'] !== 'login') {
+                       return FALSE;
+               }
+               if (!$this->login['uident']) {
+                       // Failed Login attempt (no password given)
+                       $this->writelog(255, 3, 3, 2, 'Login-attempt from %s (%s) for username \'%s\' with an empty password!', array(
+                               $this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']
+                       ));
+                       GeneralUtility::sysLog(sprintf('Login-attempt from %s (%s), for username \'%s\' with an empty password!', $this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']), 'Core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
+                       return FALSE;
+               }
+
+               $user = $this->fetchUserRecord($this->login['uname']);
+               if (!is_array($user)) {
+                       // Failed login attempt (no username found)
+                       $this->writelog(255, 3, 3, 2, 'Login-attempt from %s (%s), username \'%s\' not found!!', array($this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']));
+                       // Logout written to log
+                       GeneralUtility::sysLog(sprintf('Login-attempt from %s (%s), username \'%s\' not found!', $this->authInfo['REMOTE_ADDR'], $this->authInfo['REMOTE_HOST'], $this->login['uname']), 'Core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
+               } else {
+                       if ($this->writeDevLog) {
+                               GeneralUtility::devLog('User found: ' . GeneralUtility::arrayToLogString($user, array($this->db_user['userid_column'], $this->db_user['username_column'])), AuthenticationService::class);
                        }
                }
                return $user;
@@ -93,13 +77,13 @@ class AuthenticationService extends AbstractAuthenticationService {
         *
         * @param array $user Data of user.
         * @return int >= 200: User authenticated successfully.
-        *                         No more checking is needed by other auth services.
-        *                 >= 100: User not authenticated; this service is not responsible.
-        *                         Other auth services will be asked.
-        *                 > 0:    User authenticated successfully.
-        *                         Other auth services will still be asked.
-        *                 <= 0:   Authentication failed, no more checking needed
-        *                         by other auth services.
+        *                     No more checking is needed by other auth services.
+        *             >= 100: User not authenticated; this service is not responsible.
+        *                     Other auth services will be asked.
+        *             > 0:    User authenticated successfully.
+        *                     Other auth services will still be asked.
+        *             <= 0:   Authentication failed, no more checking needed
+        *                     by other auth services.
         */
        public function authUser(array $user) {
                $OK = 100;
diff --git a/typo3/sysext/sv/Classes/LoginFormHook.php b/typo3/sysext/sv/Classes/LoginFormHook.php
deleted file mode 100644 (file)
index 1259893..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-namespace TYPO3\CMS\Sv;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Controller\LoginController;
-
-/**
- * This class contains a BE login form hook. It adds all necessary JavaScript
- * for the superchallenged authentication.
- *
- * @author Dmitry Dulepov <dmitry@typo3.org>
- */
-class LoginFormHook {
-
-       /**
-        * Provides form code for the superchallenged authentication.
-        *
-        * @param array $params Parameters to the script
-        * @param LoginController $pObj Calling object
-        * @return string The code for the login form
-        */
-       public function getLoginFormTag(array $params, LoginController &$pObj) {
-               // Get the code according to the login level
-               switch ($pObj->loginSecurityLevel) {
-                       case 'challenged':
-                       case 'superchallenged':
-                               $_SESSION['login_challenge'] = $this->getChallenge();
-                               $content = '<form action="index.php" method="post" name="loginform" ' . 'onsubmit="doChallengeResponse(' . ($pObj->loginSecurityLevel == 'challenged' ? 0 : 1) . ');">' . '<input type="hidden" name="challenge" value="' . htmlspecialchars($_SESSION['login_challenge']) . '" />';
-                               break;
-                       case 'normal':
-                               $content = '<form action="index.php" method="post" name="loginform" onsubmit="document.loginform.userident.value=document.loginform.p_field.value;document.loginform.p_field.value=\'\';return true;">';
-                               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 LoginController $pObj Calling object
-        * @return string The code for the login form
-        */
-       public function getLoginScripts(array $params, LoginController &$pObj) {
-               $content = '';
-               if ($pObj->loginSecurityLevel === 'superchallenged' || $pObj->loginSecurityLevel === 'challenged') {
-                       $content = '
-                               <script type="text/javascript" src="sysext/backend/Resources/Public/JavaScript/md5.js"></script>
-                               ' . $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() {
-               return md5(uniqid('', TRUE) . getmypid());
-       }
-
-}
index 5d6b185..c5ef2c8 100644 (file)
@@ -33,34 +33,12 @@ class AuthenticationServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                                        'status' => 'login',
                                        'uname' => 'admin',
                                        'uident' => 'password',
-                                       'chalvalue' => NULL
                                ),
                                array(
                                        'status' => 'login',
                                        'uname' => 'admin',
                                        'uident' => 'password',
-                                       'chalvalue' => NULL,
                                        'uident_text' => 'password',
-                                       'uident_challenged' => '458203772635d38f05ca9e62d8237974',
-                                       'uident_superchallenged' => '651219fccfbe0c9004c7196515d780ce'
-                               )
-                       ),
-                       'Backend login with securityLevel "superchallenged"' => array(
-                               'superchallenged',
-                               array(
-                                       'status' => 'login',
-                                       'uname' => 'admin',
-                                       'uident' => '651219fccfbe0c9004c7196515d780ce',
-                                       'chalvalue' => NULL
-                               ),
-                               array(
-                                       'status' => 'login',
-                                       'uname' => 'admin',
-                                       'uident' => '651219fccfbe0c9004c7196515d780ce',
-                                       'chalvalue' => NULL,
-                                       'uident_text' => '',
-                                       'uident_challenged' => '',
-                                       'uident_superchallenged' => '651219fccfbe0c9004c7196515d780ce'
                                )
                        ),
                        'Frontend login with securityLevel "normal"' => array(
@@ -69,36 +47,14 @@ class AuthenticationServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                                        'status' => 'login',
                                        'uname' => 'admin',
                                        'uident' => 'password',
-                                       'chalvalue' => NULL
                                ),
                                array(
                                        'status' => 'login',
                                        'uname' => 'admin',
                                        'uident' => 'password',
-                                       'chalvalue' => NULL,
                                        'uident_text' => 'password',
-                                       'uident_challenged' => '458203772635d38f05ca9e62d8237974',
-                                       'uident_superchallenged' => '651219fccfbe0c9004c7196515d780ce'
                                )
                        ),
-                       'Frontend login with securityLevel "challenged"' => array(
-                               'challenged',
-                               array(
-                                       'status' => 'login',
-                                       'uname' => 'admin',
-                                       'uident' => '458203772635d38f05ca9e62d8237974',
-                                       'chalvalue' => NULL
-                               ),
-                               array(
-                                       'status' => 'login',
-                                       'uname' => 'admin',
-                                       'uident' => '458203772635d38f05ca9e62d8237974',
-                                       'chalvalue' => NULL,
-                                       'uident_text' => '',
-                                       'uident_challenged' => '458203772635d38f05ca9e62d8237974',
-                                       'uident_superchallenged' => ''
-                               )
-                       )
                );
        }
 
index 59d57d7..58d73ce 100644 (file)
@@ -18,6 +18,3 @@ defined('TYPO3_MODE') or die();
                'className' => \TYPO3\CMS\Sv\AuthenticationService::class
        )
 );
-// Add hooks to the backend login form
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginFormHook']['sv'] = \TYPO3\CMS\Sv\LoginFormHook::class . '->getLoginFormTag';
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/index.php']['loginScriptHook']['sv'] = \TYPO3\CMS\Sv\LoginFormHook::class . '->getLoginScripts';
index f239c02..05f6a1b 100644 (file)
@@ -197,19 +197,13 @@ class PreviewController extends AbstractController {
                if (!$GLOBALS['BE_USER']->check('modules', $pageModule)) {
                        $pageModule = '';
                }
-               // Determine security level from conf vars and default to super challenged
-               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) {
-                       $loginSecurityLevel = $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'];
-               } else {
-                       $loginSecurityLevel = 'superchallenged';
-               }
                $t3Configuration = array(
                        'siteUrl' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL'),
                        'PATH_typo3' => $pathTYPO3,
                        'PATH_typo3_enc' => rawurlencode($pathTYPO3),
                        'username' => htmlspecialchars($GLOBALS['BE_USER']->user['username']),
                        'uniqueID' => GeneralUtility::shortMD5(uniqid('', TRUE)),
-                       'securityLevel' => $loginSecurityLevel,
+                       'securityLevel' => trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal',
                        'TYPO3_mainDir' => TYPO3_mainDir,
                        'pageModule' => $pageModule,
                        'inWorkspace' => $GLOBALS['BE_USER']->workspace !== 0,