diff --git a/doc/user-api/sections/user.text.tex b/doc/user-api/sections/user.text.tex index a1394a2f7..af04089dd 100644 --- a/doc/user-api/sections/user.text.tex +++ b/doc/user-api/sections/user.text.tex @@ -135,6 +135,52 @@ \subsection*{\textit{enableUser}} } \end{verbatim} } +\subsection*{\textit{disableLDAP}} + Disables LDAP authentication for an account. + { + \color{blue} + \begin{verbatim} +{ + "section": "user", + "request": "disableLDAP", + "userId": 3, + "accessKey": "mykey" +} + \end{verbatim} + } + { + \color{OliveGreen} + \begin{verbatim} +{ + "section": "user", + "request": "disableLDAP", + "response": "OK" +} + \end{verbatim} + } +\subsection*{\textit{enableLDAP}} + Enables LDAP authentication for an account. + { + \color{blue} + \begin{verbatim} +{ + "section": "user", + "request": "enableLDAP", + "userId": 3, + "accessKey": "mykey" +} + \end{verbatim} + } + { + \color{OliveGreen} + \begin{verbatim} +{ + "section": "user", + "request": "enableLDAP", + "response": "OK" +} + \end{verbatim} + } \subsection*{\textit{setUserPassword}} Set a new password for the user. This will not affect open sessions, only new logins. { diff --git a/src/dba/models/User.class.php b/src/dba/models/User.class.php index 2bcf5e135..10f817d22 100644 --- a/src/dba/models/User.class.php +++ b/src/dba/models/User.class.php @@ -9,6 +9,7 @@ class User extends AbstractModel { private $passwordHash; private $passwordSalt; private $isValid; + private $isLDAP; private $isComputedPassword; private $lastLoginDate; private $registeredSince; @@ -20,13 +21,14 @@ class User extends AbstractModel { private $otp3; private $otp4; - function __construct($userId, $username, $email, $passwordHash, $passwordSalt, $isValid, $isComputedPassword, $lastLoginDate, $registeredSince, $sessionLifetime, $rightGroupId, $yubikey, $otp1, $otp2, $otp3, $otp4) { + function __construct($userId, $username, $email, $passwordHash, $passwordSalt, $isValid, $isLDAP, $isComputedPassword, $lastLoginDate, $registeredSince, $sessionLifetime, $rightGroupId, $yubikey, $otp1, $otp2, $otp3, $otp4) { $this->userId = $userId; $this->username = $username; $this->email = $email; $this->passwordHash = $passwordHash; $this->passwordSalt = $passwordSalt; $this->isValid = $isValid; + $this->isLDAP = $isLDAP; $this->isComputedPassword = $isComputedPassword; $this->lastLoginDate = $lastLoginDate; $this->registeredSince = $registeredSince; @@ -47,6 +49,7 @@ function getKeyValueDict() { $dict['passwordHash'] = $this->passwordHash; $dict['passwordSalt'] = $this->passwordSalt; $dict['isValid'] = $this->isValid; + $dict['isLDAP'] = $this->isLDAP; $dict['isComputedPassword'] = $this->isComputedPassword; $dict['lastLoginDate'] = $this->lastLoginDate; $dict['registeredSince'] = $this->registeredSince; @@ -125,6 +128,14 @@ function setIsValid($isValid) { $this->isValid = $isValid; } + function getIsLDAP() { + return $this->isLDAP; + } + + function setIsLDAP($isLDAP) { + $this->isLDAP = $isLDAP; + } + function getIsComputedPassword() { return $this->isComputedPassword; } @@ -211,6 +222,7 @@ function setOtp4($otp4) { const PASSWORD_HASH = "passwordHash"; const PASSWORD_SALT = "passwordSalt"; const IS_VALID = "isValid"; + const IS_LDAP = "isLDAP"; const IS_COMPUTED_PASSWORD = "isComputedPassword"; const LAST_LOGIN_DATE = "lastLoginDate"; const REGISTERED_SINCE = "registeredSince"; @@ -221,4 +233,4 @@ function setOtp4($otp4) { const OTP2 = "otp2"; const OTP3 = "otp3"; const OTP4 = "otp4"; -} +} \ No newline at end of file diff --git a/src/dba/models/UserFactory.class.php b/src/dba/models/UserFactory.class.php index f50a06b52..b91386925 100644 --- a/src/dba/models/UserFactory.class.php +++ b/src/dba/models/UserFactory.class.php @@ -23,7 +23,7 @@ function getCacheValidTime() { * @return User */ function getNullObject() { - $o = new User(-1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + $o = new User(-1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); return $o; } @@ -33,7 +33,7 @@ function getNullObject() { * @return User */ function createObjectFromDict($pk, $dict) { - $o = new User($dict['userId'], $dict['username'], $dict['email'], $dict['passwordHash'], $dict['passwordSalt'], $dict['isValid'], $dict['isComputedPassword'], $dict['lastLoginDate'], $dict['registeredSince'], $dict['sessionLifetime'], $dict['rightGroupId'], $dict['yubikey'], $dict['otp1'], $dict['otp2'], $dict['otp3'], $dict['otp4']); + $o = new User($dict['userId'], $dict['username'], $dict['email'], $dict['passwordHash'], $dict['passwordSalt'], $dict['isValid'], $dict['isLDAP'], $dict['isComputedPassword'], $dict['lastLoginDate'], $dict['registeredSince'], $dict['sessionLifetime'], $dict['rightGroupId'], $dict['yubikey'], $dict['otp1'], $dict['otp2'], $dict['otp3'], $dict['otp4']); return $o; } diff --git a/src/inc/Login.class.php b/src/inc/Login.class.php index 9b4f8c2f3..130511f37 100755 --- a/src/inc/Login.class.php +++ b/src/inc/Login.class.php @@ -123,6 +123,22 @@ public function login($username, $password, $otp = NULL) { if ($user->getIsValid() != 1) { return false; } + else if ($user->getIsLDAP() == 1) { + $domain = SConfig::getInstance()->getVal(DConfig::LDAP_DOMAIN); + $ldap_conn = ldap_connect(SConfig::getInstance()->getVal(DConfig::LDAP_SERVER)); + $ldapbind=false; + if(ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3)) + if(ldap_set_option($ldap_conn, LDAP_OPT_REFERRALS, 0)) + if(ldap_start_tls($ldap_conn)) + $ldapbind = @ldap_bind($ldap_conn, $username."@".$domain, $password); + ldap_close($ldap_conn); + if (!$ldapbind) { + Util::createLogEntry(DLogEntryIssuer::USER, $user->getId(), DLogEntry::WARN, "Failed LDAP login attempt due to wrong password!"); + $payload = new DataSet(array(DPayloadKeys::USER => $user)); + NotificationHandler::checkNotifications(DNotificationType::USER_LOGIN_FAILED, $payload); + return false; + } + } else if (!Encryption::passwordVerify($password, $user->getPasswordSalt(), $user->getPasswordHash())) { Util::createLogEntry(DLogEntryIssuer::USER, $user->getId(), DLogEntry::WARN, "Failed login attempt due to wrong password!"); @@ -191,7 +207,3 @@ public function login($username, $password, $otp = NULL) { return true; } } - - - - diff --git a/src/inc/defines/config.php b/src/inc/defines/config.php index 0980e65b7..b4dfd89d3 100644 --- a/src/inc/defines/config.php +++ b/src/inc/defines/config.php @@ -59,6 +59,10 @@ class DConfig { const YUBIKEY_ID = "yubikey_id"; const YUBIKEY_KEY = "yubikey_key"; const YUBIKEY_URL = "yubikey_url"; + + // Section: LDAP + const LDAP_SERVER = "ldap_server"; + const LDAP_DOMAIN = "ldap_domain"; // Section: Finetuning const HASHES_PAGE_SIZE = "pagingSize"; @@ -316,6 +320,10 @@ public static function getConfigDescription($config) { return "Yubikey Secret Key."; case DConfig::YUBIKEY_URL: return "Yubikey API URL."; + case DConfig::LDAP_SERVER: + return "LDAP Server."; + case DConfig::LDAP_DOMAIN: + return "LDAP Domain."; case DConfig::BASE_HOST: return "Base hostname/port/protocol to use. Only fill this in to override the auto-determined value."; case DConfig::DONATE_OFF: diff --git a/src/inc/defines/userApi.php b/src/inc/defines/userApi.php index 7864b1a35..7c4d3a7be 100644 --- a/src/inc/defines/userApi.php +++ b/src/inc/defines/userApi.php @@ -900,6 +900,8 @@ class USectionUser extends UApi { const CREATE_USER = "createUser"; const DISABLE_USER = "disableUser"; const ENABLE_USER = "enableUser"; + const DISABLE_LDAP = "disableLDAP"; + const ENABLE_LDAP = "enableLDAP"; const SET_USER_PASSWORD = "setUserPassword"; const SET_USER_RIGHT_GROUP = "setUserRightGroup"; @@ -915,6 +917,10 @@ public function describe($constant) { return "Disable a user account"; case USectionUser::ENABLE_USER: return "Enable a user account"; + case USectionUser::DISABLE_LDAP: + return "Disable LDAP auth"; + case USectionUser::ENABLE_LDAP: + return "Enable LDAP auth"; case USectionUser::SET_USER_PASSWORD: return "Set a user's password"; case USectionUser::SET_USER_RIGHT_GROUP: diff --git a/src/inc/defines/users.php b/src/inc/defines/users.php index f220b3edf..99eae414b 100644 --- a/src/inc/defines/users.php +++ b/src/inc/defines/users.php @@ -38,6 +38,12 @@ class DUserAction { const DISABLE_USER = "disableUser"; const DISABLE_USER_PERM = DAccessControl::USER_CONFIG_ACCESS; + + const ENABLE_LDAP = "enableLDAP"; + const ENABLE_LDAP_PERM = DAccessControl::USER_CONFIG_ACCESS; + + const DISABLE_LDAP = "disableLDAP"; + const DISABLE_LDAP_PERM = DAccessControl::USER_CONFIG_ACCESS; const SET_RIGHTS = "setRights"; const SET_RIGHTS_PERM = DAccessControl::USER_CONFIG_ACCESS; diff --git a/src/inc/handlers/ConfigHandler.class.php b/src/inc/handlers/ConfigHandler.class.php index 794ac914e..63a970908 100644 --- a/src/inc/handlers/ConfigHandler.class.php +++ b/src/inc/handlers/ConfigHandler.class.php @@ -21,7 +21,7 @@ public function handle($action) { case DConfigAction::RESCAN_FILES: AccessControl::getInstance()->checkPermission(DConfigAction::RESCAN_FILES_PERM); ConfigUtils::scanFiles(); - UI::addMessage(UI::SUCCESS, "File scan was successfull, no actions required!"); + UI::addMessage(UI::SUCCESS, "File scan was successful, no actions required!"); break; case DConfigAction::CLEAR_ALL: AccessControl::getInstance()->checkPermission(DConfigAction::CLEAR_ALL_PERM); diff --git a/src/inc/handlers/UsersHandler.class.php b/src/inc/handlers/UsersHandler.class.php index ec65405bd..a3cdf187a 100644 --- a/src/inc/handlers/UsersHandler.class.php +++ b/src/inc/handlers/UsersHandler.class.php @@ -23,6 +23,16 @@ public function handle($action) { UserUtils::disableUser($_POST['user'], Login::getInstance()->getUser()); UI::addMessage(UI::SUCCESS, "User was disabled successfully!"); break; + case DUserAction::ENABLE_LDAP: + AccessControl::getInstance()->checkPermission(DUserAction::ENABLE_LDAP_PERM); + UserUtils::enableLDAP($_POST['user']); + UI::addMessage(UI::SUCCESS, "LDAP enabled successfully!"); + break; + case DUserAction::DISABLE_LDAP: + AccessControl::getInstance()->checkPermission(DUserAction::DISABLE_LDAP_PERM); + UserUtils::disableLDAP($_POST['user'], Login::getInstance()->getUser()); + UI::addMessage(UI::SUCCESS, "LDAP was disabled successfully!"); + break; case DUserAction::SET_RIGHTS: AccessControl::getInstance()->checkPermission(DUserAction::SET_RIGHTS_PERM); UserUtils::setRights($_POST['user'], $_POST['group'], Login::getInstance()->getUser()); diff --git a/src/inc/user-api/UserAPIUser.class.php b/src/inc/user-api/UserAPIUser.class.php index 3d582f5cf..7024def53 100644 --- a/src/inc/user-api/UserAPIUser.class.php +++ b/src/inc/user-api/UserAPIUser.class.php @@ -19,6 +19,12 @@ public function execute($QUERY = array()) { case USectionUser::ENABLE_USER: $this->enableUser($QUERY); break; + case USectionUser::DISABLE_LDAP: + $this->disableLDAP($QUERY); + break; + case USectionUser::ENABLE_LDAP: + $this->enableLDAP($QUERY); + break; case USectionUser::SET_USER_PASSWORD: $this->setUserPassword($QUERY); break; @@ -82,6 +88,30 @@ private function disableUser($QUERY) { $this->sendSuccessResponse($QUERY); } + /** + * @param array $QUERY + * @throws HTException + */ + private function enableLDAP($QUERY) { + if (!isset($QUERY[UQueryUser::USER_ID])) { + throw new HTException("Invalid query!"); + } + UserUtils::enableLDAP($QUERY[UQueryUser::USER_ID]); + $this->sendSuccessResponse($QUERY); + } + + /** + * @param array $QUERY + * @throws HTException + */ + private function disableLDAP($QUERY) { + if (!isset($QUERY[UQueryUser::USER_ID])) { + throw new HTException("Invalid query!"); + } + UserUtils::disableLDAP($QUERY[UQueryUser::USER_ID], $this->user); + $this->sendSuccessResponse($QUERY); + } + /** * @param array $QUERY * @throws HTException diff --git a/src/inc/utils/UserUtils.class.php b/src/inc/utils/UserUtils.class.php index 94357f526..6a9879740 100644 --- a/src/inc/utils/UserUtils.class.php +++ b/src/inc/utils/UserUtils.class.php @@ -73,7 +73,26 @@ public static function disableUser($userId, $adminUser) { Factory::getSessionFactory()->massUpdate([Factory::FILTER => $qF, Factory::UPDATE => $uS]); Factory::getUserFactory()->set($user, User::IS_VALID, 0); } + + /** + * @param int $userId + * @throws HTException + */ + public static function enableLDAP($userId) { + $user = UserUtils::getUser($userId); + Factory::getUserFactory()->set($user, User::IS_LDAP, 1); + } + + /** + * @param int $userId + * @throws HTException + */ + public static function disableLDAP($userId) { + $user = UserUtils::getUser($userId); + Factory::getUserFactory()->set($user, User::IS_LDAP, 0); + } + /** * @param int $userId * @param int $groupId @@ -134,7 +153,7 @@ public static function createUser($username, $email, $rightGroupId, $adminUser) $newPass = Util::randomString(10); $newSalt = Util::randomString(20); $newHash = Encryption::passwordHash($newPass, $newSalt); - $user = new User(null, $username, $email, $newHash, $newSalt, 1, 1, 0, time(), 3600, $group->getId(), 0, "", "", "", ""); + $user = new User(null, $username, $email, $newHash, $newSalt, 1, 0,1, 0, time(), 3600, $group->getId(), 0, "", "", "", ""); Factory::getUserFactory()->save($user); // add user to default group diff --git a/src/install/.htaccess b/src/install/.htaccess new file mode 100644 index 000000000..896fbc5a3 --- /dev/null +++ b/src/install/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all \ No newline at end of file diff --git a/src/install/hashtopolis.sql b/src/install/hashtopolis.sql index 1bb1f7438..70f068ccb 100644 --- a/src/install/hashtopolis.sql +++ b/src/install/hashtopolis.sql @@ -171,7 +171,10 @@ INSERT INTO `Config` (`configId`, `configSectionId`, `item`, `value`) VALUES (74, 4, 'agentUtilThreshold1', '90'), (75, 4, 'agentUtilThreshold2', '75'), (76, 3, 'uApiSendTaskIsComplete', '0'), - (77, 1, 'hcErrorIgnore', 'DeviceGetFanSpeed'); + (77, 1, 'hcErrorIgnore', 'DeviceGetFanSpeed'), + (78, 8, 'ldap_server', ''), + (79, 8, 'ldap_domain', ''); + CREATE TABLE `ConfigSection` ( `configSectionId` INT(11) NOT NULL, @@ -185,7 +188,8 @@ INSERT INTO `ConfigSection` (`configSectionId`, `sectionName`) VALUES (4, 'UI'), (5, 'Server'), (6, 'Multicast'), - (7, 'Notifications'); + (7, 'Notifications'), + (8, 'LDAP'); CREATE TABLE `CrackerBinary` ( `crackerBinaryId` INT(11) NOT NULL, @@ -746,6 +750,7 @@ CREATE TABLE `User` ( `passwordHash` VARCHAR(256) NOT NULL, `passwordSalt` VARCHAR(256) NOT NULL, `isValid` TINYINT(4) NOT NULL, + `isLDAP` TINYINT(4) NOT NULL DEFAULT 0, `isComputedPassword` TINYINT(4) NOT NULL, `lastLoginDate` BIGINT NOT NULL, `registeredSince` BIGINT NOT NULL, diff --git a/src/install/index.php b/src/install/index.php index 707417330..fa1d6c3e5 100755 --- a/src/install/index.php +++ b/src/install/index.php @@ -180,7 +180,7 @@ $group = $group[0]; $newSalt = Util::randomString(20); $newHash = Encryption::passwordHash($password, $newSalt); - $user = new User(null, $username, $email, $newHash, $newSalt, 1, 1, 0, time(), 3600, $group->getId(), 0, "", "", "", ""); + $user = new User(null, $username, $email, $newHash, $newSalt, 1, 0, 1, 0, time(), 3600, $group->getId(), 0, "", "", "", ""); Factory::getUserFactory()->save($user); // create default group diff --git a/src/templates/account.template.html b/src/templates/account.template.html index 4df5deafa..7c48f6877 100755 --- a/src/templates/account.template.html +++ b/src/templates/account.template.html @@ -39,6 +39,7 @@