diff --git a/CHANGELOG b/CHANGELOG index 2f9209b3c..baeb287b8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ === ** v1.2.0.10 === +* [MOD] Improved login when the webserver auth is used. * [MOD] Updated Russian translation. Thanks to @TitovLab * [FIX] Fixed user id checking instead login when using webserver auth. Thanks to @TitovLab * [FIX] Integer casting for boolean values on users management. Thanks to @maseht diff --git a/CHANGELOG-ES b/CHANGELOG-ES index e72007f39..68c7086ce 100644 --- a/CHANGELOG-ES +++ b/CHANGELOG-ES @@ -1,6 +1,7 @@ === ** v1.2.0.10 === -* [ADD] Actualizada traducción al ruso. Gracias a @TitovLab +* [MOD] Mejorado el login cuando la autentificación del servidor web es usada. +* [MOD] Actualizada traducción al ruso. Gracias a @TitovLab * [FIX] Corregida la comprobación del usuario cuando se usa la autentificación del servidor. Gracias a @TitovLab * [FIX] Casting a entero desde booleano en gestion de usuarios. Gracias a @maseht * [FIX] Corregido truncado de cadenas multibyte. Gracias a @TitovLab diff --git a/ajax/ajax_doLogin.php b/ajax/ajax_doLogin.php index 3b9d003ca..ec587846f 100644 --- a/ajax/ajax_doLogin.php +++ b/ajax/ajax_doLogin.php @@ -23,6 +23,7 @@ * */ +use SP\Auth; use SP\CryptMasterPass; use SP\Request; use SP\SessionUtil; @@ -63,7 +64,7 @@ // Autentificamos por LDAP if ($resLdap === true) { $Log->addDescription('(LDAP)'); - $Log->addDescription(sprintf('%s : %s', _('Servidor Login'), \SP\Ldap::getLdapServer())); + $Log->addDescription(sprintf('%s: %s', _('Servidor Login'), \SP\Ldap::getLdapServer())); // Verificamos si el usuario existe en la BBDD if (!UserLdap::checkLDAPUserInDB($userLogin)) { @@ -86,21 +87,21 @@ } else if ($resLdap == 49) { $Log->addDescription('(LDAP)'); $Log->addDescription(_('Login incorrecto')); - $Log->addDescription(_('Usuario') . ": " . $userLogin); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); $Log->writeLog(); SP\Response::printJSON(_('Usuario/Clave incorrectos')); } else if ($resLdap === 701) { $Log->addDescription('(LDAP)'); $Log->addDescription(_('Cuenta expirada')); - $Log->addDescription(_('Usuario') . ": " . $userLogin); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); $Log->writeLog(); SP\Response::printJSON(_('Cuenta expirada')); } else if ($resLdap === 702) { $Log->addDescription('(LDAP)'); $Log->addDescription(_('El usuario no tiene grupos asociados')); - $Log->addDescription(_('Usuario') . ": " . $userLogin); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); $Log->writeLog(); SP\Response::printJSON(_('Usuario/Clave incorrectos')); @@ -111,17 +112,27 @@ // Autentificamos con la BBDD if (!SP\Auth::authUserMySQL($userLogin, $userPass)) { $Log->addDescription(_('Login incorrecto')); - $Log->addDescription(_('Usuario') . ": " . $userLogin); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); $Log->writeLog(); SP\Response::printJSON(_('Usuario/Clave incorrectos')); } } +// Comprobar si concide el login con la autentificación del servidor web +if (!Auth::checkServerAuthUser($userLogin)){ + $Log->addDescription(_('Login incorrecto')); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); + $Log->addDescription(sprintf('%s: %s (%s)', _('Autentificación'), Auth::getServerAuthType(), Auth::getServerAuthUser())); + $Log->writeLog(); + + SP\Response::printJSON(_('Usuario/Clave incorrectos')); +} + // Comprobar si el usuario está deshabilitado if (UserUtil::checkUserIsDisabled($userLogin)) { $Log->addDescription(_('Usuario deshabilitado')); - $Log->addDescription(_('Usuario') . ": " . $userLogin); + $Log->addDescription(sprintf('%s: %s', _('Usuario'), $userLogin)); $Log->writeLog(); SP\Response::printJSON(_('Usuario deshabilitado')); @@ -171,9 +182,9 @@ // Cargar las variables de sesión del usuario SessionUtil::loadUserSession($User); - $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->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\Response::printJSON(_('Error interno')); diff --git a/inc/Auth.class.php b/inc/Auth.class.php index d93847f64..1a7518e3f 100644 --- a/inc/Auth.class.php +++ b/inc/Auth.class.php @@ -220,4 +220,44 @@ public static function checkAuthToken($actionId, $token) return (DB::$lastNumRows === 1); } + + /** + * Comprobar si el usuario es autentificado por el servidor web + * + * @param $login string El login del usuario a comprobar + * @return bool + */ + public static function checkServerAuthUser($login) + { + if (isset($_SERVER['PHP_AUTH_USER']) || isset($_SERVER['REMOTE_USER'])) { + return self::getServerAuthUser() == $login; + } + + return true; + } + + /** + * Devuelve el typo de autentificación del servidor web + * @return string + */ + public static function getServerAuthType() + { + return strtoupper($_SERVER['AUTH_TYPE']); + } + + /** + * Devolver el nombre del usuario autentificado por el servidor web + * + * @return string + */ + public static function getServerAuthUser() + { + if (isset($_SERVER['PHP_AUTH_USER'])) { + return $_SERVER['PHP_AUTH_USER']; + } elseif (isset($_SERVER['REMOTE_USER'])) { + return $_SERVER['REMOTE_USER']; + } + + return ''; + } } diff --git a/inc/Init.class.php b/inc/Init.class.php index ad0ad8a66..f6c9a4858 100644 --- a/inc/Init.class.php +++ b/inc/Init.class.php @@ -94,12 +94,6 @@ function __autoload($classname) } } - error_reporting(E_ALL | E_STRICT); - - if (defined('DEBUG') && DEBUG) { - ini_set('display_errors', 1); - } - date_default_timezone_set('UTC'); // Intentar desactivar magic quotes. @@ -107,44 +101,11 @@ function __autoload($classname) ini_set('magic_quotes_runtime', 0); } - // Copiar la cabecera http de autentificación para apache+php-fcgid - if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) { - $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION']; - } - - // Establecer las cabeceras de autentificación para apache+php-cgi - if (isset($_SERVER['HTTP_AUTHORIZATION']) - && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches) - ) { - list($name, $password) = explode(':', base64_decode($matches[1]), 2); - $_SERVER['PHP_AUTH_USER'] = strip_tags($name); - $_SERVER['PHP_AUTH_PW'] = strip_tags($password); - } - - // Establecer las cabeceras de autentificación para que apache+php-cgi funcione si la variable es renombrada por apache - if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) - && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches) - ) { - list($name, $password) = explode(':', base64_decode($matches[1]), 2); - $_SERVER['PHP_AUTH_USER'] = strip_tags($name); - $_SERVER['PHP_AUTH_PW'] = strip_tags($password); - } - - // Establecer el modo debug si una sesión de xdebug está activa - if (isset($_COOKIE['XDEBUG_SESSION']) && !defined('DEBUG')) { - define('DEBUG', true); - ini_set('display_errors', 1); - } + // Variables de autentificación + self::setAuth(); // Establecer el nivel de logging - if (defined('DEBUG') && DEBUG) { -// error_log('sysPass DEBUG'); - error_reporting(E_ALL); - ini_set('display_errors', 'On'); - } else { - error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE)); - ini_set('display_errors', 'Off'); - } + self::setLogging(); // Cargar las extensiones self::loadExtensions(); @@ -196,16 +157,14 @@ function __autoload($classname) self::checkPreLoginActions(); // Intentar establecer el tiempo de vida de la sesión en PHP - $sessionLifeTime = self::getSessionLifeTime(); - @ini_set('gc_maxlifetime', (string)$sessionLifeTime); + @ini_set('gc_maxlifetime', (string)self::getSessionLifeTime()); if (!Config::getValue("installed", false)) { Session::setUserId(''); } - if (isset($_SERVER['PHP_AUTH_USER']) && Session::getUserId() - && $_SERVER['PHP_AUTH_USER'] != Session::getUserLogin() - ) { + // Comprobar si se ha identificado mediante el servidor web y el usuario coincide + if (self::isLoggedIn() && !Auth::checkServerAuthUser(Session::getUserLogin())) { self::logout(); } @@ -213,7 +172,7 @@ function __autoload($classname) if (Request::analyze('redirect_url', '', true) && self::isLoggedIn()) { $location = 'index.php'; - // Denegar la regirección si la URL contiene una @ + // Denegar la redirección si la URL contiene una @ // Esto previene redirecciones como ?redirect_url=:user@domain.com if (strpos($location, '@') === false) { header('Location: ' . $location); @@ -222,7 +181,7 @@ function __autoload($classname) } // Volver a cargar la configuración si se recarga la página - if (Request::checkReload()){ + if (Request::checkReload()) { Config::readConfig(); // Restablecer el idioma y el tema visual @@ -260,11 +219,71 @@ public static function loadClass($class) foreach (explode(PATH_SEPARATOR, get_include_path()) as $includePath) { $classFile = $includePath . DIRECTORY_SEPARATOR . $class . '.class.php'; if (is_readable($classFile)) { - require $classFile; + require $classFile; } } } + /** + * Establecer variables de autentificación + */ + private static function setAuth() + { + // Copiar la cabecera http de autentificación para apache+php-fcgid + if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) { + $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION']; + } + + // Establecer las cabeceras de autentificación para apache+php-cgi + if (isset($_SERVER['HTTP_AUTHORIZATION']) + && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches) + ) { + list($name, $password) = explode(':', base64_decode($matches[1]), 2); + $_SERVER['PHP_AUTH_USER'] = strip_tags($name); + $_SERVER['PHP_AUTH_PW'] = strip_tags($password); + } + + // Establecer las cabeceras de autentificación para que apache+php-cgi funcione si la variable es renombrada por apache + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) + && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches) + ) { + list($name, $password) = explode(':', base64_decode($matches[1]), 2); + $_SERVER['PHP_AUTH_USER'] = strip_tags($name); + $_SERVER['PHP_AUTH_PW'] = strip_tags($password); + } + } + + /** + * Establecer el nivel de logging + */ + private static function setLogging() + { + // Establecer el modo debug si una sesión de xdebug está activa + if (isset($_COOKIE['XDEBUG_SESSION']) && !defined('DEBUG')) { + define('DEBUG', true); + } + + if (defined('DEBUG') && DEBUG) { + error_reporting(E_ALL); + ini_set('display_errors', 'On'); + } else { + error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE)); + ini_set('display_errors', 'Off'); + } + } + + /** + * Cargar las clases de las extensiones de sysPass + */ + private static function loadExtensions() + { + // Utilizar un cargador de clases PSR-0 + require EXTENSIONS_PATH . DIRECTORY_SEPARATOR . 'SplClassLoader.php'; + + $phpSecLoader = new \SplClassLoader('phpseclib', EXTENSIONS_PATH); + $phpSecLoader->register(); + } + /** * Iniciar la sesión PHP */ @@ -343,6 +362,18 @@ private static function setPaths() self::$WEBURI .= $protocol . $_SERVER['HTTP_HOST'] . self::$WEBROOT; } + /** + * Comprobar y forzar (si es necesario) la coneción HTTPS + */ + private static function checkHttps() + { + if (Util::forceHttpsIsEnabled() && !Util::httpsEnabled()) { + $port = ($_SERVER['SERVER_PORT'] != 443) ? ':' . $_SERVER['SERVER_PORT'] : ''; + $fullUrl = 'https://' . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI']; + header('Location: ' . $fullUrl); + } + } + /** * Comprobar el archivo que realiza el include necesita inicialización. * @@ -475,7 +506,7 @@ private static function wrLogoutInfo() */ private static function goLogin() { - $controller = new Controller\MainC(null,'login'); + $controller = new Controller\MainC(null, 'login'); $controller->getLogin(); $controller->view(); exit; @@ -629,6 +660,22 @@ public static function checkPreLoginActions() exit(); } + /** + * Comprobar si el usuario está logado. + * + * @returns bool + */ + public static function isLoggedIn() + { + if (Session::getUserLogin() + && Session::get2FApassed() + ) { + return true; + } + + return false; + } + /** * Comprobar si hay que ejecutar acciones de URL después del login. * @@ -641,7 +688,7 @@ public static function checkPostLoginActions() } $action = Request::analyze('a'); - $controller = new Controller\MainC(null , 'main'); + $controller = new Controller\MainC(null, 'main'); switch ($action) { case 'accView': @@ -656,22 +703,6 @@ public static function checkPostLoginActions() return true; } - /** - * Comprobar si el usuario está logado. - * - * @returns bool - */ - public static function isLoggedIn() - { - if (Session::getUserLogin() - && Session::get2FApassed() - ) { - return true; - } - - return false; - } - /** * Devuelve el tiempo actual en coma flotante. * Esta función se utiliza para calcular el tiempo de renderizado con coma flotante @@ -683,28 +714,4 @@ public static function microtime_float() list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } - - /** - * Cargar las clases de las extensiones de sysPass - */ - private static function loadExtensions() - { - // Utilizar un cargador de clases PSR-0 - require EXTENSIONS_PATH . DIRECTORY_SEPARATOR . 'SplClassLoader.php'; - - $phpSecLoader = new \SplClassLoader('phpseclib', EXTENSIONS_PATH); - $phpSecLoader->register(); - } - - /** - * Comprobar y forzar (si es necesario) la coneción HTTPS - */ - private static function checkHttps() - { - if(Util::forceHttpsIsEnabled() && !Util::httpsEnabled()){ - $port = ($_SERVER['SERVER_PORT'] != 443) ? ':' . $_SERVER['SERVER_PORT'] : ''; - $fullUrl = 'https://' . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI']; - header('Location: ' . $fullUrl); - } - } } \ No newline at end of file