diff --git a/include/class_exceptions.inc b/include/class_exceptions.inc index 1dc822e6c69d34e4cdf4436af8f0671e919aa0cc..ecaa716f15b15faee8e8a218c72a1a7f053973b2 100644 --- a/include/class_exceptions.inc +++ b/include/class_exceptions.inc @@ -78,3 +78,11 @@ class UnknownClassException extends FusionDirectoryException class LDAPFailureException extends FusionDirectoryException { } + +class LoginFailureException extends FusionDirectoryException +{ +} + +class LoginFailurePpolicyException extends LoginFailureException +{ +} diff --git a/include/class_userinfo.inc b/include/class_userinfo.inc index 101473a8dad480ed70993d10c74941dc317ce779..61995447703f1d60a843f7d6518d36d82f20a126 100644 --- a/include/class_userinfo.inc +++ b/include/class_userinfo.inc @@ -30,7 +30,6 @@ define('POSIX_ACCOUNT_EXPIRED', 1); define('POSIX_WARN_ABOUT_EXPIRATION', 2); define('POSIX_FORCE_PASSWORD_CHANGE', 4); define('POSIX_DISALLOW_PASSWORD_CHANGE', 8); -define('PPOLICY_ACCOUNT_EXPIRED', 16); /*! * \brief Class userinfo @@ -912,12 +911,6 @@ class userinfo $ldap = $config->get_ldap_link(); if (class_available('ppolicyAccount')) { - $ldap->cd($config->current['BASE']); - $ldap->search('(objectClass=*)', [], 'one'); - if (!$ldap->success()) { - return PPOLICY_ACCOUNT_EXPIRED; - } - try { list($policy, $attrs) = user::fetchPpolicy($this->dn); if ( @@ -1209,17 +1202,17 @@ class userinfo * * \return TRUE on SUCCESS, NULL or FALSE on error */ - public static function loginUser (string $username, string $password) + public static function loginUser (string $username, string $password): userinfo { global $config; $ui = static::getLdapUser($username); if ($ui === FALSE) { - return NULL; + throw new LoginFailureException('User not found'); } elseif (is_string($ui)) { msg_dialog::display(_('Internal error'), $ui, FATAL_ERROR_DIALOG); - return NULL; + exit(); } /* password check, bind as user with supplied password */ @@ -1229,7 +1222,15 @@ class userinfo ); $ldap = new ldapMultiplexer($ldapObj); if (!$ldap->success()) { - return NULL; + throw new LoginFailureException($ldap->get_error()); + } + + if (class_available('ppolicyAccount')) { + $ldap->cd($config->current['BASE']); + $ldap->search('(objectClass=*)', [], 'one'); + if (!$ldap->success()) { + throw new LoginFailurePpolicyException(_('It seems your user password has expired. Please use <a href="recovery.php">password recovery</a> to change it.')); + } } /* Username is set, load subtreeACL's now */ diff --git a/include/login/class_LoginMethod.inc b/include/login/class_LoginMethod.inc index 18a86edec6ffb2f0d405f9214a8a80523aaa1958..92797de643ac95e5610ef366b2aefe4018cf4e85 100644 --- a/include/login/class_LoginMethod.inc +++ b/include/login/class_LoginMethod.inc @@ -95,13 +95,21 @@ class LoginMethod { global $ui, $config, $message, $smarty; /* Login as user, initialize user ACL's */ - $ui = userinfo::loginUser(static::$username, static::$password); - if ($ui === NULL) { + try { + $ui = userinfo::loginUser(static::$username, static::$password); + } catch (LoginFailurePpolicyException $e) { + msg_dialog::display(_('Authentication error'), $e->getMessage(), ERROR_DIALOG); + logging::log('security', 'login', '', [], 'Account for user "'.static::$username.'" has expired (ppolicy)'); + $message = _('Password expired'); + $smarty->assign('focusfield', 'username'); + return FALSE; + } catch (LoginFailureException $e) { if (isset($_SERVER['REMOTE_ADDR'])) { - logging::log('security', 'login', '', [], 'Authentication failed for user "'.static::$username.'" [from '.$_SERVER['REMOTE_ADDR'].']'); + logging::log('security', 'login', '', [], 'Authentication failed for user "'.static::$username.'" [from '.$_SERVER['REMOTE_ADDR'].']: '.$e->getMessage()); } else { - logging::log('security', 'login', '', [], 'Authentication failed for user "'.static::$username.'"'); + logging::log('security', 'login', '', [], 'Authentication failed for user "'.static::$username.'": '.$e->getMessage()); } + /* Show the same message whether the user exists or not to avoid information leak */ $message = _('Please check the username/password combination.'); $smarty->assign('focusfield', 'password'); return FALSE; @@ -133,17 +141,6 @@ class LoginMethod /* Check account expiration */ $expired = $ui->expired_status(); - if ($expired == PPOLICY_ACCOUNT_EXPIRED) { - msg_dialog::display( - _('Authentication error'), - _('It seems your user password has expired. Please use <a href="recovery.php">password recovery</a> to change it.'), - ERROR_DIALOG - ); - logging::log('security', 'login', '', [], 'Account for user "'.static::$username.'" has expired (ppolicy)'); - $message = _('Password expired'); - $smarty->assign('focusfield', 'username'); - return FALSE; - } if ($expired == POSIX_ACCOUNT_EXPIRED) { logging::log('security', 'login', '', [], 'Account for user "'.static::$username.'" has expired');