diff --git a/app/modules/web/Controllers/ConfigLdapController.php b/app/modules/web/Controllers/ConfigLdapController.php index 2885f313..9ee9c92f 100644 --- a/app/modules/web/Controllers/ConfigLdapController.php +++ b/app/modules/web/Controllers/ConfigLdapController.php @@ -35,6 +35,7 @@ use SP\Http\JsonResponse; use SP\Modules\Web\Controllers\Traits\ConfigTrait; use SP\Mvc\View\Template; use SP\Providers\Auth\Ldap\LdapParams; +use SP\Providers\Auth\Ldap\LdapTypeInterface; use SP\Services\Ldap\LdapCheckService; use SP\Services\Ldap\LdapImportParams; use SP\Services\Ldap\LdapImportService; @@ -73,7 +74,7 @@ final class ConfigLdapController extends SimpleControllerBase if ($ldapEnabled) { $configData->setLdapEnabled(true); - $configData->setLdapAds($ldapParams->isAds()); + $configData->setLdapType($ldapParams->getType()); $configData->setLdapTlsEnabled($ldapParams->isTlsEnabled()); $configData->setLdapServer($ldapParams->getServer()); $configData->setLdapBase($ldapParams->getSearchBase()); @@ -128,7 +129,7 @@ final class ConfigLdapController extends SimpleControllerBase ->setGroup($this->request->analyzeString('ldap_group')) ->setBindDn($this->request->analyzeString('ldap_binduser')) ->setBindPass($this->request->analyzeEncrypted('ldap_bindpass')) - ->setAds($this->request->analyzeBool('ldap_ads_enabled', false)) + ->setType($this->request->analyzeInt('ldap_server_type', LdapTypeInterface::LDAP_STD)) ->setTlsEnabled($this->request->analyzeBool('ldap_tls_enabled', false)); } diff --git a/app/modules/web/Controllers/ConfigManagerController.php b/app/modules/web/Controllers/ConfigManagerController.php index 8483c806..9f75ac1c 100644 --- a/app/modules/web/Controllers/ConfigManagerController.php +++ b/app/modules/web/Controllers/ConfigManagerController.php @@ -34,6 +34,7 @@ use SP\Modules\Web\Controllers\Helpers\TabsHelper; use SP\Mvc\View\Components\DataTab; use SP\Mvc\View\Components\SelectItemAdapter; use SP\Plugin\PluginManager; +use SP\Providers\Auth\Ldap\LdapTypeInterface; use SP\Providers\Log\LogInterface; use SP\Providers\Mail\MailHandler; use SP\Services\Account\AccountService; @@ -222,6 +223,14 @@ final class ConfigManagerController extends ControllerBase $template->assign('userGroups', SelectItemAdapter::factory(UserGroupService::getItemsBasic())->getItemsFromModel()); $template->assign('userProfiles', SelectItemAdapter::factory(UserProfileService::getItemsBasic())->getItemsFromModel()); + $serverTypes = [ + LdapTypeInterface::LDAP_STD => 'Standard', + LdapTypeInterface::LDAP_ADS => 'Active Directory', + LdapTypeInterface::LDAP_AZURE => 'Azure Active Directory', + ]; + + $template->assign('serverTypes', SelectItemAdapter::factory($serverTypes)->getItemsFromArraySelected([$this->configData->getLdapType()])); + return new DataTab(__('LDAP'), $template); } diff --git a/app/modules/web/themes/material-blue/views/config/ldap.inc b/app/modules/web/themes/material-blue/views/config/ldap.inc index af132f32..92e318d4 100644 --- a/app/modules/web/themes/material-blue/views/config/ldap.inc +++ b/app/modules/web/themes/material-blue/views/config/ldap.inc @@ -52,23 +52,6 @@ -
  • -
    - -
    - - - - - - - -
  • -
  • + getLdapBindPass()): ?> +
    getIconWarning()->getIcon(); ?>
    +
    +

    + +

    +
    + diff --git a/lib/SP/Config/Config.php b/lib/SP/Config/Config.php index 325548a5..77673f19 100644 --- a/lib/SP/Config/Config.php +++ b/lib/SP/Config/Config.php @@ -187,7 +187,7 @@ final class Config } $configData->setConfigDate(time()); - $configData->setConfigSaver($this->context->getUserData()->getLogin()); + $configData->setConfigSaver($this->context->getUserData()->getLogin() ?: 'sysPass'); $configData->setConfigHash(); $this->fileStorage->save($configData, 'config'); diff --git a/lib/SP/Config/ConfigData.php b/lib/SP/Config/ConfigData.php index b9a57a70..1764faa8 100644 --- a/lib/SP/Config/ConfigData.php +++ b/lib/SP/Config/ConfigData.php @@ -201,6 +201,10 @@ final class ConfigData implements JsonSerializable * @var bool */ private $ldapAds = false; + /** + * @var int + */ + private $ldapType; /** * @var string */ @@ -2149,4 +2153,20 @@ final class ConfigData implements JsonSerializable { $this->filesAllowedMime = $filesAllowedMime; } + + /** + * @return int + */ + public function getLdapType() + { + return (int)$this->ldapType; + } + + /** + * @param int $ldapType + */ + public function setLdapType(int $ldapType) + { + $this->ldapType = $ldapType; + } } diff --git a/lib/SP/Providers/Auth/AuthProvider.php b/lib/SP/Providers/Auth/AuthProvider.php index 68c213eb..a9413ee0 100644 --- a/lib/SP/Providers/Auth/AuthProvider.php +++ b/lib/SP/Providers/Auth/AuthProvider.php @@ -31,12 +31,11 @@ use SP\Providers\Auth\Browser\Browser; use SP\Providers\Auth\Browser\BrowserAuthData; use SP\Providers\Auth\Database\Database; use SP\Providers\Auth\Database\DatabaseAuthData; +use SP\Providers\Auth\Ldap\Ldap; use SP\Providers\Auth\Ldap\LdapAuth; use SP\Providers\Auth\Ldap\LdapAuthData; -use SP\Providers\Auth\Ldap\LdapConnection; -use SP\Providers\Auth\Ldap\LdapMsAds; +use SP\Providers\Auth\Ldap\LdapException; use SP\Providers\Auth\Ldap\LdapParams; -use SP\Providers\Auth\Ldap\LdapStd; use SP\Providers\Provider; use SP\Services\Auth\AuthException; @@ -77,6 +76,10 @@ final class AuthProvider extends Provider * * @param UserLoginData $userLoginData * + * @uses authLdap + * @uses authDatabase + * @uses authBrowser + * * @return false|AuthResult[] */ public function doAuth(UserLoginData $userLoginData) @@ -101,33 +104,12 @@ final class AuthProvider extends Provider * Autentificación de usuarios con LDAP. * * @return bool|LdapAuthData - * @throws Ldap\LdapException + * @throws AuthException + * @throws LdapException */ public function authLdap() { - $data = LdapParams::getServerAndPort($this->configData->getLdapServer()); - - $ldapParams = (new LdapParams()) - ->setServer($data['server']) - ->setPort(isset($data['port']) ? $data['port'] : 389) - ->setSearchBase($this->configData->getLdapBase()) - ->setGroup($this->configData->getLdapGroup()) - ->setBindDn($this->configData->getLdapBindUser()) - ->setBindPass($this->configData->getLdapBindPass()) - ->setAds($this->configData->isLdapAds()); - - $ldapConnection = new LdapConnection($ldapParams, $this->eventDispatcher, $this->configData->isDebug()); - - if ($this->configData->isLdapAds()) { - $ldap = new LdapAuth( - new LdapMsAds($ldapConnection, $this->eventDispatcher), - $this->eventDispatcher); - } else { - $ldap = new LdapAuth( - new LdapStd($ldapConnection, $this->eventDispatcher), - $this->eventDispatcher); - } - + $ldap = $this->getLdapAuth(); $ldapAuthData = $ldap->getLdapAuthData(); $ldapAuthData->setAuthenticated($ldap->authenticate($this->userLoginData)); @@ -144,6 +126,32 @@ final class AuthProvider extends Provider return $ldapAuthData; } + /** + * @return LdapAuth + * @throws LdapException + */ + private function getLdapAuth() + { + $data = LdapParams::getServerAndPort($this->configData->getLdapServer()); + + $ldapParams = (new LdapParams()) + ->setServer($data['server']) + ->setPort(isset($data['port']) ? $data['port'] : 389) + ->setSearchBase($this->configData->getLdapBase()) + ->setGroup($this->configData->getLdapGroup()) + ->setBindDn($this->configData->getLdapBindUser()) + ->setBindPass($this->configData->getLdapBindPass()) + ->setType($this->configData->getLdapType()); + + return new LdapAuth( + Ldap::factory( + $ldapParams, + $this->eventDispatcher, + $this->configData->isDebug()), + $this->eventDispatcher + ); + } + /** * Autentificación de usuarios con base de datos * diff --git a/lib/SP/Providers/Auth/Ldap/Ldap.php b/lib/SP/Providers/Auth/Ldap/Ldap.php index e4dbca9b..a7f71b8f 100644 --- a/lib/SP/Providers/Auth/Ldap/Ldap.php +++ b/lib/SP/Providers/Auth/Ldap/Ldap.php @@ -82,6 +82,34 @@ abstract class Ldap implements LdapInterface */ protected abstract function pickServer(); + /** + * @param LdapParams $ldapParams + * @param EventDispatcher $eventDispatcher + * @param bool $debug + * + * @return LdapInterface + * @throws LdapException + */ + public static function factory(LdapParams $ldapParams, EventDispatcher $eventDispatcher, bool $debug) + { + $ldapConnection = new LdapConnection($ldapParams, $eventDispatcher, $debug); + $ldapConnection->checkConnection(); + + switch ($ldapParams->getType()) { + case LdapTypeInterface::LDAP_STD: + return new LdapStd($ldapConnection, $eventDispatcher); + break; + case LdapTypeInterface::LDAP_ADS: + return new LdapMsAds($ldapConnection, $eventDispatcher); + break; + case LdapTypeInterface::LDAP_AZURE; + return new LdapMsAzureAd($ldapConnection, $eventDispatcher); + break; + } + + throw new LdapException(__u('LDAP type not set')); + } + /** * @return LdapActions */ diff --git a/lib/SP/Providers/Auth/Ldap/LdapAuth.php b/lib/SP/Providers/Auth/Ldap/LdapAuth.php index 5ae915ce..08c440d1 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapAuth.php +++ b/lib/SP/Providers/Auth/Ldap/LdapAuth.php @@ -172,7 +172,10 @@ final class LdapAuth implements AuthInterface $this->ldapAuthData->setInGroup( $this->ldap->isUserInGroup( $attributes['dn'], - (array)$attributes->get('group'))); + $userLogin, + (array)$attributes->get('group') + ) + ); return $this->ldapAuthData; } diff --git a/lib/SP/Providers/Auth/Ldap/LdapConnection.php b/lib/SP/Providers/Auth/Ldap/LdapConnection.php index b08f32de..df0ebe03 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapConnection.php +++ b/lib/SP/Providers/Auth/Ldap/LdapConnection.php @@ -151,6 +151,7 @@ final class LdapConnection implements LdapConnectionInterface @ldap_set_option($this->ldapHandler, LDAP_OPT_NETWORK_TIMEOUT, self::TIMEOUT); @ldap_set_option($this->ldapHandler, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_set_option($this->ldapHandler, LDAP_OPT_REFERRALS, 0); $this->isTls = $this->connectTls(); diff --git a/lib/SP/Providers/Auth/Ldap/LdapInterface.php b/lib/SP/Providers/Auth/Ldap/LdapInterface.php index b73ff332..09be3625 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapInterface.php +++ b/lib/SP/Providers/Auth/Ldap/LdapInterface.php @@ -52,11 +52,12 @@ interface LdapInterface * Buscar al usuario en un grupo. * * @param string $userDn + * @param string $userLogin * @param array $groupsDn * * @return bool */ - public function isUserInGroup(string $userDn, array $groupsDn): bool; + public function isUserInGroup(string $userDn, string $userLogin, array $groupsDn): bool; /** * Devolver el filtro para objetos del tipo grupo diff --git a/lib/SP/Providers/Auth/Ldap/LdapMsAds.php b/lib/SP/Providers/Auth/Ldap/LdapMsAds.php index e3e72842..c51d2290 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapMsAds.php +++ b/lib/SP/Providers/Auth/Ldap/LdapMsAds.php @@ -31,13 +31,13 @@ use SP\Http\Address; /** * Class LdapAds * - * Autentificación basada en Active Directory + * LDAP authentication based on Active Directory * * @package SP\Auth\Ldap */ final class LdapMsAds extends Ldap { - const FILTER_USER_OBJECT = '(|(objectCategory=person)(objectClass=user))'; + const FILTER_USER_OBJECT = '(&(!(UserAccountControl:1.2.840.113556.1.4.804:=34))(|(objectCategory=person)(objectClass=user)))'; const FILTER_GROUP_OBJECT = '(objectCategory=group)'; const FILTER_USER_ATTRIBUTES = ['samaccountname', 'cn', 'uid', 'userPrincipalName']; const FILTER_GROUP_ATTRIBUTES = ['memberOf', 'groupMembership', 'memberof:1.2.840.113556.1.4.1941:']; @@ -93,12 +93,13 @@ final class LdapMsAds extends Ldap * Buscar al usuario en un grupo. * * @param string $userDn + * @param string $userLogin * @param array $groupsDn * * @return bool * @throws LdapException */ - public function isUserInGroup(string $userDn, array $groupsDn): bool + public function isUserInGroup(string $userDn, string $userLogin, array $groupsDn): bool { // Comprobar si está establecido el filtro de grupo o el grupo coincide con // los grupos del usuario @@ -109,27 +110,27 @@ final class LdapMsAds extends Ldap $this->eventDispatcher->notifyEvent('ldap.check.group', new Event($this, EventMessage::factory() ->addDescription(__u('User in group verified')) - ->addDetail(__u('User'), $userDn) + ->addDetail(__u('User'), $userLogin) ->addDetail(__u('Group'), $this->ldapParams->getGroup()))); return true; } - return $this->checkUserInGroupByFilter($userDn); + return $this->checkUserInGroupByFilter($userLogin); } /** - * @param string $userDn + * @param string $userLogin * * @return bool * @throws LdapException */ - private function checkUserInGroupByFilter(string $userDn): bool + private function checkUserInGroupByFilter(string $userLogin): bool { $groupDn = $this->getGroupDn(); $filter = '(&(|' - . LdapUtil::getAttributesForFilter(self::FILTER_USER_ATTRIBUTES, $userDn) + . LdapUtil::getAttributesForFilter(self::FILTER_USER_ATTRIBUTES, $userLogin) . ')(|' . LdapUtil::getAttributesForFilter(self::FILTER_GROUP_ATTRIBUTES, $groupDn) . '))'; @@ -142,7 +143,7 @@ final class LdapMsAds extends Ldap $this->eventDispatcher->notifyEvent('ldap.check.group', new Event($this, EventMessage::factory() ->addDescription(__u('User does not belong to the group')) - ->addDetail(__u('User'), $userDn) + ->addDetail(__u('User'), $userLogin) ->addDetail(__u('Group'), $groupDn) ->addDetail('LDAP FILTER', $filter))); @@ -152,25 +153,12 @@ final class LdapMsAds extends Ldap $this->eventDispatcher->notifyEvent('ldap.check.group', new Event($this, EventMessage::factory() ->addDescription(__u('User in group verified')) - ->addDetail(__u('User'), $userDn) + ->addDetail(__u('User'), $userLogin) ->addDetail(__u('Group'), $groupDn))); return true; } - /** - * @return bool - * @throws \SP\Core\Exceptions\SPException - */ - public function connect() - { - $handler = parent::connect(); - - @ldap_set_option($handler, LDAP_OPT_REFERRALS, 0); - - return true; - } - /** * Obtener el servidor de LDAP a utilizar * @@ -184,28 +172,22 @@ final class LdapMsAds extends Ldap return $server; } - $serverDomain = ''; - $serverFQDN = explode('.', $server); + $dnsServerQuery = '_msdcs' . substr($server, strpos($server, '.')); - for ($i = 1; $i <= count($serverFQDN) - 1; $i++) { - $serverDomain .= $serverFQDN[$i] . '.'; - } + logger(sprintf('Querying DNS zone: %s', $dnsServerQuery)); - $dnsServerQuery = '_msdcs.' . $serverDomain; $records = dns_get_record($dnsServerQuery, DNS_NS); - if (count($records) === 0) { + if (empty($records)) { return $server; } - $ads = []; + $adServers = []; foreach ($records as $record) { - $ads[] = $record['target']; + $adServers[] = $record['target']; }; - $nAds = count($ads); - - return $nAds > 0 ? $ads[mt_rand(0, $nAds)] : $server; + return count($adServers) > 0 ? array_rand($adServers) : $server; } } diff --git a/lib/SP/Providers/Auth/Ldap/LdapMsAzureAd.php b/lib/SP/Providers/Auth/Ldap/LdapMsAzureAd.php new file mode 100644 index 00000000..4454484b --- /dev/null +++ b/lib/SP/Providers/Auth/Ldap/LdapMsAzureAd.php @@ -0,0 +1,193 @@ +. + */ + +namespace SP\Providers\Auth\Ldap; + +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Http\Address; + +/** + * Class LdapMsAzureAd + * + * LDAP authentication based on Azure Active Directory + * + * @package SP\Auth\Ldap + */ +final class LdapMsAzureAd extends Ldap +{ + const FILTER_USER_OBJECT = '(|(objectCategory=person)(objectClass=user))'; + const FILTER_GROUP_OBJECT = '(objectCategory=group)'; + const FILTER_USER_ATTRIBUTES = ['samaccountname', 'cn', 'uid', 'userPrincipalName']; + const FILTER_GROUP_ATTRIBUTES = ['memberOf', 'groupMembership', 'memberof:1.2.840.113556.1.4.1941:']; + + /** + * Devolver el filtro para comprobar la pertenecia al grupo + * + * @return string + * @throws \SP\Core\Exceptions\SPException + */ + public function getGroupMembershipFilter(): string + { + if (empty($this->ldapParams->getGroup())) { + return self::FILTER_USER_OBJECT; + } + + return '(&(|' + . LdapUtil::getAttributesForFilter( + self::FILTER_GROUP_ATTRIBUTES, + $this->getGroupDn()) + . ')' + . self::FILTER_USER_OBJECT + . ')'; + } + + /** + * Obtener el filtro para buscar el usuario + * + * @param string $userLogin + * + * @return string + */ + public function getUserDnFilter(string $userLogin): string + { + return '(&(|' + . LdapUtil::getAttributesForFilter(self::FILTER_USER_ATTRIBUTES, $userLogin) + . ')' + . self::FILTER_USER_OBJECT + . ')'; + } + + /** + * Devolver el filtro para objetos del tipo grupo + * + * @return string + */ + public function getGroupObjectFilter(): string + { + return self::FILTER_GROUP_OBJECT; + } + + /** + * Buscar al usuario en un grupo. + * + * @param string $userDn + * @param string $userLogin + * @param array $groupsDn + * + * @return bool + * @throws LdapException + */ + public function isUserInGroup(string $userDn, string $userLogin, array $groupsDn): bool + { + // Comprobar si está establecido el filtro de grupo o el grupo coincide con + // los grupos del usuario + if (empty($this->ldapParams->getGroup()) + || $this->ldapParams->getGroup() === '*' + || in_array($this->getGroupDn(), $groupsDn) + ) { + $this->eventDispatcher->notifyEvent('ldap.check.group', + new Event($this, EventMessage::factory() + ->addDescription(__u('User in group verified')) + ->addDetail(__u('User'), $userLogin) + ->addDetail(__u('Group'), $this->ldapParams->getGroup()))); + + return true; + } + + return $this->checkUserInGroupByFilter($userLogin); + } + + /** + * @param string $userLogin + * + * @return bool + * @throws LdapException + */ + private function checkUserInGroupByFilter(string $userLogin): bool + { + $groupDn = $this->getGroupDn(); + + $filter = '(&(|' + . LdapUtil::getAttributesForFilter(self::FILTER_USER_ATTRIBUTES, $userLogin) + . ')(|' + . LdapUtil::getAttributesForFilter(self::FILTER_GROUP_ATTRIBUTES, $groupDn) + . '))'; + + $searchResults = $this->ldapActions->getObjects($filter, ['dn']); + + if (isset($searchResults['count']) + && (int)$searchResults['count'] === 0 + ) { + $this->eventDispatcher->notifyEvent('ldap.check.group', + new Event($this, EventMessage::factory() + ->addDescription(__u('User does not belong to the group')) + ->addDetail(__u('User'), $userLogin) + ->addDetail(__u('Group'), $groupDn) + ->addDetail('LDAP FILTER', $filter))); + + return false; + } + + $this->eventDispatcher->notifyEvent('ldap.check.group', + new Event($this, EventMessage::factory() + ->addDescription(__u('User in group verified')) + ->addDetail(__u('User'), $userLogin) + ->addDetail(__u('Group'), $groupDn))); + + return true; + } + + /** + * Obtener el servidor de LDAP a utilizar + * + * @return mixed + */ + protected function pickServer() + { + $server = $this->ldapParams->getServer(); + + if (preg_match(Address::PATTERN_IP_ADDRESS, $server)) { + return $server; + } + + $dnsServerQuery = '_msdcs' . substr($server, strpos($server, '.')); + + logger(sprintf('Querying DNS zone: %s', $dnsServerQuery)); + + $records = dns_get_record($dnsServerQuery, DNS_NS); + + if (empty($records)) { + return $server; + } + + $adServers = []; + + foreach ($records as $record) { + $adServers[] = $record['target']; + }; + + return count($adServers) > 0 ? array_rand($adServers) : $server; + } +} diff --git a/lib/SP/Providers/Auth/Ldap/LdapParams.php b/lib/SP/Providers/Auth/Ldap/LdapParams.php index b27ed055..e233ac65 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapParams.php +++ b/lib/SP/Providers/Auth/Ldap/LdapParams.php @@ -58,9 +58,9 @@ final class LdapParams */ protected $group; /** - * @var bool + * @var int */ - protected $ads = false; + protected $type; /** * @var bool */ @@ -195,21 +195,21 @@ final class LdapParams } /** - * @return bool + * @return int */ - public function isAds() + public function getType() { - return $this->ads; + return $this->type; } /** - * @param bool $ads + * @param int $type * * @return LdapParams */ - public function setAds($ads) + public function setType($type) { - $this->ads = (bool)$ads; + $this->type = (int)$type; return $this; } diff --git a/lib/SP/Providers/Auth/Ldap/LdapStd.php b/lib/SP/Providers/Auth/Ldap/LdapStd.php index 2cdda3ef..e3c79893 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapStd.php +++ b/lib/SP/Providers/Auth/Ldap/LdapStd.php @@ -30,7 +30,7 @@ use SP\Core\Events\EventMessage; /** * Class LdapStd * - * Autentificación basada en LDAP estándard + * LDAP authentication based on an standard implementation * * @package SP\Auth\Ldap */ @@ -91,12 +91,13 @@ final class LdapStd extends Ldap * Buscar al usuario en un grupo. * * @param string $userDn + * @param string $userLogin * @param array $groupsDn * * @return bool * @throws LdapException */ - public function isUserInGroup(string $userDn, array $groupsDn): bool + public function isUserInGroup(string $userDn, string $userLogin, array $groupsDn): bool { // Comprobar si está establecido el filtro de grupo o el grupo coincide con // los grupos del usuario @@ -149,19 +150,6 @@ final class LdapStd extends Ldap return true; } - /** - * @return bool - * @throws \SP\Core\Exceptions\SPException - */ - public function connect() - { - $handler = parent::connect(); - - @ldap_set_option($handler, LDAP_OPT_REFERRALS, 0); - - return true; - } - /** * Obtener el servidor de LDAP a utilizar * diff --git a/lib/SP/Providers/Auth/Ldap/LdapTypeInterface.php b/lib/SP/Providers/Auth/Ldap/LdapTypeInterface.php new file mode 100644 index 00000000..6c34f334 --- /dev/null +++ b/lib/SP/Providers/Auth/Ldap/LdapTypeInterface.php @@ -0,0 +1,38 @@ +. + */ + +namespace SP\Providers\Auth\Ldap; + + +/** + * Interface LdapTypeInterface + * + * @package SP\Providers\Auth\Ldap + */ +interface LdapTypeInterface +{ + const LDAP_STD = 1; + const LDAP_ADS = 2; + const LDAP_AZURE = 3; +} \ No newline at end of file diff --git a/lib/SP/Providers/Auth/Ldap/LdapUtil.php b/lib/SP/Providers/Auth/Ldap/LdapUtil.php index f0f87ade..263e6479 100644 --- a/lib/SP/Providers/Auth/Ldap/LdapUtil.php +++ b/lib/SP/Providers/Auth/Ldap/LdapUtil.php @@ -75,13 +75,13 @@ final class LdapUtil */ public static function getAttributesForFilter(array $attributes, $value): string { - $out = []; $value = ldap_escape((string)$value, null, LDAP_ESCAPE_FILTER); - foreach ($attributes as $attribute) { - $out[] = '(' . $attribute . '=' . $value . ')'; - } - - return implode('', $out); + return implode( + '', + array_map(function ($attribute) use ($value) { + return sprintf('(%s=%s)', $attribute, $value); + }, $attributes) + ); } } \ No newline at end of file diff --git a/lib/SP/Services/Ldap/LdapCheckService.php b/lib/SP/Services/Ldap/LdapCheckService.php index 6fcacc13..2d27eda2 100644 --- a/lib/SP/Services/Ldap/LdapCheckService.php +++ b/lib/SP/Services/Ldap/LdapCheckService.php @@ -25,11 +25,8 @@ namespace SP\Services\Ldap; use SP\Providers\Auth\Ldap\Ldap; -use SP\Providers\Auth\Ldap\LdapConnection; use SP\Providers\Auth\Ldap\LdapException; -use SP\Providers\Auth\Ldap\LdapMsAds; use SP\Providers\Auth\Ldap\LdapParams; -use SP\Providers\Auth\Ldap\LdapStd; use SP\Services\Service; /** @@ -51,14 +48,7 @@ final class LdapCheckService extends Service */ public function checkConnection(LdapParams $ldapParams) { - $ldapConnection = new LdapConnection($ldapParams, $this->eventDispatcher, true); - $ldapConnection->checkConnection(); - - if ($ldapParams->isAds()) { - $this->ldap = new LdapMsAds($ldapConnection, $this->eventDispatcher); - } else { - $this->ldap = new LdapStd($ldapConnection, $this->eventDispatcher); - } + $this->ldap = Ldap::factory($ldapParams, $this->eventDispatcher, true); } /** diff --git a/lib/SP/Services/Ldap/LdapImportService.php b/lib/SP/Services/Ldap/LdapImportService.php index 25070878..39b8405c 100644 --- a/lib/SP/Services/Ldap/LdapImportService.php +++ b/lib/SP/Services/Ldap/LdapImportService.php @@ -29,11 +29,9 @@ use SP\Core\Events\EventMessage; use SP\DataModel\UserData; use SP\DataModel\UserGroupData; use SP\Providers\Auth\Ldap\Ldap; -use SP\Providers\Auth\Ldap\LdapConnection; use SP\Providers\Auth\Ldap\LdapException; -use SP\Providers\Auth\Ldap\LdapMsAds; +use SP\Providers\Auth\Ldap\LdapInterface; use SP\Providers\Auth\Ldap\LdapParams; -use SP\Providers\Auth\Ldap\LdapStd; use SP\Services\Service; use SP\Services\User\UserService; use SP\Services\UserGroup\UserGroupService; @@ -157,18 +155,12 @@ final class LdapImportService extends Service /** * @param LdapParams $ldapParams * - * @return Ldap + * @return LdapInterface * @throws LdapException */ protected function getLdap(LdapParams $ldapParams) { - $ldapConnection = new LdapConnection($ldapParams, $this->eventDispatcher, $this->config->getConfigData()->isDebug()); - - if ($ldapParams->isAds()) { - return new LdapMsAds($ldapConnection, $this->eventDispatcher); - } else { - return new LdapStd($ldapConnection, $this->eventDispatcher); - } + return Ldap::factory($ldapParams, $this->eventDispatcher, $this->config->getConfigData()->isDebug()); } /** diff --git a/lib/SP/Services/Upgrade/UpgradeConfigService.php b/lib/SP/Services/Upgrade/UpgradeConfigService.php index 0ea110d5..039a8b80 100644 --- a/lib/SP/Services/Upgrade/UpgradeConfigService.php +++ b/lib/SP/Services/Upgrade/UpgradeConfigService.php @@ -28,6 +28,7 @@ use SP\Config\ConfigData; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Core\MimeTypes; +use SP\Providers\Auth\Ldap\LdapTypeInterface; use SP\Providers\Log\FileLogHandler; use SP\Services\Service; use SP\Util\VersionUtil; @@ -42,7 +43,13 @@ final class UpgradeConfigService extends Service implements UpgradeInterface /** * @var array Versiones actualizables */ - const UPGRADES = ['112.4', '130.16020501', '200.17011202', '300.18111001']; + const UPGRADES = [ + '112.4', + '130.16020501', + '200.17011202', + '300.18111001', + '300.18112501' + ]; /** * @var ConfigData */ @@ -197,8 +204,6 @@ final class UpgradeConfigService extends Service implements UpgradeInterface * @param $version * @param ConfigData $configData * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ public function upgrade($version, ConfigData $configData) @@ -220,8 +225,6 @@ final class UpgradeConfigService extends Service implements UpgradeInterface /** * @param $version * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ private function applyUpgrade($version) @@ -233,14 +236,15 @@ final class UpgradeConfigService extends Service implements UpgradeInterface case '300.18111001': $this->upgrade_300_18111001($version); break; + case '300.18112501': + $this->upgrade_300_18112501($version); + break; } } /** * @param $version * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ private function upgrade_200_17011202($version) @@ -260,8 +264,6 @@ final class UpgradeConfigService extends Service implements UpgradeInterface /** * @param $version * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ private function upgrade_300_18111001($version) @@ -308,6 +310,32 @@ final class UpgradeConfigService extends Service implements UpgradeInterface ); } + /** + * @param $version + * + * @throws \SP\Storage\File\FileException + */ + private function upgrade_300_18112501($version) + { + if ($this->configData->isLdapEnabled()) { + if ($this->configData->isLdapAds()) { + $this->configData->setLdapType(LdapTypeInterface::LDAP_ADS); + } else { + $this->configData->setLdapType(LdapTypeInterface::LDAP_STD); + } + + $this->configData->setConfigVersion($version); + + $this->config->saveConfig($this->configData, false); + + $this->eventDispatcher->notifyEvent('upgrade.config.process', + new Event($this, EventMessage::factory() + ->addDescription(__u('Update Configuration')) + ->addDetail(__u('Version'), $version)) + ); + } + } + /** * initialize */