Commit 2f0338a9 authored by Christian Kuhn's avatar Christian Kuhn Committed by Benni Mack
Browse files

[!!!][TASK] Simplify TCA authMode settings

To prepare towards a deployable backend group access
rights system, some of the more obscure options are
removed to reduce overall complexity.

* TYPO3_CONF_VARS['BE']['explicitADmode'] is finally
  gone: Following a deny list approach is a flawed security
  system. TYPO3's default setting (explicitADmode=allow)
  follows the very common "Least Privileged" principle,
  so editors need to be explicitly given access to a
  CType, as is done with all other permissions.

* The only valid value for TCA config option "authMode"
  on type="select" fields is now "explicitAllow". The
  previous "explicitDeny" value is abandoned following
  the reasoning above. The value "individual" is abandoned
  since it is a very rarely used setting (not a single
  match in TER).

* With authMode="individual" being gone, the select item
  array keys on position six that could be set to "EXPL_DENY"
  and "EXPL_ALLOW" are obsolete.

* Field "explicit_allowdeny" in table be_groups is
  simplified. This was a comma separated list of
  colon separated: "table:field:value:ALLOW/DENY".
  The last "ALLOW" or "DENY" is now obsolete.

The patch removes the above handling from the core. A
TCA migration scans TCA for invalid options and adapts
them. An upgrade wizard is in place to clean up the
be_groups explicit_allowdeny field of existing rows.

