[TASK] Remove saltedpasswords bulk update task 77/56977/5
authorChristian Kuhn <lolli@schwarzbu.ch>
Wed, 16 May 2018 09:45:09 +0000 (11:45 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 16 May 2018 12:54:06 +0000 (14:54 +0200)
This patch is one step into merging the salted passwords
extension code into the core extension, starting with removing
obsolete stuff: The bulk update task is a use-once-throw-away
task aimed to help upgrading systems older than 10 years.
It is removed now. The patch includes an extensive
important ReST file explaining details and alternatives.

Change-Id: I2e9064438e0ac257e95bb0768860f587d8e29375
Resolves: #85022
Releases: master
Reviewed-on: https://review.typo3.org/56977
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
12 files changed:
typo3/sysext/core/Documentation/Changelog/master/Feature-79889-SaltedpasswordsSupportPHPPasswordAPI.rst
typo3/sysext/core/Documentation/Changelog/master/Important-85022-SaltedpasswordsBulkUpdateTaskRemoved.rst [new file with mode: 0644]
typo3/sysext/saltedpasswords/Classes/Salt/Md5Salt.php
typo3/sysext/saltedpasswords/Classes/Salt/PhpassSalt.php
typo3/sysext/saltedpasswords/Classes/Salt/SaltInterface.php
typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateFieldProvider.php [deleted file]
typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateTask.php [deleted file]
typo3/sysext/saltedpasswords/Resources/Private/Language/locallang.xlf
typo3/sysext/saltedpasswords/Resources/Private/Language/locallang_csh_saltedpasswords.xlf [deleted file]
typo3/sysext/saltedpasswords/Tests/Functional/Task/BulkUpdateTaskTest.php [deleted file]
typo3/sysext/saltedpasswords/ext_localconf.php
typo3/sysext/saltedpasswords/ext_tables.php [deleted file]

index 52de18e..ea1fc56 100644 (file)
@@ -21,4 +21,4 @@ None. You can start to use the new password hashing methods by selecting "Standa
 or "Standard PHP password hashing (argon2i)" in Extension Manager Configuration of saltedpasswords. Password
 hashes of existing users will be updated as soon as users log in.
 
-.. index:: Backend, Frontend, PHP-API
+.. index:: Backend, Frontend, PHP-API, ext:saltedpasswords
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-85022-SaltedpasswordsBulkUpdateTaskRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-85022-SaltedpasswordsBulkUpdateTaskRemoved.rst
new file mode 100644 (file)
index 0000000..ab00b46
--- /dev/null
@@ -0,0 +1,49 @@
+.. include:: ../../Includes.txt
+
+============================================================
+Important: #85022 - saltedpasswords bulk update task removed
+============================================================
+
+See :issue:`85022`
+
+Description
+===========
+
+The "Convert user passwords to salted hashes" scheduler bulk update task of the `saltedpasswords`
+extension has been removed from the system.
+
+The time line of salted password milestones in the core:
+
+* 4.3.0 (05/2008) Introduction of salted passwords extension
+* 4.5.0 (01/2011) Introduction of salted passwords bulk update scheduler task
+* 4.5.0 (01/2011) Default hash algorithm is phpass
+* 4.5.0 (01/2011) The reports module shows a warning if saltedpasswords extension is not loaded
+* 6.2.0 (03/2014) Salted passwords extension is mandatory
+* 8.0.0 (03/2016) Default hash algorithm of new instances is pbkdf2
+
+The salted passwords extension is by default configured to upgrade single password hashes to the
+currently configured hash algorithm if a user logs in.
+
+The scheduler task itself allowed to convert plain-text and simple md5 hashed passwords of frontend
+and backend users to salted md5 passwords. This hash method however is in itself outdated and not
+considered secure enough anymore. The task needed to be run only once and disabled itself as soon
+as it walked through all frontend and backend users.
+
+We assume all admins took care of basic salted password security within the last ten years if upgrading
+from instances older than version 4.3 by running this task once, so we now removed this task with core version 9.
+
+If there are still plain-text or simple md5 stored passwords, they can be found by searching the database
+field `password` of tables `fe_users` and `be_users` for entries not starting with `$`. If there are still entries
+like that, an administrator should convert them to simple md5 salted hashes by using the convert bulk update
+scheduler task in a core version prior to v9, before upgrading the system to v9.
+
+Additionally, as a general note on data protection, inactive frontend and backend users should be removed
+from the database after a while! The general idea is that not existing data can't be compromised in
+case of a security breach. The `lastlogin` field of the two user tables `fe_users` and `be_users` store
+the last login timestamp of a user, and soft deleted user records have the `deleted` field set to `1`.
+The "Table garbage collection task" scheduler task can be configured to fully remove those inactive or deleted users
+from the system. See the
+`scheduler documentation <https://docs.typo3.org/typo3cms/extensions/scheduler/Installation/BaseTasks/Index.html>`__
+for details on this task.
+
+.. index:: Backend, Database, Frontend, ext:saltedpasswords
index 09cd22d..3111369 100644 (file)
@@ -179,9 +179,7 @@ class Md5Salt extends AbstractComposedSalt
      *
      * This is typically called during the login process when the plain text
      * password is available.  A new hash is needed when the desired iteration
-     * count has changed through a change in the variable $hashCount or
-     * HASH_COUNT or if the user's password hash was generated in an bulk update
-     * with class ext_update.
+     * count has changed through a change in the variable $hashCount or HASH_COUNT.
      *
      * @param string $passString Salted hash to check if it needs an update
      * @return bool TRUE if salted hash needs an update, otherwise FALSE
index 4f6ca21..6c05b03 100644 (file)
@@ -299,9 +299,7 @@ class PhpassSalt extends AbstractComposedSalt
      *
      * This is typically called during the login process when the plain text
      * password is available. A new hash is needed when the desired iteration
-     * count has changed through a change in the variable $hashCount or
-     * HASH_COUNT or if the user's password hash was generated in an bulk update
-     * with class ext_update.
+     * count has changed through a change in the variable $hashCount or HASH_COUNT.
      *
      * @param string $passString Salted hash to check if it needs an update
      * @return bool TRUE if salted hash needs an update, otherwise FALSE
index 6d45ff4..a10745a 100644 (file)
@@ -52,9 +52,7 @@ interface SaltInterface
      *
      * This is typically called during the login process when the plain text
      * password is available.  A new hash is needed when the desired iteration
-     * count has changed through a change in the variable $hashCount or
-     * HASH_COUNT or if the user's password hash was generated in an bulk update
-     * with class ext_update.
+     * count has changed through a change in the variable $hashCount or HASH_COUNT.
      *
      * @param string $passString Salted hash to check if it needs an update
      * @return bool TRUE if salted hash needs an update, otherwise FALSE
diff --git a/typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateFieldProvider.php b/typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateFieldProvider.php
deleted file mode 100644 (file)
index e0ecdfb..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-namespace TYPO3\CMS\Saltedpasswords\Task;
-
-/*
- * 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!
- */
-
-/**
- * Additional field for salted passwords bulk update task
- */
-class BulkUpdateFieldProvider implements \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface
-{
-    /**
-     * Default value whether the task deactivates itself after last run.
-     *
-     * @var bool Whether the task is allowed to deactivate itself after processing all existing user records.
-     */
-    protected $defaultCanDeactivateSelf = true;
-
-    /**
-     * Default value for the number of records to handle at each run.
-     *
-     * @var int Number of records
-     */
-    protected $defaultNumberOfRecords = 250;
-
-    /**
-     * Add a field for the number of records and if the task should deactivate itself after
-     * processing all records
-     *
-     * @param array $taskInfo Reference to the array containing the info used in the add/edit form
-     * @param \TYPO3\CMS\Saltedpasswords\Task\BulkUpdateTask $task When editing, reference to the current task object. Null when adding.
-     * @param \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject Reference to the calling object (Scheduler's BE module)
-     * @return array Array containing all the information pertaining to the additional fields
-     */
-    public function getAdditionalFields(array &$taskInfo, $task, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject)
-    {
-        // Initialize selected fields
-        if (!isset($taskInfo['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf'])) {
-            $taskInfo['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf'] = $this->defaultCanDeactivateSelf;
-            if ($parentObject->CMD === 'edit') {
-                $taskInfo['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf'] = $task->getCanDeactivateSelf();
-            }
-        }
-        if (!isset($taskInfo['scheduler_saltedpasswordsBulkUpdateNumberOfRecords'])) {
-            $taskInfo['scheduler_saltedpasswordsBulkUpdateNumberOfRecords'] = $this->defaultNumberOfRecords;
-            if ($parentObject->CMD === 'edit') {
-                $taskInfo['scheduler_saltedpasswordsBulkUpdateNumberOfRecords'] = $task->getNumberOfRecords();
-            }
-        }
-        // Configuration for canDeactivateSelf
-        $fieldName = 'tx_scheduler[scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf]';
-        $fieldId = 'task_saltedpasswordsBulkUpdateCanDeactivateSelf';
-        $fieldValue = 'IsChecked';
-        $fieldChecked = (bool)$taskInfo['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf'];
-        $fieldHtml = '<div class="checkbox"><label><input type="checkbox"' . ' name="' . $fieldName . '"' . ' id="' . $fieldId . '"' . ' value="' . $fieldValue . '"' . ($fieldChecked ? ' checked="checked"' : '') . '></label></div>';
-        $additionalFields[$fieldId] = [
-            'code' => $fieldHtml,
-            'label' => 'LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.label.canDeactivateSelf',
-            'cshKey' => '_txsaltedpasswords',
-            'cshLabel' => $fieldId
-        ];
-        // Configuration for numberOfRecords
-        $fieldName = 'tx_scheduler[scheduler_saltedpasswordsBulkUpdateNumberOfRecords]';
-        $fieldId = 'task_saltedpasswordsBulkUpdateNumberOfRecords';
-        $fieldValue = (int)$taskInfo['scheduler_saltedpasswordsBulkUpdateNumberOfRecords'];
-        $fieldHtml = '<input type="text" class="form-control" name="' . $fieldName . '" id="' . $fieldId . '" value="' . htmlspecialchars($fieldValue) . '">';
-        $additionalFields[$fieldId] = [
-            'code' => $fieldHtml,
-            'label' => 'LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.label.numberOfRecords',
-            'cshKey' => '_txsaltedpasswords',
-            'cshLabel' => $fieldId
-        ];
-        return $additionalFields;
-    }
-
-    /**
-     * Checks if the given values are boolean and integer
-     *
-     * @param array $submittedData Reference to the array containing the data submitted by the user
-     * @param \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject Reference to the calling object (Scheduler's BE module)
-     * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise
-     */
-    public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject)
-    {
-        $result = true;
-        // Check if number of records is indeed a number and greater or equals to 0
-        // If not, fail validation and issue error message
-        if (!is_numeric($submittedData['scheduler_saltedpasswordsBulkUpdateNumberOfRecords']) || (int)$submittedData['scheduler_saltedpasswordsBulkUpdateNumberOfRecords'] < 0) {
-            $result = false;
-            $parentObject->addMessage($GLOBALS['LANG']->sL('LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.invalidNumberOfRecords'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
-        }
-        return $result;
-    }
-
-    /**
-     * Saves given values in task object
-     *
-     * @param array $submittedData Contains data submitted by the user
-     * @param \TYPO3\CMS\Scheduler\Task\AbstractTask|\TYPO3\CMS\Saltedpasswords\Task\BulkUpdateTask $task Reference to the current task object
-     */
-    public function saveAdditionalFields(array $submittedData, \TYPO3\CMS\Scheduler\Task\AbstractTask $task)
-    {
-        if (isset($submittedData['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf']) && $submittedData['scheduler_saltedpasswordsBulkUpdateCanDeactivateSelf'] === 'IsChecked') {
-            $task->setCanDeactivateSelf(true);
-        } else {
-            $task->setCanDeactivateSelf(false);
-        }
-        $task->setNumberOfRecords((int)$submittedData['scheduler_saltedpasswordsBulkUpdateNumberOfRecords']);
-    }
-}
diff --git a/typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateTask.php b/typo3/sysext/saltedpasswords/Classes/Task/BulkUpdateTask.php
deleted file mode 100644 (file)
index 5c22fbd..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-<?php
-namespace TYPO3\CMS\Saltedpasswords\Task;
-
-/*
- * 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\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * Update plaintext and hashed passwords of existing users to salted passwords.
- */
-class BulkUpdateTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask
-{
-    /**
-     * @var bool Whether or not the task is allowed to deactivate itself after processing all existing user records.
-     */
-    protected $canDeactivateSelf = true;
-
-    /**
-     * Converting a password to a salted hash takes some milliseconds (~100ms on an entry system in 2010).
-     * If all users are updated in one run, the task might run a long time if a lot of users must be handled.
-     * Therefore only a small number of frontend and backend users are processed.
-     * If saltedpasswords is enabled for both frontend and backend 2 * numberOfRecords will be handled.
-     *
-     * @var int Number of records
-     */
-    protected $numberOfRecords = 250;
-
-    /**
-     * @var int Pointer to last handled frontend and backend user row
-     */
-    protected $userRecordPointer = [];
-
-    /**
-     * Constructor initializes user record pointer
-     */
-    public function __construct()
-    {
-        parent::__construct();
-        $this->userRecordPointer = [
-            'FE' => 0,
-            'BE' => 0
-        ];
-    }
-
-    /**
-     * Execute task
-     *
-     * @return bool
-     */
-    public function execute()
-    {
-        $processedAllRecords = true;
-        // For frontend and backend
-        foreach ($this->userRecordPointer as $mode => $pointer) {
-            // If saltedpasswords is active for frontend / backend
-            if (\TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::isUsageEnabled($mode)) {
-                $usersToUpdate = $this->findUsersToUpdate($mode);
-                $numberOfRows = count($usersToUpdate);
-                if ($numberOfRows > 0) {
-                    $processedAllRecords = false;
-                    $this->activateSelf();
-                    $this->incrementUserRecordPointer($mode, $numberOfRows);
-                    $this->convertPasswords($mode, $usersToUpdate);
-                }
-            }
-        }
-        if ($processedAllRecords) {
-            // Reset the user record pointer
-            $this->userRecordPointer = [
-                'FE' => 0,
-                'BE' => 0
-            ];
-            // Determine if task should disable itself
-            if ($this->canDeactivateSelf) {
-                $this->deactivateSelf();
-            }
-        }
-        // Use save() of parent class \TYPO3\CMS\Scheduler\Task\AbstractTask to persist changed task variables
-        $this->save();
-        return true;
-    }
-
-    /**
-     * Get additional information
-     *
-     * @return string Additional information
-     */
-    public function getAdditionalInformation()
-    {
-        $information = $GLOBALS['LANG']->sL('LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.label.additionalinformation.deactivateself') . $this->getCanDeactivateSelf() . '; ' . $GLOBALS['LANG']->sL('LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.label.additionalinformation.numberofrecords') . $this->getNumberOfRecords();
-        return $information;
-    }
-
-    /**
-     * Finds next set of frontend or backend users to update.
-     *
-     * @param string $mode 'FE' for frontend, 'BE' for backend user records
-     * @return array Rows with uid and password
-     */
-    protected function findUsersToUpdate($mode)
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getQueryBuilderForTable($this->getTablename($mode));
-        $queryBuilder->getRestrictions()->removeAll();
-
-        $usersToUpdate = $queryBuilder
-            ->select('uid', 'password')
-            ->from($this->getTablename($mode))
-            ->orderBy('uid')
-            ->setFirstResult($this->userRecordPointer[$mode])
-            ->setMaxResults($this->numberOfRecords)
-            ->execute()
-            ->fetchAll();
-
-        return $usersToUpdate;
-    }
-
-    /**
-     * Iterates over given user records and update password if needed.
-     *
-     * @param string $mode 'FE' for frontend, 'BE' for backend user records
-     * @param array $users With user uids and passwords
-     */
-    protected function convertPasswords($mode, array $users)
-    {
-        $updateUsers = [];
-        foreach ($users as $user) {
-            // If a password is already a salted hash it must not be updated
-            if ($this->isSaltedHash($user['password'])) {
-                continue;
-            }
-            $updateUsers[] = $user;
-        }
-        if (!empty($updateUsers)) {
-            $this->updatePasswords($mode, $updateUsers);
-        }
-    }
-
-    /**
-     * Updates password and persist salted hash.
-     *
-     * @param string $mode 'FE' for frontend, 'BE' for backend user records
-     * @param array $users With user uids and passwords
-     */
-    protected function updatePasswords($mode, array $users)
-    {
-        /** @var $saltedpasswordsInstance \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface */
-        $saltedpasswordsInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(null, $mode);
-        foreach ($users as $user) {
-            $newPassword = $saltedpasswordsInstance->getHashedPassword($user['password']);
-            // If a given password is a md5 hash (usually default be_users without saltedpasswords activated),
-            // result of getHashedPassword() is a salted hashed md5 hash.
-            // We prefix those with 'M', saltedpasswords will then update this password
-            // to a usual salted hash upon first login of the user.
-            if ($this->isMd5Password($user['password'])) {
-                $newPassword = 'M' . $newPassword;
-            }
-            // Persist updated password
-
-            GeneralUtility::makeInstance(ConnectionPool::class)
-                ->getConnectionForTable($this->getTablename($mode))
-                ->update(
-                    $this->getTablename($mode),
-                    ['password' => $newPassword],
-                    ['uid' => (int)$user['uid']]
-                );
-        }
-    }
-
-    /**
-     * Passwords prefixed with M or C might be salted passwords:
-     * M means: originally a md5 hash before it was salted (eg. default be_users).
-     * C means: originally a cleartext password with lower hash looping count generated by t3sec_saltedpw.
-     * Both M and C will be updated to usual salted hashes on first login of user.
-     *
-     * If a password does not start with M or C determine if a password is already a usual salted hash.
-     *
-     * @param string $password Password
-     * @return bool TRUE if password is a salted hash
-     */
-    protected function isSaltedHash($password)
-    {
-        $isSaltedHash = false;
-        if (strlen($password) > 2 && (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($password, 'C$') || \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($password, 'M$'))) {
-            // Cut off M or C and test if we have a salted hash
-            $isSaltedHash = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::determineSaltingHashingMethod(substr($password, 1));
-        }
-        // Test if given password is already a usual salted hash
-        if (!$isSaltedHash) {
-            $isSaltedHash = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::determineSaltingHashingMethod($password);
-        }
-        return $isSaltedHash;
-    }
-
-    /**
-     * Checks if a given password is a md5 hash, the default for be_user records before saltedpasswords.
-     *
-     * @param string $password The password to test
-     * @return bool TRUE if password is md5
-     */
-    protected function isMd5Password($password)
-    {
-        return (bool)preg_match('/[0-9abcdef]{32,32}/i', $password);
-    }
-
-    /**
-     * Increments current user record counter by number of handled rows.
-     *
-     * @param string $mode 'FE' for frontend, 'BE' for backend user records
-     * @param int $number Number of handled rows
-     */
-    protected function incrementUserRecordPointer($mode, $number)
-    {
-        $this->userRecordPointer[$mode] += $number;
-    }
-
-    /**
-     * Activates this task instance.
-     * Uses setDisabled() method of parent \TYPO3\CMS\Scheduler\Task\AbstractTask
-     */
-    protected function activateSelf()
-    {
-        $this->setDisabled(false);
-    }
-
-    /**
-     * Deactivates this task instance.
-     * Uses setDisabled() method of parent \TYPO3\CMS\Scheduler\Task\AbstractTask
-     */
-    protected function deactivateSelf()
-    {
-        $this->setDisabled(true);
-    }
-
-    /**
-     * Set if it can deactivate self
-     *
-     * @param bool $canDeactivateSelf
-     */
-    public function setCanDeactivateSelf($canDeactivateSelf)
-    {
-        $this->canDeactivateSelf = $canDeactivateSelf;
-    }
-
-    /**
-     * Get if it can deactivate self
-     *
-     * @return bool TRUE if task shall deactivate itself, FALSE otherwise
-     */
-    public function getCanDeactivateSelf()
-    {
-        return $this->canDeactivateSelf;
-    }
-
-    /**
-     * Set number of records
-     *
-     * @param int $numberOfRecords
-     */
-    public function setNumberOfRecords($numberOfRecords)
-    {
-        $this->numberOfRecords = $numberOfRecords;
-    }
-
-    /**
-     * Get number of records
-     *
-     * @return int The number of records
-     */
-    public function getNumberOfRecords()
-    {
-        return $this->numberOfRecords;
-    }
-
-    /**
-     * @param string $mode FE for fe_users, BE for be_users
-     * @return string
-     * @throws \InvalidArgumentException
-     */
-    protected function getTablename(string $mode): string
-    {
-        $mode = strtolower($mode);
-        if ($mode === 'be') {
-            return 'be_users';
-        }
-        if ($mode === 'fe') {
-            return 'fe_users';
-        }
-        throw new \InvalidArgumentException(
-                'Invalid mode "' . $mode . '" for salted passwords bulk update',
-                1465392861
-            );
-    }
-}
index 520f6a2..1368a92 100644 (file)
                        <trans-unit id="ext.saltedpasswords.title.argon2isalt">
                                <source>Argon2i password hashing (PHP native)</source>
                        </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.name">
-                               <source>Convert user passwords to salted hashes</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.description">
-                               <source>Update all frontend and backend user passwords to salted hashes. This task deactivates itself when completed.</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.label.numberOfRecords">
-                               <source>The number of records to process on each run</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.invalidNumberOfRecords">
-                               <source>The number of records to process on each run must be greater than zero and numeric.</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.label.canDeactivateSelf">
-                               <source>Deactivate if all records are converted</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.label.additionalinformation.deactivateself">
-                               <source>Deactivate=</source>
-                       </trans-unit>
-                       <trans-unit id="ext.saltedpasswords.tasks.bulkupdate.label.additionalinformation.numberofrecords">
-                               <source>Number of records=</source>
-                       </trans-unit>
                        <trans-unit id="ext.saltedpasswords.configuration.header.noErrorsFound">
                                <source>No errors were found</source>
                        </trans-unit>
diff --git a/typo3/sysext/saltedpasswords/Resources/Private/Language/locallang_csh_saltedpasswords.xlf b/typo3/sysext/saltedpasswords/Resources/Private/Language/locallang_csh_saltedpasswords.xlf
deleted file mode 100644 (file)
index 8849b75..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
-       <file t3:id="1415814982" source-language="en" datatype="plaintext" original="messages" date="2012-02-22T00:00:00Z" product-name="saltedpasswords">
-               <header/>
-               <body>
-                       <trans-unit id="task_saltedpasswordsBulkUpdateNumberOfRecords.alttitle">
-                               <source>Number of records to process</source>
-                       </trans-unit>
-                       <trans-unit id="task_saltedpasswordsBulkUpdateNumberOfRecords.description">
-                               <source>Number of records to process for each run. If enabled for both FE &amp; BE, the value will be doubled.</source>
-                       </trans-unit>
-                       <trans-unit id="task_saltedpasswordsBulkUpdateNumberOfRecords.details" xml:space="preserve">
-                               <source>Converting a password to a salted hash takes some milliseconds (~100ms on an entry system in 2010).
-                                       If all users are updated in one run, the task might run a long time if a lot of users must be handled.
-                                       Therefore only a small number of frontend and backend users are processed.
-                                       If saltedpasswords is enabled for both FE &amp; BE, this value will be doubled.</source>
-                       </trans-unit>
-                       <trans-unit id="task_saltedpasswordsBulkUpdateCanDeactivateSelf.alttitle">
-                               <source>Deactivate this task</source>
-                       </trans-unit>
-                       <trans-unit id="task_saltedpasswordsBulkUpdateCanDeactivateSelf.description" xml:space="preserve">
-                               <source>Whether the task should deactivate itself after all records are processed.
-                                       Uncheck this if you are importing users from an external source and/or need to run this task periodically.</source>
-                       </trans-unit>
-               </body>
-       </file>
-</xliff>
diff --git a/typo3/sysext/saltedpasswords/Tests/Functional/Task/BulkUpdateTaskTest.php b/typo3/sysext/saltedpasswords/Tests/Functional/Task/BulkUpdateTaskTest.php
deleted file mode 100644 (file)
index f31e880..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-<?php
-namespace TYPO3\CMS\Saltedpasswords\Tests\Functional\Task;
-
-/*
- * 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\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Saltedpasswords\Task\BulkUpdateTask;
-
-/**
- * Test case for \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility
- */
-class BulkUpdateTaskTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
-{
-    /**
-     * XML database fixtures to be loaded into database.
-     *
-     * @var array
-     */
-    protected $xmlDatabaseFixtures = [
-        'typo3/sysext/saltedpasswords/Tests/Functional/Fixtures/be_users.xml',
-        'typo3/sysext/saltedpasswords/Tests/Functional/Fixtures/fe_users.xml'
-    ];
-
-    /**
-     * Core extensions to load
-     *
-     * @var array
-     */
-    protected $testExtensionsToLoad = [
-        'typo3/sysext/scheduler'
-    ];
-
-    /**
-     * @var BulkUpdateTask
-     */
-    protected $subject;
-
-    /**
-     * Sets up this test suite.
-     */
-    protected function setUp()
-    {
-        parent::setUp();
-        foreach ($this->xmlDatabaseFixtures as $fixture) {
-            $this->importDataSet($fixture);
-        }
-        $this->subject = GeneralUtility::makeInstance(BulkUpdateTask::class);
-    }
-
-    /**
-     * Test if bulk update task finds backend users to be updated
-     *
-     * @test
-     */
-    public function testIfBulkUpdateTaskFindsBackendUsersToBeUpdated()
-    {
-        $expectedOutput = [
-            [
-                'uid' => 1,
-                'password' => '$P$CDmA2Juu2h9/9MNaKaxtgzZgIVmjkh/'
-            ],
-            [
-                'uid' => 2,
-                'password' => 'M$v2AultVYItaCpb.tpdx2aGAue8eL3/'
-            ],
-            [
-                'uid' => 3,
-                'password' => '5f4dcc3b5aa765d61d8327deb882cf99'
-            ],
-            [
-                'uid' => 4,
-                'password' => ''
-            ],
-            [
-                'uid' => 5,
-                'password' => '819b0643d6b89dc9b579fdfc9094f28e'
-            ],
-            [
-                'uid' => 6,
-                'password' => '34cc93ece0ba9e3f6f235d4af979b16c'
-            ]
-        ];
-
-        $this->assertEquals($expectedOutput, $this->callInaccessibleMethod($this->subject, 'findUsersToUpdate', 'BE'));
-    }
-
-    /**
-     * Test if bulk update task finds frontend users to be updated
-     *
-     * @test
-     */
-    public function testIfBulkUpdateTaskFindsFrontendUsersToBeUpdated()
-    {
-        $expectedOutput = [
-            [
-                'uid' => 1,
-                'password' => '$P$CDmA2Juu2h9/9MNaKaxtgzZgIVmjkh/'
-            ],
-            [
-                'uid' => 2,
-                'password' => '5f4dcc3b5aa765d61d8327deb882cf99'
-            ]
-        ];
-
-        $this->assertEquals($expectedOutput, $this->callInaccessibleMethod($this->subject, 'findUsersToUpdate', 'FE'));
-    }
-
-    /**
-     * Test, if passwords are updated with salted hashes for a given user list
-     *
-     * @test
-     */
-    public function testIfPasswordsAreUpdatedWithSaltedHashesForGivenUserList()
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('fe_users');
-        $usersToBeUpdated = $queryBuilder
-            ->select('uid', 'password')
-            ->from('fe_users')
-            ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)))
-            ->execute()
-            ->fetchAll();
-
-        $originalMd5Password = $usersToBeUpdated[0]['password'];
-
-        $this->callInaccessibleMethod($this->subject, 'updatePasswords', 'FE', $usersToBeUpdated);
-
-        $saltedPassword = $queryBuilder
-            ->select('password')
-            ->from('fe_users')
-            ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)))
-            ->execute()
-            ->fetchColumn();
-
-        $this->assertNotEquals($originalMd5Password, $saltedPassword);
-
-        $saltedPasswordsInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(substr($saltedPassword, 1));
-        $this->assertTrue($saltedPasswordsInstance->checkPassword($originalMd5Password, substr($saltedPassword, 1)));
-    }
-}
index 12f964f..6a548cc 100644 (file)
@@ -24,11 +24,3 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods']
     'exec' => '',
     'className' => \TYPO3\CMS\Saltedpasswords\SaltedPasswordService::class
 ]);
-
-// Register bulk update task
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\TYPO3\CMS\Saltedpasswords\Task\BulkUpdateTask::class] = [
-    'extension' => 'saltedpasswords',
-    'title' => 'LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.name',
-    'description' => 'LLL:EXT:saltedpasswords/Resources/Private/Language/locallang.xlf:ext.saltedpasswords.tasks.bulkupdate.description',
-    'additionalFields' => \TYPO3\CMS\Saltedpasswords\Task\BulkUpdateFieldProvider::class
-];
diff --git a/typo3/sysext/saltedpasswords/ext_tables.php b/typo3/sysext/saltedpasswords/ext_tables.php
deleted file mode 100644 (file)
index 7391d56..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-// Add context sensitive help (csh) for scheduler task
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('_txsaltedpasswords', 'EXT:saltedpasswords/Resources/Private/Language/locallang_csh_saltedpasswords.xlf');