From 341dcc68acdbae343f89953ba678af1f3d0ecb0d Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 3 Feb 2014 00:39:20 +0100 Subject: [PATCH] * Improved LDAP access and error handling. Tested aganist OpenLDAP with ldap and ldaps on Debian. More info at Wiki http://wiki.syspass.org/doku.php/en:ldap --- ajax/ajax_doLogin.php | 19 +- inc/auth.class.php | 187 +++++++++----------- inc/ldap.class.php | 206 ++++++++++++++++++++++ inc/locales/en_US/LC_MESSAGES/messages.mo | Bin 41638 -> 41740 bytes inc/users.class.php | 4 +- 5 files changed, 304 insertions(+), 112 deletions(-) create mode 100644 inc/ldap.class.php diff --git a/ajax/ajax_doLogin.php b/ajax/ajax_doLogin.php index 346d1098..58b4b1df 100644 --- a/ajax/ajax_doLogin.php +++ b/ajax/ajax_doLogin.php @@ -36,18 +36,18 @@ $userLogin = SP_Common::parseParams('p', 'user'); $userPass = SP_Common::parseParams('p', 'pass'); $masterPass = SP_Common::parseParams('p', 'mpass'); -if (!$userLogin OR !$userPass) { +if (!$userLogin || !$userPass) { SP_Common::printJSON(_('Usuario/Clave no introducidos')); } +$resLdap = SP_Auth::authUserLDAP($userLogin,$userPass); + $objUser = new SP_Users; -$objUser->userLogin = SP_Auth::$userLogin = $userLogin; -$objUser->userPass = SP_Auth::$userPass = $userPass; +$objUser->userLogin = $userLogin; +$objUser->userPass = $userPass; $objUser->userName = SP_Auth::$userName; $objUser->userEmail = SP_Auth::$userEmail; -$resLdap = SP_Auth::authUserLDAP(); - // Autentificamos por LDAP if ($resLdap == 1) { $message['action'] = _('Inicio sesión (LDAP)'); @@ -71,6 +71,7 @@ if ($resLdap == 1) { } } } else if ($resLdap == 49) { + $message['action'] = _('Inicio sesión (LDAP)'); $message['text'][] = _('Login incorrecto'); $message['text'][] = _('Usuario') . ": " . $userLogin; $message['text'][] = _('IP') . ": " . $_SERVER['REMOTE_ADDR']; @@ -81,7 +82,7 @@ if ($resLdap == 1) { $message['action'] = _('Inicio sesión (MySQL)'); // Autentificamos con la BBDD - if (!SP_Auth::authUserMySQL()) { + if (!SP_Auth::authUserMySQL($userLogin,$userPass)) { $message['text'][] = _('Login incorrecto'); $message['text'][] = _('Usuario') . ": " . $userLogin; $message['text'][] = _('IP') . ": " . $_SERVER['REMOTE_ADDR']; @@ -92,7 +93,7 @@ if ($resLdap == 1) { } // Comprobar si el usuario está deshabilitado -if (SP_Auth::checkUserIsDisabled()) { +if (SP_Auth::checkUserIsDisabled($userLogin)) { $message['text'][] = _('Usuario deshabilitado'); $message['text'][] = _('Usuario') . ": " . $userLogin; $message['text'][] = _('IP') . ": " . $_SERVER['REMOTE_ADDR']; @@ -139,9 +140,7 @@ if ($objUser->getUserMPass()) { } } - if ( isset($params) ){ - $urlParams = '?'.implode('&', $params); - } + $urlParams = isset($params) ? '?'.implode('&', $params) : ''; SP_Common::printJSON('index.php'.$urlParams, 0); } diff --git a/inc/auth.class.php b/inc/auth.class.php index 55b52b74..e7c08d39 100644 --- a/inc/auth.class.php +++ b/inc/auth.class.php @@ -30,134 +30,101 @@ defined('APP_ROOT') || die(_('No es posible acceder directamente a este archivo' */ class SP_Auth { - static $userLogin; - static $userPass; static $userName; static $userEmail; /** * @brief Autentificación de usuarios con LDAP + * @param string $userLogin con el login del usuario + * @param string $userPass con la clave del usuario * @return bool */ - public static function authUserLDAP() { - if (SP_Config::getValue('ldapenabled', 0) === 0 || !SP_Util::ldapIsAvailable()) { - return FALSE; - } - - $searchBase = SP_Config::getValue('ldapbase'); - $ldapserver = SP_Config::getValue('ldapserver'); - $ldapgroup = SP_Config::getValue('ldapgroup'); - $bindDN = SP_Config::getValue('ldapbinduser'); - $bindPass = SP_Config::getValue('ldapbindpass'); - - if (!$searchBase || !$ldapserver || !$ldapgroup || !$bindDN || !$bindPass) { + public static function authUserLDAP($userLogin, $userPass) { + if (!SP_Util::ldapIsAvailable() + || !SP_Config::getValue('ldapenabled', FALSE) + || !SP_LDAP::checkLDAPParams()) { return FALSE; } $ldapAccess = FALSE; $message['action'] = __FUNCTION__; - // Conexión al servidor LDAP - if (!$ldapConn = @ldap_connect($ldapserver)) { - $message['text'][] = _('No es posible conectar con el servidor de LDAP') . " '" . $ldapserver . "'"; - $message['text'][] = 'LDAP ERROR: ' . ldap_error($ldapConn) . '(' . ldap_errno($ldapConn) . ')'; + // Conectamos al servidor realizamos la conexión con el usuario proxy + try { + SP_LDAP::connect(); + SP_LDAP::bind(); + SP_LDAP::getUserDN($userLogin); + } catch (Exception $e) { + return FALSE; + } + + $userDN = SP_LDAP::$ldapSearchData[0]['dn']; + // Mapeo de los atributos + $attribsMap = array( + 'groupmembership' => 'group', + 'memberof' => 'group', + 'displayname' => 'name', + 'fullname' => 'name', + 'mail' => 'mail', + 'lockouttime' => 'expire'); + + // Realizamos la conexión con el usuario real y obtenemos los atributos + try{ + SP_LDAP::bind($userDN, $userPass); + SP_LDAP::unbind(); + $attribs = SP_LDAP::getLDAPAttr($attribsMap); + } catch (Exception $e) { + return ldap_errno(SP_LDAP::getConn()); + } + // Comprobamos si la cuenta está bloqueada o expirada + if ( isset($attribs['expire']) && $attribs['expire'] > 0){ + return FALSE; + } + + if ( !isset($attribs['group']) ){ + $message['text'][] = _('El usuario no tiene grupos asociados'); SP_Common::wrLogInfo($message); return FALSE; } + + if (is_array($attribs['group'])){ + foreach ($attribs['group'] as $group) { + if (is_int($group)) { + continue; + } - @ldap_set_option($ldapConn, LDAP_OPT_NETWORK_TIMEOUT, 10); // Set timeout - @ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3); // Set LDAP version - - if (!@ldap_bind($ldapConn, $bindDN, $bindPass)) { - $message['text'][] = _('Error al conectar (bind)'); - $message['text'][] = 'LDAP ERROR: ' . ldap_error($ldapConn) . '(' . ldap_errno($ldapConn) . ')'; - - SP_Common::wrLogInfo($message); - return FALSE; - } - - $filter = '(&(|(samaccountname=' . self::$userLogin . ')(cn=' . self::$userLogin . '))(|(objectClass=inetOrgPerson)(objectClass=person)))'; - $filterAttr = array("dn", "displayname", "samaccountname", "mail", "memberof", "lockouttime", "fullname", "groupmembership", "mail"); - - $searchRes = @ldap_search($ldapConn, $searchBase, $filter, $filterAttr); - - if (!$searchRes) { - $message['text'][] = _('Error al buscar el DN del usuario'); - $message['text'][] = 'LDAP ERROR: ' . ldap_error($ldapConn) . '(' . ldap_errno($ldapConn) . ')'; - - SP_Common::wrLogInfo($message); - return FALSE; - } - - if (@ldap_count_entries($ldapConn, $searchRes) === 1) { - $searchUser = @ldap_get_entries($ldapConn, $searchRes); - - if (!$searchUser) { - $message['text'][] = _('Error al localizar el usuario en LDAP'); - $message['text'][] = 'LDAP ERROR: ' . ldap_error($ldapConn) . '(' . ldap_errno($ldapConn) . ')'; - - SP_Common::wrLogInfo($message); - return FALSE; - } - - $userDN = $searchUser[0]["dn"]; - } - - if (@ldap_bind($ldapConn, $userDN, self::$userPass)) { - @ldap_unbind($ldapConn); - - foreach ($searchUser as $entryValue) { - if (is_array($entryValue)) { - foreach ($entryValue as $entryAttr => $attrValue) { - if (is_array($attrValue)) { - if ($entryAttr == "groupmembership" || $entryAttr == "memberof") { - foreach ($attrValue as $group) { - if (is_int($group)) { - continue; - } - - preg_match('/^cn=([\w\s-]+),.*/i', $group, $groupName); - - // Comprobamos que el usuario está en el grupo indicado - if ($groupName[1] == $ldapgroup || $group == $ldapgroup) { - $ldapAccess = TRUE; - break; - } - } - } elseif ($entryAttr == "displayname" | $entryAttr == "fullname") { - self::$userName = $attrValue[0]; - } elseif ($entryAttr == "mail") { - self::$userEmail = $attrValue[0]; - } elseif ($entryAttr == "lockouttime") { - if ($attrValue[0] > 0) - return FALSE; - } - } - } + // Comprobamos que el usuario está en el grupo indicado + if ( self::checkLDAPGroup($group) ) { + $ldapAccess = TRUE; + break; } } - } else { - $message['text'][] = _('Error al conectar con el usuario'); - $message['text'][] = 'LDAP ERROR: ' . ldap_error($ldapConn) . '(' . ldap_errno($ldapConn) . ')'; - - SP_Common::wrLogInfo($message); - return ldap_errno($ldapConn); + } else{ + // Comprobamos que el usuario está en el grupo indicado + if ( self::checkLDAPGroup($attribs['group']) ) { + $ldapAccess = TRUE; + } } - + + self::$userName = $attribs['name']; + self::$userEmail = $attribs['mail']; + return $ldapAccess; } /** * @brief Autentificación de usuarios con MySQL + * @param string $userLogin con el login del usuario + * @param string $userPass con la clave del usuario * @return bool * * Esta función comprueba la clave del usuario. Si el usuario necesita ser migrado desde phpPMS, * se ejecuta el proceso para actualizar la clave. */ - public static function authUserMySQL() { - if (SP_Users::checkUserIsMigrate(self::$userLogin)) { - if (!SP_Users::migrateUser(self::$userLogin, self::$userPass)) { + public static function authUserMySQL($userLogin, $userPass) { + if (SP_Users::checkUserIsMigrate($userLogin)) { + if (!SP_Users::migrateUser($userLogin, $userPass)) { return FALSE; } } @@ -165,9 +132,9 @@ class SP_Auth { $query = "SELECT user_login," . "user_pass " . "FROM usrData " - . "WHERE user_login = '" . DB::escape(self::$userLogin) . "' " + . "WHERE user_login = '" . DB::escape($userLogin) . "' " . "AND user_isMigrate = 0 " - . "AND user_pass = SHA1(CONCAT(user_hashSalt,'" . DB::escape(self::$userPass) . "')) LIMIT 1"; + . "AND user_pass = SHA1(CONCAT(user_hashSalt,'" . DB::escape($userPass) . "')) LIMIT 1"; if (DB::doQuery($query, __FUNCTION__) === FALSE) { return FALSE; @@ -182,12 +149,13 @@ class SP_Auth { /** * @brief Comprobar si un usuario está deshabilitado + * @param string $userLogin con el login del usuario * @return bool */ - public static function checkUserIsDisabled() { + public static function checkUserIsDisabled($userLogin) { $query = "SELECT user_isDisabled " . "FROM usrData " - . "WHERE user_login = '" . DB::escape(self::$userLogin) . "' LIMIT 1"; + . "WHERE user_login = '" . DB::escape($userLogin) . "' LIMIT 1"; $queryRes = DB::getResults($query, __FUNCTION__); if ($queryRes === FALSE) { @@ -200,4 +168,21 @@ class SP_Auth { return TRUE; } + + /** + * @brief Comprobar si el grupo de LDAP está habilitado + * @param string $group con el nombre del grupo + * @return bool + */ + private static function checkLDAPGroup($group){ + $ldapgroup = SP_Config::getValue('ldapgroup'); + + preg_match('/^cn=([\w\s-]+),.*/i', $group, $groupName); + + if ($groupName[1] == $ldapgroup || $group == $ldapgroup) { + return TRUE; + } + + return FALSE; + } } diff --git a/inc/ldap.class.php b/inc/ldap.class.php new file mode 100644 index 00000000..52a5f609 --- /dev/null +++ b/inc/ldap.class.php @@ -0,0 +1,206 @@ +. + * + */ +defined('APP_ROOT') || die(_('No es posible acceder directamente a este archivo')); + +/** + * Esta clase es la encargada de realizar la autentificación de usuarios de sysPass. + */ +class SP_LDAP { + private static $ldapConn; + private static $ldapServer; + private static $searchBase; + private static $bindDN; + private static $bindPass; + private static $ldapGroup; + + public static $ldapSearchData; + + /** + * @brief Obtener el recurso de conexión a LDAP + * @return resource + */ + public static function getConn(){ + if (is_resource(self::$ldapConn)){ + return self::$ldapConn; + } + } + + /** + * @brief Comprobar la conexión al servidor de LDAP + * @return bool + */ + public static function checkLDAPConn(){ + + } + + /** + * @brief Comprobar si los parámetros necesario de LDAP están establecidos + * @return bool + */ + public static function checkLDAPParams(){ + self::$searchBase = SP_Config::getValue('ldapbase'); + self::$ldapServer = SP_Config::getValue('ldapserver'); + self::$bindDN = SP_Config::getValue('ldapbinduser'); + self::$bindPass = SP_Config::getValue('ldapbindpass'); + self::$ldapGroup = SP_Config::getValue('ldapgroup'); + + if (!self::$searchBase || !self::$ldapServer || !self::$ldapGroup || !self::$bindDN || !self::$bindPass) { + $message['action'] = __FUNCTION__; + $message['text'][] = _('Los parámetros de LDAP no están configurados'); + + SP_Common::wrLogInfo($message); + + return FALSE; + } + + return TRUE; + } + + /** + * @brief Realizar la conexión al servidor de LDAP + * @param string $server con la dirección del servidor + * @return bool + */ + public static function connect(){ + $message['action'] = __FUNCTION__; + + // Conexión al servidor LDAP + if (!self::$ldapConn = @ldap_connect(self::$ldapServer)) { + $message['text'][] = _('No es posible conectar con el servidor de LDAP') . " '" . self::$ldapServer . "'"; + $message['text'][] = 'LDAP ERROR: ' . ldap_error(self::$ldapConn) . '(' . ldap_errno(self::$ldapConn) . ')'; + + SP_Common::wrLogInfo($message); + + throw new Exception(_('No es posible conectar con el servidor de LDAP')); + } + + @ldap_set_option(self::$ldapConn, LDAP_OPT_NETWORK_TIMEOUT, 10); // Set timeout + @ldap_set_option(self::$ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3); // Set LDAP version + + return TRUE; + } + + /** + * @brief Realizar la autentificación con el servidor de LDAP + * @param string $dn con el DN del usuario + * @param string $pass con la clave del usuario + * @return bool + */ + public static function bind($userDN = '', $userPass = ''){ + $message['action'] = __FUNCTION__; + + $dn = ( $userDN ) ? $userDN : self::$bindDN; + $pass = ( $userPass ) ? $userPass : self::$bindPass; + + if (!@ldap_bind(self::$ldapConn, $dn, $pass)) { + $message['text'][] = _('Error al conectar (BIND)'); + $message['text'][] = 'LDAP ERROR: ' . ldap_error(self::$ldapConn) . '(' . ldap_errno(self::$ldapConn) . ')'; + $message['text'][] = 'LDAP DN: ' . $dn; + + SP_Common::wrLogInfo($message); + + throw new Exception(_('Error al conectar (BIND)')); + } + + return TRUE; + } + + /** + * @brief Obtener el RDN del usuario que realiza el login + * @param string $userLogin con el login del usuario + * @return none + */ + public static function getUserDN($userLogin){ + $message['action'] = __FUNCTION__; + + $filter = '(&(|(samaccountname=' . $userLogin . ')(cn=' . $userLogin . ')(uid=' . $userLogin . '))(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject)))'; + $filterAttr = array("dn", "displayname", "samaccountname", "mail", "memberof", "lockouttime", "fullname", "groupmembership", "mail"); + + $searchRes = @ldap_search(self::$ldapConn, self::$searchBase, $filter, $filterAttr); + + if (!$searchRes) { + $message['text'][] = _('Error al buscar el DN del usuario'); + $message['text'][] = 'LDAP ERROR: ' . ldap_error(self::$ldapConn) . '(' . ldap_errno(self::$ldapConn) . ')'; + $message['text'][] = 'LDAP FILTER: ' . $filter; + + SP_Common::wrLogInfo($message); + + throw new Exception(_('Error al buscar el DN del usuario')); + } + + if (@ldap_count_entries(self::$ldapConn, $searchRes) === 1) { + self::$ldapSearchData = @ldap_get_entries(self::$ldapConn, $searchRes); + + if (!self::$ldapSearchData) { + $message['text'][] = _('Error al localizar el usuario en LDAP'); + $message['text'][] = 'LDAP ERROR: ' . ldap_error(self::$ldapConn) . '(' . ldap_errno(self::$ldapConn) . ')'; + + SP_Common::wrLogInfo($message); + + throw new Exception(_('Error al localizar el usuario en LDAP')); + } + + //return $searchUser[0]["dn"]; + } else { + $message['text'][] = _('Error al buscar el DN del usuario'); + $message['text'][] = 'LDAP FILTER: ' . $filter; + + SP_Common::wrLogInfo($message); + + throw new Exception(_('Error al buscar el DN del usuario')); + } + } + + /** + * @brief Realizar la desconexión del servidor de LDAP + * @return none + */ + public static function unbind(){ + @ldap_unbind(self::$ldapConn); + } + + public static function getLDAPAttr($attribs){ + $res = array(); + + foreach (self::$ldapSearchData as $entryValue) { + if (is_array($entryValue)) { + foreach ($entryValue as $entryAttr => $attrValue) { + if (is_array($attrValue)) { + if (array_key_exists($entryAttr, $attribs)){ + if ( $attrValue['count'] > 1 ){ + $res[$attribs[$entryAttr]] = $attrValue; + } else{ + $res[$attribs[$entryAttr]] = $attrValue[0]; + } + } + } + } + } + } + + return $res; + } +} \ No newline at end of file diff --git a/inc/locales/en_US/LC_MESSAGES/messages.mo b/inc/locales/en_US/LC_MESSAGES/messages.mo index a5ae6ecedb0db0fe139bcc28958f9b6cfe0c22fd..62f08220e6a66013e0a2446845c6d4425f1d5e83 100644 GIT binary patch delta 11816 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 delta 11689 zcmYk?37C&n|HturW(>y6G-k$Z2J;(Z%)VhTW6%uQA4@#evSdp!Jj9UYXA9ZFk1QEP zwj^qlEs09_6V*SY$G$~TL|QD*`!nZsUESApdYyCbbD!mV&VB!;u4W(bUiZ1T`)o*= zMGjXpZ^x;EZ9*I;)W>ng)ljYD9L#i_C-4xK!&BDt7)<#GZs%7rkyQB9G83qR!IX0_5L;sic0+YI7}b6(#^6F!$Ju_6Z7Hs$K5=jvd2#&Q!2HuJ6kaGmp(Q#Bn z&SDteM?&iaW;;#=tcvO<5i4OHYO6Y+JB-X>M{*s1+BZI#`41paeD0$EXgDpjLPR zHKAWo9hR-@I4su5L~Thw)N?aY5nO`d_&#dFhw2jl2r?IKgFi8Wa;17E)Oo0ZnqnAs zM$VZt7}a4h{u{TW&TAm?)&y!HT{#0V4vSIG?Zb4ugNk@;4)L!{CNsy(tTk%o&!Nu3 zaMV_eLk%zotK$3C)W$`Pmsr=bR3 zhVeIuz5Eo*;7L@3{)=jV%a$KogL(HNsgJ_|%tO5;EioM31ITE=@wUM%)I^q` z_IeXm!%wW|P%Cd-gOJRgE8yKFfPwc-Y-fm+%6KB(u1A`5dnqsWw}Vgjb&bd10c zP!l+cv3L10Y>Rqp)?*?b#;W+MEeG>8QvbQA2sJ@PuoDL9{ePZ}W;(jG zf(f7+F1Bt!J+RZ>KZ;qD&!FCxpvLA5g;_IE3u%on;}}$g@1iE+{iKP2KL)rR!cC?M z#-I!HP%C&AtKnGG{bi`ry&XBg&X1@_)W|mjwnLrz@yH9|Y(qW&6UL%{fjJ9l=%U;V z-3r}6GJ0QUqV{SlY74%=7(9nMM32#hkxk6&mxJoKBdUHR#^LLzes-ar`wA7Y8>n%r zG&TJfG$sC-RCK38E1ZRuaRWxE{f@*&k zQ?XJrb5`;(o^rotZu8(wDqK{&i5hr6s-v^075s%dT$P%e4jN(#<=&_*n2ox>9kq4m zQ7e9gH8Hb=nNSzheK%^HVr4YYPE^AasQ3IK*1*t~W^e1GwqyY6Fik)g&c+PfjB$7d zHGo$uvo$fO{_?F|tV8U5_Y^WN8mvWy>HzA{T($MStxZQYQ6X-Dnn*9y1dD9_a@1Co zU@g3C%MoqN-vcdBTR0ud;)hsW@Bbb$>gYTsq3^#;XfseBq8_LS6{60@EbBT9pu7(& z;FqY^^gGn+d=vff0s3Isw&qJ&0n1UYf)RTEYmg~VMILIvr%)fBuGS&e$;gbI#i$7E zLbdrLj9)1pgz?ZsEOxeE5>))k_p14sL*Ugb-Wc7(oaz{zKe>` z1Jrk*W_$Am?2bJsm!Q52K^;s4TA=p63u^0zpbqm?)Iy5Utv&yQOfa5D&HN5};{)qs z)Qr8KHWLg&MIaotHR-7Ptx^4T#b6wbYBv)r;%d|umY`1mmroOa9kv@(=mEcu<~51N zRLV^-2#28tnur-#jC$@UX5mkmht)cn)87N5D33u6# zvRzmQPhu!$XC?ai+awdt9gB07(qE7weoJLg^a)_a4h=bOw<<4 zv${8t(cT=uMtBmlF}$1kyS)uoqC5k&6~(B5He(cij*)l{)z9y!c7EMWISRG4$*6wv zQ0+S)XU6TkKqiEWBJ6-OQ6c^>hT#p=`>P|aLs62!uU|XtPkAD$qpMgIeR~??P%FzvMWi!E z<1o~g&PKK0hnna)Yd|kP?Tqi_kkM%zh&ptO(H~b}HGCTt+Cx|cPooC9kCidFw=osf zt~n~?T`>h;z*_h^>I@u0MfMoF^}rP}q4*nWrWN{__c;-DKO6O6Gt}0!K~1nbvWLz9 zTR#GuQJ#c)D-NOt`U=DG8fu(Js4Wk9j`%Bd@z0qXxu}8KqQ2>!P=~D-Dl$c=2PdE= zG9NX;m8b!?T6dy8Wc!h?v2z5qu;{+#aOR*Q*|M+OtYiQc>S#DBbW>0REJB^;HK;u; zL9O7JEnh+n^cXc!zkcS^8jGrLiduPF%*6iajjy8?y3|c3p3F+j!Ou|-JVp%^-rv4H zsFmm0ay!)7=!1&jL{tP8p(efp)9@Ws_%$tcv*(Ff;X1)Pt5xEwX}b*NC5pg-ta*X z7L7%>DoV)I#v523s|_&&CZIxB2elP>n1K1%00*HaycQLaji`w2MXmIh^{n+KdU5<8 zU;y_Y4JH0sx&JV8N`p}kMxth%fQguk^|3FO#pSks4JrahP!qj`io}n${vImS0sk>u zn1F$lb8NZ!e~7;Z>_&w;dLFfhZgk;NR0q3I5%?B0^V6s;x@OCFQ0*S07F2n-*&-Ke zVyUR->)3J*>Q^w|O-3Q?j+$9dRL6r+p)5kJcslyyT#UhGwtg3?-9FSpzOwb_ZTTAN z@coAB-+zQ@ABFl5xs%A~Mk;C|xwb(g)PrqNk?CveUq+pgnWzChSP@sFz6&L`{4HuB zS5fV6V=(@ST1dc4r4w;Gk!18?Nknz@Bx*t(um<)*bvzZ-ZXIgHAKUVm)~nV>s4Wa1 zX(pbDIz!D-6B&k~I0i%X{?8#3N5v}C3_n91wiBpk3{b{`yw;r^1C(P+zvUPC)9g^W6^FvWx{ z)!GTGQ$G&%z)I8vKEgP>h%PKU)pVSI8ZaN#zB@)^5h?;6)WkMf51?BW7s%+;K0r;x z{}nS(8tQ&W)L|?{ZNXGj`=!MNnX6N%G^zi#AGq1UH1 zYQP@0JPLJ)reR%t7d62v*Z|8-H~)sy1brzFMXhus*2Fnj1Gixceup9GJHxb#oI(8c zK&Gu|fqGASqh6!Is1+BXUenpA57097!M9M6*ns75J8BE|qMkp6TInTJMDC#$?Dwj% zvYU(!MG7j!PoW;@fqGyF>VZkYzhv#|JL`R|~I32ZhOHdIgL4Q1gip(kW z#`D%oSV8aqRWjwdaT|38{zOHh!fdlb7pmhF)IiNpThay9elY4a9fyjT2eqZ^F#z{s zJRU)vi94u>Ma@xr_CJA)255j9xHIaI4MsgU7uE4L)W8Q(1Drv%zh~?H=bBHn%i10l zp^2z1TVP#+>SqOp>HRMuqnRF31)e~K>?cgeyQsa2d(Esg5%vBz#w6^EE}Vm!_`9er zIF4y}-IgQfnLlhYQ6H>9=vHP18SVLc)Xc7<4&@`%>k>KNOe_Vpl6>^T=C<4c11Wbw zZAE_!!f~jxH5)aNy_ktNQSGZOApUBYy1)#Shl)TuTkemF%xL7WIIr09Jk$h=Q5~&E zP5c9U|1btqK8ZPa-PXr>OnoNm^)2uaf1S!^RA^6IVnghMdK*@v4$W?K;YCzCpM@qu z(WsDTqaxS^tKw4B7Hzlpzek;=hnR?Qi_CwrZQ~}R2y8$X?!XxQ4#V&dREI&Yo710$ z`l2<$5bTS(KMHH(LR5$kqR!4AsI!x}*qo^}tVB5*6VXo}kJ2Zo$Xr65i3&^1a}`nT5-}9BQ9nj4(H{rc`@@kfa64{WF$J}!^H2?!p}q_2 zus&`!{$7-N|BGycDX5jrK@GGL zHL>*=h1*dp`3kl2Q<#d^QKvcl4RgOT>QKgF1~x(UGr~FrH4zWGpCGe}jApb2wSwKY z!8fP@&!bjw4O8$oYJydln~B6@d&+fDXJtD63m0H6p11YU#pW>9MD>?aO#DkvBNbJs zXoW5uh??OH)L~nM8h8ilwYrR&aQPLc!%C>gMWGgyf(m^uYCbVPUTX7RL@O@MVzN^d!C=i&5=XqsG}{ z%kDika~Ml!hWfBvKsCIJ8rb_yv+_u58Yu5}%yb?3;3)ES;k6Q6#)S2>M zT{^K=P6!!=Gy?TnrJ^_XMeXST)Wk-kI+$#oYh8w3)PLleUnA6A%bV;!uBRw>q+D0^ z_TB}WzfDo^Odax-sUL_*l&6szP%cM`r7qMyL$$M*@*{MUwvyMdPeP=moxc}9tNP08 z%A#U0#^a|ns6oD>CqF*aZxgw$)Xefc8y}Gq!hKz_c$V59$p4I;u{xDAaiqrxT6zM7%#B-?WUcYdUHEV@axNC~9Bub*uGL+eg%)Fgiq2a<}( zhml5-uWtJ!>y)?ou_|zFqRm3mYo-|Pq}m3jsMx~|U6Vb75}E}5my*6FX}HC+Ga;cv zB5nVolz~UNGs?C)Aj#5nG)z)!i~3qSE>B_?=1^mI#%$$3Qi z7ZN|f&RTqdG@hiZ3f{(i{1B5#V@OR&Z+YHJOz_=K?!Mduqbw|*7L&$BTpddM5(np4}5 zyO*&V>Ix@ch@G$=X$tuudoKqYQP-QgUvVj^7I|Iiw`byRGWF?1Y@1-Wk z*50DFAE|`$4*ciUn8F5I@xEtFa!hk+R%&Sc8vBgyJS3%)GD&wxYe_9g zWj%vZQ@mDr7Ny4YkF?`orT!1nF8h20-Xx`PzXyin4SSDf&N|YIlmn@M0w+@bj1)sU zM!5iW)#v^;PgGi*dx?Ge6+CG3^-LotomK^;uPJA7?+?;h@+U|&sBewGQCErlVVqBD zNu91f2uNm$|0nDd!H(&4P{;L;y0cv=?U%tofO3rUiPVl zrR~i>M%#Qc_b!vKW82i{8C@GmiKRJSM-1cs@7y~;8gA>wDcgRv7fX4Eiq~w#65FT( z5B|SrZAJt47u@-R+Q00bZPx45>o2NNqz>d=wuig8fV7ADP+Qj*KO@Z~eM`!w_g7KZ zN2I%?5Ebmzj(ZWbnd;^AEUkKuihZQUtIx#@c+nl0Aj{14>qpZRHbN`n1!gX?}ax$PxXAyXd2^f8Un| Z4J~x_A3l8Oa97Fg36Y^C@e8h1{2%m2;^zPW diff --git a/inc/users.class.php b/inc/users.class.php index 5c384ab1..268ef454 100644 --- a/inc/users.class.php +++ b/inc/users.class.php @@ -482,7 +482,7 @@ class SP_Users { public function newUserLDAP() { $passdata = SP_Users::makeUserPass($this->userPass); - $query = "INSERT INTO usrData SET" + $query = "INSERT INTO usrData SET " . "user_name = '" . DB::escape($this->userName) . "'," . "user_groupId = 0," . "user_login = '" . DB::escape($this->userLogin) . "'," @@ -614,6 +614,8 @@ class SP_Users { $query = "UPDATE usrData SET " . "user_pass = '" . $passdata['pass'] . "'," . "user_hashSalt = '" . $passdata['salt'] . "'," + . "user_name = '" . DB::escape($this->userName) . "'," + . "user_email = '" . DB::escape($this->userEmail) . "'," . "user_lastUpdate = NOW() " . "WHERE user_id = " . $this->getUserIdByLogin($this->userLogin) . " LIMIT 1";