Resolves: #97265
Releases: main
Change-Id: I545b08fc694e9081ad79e69e7f55f684316e7b0f
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/74126


Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Stefan Bürk's avatarStefan Bürk <stefan@buerk.tech>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent d0a4bbfa
......@@ -298,8 +298,8 @@ class NewContentElementController
}
// Get information about if the field value is OK:
$config = $GLOBALS['TCA']['tt_content']['columns'][$fieldName]['config'] ?? [];
$authModeDeny = ($config['type'] ?? '') === 'select' && ($config['authMode'] ?? false)
&& !$backendUser->checkAuthMode('tt_content', $fieldName, $value, $config['authMode']);
$userNotAllowedToAccess = ($config['type'] ?? '') === 'select' && ($config['authMode'] ?? false)
&& !$backendUser->checkAuthMode('tt_content', $fieldName, $value);
// Check removeItems
if (!isset($removeItems[$fieldName]) && ($TCEFORM_TSconfig[$fieldName]['removeItems'] ?? false)) {
$removeItems[$fieldName] = array_flip(GeneralUtility::trimExplode(
......@@ -317,7 +317,7 @@ class NewContentElementController
));
}
$isNotInKeepItems = !empty($keepItems[$fieldName]) && !isset($keepItems[$fieldName][$value]);
if ($authModeDeny || ($fieldName === 'CType' && (isset($removeItems[$fieldName][$value]) || $isNotInKeepItems))) {
if ($userNotAllowedToAccess || ($fieldName === 'CType' && (isset($removeItems[$fieldName][$value]) || $isNotInKeepItems))) {
// Remove element all together:
unset($wizardItems[$key]);
break;
......
......@@ -457,7 +457,7 @@ abstract class AbstractItemProvider
$authMode = $result['processedTca']['columns'][$fieldName]['config']['authMode'];
foreach ($items as $key => $itemValues) {
// @todo: checkAuthMode() uses $GLOBAL access for "individual" authMode - get rid of this
if (!$backendUser->checkAuthMode($result['tableName'], $fieldName, $itemValues[1], $authMode)) {
if (!$backendUser->checkAuthMode($result['tableName'], $fieldName, $itemValues[1])) {
unset($items[$key]);
}
}
......
......@@ -228,7 +228,7 @@ class GridColumnItem extends AbstractGridObject
$this->getBackendUser()->isAdmin()
|| ((int)$this->record['editlock'] === 0 && (int)$pageRecord['editlock'] === 0)
&& $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT)
&& $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $this->record['CType'], $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
&& $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $this->record['CType'])
)
;
}
......
......@@ -1120,7 +1120,7 @@ class PageLayoutView implements LoggerAwareInterface
$this->getBackendUser()->isAdmin()
|| ((int)$row['editlock'] === 0 && (int)$this->pageinfo['editlock'] === 0)
&& $this->hasContentModificationAndAccessPermissions()
&& $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $row['CType'], $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
&& $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $row['CType'])
)
) {
return true;
......
......@@ -1908,55 +1908,6 @@ class TcaSelectItemsTest extends UnitTestCase
self::assertEquals($expected, (new TcaSelectItems())->addData($input));
}
/**
* @test
*/
public function addDataRemovesItemsByUserAuthModeRestriction(): void
{
$input = [
'databaseRow' => [
'aField' => 'keep,remove',
],
'tableName' => 'aTable',
'processedTca' => [
'columns' => [
'aField' => [
'config' => [
'type' => 'select',
'renderType' => 'selectSingle',
'authMode' => 'explicitAllow',
'items' => [
0 => [
0 => 'keepMe',
1 => 'keep',
null,
null,
null,
],
1 => [
0 => 'removeMe',
1 => 'remove',
],
],
'maxitems' => 99999,
],
],
],
],
];
$backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
$backendUserProphecy->checkAuthMode('aTable', 'aField', 'keep', 'explicitAllow')->shouldBeCalled()->willReturn(true);
$backendUserProphecy->checkAuthMode('aTable', 'aField', 'remove', 'explicitAllow')->shouldBeCalled()->willReturn(false);
$expected = $input;
$expected['databaseRow']['aField'] = ['keep'];
unset($expected['processedTca']['columns']['aField']['config']['items'][1]);
self::assertEquals($expected, (new TcaSelectItems())->addData($input));
}
/**
* @test
*/
......
......@@ -612,10 +612,9 @@ class BackendUserAuthentication extends AbstractUserAuthentication
* @param string $table Table name
* @param string $field Field name (must be configured in TCA and of type "select" with authMode set!)
* @param string $value Value to evaluation (single value, must not contain any of the chars ":,|")
* @param string $authMode Auth mode keyword (explicitAllow, explicitDeny, individual)
* @return bool Whether access is granted or not
*/
public function checkAuthMode($table, $field, $value, $authMode)
public function checkAuthMode($table, $field, $value)
{
// Admin users can do anything:
if ($this->isAdmin()) {
......@@ -636,45 +635,8 @@ class BackendUserAuthentication extends AbstractUserAuthentication
// Initialize:
$testValue = $table . ':' . $field . ':' . $value;
$out = true;
// Checking value:
switch ((string)$authMode) {
case 'explicitAllow':
if (!GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':ALLOW')) {
$out = false;
}
break;
case 'explicitDeny':
if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
$out = false;
}
break;
case 'individual':
if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$field])) {
$items = $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'];
if (is_array($items)) {
foreach ($items as $iCfg) {
if ((string)$iCfg[1] === (string)$value && ($iCfg[5] ?? '')) {
switch ((string)($iCfg[5] ?? '')) {
case 'EXPL_ALLOW':
if (!GeneralUtility::inList(
$this->groupData['explicit_allowdeny'],
$testValue . ':ALLOW'
)) {
$out = false;
}
break;
case 'EXPL_DENY':
if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
$out = false;
}
break;
}
break;
}
}
}
}
break;
if (!GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue)) {
$out = false;
}
return $out;
}
......@@ -806,8 +768,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication
if (isset($idOrRow[$fieldName])
&& ($fieldValue['config']['type'] ?? '') === 'select'
&& ($fieldValue['config']['authMode'] ?? false)
&& ($fieldValue['config']['authMode_enforce'] ?? '') === 'strict'
&& !$this->checkAuthMode($table, $fieldName, $idOrRow[$fieldName], $fieldValue['config']['authMode'])) {
&& !$this->checkAuthMode($table, $fieldName, $idOrRow[$fieldName])) {
$this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
. '" failed for field "' . $fieldName . '" with value "'
. $idOrRow[$fieldName] . '" evaluated';
......
......@@ -2269,7 +2269,7 @@ class DataHandler implements LoggerAwareInterface
if ($tcaFieldConf['type'] === 'select' && ($tcaFieldConf['authMode'] ?? false)) {
$preCount = count($valueArray);
foreach ($valueArray as $index => $key) {
if (!$this->BE_USER->checkAuthMode($table, $field, $key, $tcaFieldConf['authMode'])) {
if (!$this->BE_USER->checkAuthMode($table, $field, $key)) {
unset($valueArray[$index]);
}
}
......
......@@ -29,23 +29,20 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
class BackendUserGroupIntegrityCheck
{
/**
* @param string $status
* @param string $_ unused
* @param string $table
* @param int $id
* @param array $fieldArray
* @param DataHandler $parentObject
*/
public function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, $parentObject)
public function processDatamap_afterDatabaseOperations($_, $table, $id)
{
if ($table !== 'be_groups' || $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'] !== 'explicitAllow') {
if ($table !== 'be_groups') {
return;
}
$backendUserGroup = BackendUtility::getRecord($table, $id, 'explicit_allowdeny');
$explicitAllowDenyFields = GeneralUtility::trimExplode(',', $backendUserGroup['explicit_allowdeny'] ?? '');
foreach ($explicitAllowDenyFields as $value) {
if ($value !== '' && strpos($value, 'tt_content:list_type:') === 0) {
if (!in_array('tt_content:CType:list:ALLOW', $explicitAllowDenyFields, true)) {
if (!in_array('tt_content:CType:list', $explicitAllowDenyFields, true)) {
/** @var FlashMessage $flashMessage */
$flashMessage = GeneralUtility::makeInstance(
FlashMessage::class,
......
......@@ -147,10 +147,6 @@ class TcaItemsProcessorFunctions
public function populateExplicitAuthValues(array &$fieldDefinition): void
{
$icons = [
'ALLOW' => 'status-status-permission-granted',
'DENY' => 'status-status-permission-denied',
];
// Traverse grouped field values:
foreach ($this->getGroupedExplicitAuthFieldValues() as $groupKey => $tableFields) {
if (empty($tableFields['items']) || !is_array($tableFields['items'])) {
......@@ -163,12 +159,10 @@ class TcaItemsProcessorFunctions
];
// Traverse options for this field:
foreach ($tableFields['items'] as $itemValue => $itemContent) {
[$allowDenyMode, $itemLabel, $allowDenyModeLabel] = $itemContent;
// Add item to be selected:
$fieldDefinition['items'][] = [
'[' . $allowDenyModeLabel . '] ' . $itemLabel,
$groupKey . ':' . preg_replace('/[:|,]/', '', (string)$itemValue) . ':' . $allowDenyMode,
$icons[$allowDenyMode],
$itemContent,
$groupKey . ':' . preg_replace('/[:|,]/', '', (string)$itemValue),
'status-status-permission-granted',
];
}
}
......@@ -413,7 +407,7 @@ class TcaItemsProcessorFunctions
}
/**
* Returns an array with explicit Allow/Deny fields.
* Returns an array with explicit allow fields.
* Used for listing these field/value pairs in be_groups forms
*
* @return array Array with information from all of $GLOBALS['TCA']
......@@ -421,11 +415,7 @@ class TcaItemsProcessorFunctions
protected function getGroupedExplicitAuthFieldValues(): array
{
$languageService = $this->getLanguageService();
$allowDenyLabels = [
'ALLOW' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.allow'),
'DENY' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.deny'),
];
$allowDenyOptions = [];
$allowOptions = [];
foreach ($GLOBALS['TCA'] as $table => $tableConfiguration) {
if (empty($tableConfiguration['columns']) || !is_array($tableConfiguration['columns'])) {
continue;
......@@ -433,15 +423,15 @@ class TcaItemsProcessorFunctions
// All field names configured:
foreach ($tableConfiguration['columns'] as $field => $fieldDefinition) {
$fieldConfig = $fieldDefinition['config'] ?? [];
if (($fieldConfig['type'] ?? '') !== 'select' || !(bool)($fieldConfig['authMode'] ?? false)) {
continue;
}
// Check for items
if (empty($fieldConfig['items']) || !is_array($fieldConfig['items'])) {
if (($fieldConfig['type'] ?? '') !== 'select'
|| ($fieldConfig['authMode'] ?? false) !== 'explicitAllow'
|| empty($fieldConfig['items'])
|| !is_array($fieldConfig['items'])
) {
continue;
}
// Get Human Readable names of fields and table:
$allowDenyOptions[$table . ':' . $field]['tableFieldLabel'] =
$allowOptions[$table . ':' . $field]['tableFieldLabel'] =
$languageService->sL($GLOBALS['TCA'][$table]['ctrl']['title'] ?? '') . ': '
. $languageService->sL($GLOBALS['TCA'][$table]['columns'][$field]['label'] ?? '');
......@@ -451,37 +441,11 @@ class TcaItemsProcessorFunctions
if ($itemIdentifier === '' || $itemIdentifier === '--div--') {
continue;
}
// Find allowDenyMode
$allowDenyMode = '';
switch ((string)$fieldConfig['authMode']) {
case 'explicitAllow':
$allowDenyMode = 'ALLOW';
break;
case 'explicitDeny':
$allowDenyMode = 'DENY';
break;
case 'individual':
if ($item[5] ?? false) {
if ($item[5] === 'EXPL_ALLOW') {
$allowDenyMode = 'ALLOW';
} elseif ($item[5] === 'EXPL_DENY') {
$allowDenyMode = 'DENY';
}
}
break;
}
// Set allowDenyMode
if ($allowDenyMode) {
$allowDenyOptions[$table . ':' . $field]['items'][$itemIdentifier] = [
$allowDenyMode,
$languageService->sL($item[0] ?? ''),
$allowDenyLabels[$allowDenyMode],
];
}
$allowOptions[$table . ':' . $field]['items'][$itemIdentifier] = $languageService->sL($item[0] ?? '');
}
}
}
return $allowDenyOptions;
return $allowOptions;
}
protected function getLanguageService(): LanguageService
......
......@@ -66,7 +66,6 @@ class TcaMigration
$tca = $this->migrateFileFolderConfiguration($tca);
$tca = $this->migrateLevelLinksPosition($tca);
$tca = $this->migrateRootUidToStartingPoints($tca);
$tca = $this->migrateSelectAuthModeIndividualItemsKeywordToNewPosition($tca);
$tca = $this->migrateInternalTypeFolderToTypeFolder($tca);
$tca = $this->migrateRequiredFlag($tca);
$tca = $this->migrateEmailFlagToEmailType($tca);
......@@ -74,6 +73,9 @@ class TcaMigration
$tca = $this->migrateRenderTypeInputLinkToTypeLink($tca);
$tca = $this->migratePasswordAndSaltedPasswordToPasswordType($tca);
$tca = $this->migrateRenderTypeInputDateTimeToTypeDatetime($tca);
$tca = $this->removeAuthModeEnforce($tca);
$tca = $this->removeSelectAuthModeIndividualItemsKeyword($tca);
$tca = $this->migrateAuthMode($tca);
return $tca;
}
......@@ -526,40 +528,6 @@ class TcaMigration
return $tca;
}
/**
* If a column has authMode=individual and items with the corresponding key on position 5
* defined, migrate the key to position 6, since position 5 is used for the description.
*
* @param array $tca
* @return array
*/
protected function migrateSelectAuthModeIndividualItemsKeywordToNewPosition(array $tca): array
{
foreach ($tca as $table => $tableDefinition) {
if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
continue;
}
foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
if (($fieldConfig['config']['type'] ?? '') !== 'select' || ($fieldConfig['config']['authMode'] ?? '') !== 'individual') {
continue;
}
foreach ($fieldConfig['config']['items'] ?? [] as $index => $item) {
if (in_array($item[4] ?? '', ['EXPL_ALLOW', 'EXPL_DENY'], true)) {
$tca[$table]['columns'][$fieldName]['config']['items'][$index][5] = $item[4];
$tca[$table]['columns'][$fieldName]['config']['items'][$index][4] = '';
$this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' sets ' . $item[4]
. ' at position 5 of the items array. This option has been shifted to position 6 and should be adjusted accordingly.';
}
}
}
}
return $tca;
}
/**
* Migrates [config][internal_type] = 'folder' to [config][type] = 'folder'.
* Also removes [config][internal_type] completely, if present.
......@@ -936,4 +904,84 @@ class TcaMigration
return $tca;
}
/**
* Remove ['columns'][aField]['config']['authMode_enforce']
*/
protected function removeAuthModeEnforce(array $tca): array
{
foreach ($tca as $table => $tableDefinition) {
if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'] ?? false)) {
continue;
}
foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
if (array_key_exists('authMode_enforce', $fieldConfig['config'] ?? [])) {
unset($tca[$table]['columns'][$fieldName]['config']['authMode_enforce']);
$this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' uses '
. '\'authMode_enforce\'. This config key is obsolete and has been removed.'
. ' Please adjust your TCA accordingly.';
}
}
}
return $tca;
}
/**
* If a column has authMode=individual and items with the corresponding key on position 5
* defined, or if EXPL_ALLOW or EXPL_DENY is set for position 6, migrate or remove them.
*/
protected function removeSelectAuthModeIndividualItemsKeyword(array $tca): array
{
foreach ($tca as $table => $tableDefinition) {
if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
continue;
}
foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
if (($fieldConfig['config']['type'] ?? '') !== 'select' || ($fieldConfig['config']['authMode'] ?? '') !== 'individual') {
continue;
}
foreach ($fieldConfig['config']['items'] ?? [] as $index => $item) {
if (in_array($item[4] ?? '', ['EXPL_ALLOW', 'EXPL_DENY'], true)) {
$tca[$table]['columns'][$fieldName]['config']['items'][$index][4] = '';
$this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' sets ' . $item[4]
. ' at position 5 of the items array. This was used in combination with \'authMode=individual\' and'
. ' is obsolete since \'individual\' is no longer supported.';
}
if (isset($item[5])) {
unset($tca[$table]['columns'][$fieldName]['config']['items'][$index][5]);
$this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' sets ' . $item[5]
. ' at position 6 of the items array. This was used in combination with \'authMode=individual\' and'
. ' is obsolete since \'individual\' is no longer supported.';
}
}
}
}
return $tca;
}
/**
* See if ['columns'][aField]['config']['authMode'] is not set to 'explicitAllow' and
* set it to this value if needed.
*/
protected function migrateAuthMode(array $tca): array
{
foreach ($tca as $table => $tableDefinition) {
if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'] ?? false)) {
continue;
}
foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
if (array_key_exists('authMode', $fieldConfig['config'] ?? [])
&& $fieldConfig['config']['authMode'] !== 'explicitAllow'
) {
$tca[$table]['columns'][$fieldName]['config']['authMode'] = 'explicitAllow';
$this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' sets '
. '\'authMode\' to \'' . $fieldConfig['config']['authMode'] . '\'. The only allowed value is \'explicitAllow\','
. ' and that value has been set now. Please adjust your TCA accordingly. Note this has impact on'
. ' backend group access rights, these should be reviewed and new access right for this field should'
. ' be set. An upgrade wizard partially migrates this and reports be_groups rows that need manual attention.';
}
}
}
return $tca;
}
}
......@@ -1296,7 +1296,6 @@ return [
'defaultUC' => [],
'customPermOptions' => [], // Array with sets of custom permission options. Syntax is; 'key' => array('header' => 'header string, language split', 'items' => array('key' => array('label, language split','icon reference', 'Description text, language split'))). Keys cannot contain ":|," characters.
'interfaces' => 'backend',
'explicitADmode' => 'explicitAllow',
'flexformForceCDATA' => 0,
'versionNumberInFilename' => false,
'debug' => false,
......
......@@ -357,12 +357,6 @@ BE:
interfaces:
type: text
description: 'This determines which interface options are available in the login prompt (All options: "backend,frontend")'
explicitADmode:
type: dropdown
allowedValues:
'explicitAllow': 'Administrators have to explicitly grant access for all editors and groups'
'explicitDeny': 'Editors have access to all content types by default, access has to explicitly restricted'
description: 'Sets the general allow/deny mode for Content Element Types (CTypes) when granting or restricting access for backend users'
flexformForceCDATA:
type: bool
description: 'If set, will add CDATA to Flexform XML. Some versions of libxml have a bug that causes HTML entities to be stripped from any XML content and this setting will avoid the bug by adding CDATA.'
......
......@@ -6,9 +6,6 @@
* from eg. the government or introduction package.
*/
return [
'BE' => [
'explicitADmode' => 'explicitAllow',
],
'DB' => [
'Connections' => [
'Default' => [
......
.. include:: ../../Includes.txt
================================================
Breaking: #97265 - Simplified access mode system
================================================
See :issue:`97265`
Description
===========
In preparation of a deployable backend access rights system based on
configuration files, some rarely used details of the permission system
have been streamlined and simplified:
* The global configuration option :php:`TYPO3_CONF_VARS['BE']['explicitADmode']`
has been removed and is not evaluated anymore.
* The only valid value for TCA config option :php:`authMode` on :php:`'type' => 'select'`
fields is now :php:`explicitAllow`. The values :php:`explicitDeny` and :php:`individual`
are invalid and no longer evaluated.
* With removal of :php:`authMode' => 'individual'` for TCA select fields, the sixth
:php:`items` option is obsolete and removed. The values :php:`EXPL_ALLOW` and
:php:`EXPL_DENY` are without any effect.
* Handling of TCA config option :php:`authMode_enforce` has been removed.
* The fourth tuple of :sql:`be_groups` field :sql:`explicit_allowdeny` that was
previously set to either :sql:`ALLOW` or :sql:`DENY` is removed.
* The fourth argument on :php:`BackendUserAuthentication->checkAuthMode()` has
been removed.
Impact
======
Using any of the above removed options will log deprecation level error messages.
Using :php:`explicitDeny` and :php:`individual` as value for TCA config option
:php:`authMode` is no longer supported by the system and may need manual
adaptions. Accessing :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode']`
may lead to a PHP warning level error.
Affected Installations
======================
* Instances with extensions using :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode']`.
The extension scanner will typically find affected instances.
* Instances with TCA select fields using :php:`'authMode' => 'explicitDeny'`.
* Instances with TCA select fields using :php:`'authMode' => 'individual'` and select
items being set to :php:`EXPL_ALLOW` or :php:`EXPL_DENY`. This is a very rarely used
option and it's unlikely modern extensions use this in practice: There is not a single
extension in the TER using this option combination and it's unlikely to be used in
custom extensions, either.