diff --git a/lam/lib/account.inc b/lam/lib/account.inc index cc3efd718..ca32393aa 100644 --- a/lam/lib/account.inc +++ b/lam/lib/account.inc @@ -492,7 +492,7 @@ function getNumberOfCharacterClasses($password): int { /** * Returns an array with all Samba 3 domain entries under the given suffix * - * @param handle LDAP handle (if null then $_SESSION['ldap']->server() is used) + * @param Connection|null $server LDAP handle (if null then $_SESSION['ldap']->server() is used) * @param String $suffix LDAP suffix to search (if null then $_SESSION['config']->get_Suffix('smbDomain') is used) * @return array list of samba3domain objects */ diff --git a/lam/lib/baseModule.inc b/lam/lib/baseModule.inc index 96ba36895..52d5a336a 100644 --- a/lam/lib/baseModule.inc +++ b/lam/lib/baseModule.inc @@ -81,7 +81,7 @@ abstract class baseModule { protected $moduleSettings; /** - * self service profile with settings of all modules + * self-service profile with settings of all modules * @var selfServiceProfile profile */ protected $selfServiceSettings; @@ -89,10 +89,10 @@ abstract class baseModule { /** name of parent accountContainer ($_SESSION[$base]) */ private $base; - /** contains all ldap attributes which should be written */ + /** @var array|null contains all ldap attributes which should be written */ protected $attributes; - /** contains all ldap attributes which are loaded from ldap */ + /** @var array|null contains all ldap attributes which are loaded from LDAP */ protected $orig; /** contains all error messages of a module */ diff --git a/lam/lib/baseType.inc b/lam/lib/baseType.inc index 0874814dc..211f36ece 100644 --- a/lam/lib/baseType.inc +++ b/lam/lib/baseType.inc @@ -235,7 +235,7 @@ class baseType { */ private function buildAccountStatusDialogDiv(AccountStatus $accountStatus, array $lockableOptions): htmlElement { $hasLockOptions = !empty($lockableOptions); - $hasUnlockOptions = $accountStatus->isLocked() || $accountStatus->isPartiallyLocked(); + $hasUnlockOptions = $accountStatus->isLocked() || $accountStatus->isPartiallyLocked() || $accountStatus->isPartiallyExpired(); $container = new htmlResponsiveRow(); $container->add(new htmlTitle(_('Change account status'))); diff --git a/lam/lib/modules/sambaSamAccount.inc b/lam/lib/modules/sambaSamAccount.inc index fda988fa7..4c49162ea 100644 --- a/lam/lib/modules/sambaSamAccount.inc +++ b/lam/lib/modules/sambaSamAccount.inc @@ -2,13 +2,14 @@ use LAM\REMOTE\Remote; use LAM\TYPES\ConfiguredType; +use LDAP\Connection; use function LAM\ACCOUNTLIST\isPasswordChangeByDefault; /* This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) Copyright (C) 2003 - 2006 Tilo Lutz - 2005 - 2024 Roland Gruber + 2005 - 2025 Roland Gruber This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -718,6 +719,8 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat // Save attributes $this->attributes['sambaDomainName'][0] = $_POST['sambaDomainName']; // Get Domain SID from name + $SID = ''; + $RIDbase = 1000; for ($i = 0; $i < count($sambaDomains); $i++) { if ($this->attributes['sambaDomainName'][0] == $sambaDomains[$i]->name) { $SID = $sambaDomains[$i]->SID; @@ -1074,19 +1077,20 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat if (isset($this->attributes['sambaSID'][0]) && $this->attributes['sambaSID'][0] != '') { $domainSID = substr($this->attributes['sambaSID'][0], 0, strrpos($this->attributes['sambaSID'][0], "-")); } - $sel_domain = []; + $sel_domain = null; + $SID = ''; for ($i = 0; $i < count($sambaDomains); $i++) { $sambaDomainNames[] = $sambaDomains[$i]->name; if (isset($domainSID)) { if ($domainSID == $sambaDomains[$i]->SID) { $SID = $domainSID; - $sel_domain = [$sambaDomains[$i]->name]; + $sel_domain = $sambaDomains[$i]->name; } } elseif (isset($this->attributes['sambaDomainName'][0]) && ($this->attributes['sambaDomainName'][0] != '')) { if ($this->attributes['sambaDomainName'][0] == $sambaDomains[$i]->name) { $SID = $sambaDomains[$i]->SID; - $sel_domain = [$sambaDomains[$i]->name]; + $sel_domain = $sambaDomains[$i]->name; } } } @@ -1241,7 +1245,7 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat $return->add(new htmlResponsiveSelect('sambaSID', $options, $selected, _('Special user'), 'specialUser')); } // domain - $return->add(new htmlResponsiveSelect('sambaDomainName', $sambaDomainNames, $sel_domain, _('Domain'), 'domain')); + $return->add(new htmlResponsiveSelect('sambaDomainName', $sambaDomainNames, [$sel_domain], _('Domain'), 'domain')); // logon hours and terminal server options if ($this->get_scope() == 'user') { if (!$this->isBooleanConfigOptionSet('sambaSamAccount_hideLogonHours')) { @@ -2590,9 +2594,9 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat * Returns the domain object of the user's domain. * * @param array $attributes LDAP attributes - * @param handle $server LDAP connection (leave empty for admin interface) + * @param Connection|null $server LDAP connection (leave empty for admin interface) * @param String $suffix LDAP search suffix (leave empty for admin interface) - * @return samba3domain domain + * @return samba3domain|null domain */ public function getUserDomain($attributes, $server = null, $suffix = null) { $attributes = array_change_key_case($attributes); @@ -2621,8 +2625,8 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat /** * Returns the group name of the group with the given group ID. * - * @param String $groupID group ID - * @return String group name + * @param string $groupID group ID + * @return string|null group name */ private function getGroupName($groupID) { $results = searchLDAPByAttribute('gidNumber', $groupID, 'posixGroup', ['cn'], ['group']); @@ -2636,12 +2640,9 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat * Returns the time when the user needs to change his password. * * @param array $domains list of domain objects - * @param String $selectedDomain selected domain name + * @param string|null $selectedDomain selected domain name */ private function getPasswordMustChangeTime($domains, $selectedDomain) { - if (is_array($selectedDomain) && ($selectedDomain !== [])) { - $selectedDomain = $selectedDomain[0]; - } $return = '-'; // check if password expires at all if ($this->noexpire) { @@ -2670,12 +2671,9 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat * Returns the time when the user can change his password. * * @param array $domains list of domain objects - * @param String $selectedDomain selected domain name + * @param string $selectedDomain selected domain name */ private function getPasswordCanChangeTime($domains, $selectedDomain) { - if (is_array($selectedDomain) && ($selectedDomain !== [])) { - $selectedDomain = $selectedDomain[0]; - } $return = '-'; // check if there is a time set for the last password change if (!isset($this->attributes['sambaPwdLastSet'][0])) { @@ -2734,7 +2732,7 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat /** * Returns a list of existing Samba 3 domains. * - * @param handle $server LDAP connection (leave empty for admin interface) + * @param Connection|null $server LDAP connection (leave empty for admin interface) * @param String $suffix LDAP search suffix (leave empty for admin interface) * @return array list of samba3domain objects */ @@ -2807,7 +2805,7 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat /** * Deactivates this account. * - * @param array $attributes LDAP attributes + * @param array $attributes LDAP attributes */ public function deactivate(array &$attributes) { if (!isset($attributes['sambaacctflags'][0])) { @@ -2817,13 +2815,13 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat if (!str_contains($flags, 'D')) { $flags[strpos($flags, ' ')] = 'D'; } - $attributes['sambaacctflags'][0] = $flags; + $attributes['sambaacctflags'][0] = (string) $flags; } /** * Activates this account. * - * @param array $attributes LDAP attributes + * @param array $attributes LDAP attributes */ public function activate(array &$attributes) { if (!isset($attributes['sambaacctflags'][0])) { @@ -2835,7 +2833,7 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat /** * Unlocks this account. * - * @param array $attributes LDAP attributes + * @param array $attributes LDAP attributes */ public function unlock(array &$attributes) { $attributes['sambaacctflags'][0] = str_replace('L', ' ', $attributes['sambaacctflags'][0]); @@ -2844,8 +2842,8 @@ class sambaSamAccount extends baseModule implements passwordService, AccountStat /** * Creates the value to store in sambaPasswordHistory attribute. * - * @param String $password password - * @return String value for sambaPasswordHistory + * @param string $password password + * @return string|null value for sambaPasswordHistory */ public static function createHistoryEntry($password) { if (empty($password)) { diff --git a/lam/lib/modules/shadowAccount.inc b/lam/lib/modules/shadowAccount.inc index 5b56f6290..dfc206442 100644 --- a/lam/lib/modules/shadowAccount.inc +++ b/lam/lib/modules/shadowAccount.inc @@ -993,7 +993,7 @@ class shadowAccount extends baseModule implements passwordService, AccountStatus } if (in_array(self::STATUS_PASSWORD_EXPIRED, $lockIds)) { $inactive = empty($attributes['shadowinactive'][0]) ? 0 : $attributes['shadowinactive'][0]; - $attributes['shadowlastchange'][0] = intval(time() / 3600 / 24) - $attributes['shadowmax'][0] - $inactive - 1; + $attributes['shadowlastchange'][0] = (string) (intval(time() / 3600 / 24) - $attributes['shadowmax'][0] - $inactive - 1); } } @@ -1008,7 +1008,7 @@ class shadowAccount extends baseModule implements passwordService, AccountStatus unset($attributes['shadowexpire']); } if (in_array(self::STATUS_PASSWORD_EXPIRED, $lockIds)) { - $attributes['shadowlastchange'][0] = intval(time() / 3600 / 24); + $attributes['shadowlastchange'][0] = (string) (time() / 3600 / 24); } } diff --git a/lam/lib/modules/windowsGroup.inc b/lam/lib/modules/windowsGroup.inc index d8073fbaa..11ffea3d4 100644 --- a/lam/lib/modules/windowsGroup.inc +++ b/lam/lib/modules/windowsGroup.inc @@ -914,7 +914,6 @@ class windowsGroup extends baseModule { $this->addPDFKeyValue($return, 'groupScope', _('Group scope'), $groupScope); $this->addPDFKeyValue($return, 'groupType', _('Group type'), $groupType); // managed by - $managedBy = ''; if (isset($this->attributes['managedBy'][0])) { $managedBy = getAbstractDN($this->attributes['managedBy'][0]); $this->addPDFKeyValue($return, 'managedBy', _('Managed by'), $managedBy); @@ -922,7 +921,7 @@ class windowsGroup extends baseModule { // members if (!empty($this->attributes['member'])) { $memberList = []; - if (isset($this->attributes['member']) && is_array($this->attributes['member'])) { + if (isset($this->attributes['member'][0])) { $memberList = $this->attributes['member']; } usort($memberList, 'compareDN'); @@ -937,7 +936,7 @@ class windowsGroup extends baseModule { // member of if (!empty($this->attributes['memberOf'])) { $memberOfList = []; - if (isset($this->attributes['memberOf']) && is_array($this->attributes['memberOf'])) { + if (isset($this->attributes['memberOf'][0])) { $memberOfList = $this->attributes['memberOf']; } usort($memberOfList, 'compareDN'); diff --git a/lam/lib/modules/windowsUser.inc b/lam/lib/modules/windowsUser.inc index ea484c799..7060e5c5e 100644 --- a/lam/lib/modules/windowsUser.inc +++ b/lam/lib/modules/windowsUser.inc @@ -77,6 +77,7 @@ class windowsUser extends baseModule implements passwordService, AccountStatusPr private const DISPLAY_GROUPS_DN = 'DN'; /** display groups as cn */ private const DISPLAY_GROUPS_CN = 'CN'; + public const ACCOUNT_DOES_NOT_EXPIRE = '9223372036854775807'; /** current group list */ private $groupList = []; @@ -2119,7 +2120,8 @@ class windowsUser extends baseModule implements passwordService, AccountStatusPr $return = new htmlResponsiveRow(); $attr = 'accountexpires'; $datetime = new DateTime('now', getTimeZone()); - if (!empty($this->attributes[$attr][0]) && ($this->attributes[$attr][0] != '0')) { + $datetime->add(new DateInterval('P1Y')); + if (!empty($this->attributes[$attr][0]) && ($this->attributes[$attr][0] !== self::ACCOUNT_DOES_NOT_EXPIRE)) { $datetime = windowsUser::getFileTime($this->attributes[$attr][0]); } $dateInput = new htmlResponsiveInputField(_('Account expiration date'), $attr, $datetime->format('Y-m-d'), 'accountexpires'); @@ -4017,10 +4019,10 @@ class windowsUser extends baseModule implements passwordService, AccountStatusPr foreach ($attrs as $key => $value) { if (strtolower($key) === 'useraccountcontrol') { if ($deactivated) { - $attrs[$key][0] = intval($value[0]) | self::AC_ACCOUNT_DISABLED; + $attrs[$key][0] = (string) (intval($value[0]) | self::AC_ACCOUNT_DISABLED); } elseif ((intval($value[0]) & self::AC_ACCOUNT_DISABLED) !== 0) { - $attrs[$key][0] = intval($value[0]) - self::AC_ACCOUNT_DISABLED; + $attrs[$key][0] = (string) (intval($value[0]) - self::AC_ACCOUNT_DISABLED); } } } @@ -4228,7 +4230,7 @@ class windowsUser extends baseModule implements passwordService, AccountStatusPr $attributes = &$this->attributes; } if (empty($attributes['accountexpires'][0]) || ($attributes['accountexpires'][0] == '0') - || ($attributes['accountexpires'][0] == '9223372036854775807')) { + || ($attributes['accountexpires'][0] == self::ACCOUNT_DOES_NOT_EXPIRE)) { return ' - '; } return $this->formatFileTime($attributes['accountexpires'][0]); @@ -4245,7 +4247,7 @@ class windowsUser extends baseModule implements passwordService, AccountStatusPr $attributes = &$this->attributes; } if (empty($attributes['msds-userpasswordexpirytimecomputed'][0]) || ($attributes['msds-userpasswordexpirytimecomputed'][0] == '0') - || ($attributes['msds-userpasswordexpirytimecomputed'][0] == '9223372036854775807')) { + || ($attributes['msds-userpasswordexpirytimecomputed'][0] == self::ACCOUNT_DOES_NOT_EXPIRE)) { return ' - '; } return $this->formatFileTime($attributes['msds-userpasswordexpirytimecomputed'][0]); @@ -4926,7 +4928,7 @@ if (interface_exists('\LAM\JOB\Job', false)) { } // skip if password does not expire if (empty($user['msds-userpasswordexpirytimecomputed'][0]) - || ($user['msds-userpasswordexpirytimecomputed'][0] == '9223372036854775807') + || ($user['msds-userpasswordexpirytimecomputed'][0] == windowsUser::ACCOUNT_DOES_NOT_EXPIRE) || ($user['msds-userpasswordexpirytimecomputed'][0] == '0')) { $this->jobResultLog->logDebug($dn . ': password does not expire.'); return; diff --git a/phpstan.neon b/phpstan.neon index f65ce4566..10f76d1f8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -22,3 +22,4 @@ parameters: - '#Variable \$helpArray might not be defined.#' - '#Function [a-zA-Z0-9\(\)\\_-]+ has invalid return type [a-zA-Z0-9\\_-]+.#' - '#Binary operation .* between .* and .* results in an error.#' + - '#Offset .SID. on array.*in isset\(\) always exists.*#'