From d243bdeea95470bba36a90b5adcff0749445bab7 Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Fri, 7 Aug 2015 13:07:19 +0200 Subject: [PATCH] * [ADD] ADS LDAP server selection by DNS records --- ajax/ajax_doLogin.php | 7 +-- inc/Auth.class.php | 2 +- inc/Ldap.class.php | 99 +++++++++-------------------------- inc/LdapADS.class.php | 119 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 78 deletions(-) create mode 100644 inc/LdapADS.class.php diff --git a/ajax/ajax_doLogin.php b/ajax/ajax_doLogin.php index bd712056..916d577b 100644 --- a/ajax/ajax_doLogin.php +++ b/ajax/ajax_doLogin.php @@ -59,6 +59,7 @@ $Log = new \SP\Log(_('Inicio sesión')); // Autentificamos por LDAP if ($resLdap === true) { $Log->addDescription('(LDAP)'); + $Log->addDescription(sprintf('%s : %s', _('Servidor Login'), \SP\Ldap::getLdapServer())); // Verificamos si el usuario existe en la BBDD if (!UserLdap::checkLDAPUserInDB($userLogin)) { @@ -163,9 +164,9 @@ if ($User->getUserMPass()) { // Establecemos las variables de sesión UserUtil::setUserSession($User); - $Log->addDescription(_('Usuario') . ": " . $userLogin); - $Log->addDescription(_('Perfil') . ": " . SP\Profile::getProfileNameById($User->getUserProfileId())); - $Log->addDescription(_('Grupo') . ": " . SP\Groups::getGroupNameById($User->getUserGroupId())); + $Log->addDescription(sprintf('%s : %s', _('Usuario'), $userLogin)); + $Log->addDescription(sprintf('%s : %s', _('Perfil'), SP\Profile::getProfileNameById($User->getUserProfileId()))); + $Log->addDescription(sprintf('%s : %s', _('Grupo'), SP\Groups::getGroupNameById($User->getUserGroupId()))); $Log->writeLog(); } else { SP\Common::printJSON(_('Error interno')); diff --git a/inc/Auth.class.php b/inc/Auth.class.php index dfd806c7..e44bfa7b 100644 --- a/inc/Auth.class.php +++ b/inc/Auth.class.php @@ -103,7 +103,7 @@ class Auth } // Comprobamos que el usuario está en el grupo indicado buscando en los atributos del grupo } else { - $ldapGroupAccess = (Ldap::searchUserInGroup($userDN) || Ldap::searchADUserInGroup($userLogin)); + $ldapGroupAccess = (Ldap::searchUserInGroup($userDN) || LdapADS::searchADUserInGroup($userLogin)); } if ($ldapGroupAccess === false) { diff --git a/inc/Ldap.class.php b/inc/Ldap.class.php index c71afb72..b0066a58 100644 --- a/inc/Ldap.class.php +++ b/inc/Ldap.class.php @@ -35,17 +35,25 @@ class Ldap { // Variabla que contiene los datos de una búsqueda public static $ldapSearchData; - // Variable para determinar si conecta con Active Directory - private static $_isADS = false; + protected static $_isADS = false; + // Variables de conexión con LDAP - private static $_ldapConn; - private static $_ldapServer; - private static $_searchBase; + protected static $_ldapConn; + protected static $_ldapServer; + protected static $_searchBase; private static $_bindDN; private static $_bindPass; private static $_ldapGroup; + /** + * @return mixed + */ + public static function getLdapServer() + { + return self::$_ldapServer; + } + /** * Obtener el recurso de conexión a LDAP. * @@ -99,8 +107,8 @@ class Ldap // Conexión al servidor LDAP if (!self::$_ldapConn = @ldap_connect(self::$_ldapServer)) { - $log->addDescription(_('No es posible conectar con el servidor de LDAP') . " '" . self::$_ldapServer . "'"); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('%s \'%s\'', _('No es posible conectar con el servidor de LDAP'), self::$_ldapServer)); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->writeLog(); throw new \Exception(_('No es posible conectar con el servidor de LDAP')); @@ -129,7 +137,7 @@ class Ldap if (!@ldap_bind(self::$_ldapConn, $dn, $pass)) { $log->addDescription(_('Error al conectar (BIND)')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->addDescription('LDAP DN: ' . $dn); $log->writeLog(); @@ -157,7 +165,7 @@ class Ldap if (!$searchRes) { $log->addDescription(_('Error al buscar objetos en DN base')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->addDescription('LDAP FILTER: ' . $filter); $log->writeLog(); @@ -173,7 +181,7 @@ class Ldap * @throws \Exception * @return string con el RDN del grupo */ - private static function searchGroupDN() + protected static function searchGroupDN() { $log = new Log(__FUNCTION__); $groupName = array(); @@ -190,7 +198,7 @@ class Ldap if (!$searchRes) { $log->addDescription(_('Error al buscar RDN de grupo')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->addDescription('LDAP FILTER: ' . $filter); $log->writeLog(); @@ -202,7 +210,7 @@ class Ldap if (!$ldapSearchData) { $log->addDescription(_('Error al buscar RDN de grupo')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->writeLog(); throw new \Exception(_('Error al buscar RDN de grupo')); @@ -229,12 +237,12 @@ class Ldap */ public static function checkLDAPParams() { + self::$_isADS = Config::getValue('ldap_ads', false); self::$_searchBase = Config::getValue('ldap_base'); - self::$_ldapServer = Config::getValue('ldap_server'); + self::$_ldapServer = (!self::$_isADS) ? Config::getValue('ldap_server') : LdapADS::getADServer(Config::getValue('ldap_server')); self::$_bindDN = Config::getValue('ldap_binduser'); self::$_bindPass = Config::getValue('ldap_bindpass'); self::$_ldapGroup = Config::getValue('ldap_group', '*'); - self::$_isADS = Config::getValue('ldap_ads', false); if (!self::$_searchBase || !self::$_ldapServer || !self::$_bindDN || !self::$_bindPass) { Log::writeNewLog(__FUNCTION__, _('Los parámetros de LDAP no están configurados')); @@ -268,7 +276,7 @@ class Ldap if (!$searchRes) { $log->addDescription(_('Error al buscar el DN del usuario')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->addDescription('LDAP FILTER: ' . $filter); $log->writeLog(); @@ -280,7 +288,7 @@ class Ldap if (!self::$ldapSearchData) { $log->addDescription(_('Error al localizar el usuario en LDAP')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->writeLog(); throw new \Exception(_('Error al localizar el usuario en LDAP')); @@ -365,7 +373,7 @@ class Ldap if (!$searchRes) { $log->addDescription(_('Error al buscar el grupo de usuarios')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); + $log->addDescription(sprintf('LDAP ERROR: %s (%d)', ldap_error(self::$_ldapConn), ldap_errno(self::$_ldapConn))); $log->addDescription('LDAP FILTER: ' . $filter); $log->writeLog(); @@ -394,62 +402,5 @@ class Ldap return preg_replace($chars, '\\\$1', $dn); } - /** - * Buscar al usuario en un grupo. - * - * @param string $userLogin con el login del usuario - * @throws \Exception - * @return bool - */ - public static function searchADUserInGroup($userLogin) - { - if (self::$_isADS === false) { - return false; - } - $log = new Log(__FUNCTION__); - - $ldapGroup = Config::getValue('ldap_group'); - - // El filtro de grupo no está establecido - if (empty($ldapGroup)) { - return true; - } - - // Obtenemos el DN del grupo - if (!$groupDN = self::searchGroupDN()) { - return false; - } - - $filter = '(memberof:1.2.840.113556.1.4.1941:=' . $groupDN . ')'; - $filterAttr = array("sAMAccountName"); - - $searchRes = @ldap_search(self::$_ldapConn, self::$_searchBase, $filter, $filterAttr); - - if (!$searchRes) { - $log->addDescription(_('Error al buscar el grupo de usuarios')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); - $log->addDescription('LDAP FILTER: ' . $filter); - $log->writeLog(); - - throw new \Exception(_('Error al buscar el grupo de usuarios')); - } - - if (@ldap_count_entries(self::$_ldapConn, $searchRes) === 0) { - $log->addDescription(_('No se encontró el grupo con ese nombre')); - $log->addDescription('LDAP ERROR: ' . ldap_error(self::$_ldapConn) . '(' . ldap_errno(self::$_ldapConn) . ')'); - $log->addDescription('LDAP FILTER: ' . $filter); - $log->writeLog(); - - throw new \Exception(_('No se encontró el grupo con ese nombre')); - } - - foreach (ldap_get_entries(self::$_ldapConn, $searchRes) as $entry) { - if ($userLogin === $entry['samaccountname'][0]) { - return true; - } - } - - return false; - } } diff --git a/inc/LdapADS.class.php b/inc/LdapADS.class.php new file mode 100644 index 00000000..09f45003 --- /dev/null +++ b/inc/LdapADS.class.php @@ -0,0 +1,119 @@ +. + * + */ + +namespace SP; + +defined('APP_ROOT') || die(_('No es posible acceder directamente a este archivo')); + +class LdapADS extends Ldap +{ + /** + * Obtener un servidor de AD aleatorio + * + * @param $server string El servidor de AD + * @return string + */ + public static function getADServer($server) + { + $serverDomain = ''; + $serverFQDN = explode('.', $server); + + for ($i = 1; $i <= count($serverFQDN) - 1; $i++){ + $serverDomain .= $serverFQDN[$i] . '.'; + } + + $dnsServerQuery = '_msdcs.' . $serverDomain; + $records = dns_get_record($dnsServerQuery, DNS_NS); + + if (count($records) === 0) { + return parent::$_ldapServer; + } + + foreach ($records as $record) { + $ads[] = $record['target']; + }; + + return $ads[rand(0, count($ads) - 1)]; + } + + /** + * Buscar al usuario en un grupo. + * + * @param string $userLogin con el login del usuario + * @throws \Exception + * @return bool + */ + public static function searchADUserInGroup($userLogin) + { + if (Ldap::$_isADS === false) { + return false; + } + + $log = new Log(__FUNCTION__); + + $ldapGroup = Config::getValue('ldap_group'); + + // El filtro de grupo no está establecido + if (empty($ldapGroup)) { + return true; + } + + // Obtenemos el DN del grupo + if (!$groupDN = Ldap::searchGroupDN()) { + return false; + } + + $filter = '(memberof:1.2.840.113556.1.4.1941:=' . $groupDN . ')'; + $filterAttr = array("sAMAccountName"); + + $searchRes = @ldap_search(Ldap::$_ldapConn, Ldap::$_searchBase, $filter, $filterAttr); + + if (!$searchRes) { + $log->addDescription(_('Error al buscar el grupo de usuarios')); + $log->addDescription('LDAP ERROR: ' . ldap_error(Ldap::$_ldapConn) . '(' . ldap_errno(Ldap::$_ldapConn) . ')'); + $log->addDescription('LDAP FILTER: ' . $filter); + $log->writeLog(); + + throw new \Exception(_('Error al buscar el grupo de usuarios')); + } + + if (@ldap_count_entries(Ldap::$_ldapConn, $searchRes) === 0) { + $log->addDescription(_('No se encontró el grupo con ese nombre')); + $log->addDescription('LDAP ERROR: ' . ldap_error(Ldap::$_ldapConn) . '(' . ldap_errno(Ldap::$_ldapConn) . ')'); + $log->addDescription('LDAP FILTER: ' . $filter); + $log->writeLog(); + + throw new \Exception(_('No se encontró el grupo con ese nombre')); + } + + foreach (ldap_get_entries(Ldap::$_ldapConn, $searchRes) as $entry) { + if ($userLogin === $entry['samaccountname'][0]) { + return true; + } + } + + return false; + } +} \ No newline at end of file