diff --git a/app/Controllers/Auth/LoginController.php b/app/Controllers/Auth/LoginController.php index 8c24509..31bcc4b 100644 --- a/app/Controllers/Auth/LoginController.php +++ b/app/Controllers/Auth/LoginController.php @@ -51,20 +51,17 @@ class LoginController extends Controller } $username = param($request, 'username'); - $user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch(); + $user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota`, `ldap` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch(); if ($this->config['ldap']['enabled']) { - $result = $this->ldapLogin($username, param($request, 'password'), $user); - if ($result) { - $user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch(); - } + $user = $this->ldapLogin($request, $username, param($request, 'password'), $user); } $validator = ValidationChecker::make() ->rules([ 'login' => $user && password_verify(param($request, 'password'), $user->password), - 'maintenance' => !isset($this->config['maintenance']) || !$this->config['maintenance'] || $user->is_admin, - 'user_active' => $user->active, + 'maintenance' => !isset($this->config['maintenance']) || !$this->config['maintenance'] || $user->is_admin ?? false, + 'user_active' => $user->active ?? false, ]) ->onFail(function ($rule) { $alerts = [ @@ -119,29 +116,55 @@ class LoginController extends Controller } /** + * @param Request $request * @param string $username * @param string $password * @param $dbUser * @return bool + * @throws \Slim\Exception\HttpNotFoundException + * @throws \Slim\Exception\HttpUnauthorizedException */ - protected function ldapLogin(string $username, string $password, $dbUser) + protected function ldapLogin(Request $request, string $username, string $password, $dbUser) { - if (!extension_loaded('ldap')) { - $this->logger->error('The LDAP extension is not loaded.'); - return false; - } - - $server = ldap_connect($this->config['ldap']['host'], $this->config['ldap']['port']); - + $server = $this->ldapConnect(); if (!$server) { $this->session->alert(lang('ldap_cant_connect'), 'warning'); - return false; + return $dbUser; + } + if (!@ldap_bind($server, $this->getLdapRdn($username), $password)) { + if ($dbUser && !$dbUser->ldap) { + return $dbUser; + } + return null; + } + if (!$dbUser) { + $email = $username; + if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { + $search = ldap_search($server, $this->config['ldap']['user_domain'].','.$this->config['ldap']['base_domain'], 'uid='.addslashes($username), ['mail']); + $entry = ldap_first_entry($server, $search); + $email = @ldap_get_values($server, $entry, 'mail')[0] ?? platform_mail($username.rand(0, 100)); // if the mail is not set, generate a placeholder + } + /** @var UserQuery $userQuery */ + $userQuery = make(UserQuery::class); + $userQuery->create($email, $username, $password, 0, 1, (int) $this->getSetting('default_user_quota', -1), null, 1); + return $userQuery->get($request, $this->database->getPdo()->lastInsertId()); } - ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3); - ldap_set_option($server, LDAP_OPT_REFERRALS, 0); - ldap_set_option($server, LDAP_OPT_NETWORK_TIMEOUT, 10); + if (!password_verify($password, $dbUser->password)) { + $userQuery = make(UserQuery::class); + $userQuery->update($dbUser->id, $dbUser->email, $username, $password, $dbUser->is_admin, $dbUser->active, $dbUser->max_disk_quota, $dbUser->ldap); + return $userQuery->get($request, $dbUser->id); + } + return $dbUser; + } + + /** + * @param string $username + * @return string + */ + private function getLdapRdn(string $username) + { $bindString = 'uid='.addslashes($username); if ($this->config['ldap']['user_domain'] !== null) { $bindString .= ','.$this->config['ldap']['user_domain']; @@ -151,40 +174,6 @@ class LoginController extends Controller $bindString .= ','.$this->config['ldap']['base_domain']; } - if (!@ldap_bind($server, $bindString, $password)) { - return false; - } - - if (!$dbUser) { - $email = $username; - if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { - $search = ldap_search($server, $this->config['ldap']['user_domain'].','.$this->config['ldap']['base_domain'], 'uid='.addslashes($username), ['mail']); - $entry = ldap_first_entry($server, $search); - $email = @ldap_get_values($server, $entry, 'mail')[0] ?? platform_mail($username.uniqid()); - } - make(UserQuery::class)->create( - $email, - $username, - $password, - 0, - 1, - (int) $this->getSetting('default_user_quota', -1) - ); - return true; - } - - if (!password_verify($password, $dbUser->password)) { - make(UserQuery::class)->update( - $dbUser->id, - $dbUser->email, - $username, - $password, - $dbUser->is_admin, - $dbUser->active, - $dbUser->max_disk_quota - ); - } - - return true; + return $bindString; } } diff --git a/app/Controllers/Auth/PasswordRecoveryController.php b/app/Controllers/Auth/PasswordRecoveryController.php index 7f78083..25edbc1 100644 --- a/app/Controllers/Auth/PasswordRecoveryController.php +++ b/app/Controllers/Auth/PasswordRecoveryController.php @@ -39,7 +39,7 @@ class PasswordRecoveryController extends Controller return redirect($response, route('home')); } - $user = $this->database->query('SELECT `id`, `username` FROM `users` WHERE `email` = ? LIMIT 1', param($request, 'email'))->fetch(); + $user = $this->database->query('SELECT `id`, `username` FROM `users` WHERE `email` = ? AND NOT `ldap` LIMIT 1', param($request, 'email'))->fetch(); if (!isset($user->id)) { $this->session->alert(lang('recover_email_sent'), 'success'); diff --git a/app/Controllers/Controller.php b/app/Controllers/Controller.php index d278ced..7005965 100644 --- a/app/Controllers/Controller.php +++ b/app/Controllers/Controller.php @@ -167,4 +167,25 @@ abstract class Controller $this->session->alert($alerts[$rule], 'danger'); }); } + + /** + * @return bool|false|resource + */ + public function ldapConnect() + { + if (!extension_loaded('ldap')) { + $this->logger->error('The LDAP extension is not loaded.'); + return false; + } + + $server = ldap_connect($this->config['ldap']['host'], $this->config['ldap']['port']); + + if ($server) { + ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3); + ldap_set_option($server, LDAP_OPT_REFERRALS, 0); + ldap_set_option($server, LDAP_OPT_NETWORK_TIMEOUT, 10); + } + + return $server; + } } diff --git a/app/Database/Queries/UserQuery.php b/app/Database/Queries/UserQuery.php index 5cd9a6f..a53f488 100644 --- a/app/Database/Queries/UserQuery.php +++ b/app/Database/Queries/UserQuery.php @@ -79,9 +79,10 @@ class UserQuery * @param int $isActive * @param int $maxUserQuota * @param string|null $activateToken + * @param int $ldap * @return bool|\PDOStatement|string */ - public function create(string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, string $activateToken = null) + public function create(string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, string $activateToken = null, int $ldap =0) { do { $userCode = humanRandomString(5); @@ -89,7 +90,7 @@ class UserQuery $token = $this->generateUserUploadToken(); - return $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`, `activate_token`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [ + return $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`, `activate_token`, `ldap`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ $email, $username, $password !== null ? password_hash($password, PASSWORD_DEFAULT) : null, @@ -99,6 +100,7 @@ class UserQuery $token, $maxUserQuota, $activateToken, + $ldap ]); } @@ -110,27 +112,30 @@ class UserQuery * @param int $isAdmin * @param int $isActive * @param int $maxUserQuota + * @param int $ldap * @return bool|\PDOStatement|string */ - public function update($id, string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1) + public function update($id, string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, int $ldap = 0) { if (!empty($password)) { - return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [ + return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=? WHERE `id` = ?', [ $email, $username, password_hash($password, PASSWORD_DEFAULT), $isAdmin, $isActive, $maxUserQuota, + $ldap, $id, ]); } else { - return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [ + return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=? WHERE `id` = ?', [ $email, $username, $isAdmin, $isActive, $maxUserQuota, + $ldap, $id, ]); } diff --git a/bin/migrate b/bin/migrate index bc24bb0..62e5414 100644 --- a/bin/migrate +++ b/bin/migrate @@ -34,7 +34,7 @@ if (isset($argv[1]) && $argv[1] === '--install') { } if (file_exists(__DIR__.'/../install') && (!isset($config['debug']) || !$config['debug'])) { - //removeDirectory(__DIR__.'/../install'); + removeDirectory(__DIR__.'/../install'); } echo 'If you are upgrading from a previous version, please run a "php bin\clean".'.PHP_EOL; diff --git a/resources/schemas/mysql/mysql.7.sql b/resources/schemas/mysql/mysql.7.sql new file mode 100644 index 0000000..6c9cc08 --- /dev/null +++ b/resources/schemas/mysql/mysql.7.sql @@ -0,0 +1 @@ +ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/resources/schemas/sqlite/sqlite.7.sql b/resources/schemas/sqlite/sqlite.7.sql new file mode 100644 index 0000000..6c9cc08 --- /dev/null +++ b/resources/schemas/sqlite/sqlite.7.sql @@ -0,0 +1 @@ +ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file