Source of file UserManager.php
Size: 15,926 Bytes - Last Modified: 2020-10-24T02:46:31+00:00
/home/travis/build/NextDom/nextdom-core/src/Managers/UserManager.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 | <?php /* This file is part of Jeedom. * * Jeedom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jeedom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jeedom. If not, see <http://www.gnu.org/licenses/>. */ /* This file is part of NextDom Software. * * NextDom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NextDom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NextDom. If not, see <http://www.gnu.org/licenses/>. */ namespace NextDom\Managers; use NextDom\Enums\DateFormat; use NextDom\Enums\LogTarget; use NextDom\Enums\SQLField; use NextDom\Enums\UserRight; use NextDom\Helpers\DBHelper; use NextDom\Helpers\LogHelper; use NextDom\Helpers\NetworkHelper; use NextDom\Helpers\NextDomHelper; use NextDom\Helpers\Utils; use NextDom\Managers\Parents\BaseManager; use NextDom\Managers\Parents\CommonManager; use NextDom\Model\Entity\User; use NextDom\Repo\RepoMarket; use PragmaRX\Google2FA\Google2FA; define('BAD_LOGIN_BLOCK_DURATION', 5); /** * Class UserManager * @package NextDom\Managers */ class UserManager extends BaseManager { use CommonManager; const DB_CLASS_NAME = '`user`'; const CLASS_NAME = User::class; /** * Retourne un object utilisateur (si les information de connection sont valide) * @param string $_login nom d'utilisateur * @param string $_mdp mot de passe en sha512 * @return User|bool object user * @throws \Exception */ public static function connect($_login, $_mdp) { $sMdp = (!Utils::isSha512($_mdp)) ? Utils::sha512($_mdp) : $_mdp; if (ConfigManager::byKey('ldap:enable') == '1' && function_exists('ldap_connect')) { LogHelper::addDebug(LogTarget::CONNECTION, __('Authentification par LDAP')); $ad = self::connectToLDAP(); if ($ad !== false) { LogHelper::addDebug(LogTarget::CONNECTION, __('Connection au LDAP OK')); $ad = ldap_connect(ConfigManager::byKey('ldap:host'), ConfigManager::byKey('ldap:port')); ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ad, LDAP_OPT_REFERRALS, 0); if (!ldap_bind($ad, 'uid=' . $_login . ',' . ConfigManager::byKey('ldap:basedn'), $_mdp)) { LogHelper::addInfo(LogTarget::CONNECTION, __('Mot de passe erroné (') . $_login . ')'); return false; } LogHelper::addDebug(LogTarget::CONNECTION, __('Bind user OK')); $result = ldap_search($ad, ConfigManager::byKey('ldap::usersearch') . '=' . $_login . ',' . ConfigManager::byKey('ldap:basedn'), ConfigManager::byKey('ldap:filter')); LogHelper::addInfo(LogTarget::CONNECTION, __('Recherche LDAP (') . $_login . ')'); if ($result) { $entries = ldap_get_entries($ad, $result); if ($entries['count'] > 0) { $user = self::byLogin($_login); if (is_object($user)) { $user->setPassword($sMdp) ->setOptions('lastConnection', date(DateFormat::FULL)); $user->save(); return $user; } $user = (new User()) ->setLogin($_login) ->setPassword($sMdp) ->setOptions('lastConnection', date(DateFormat::FULL)); $user->save(); LogHelper::addInfo(LogTarget::CONNECTION, __('Utilisateur créé depuis le LDAP : ') . $_login); NextDomHelper::event('user_connect'); LogHelper::addInfo('event', __('Connexion de l\'utilisateur ') . $_login); return $user; } else { $user = self::byLogin($_login); if (is_object($user)) { $user->remove(); } LogHelper::addInfo(LogTarget::CONNECTION, __('Utilisateur non autorisé à accéder à NextDom (') . $_login . ')'); return false; } } else { $user = self::byLogin($_login); if (is_object($user)) { $user->remove(); } LogHelper::addInfo(LogTarget::CONNECTION, __('Utilisateur non autorisé à accéder à NextDom (') . $_login . ')'); return false; } } else { LogHelper::addInfo(LogTarget::CONNECTION, __('Impossible de se connecter au LDAP')); } } $user = self::byLoginAndPassword($_login, $sMdp); if (!is_object($user)) { $user = self::byLoginAndPassword($_login, sha1($_mdp)); if (is_object($user)) { $user->setPassword($sMdp); } } if (is_object($user)) { $user->setOptions('lastConnection', date(DateFormat::FULL)); $user->save(); NextDomHelper::event('user_connect'); LogHelper::addInfo('event', __('Connexion de l\'utilisateur ') . $_login); } return $user; } /** * @return bool|resource * @throws \Exception */ public static function connectToLDAP() { $ad = ldap_connect(ConfigManager::byKey('ldap:host'), ConfigManager::byKey('ldap:port')); ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ad, LDAP_OPT_REFERRALS, 0); if (ldap_bind($ad, ConfigManager::byKey('ldap:username'), ConfigManager::byKey('ldap:password'))) { return $ad; } return false; } /** * @param $_login * @return User|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byLogin($_login) { return static::getOneByClauses([SQLField::LOGIN => $_login]); } /** * @param $_login * @param $_password * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byLoginAndPassword($_login, $_password) { return static::getOneByClauses([SQLField::LOGIN => $_login, 'password' => $_password]); } /** * @param $_hash * @return User * @throws \Exception */ public static function byHash($_hash) { return static::getOneByClauses(['hash' => $_hash]); } /** * @param $_login * @param $_hash * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byLoginAndHash($_login, $_hash) { return static::getOneByClauses([SQLField::LOGIN => $_login, 'hash' => $_hash]); } /** * * @return User[] Array with all users * @throws \Exception */ public static function all() { return static::getAll(); } /** * @param $_rights * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function searchByRight($_rights) { $values = [ 'rights' => '%"' . $_rights . '":1%', 'rights2' => '%"' . $_rights . '":"1"%', ]; $sql = static::getBaseSQL() . ' WHERE `rights` LIKE :rights OR `rights` LIKE :rights2'; return DBHelper::getAllObjects($sql, $values, self::CLASS_NAME); } /** * @param $_profils * @param bool $_enable * @return User[]|null * @throws \Exception */ public static function byProfils($_profils, $_enable = false) { return static::getMultipleByClauses(['profils' => $_profils, 'enable' => 1]); } /** * @param $_enable * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byEnable($_enable) { return static::getMultipleByClauses(['enable' => $_enable]); } public static function failedLogin() { @session_start(); $_SESSION['failed_count'] = (isset($_SESSION['failed_count'])) ? $_SESSION['failed_count'] + 1 : 1; $_SESSION['failed_datetime'] = strtotime('now'); @session_write_close(); // Wait 5 seconds (brute force protection) sleep(BAD_LOGIN_BLOCK_DURATION); } public static function removeBanIp() { $cache = CacheManager::byKey('security::banip'); $cache->remove(); } /** * @deprecated * @return bool * @throws \Exception */ public static function isBan() { return self::isBanned(); } /** * @return bool * @throws \Exception */ public static function isBanned() { $ip = NetworkHelper::getClientIp(); if ($ip == '') { return false; } $whiteIps = explode(';', ConfigManager::byKey('security::whiteips')); if (ConfigManager::byKey('security::whiteips') != '' && count($whiteIps) > 0) { foreach ($whiteIps as $whiteip) { if (NetworkHelper::netMatch($whiteip, $ip)) { return false; } } } $cache = CacheManager::byKey('security::banip'); $values = json_decode($cache->getValue('[]'), true); if (!is_array($values)) { $values = []; } $values_tmp = []; if (count($values) > 0) { foreach ($values as $value) { if (ConfigManager::byKey('security::bantime') >= 0 && $value['datetime'] + ConfigManager::byKey('security::bantime') < strtotime('now')) { continue; } $values_tmp[] = $value; } } $values = $values_tmp; if (isset($_SESSION['failed_count']) && $_SESSION['failed_count'] >= ConfigManager::byKey('security::maxFailedLogin') && (strtotime('now') - ConfigManager::byKey('security::timeLoginFailed')) < $_SESSION['failed_datetime']) { $values_tmp = []; foreach ($values as $value) { if ($value['ip'] == $ip) { continue; } $values_tmp[] = $value; } $values = $values_tmp; $values[] = ['datetime' => strtotime(DateFormat::NOW), 'ip' => NetworkHelper::getClientIp()]; @session_start(); $_SESSION['failed_count'] = 0; $_SESSION['failed_datetime'] = -1; @session_write_close(); } CacheManager::set('security::banip', json_encode($values)); if (!is_array($values)) { $values = []; } if (count($values) == 0) { return false; } foreach ($values as $value) { if ($value['ip'] != $ip) { continue; } if (ConfigManager::byKey('security::bantime') >= 0 && $value['datetime'] + ConfigManager::byKey('security::bantime') < strtotime('now')) { continue; } return true; } return false; } /** * @return string * @throws \Exception */ public static function getAccessKeyForReport() { $user = self::byLogin('internal_report'); if (!is_object($user)) { $user = new User(); $user->setLogin('internal_report'); $google2fa = new Google2FA(); $user->setOptions('twoFactorAuthentificationSecret', $google2fa->generateSecretKey()); $user->setOptions('twoFactorAuthentification', 1); } $user->setPassword(Utils::sha512(ConfigManager::genKey(255))); $user->setOptions('localOnly', 1); $user->setProfils(UserRight::ADMIN); $user->setEnable(1); $key = ConfigManager::genKey(); $registerDevice = [ Utils::sha512($key) => [ 'datetime' => date(DateFormat::FULL), 'ip' => '127.0.0.1', 'session_id' => 'none', ], ]; $user->setOptions('registerDevice', $registerDevice); $user->save(); return $user->getHash() . '-' . $key; } /** * @param bool $_enable * @throws \Exception */ public static function supportAccess($_enable = true) { if ($_enable) { $user = self::byLogin('nextdom_support'); if (!is_object($user)) { $user = new User(); $user->setLogin('nextdom_support'); } $user->setPassword(Utils::sha512(ConfigManager::genKey(255))); $user->setProfils(UserRight::ADMIN); $user->setEnable(1); $key = ConfigManager::genKey(); $registerDevice = [ Utils::sha512($key) => [ 'datetime' => date(DateFormat::FULL), 'ip' => '127.0.0.1', 'session_id' => 'none', ], ]; $user->setOptions('registerDevice', $registerDevice); $user->save(); RepoMarket::supportAccess(true, $user->getHash() . '-' . $key); } else { $user = self::byLogin('nextdom_support'); if (is_object($user)) { $user->remove(); } RepoMarket::supportAccess(false); } } /** * @param $user */ public static function storeUserInSession($user) { $_SESSION['user'] = $user; } /** * @return User|null */ public static function getStoredUser() { if (isset($_SESSION['user'])) { return $_SESSION['user']; } return null; } public static function deadCmd() { $result = []; foreach (self::all() as $user) { $cmdId = $user->getOptions('notification::cmd'); if (!empty($cmdId) && is_object(CmdManager::byId(str_replace('#', '', $cmdId)))) { $result[] = ['detail' => __('Utilisateur'), 'help' => __('Commande notification utilisateur'), 'who' => $cmdId]; } } return $result; } public static function regenerateHash(){ foreach (self::all() as $user) { if($user->getProfils() != UserRight::ADMIN || $user->getOptions('doNotRotateHash',0) == 1 || !$user->isEnabled()){ continue; } if(strtotime($user->getOptions('hashGenerated')) > strtotime('now -3 month')){ continue; } $user->setHash(''); $user->getHash(); $user->save(); } } } |