Source of file UsersourcesSourceLdap.php

Size: 12,826 Bytes - Last Modified: 2016-05-18T03:08:26+02:00

buildproject/core/module_ldap/system/usersources/UsersourcesSourceLdap.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
<?php
/*"******************************************************************************************************
*   (c) 2004-2006 by MulchProductions, www.mulchprod.de                                                 *
*   (c) 2007-2016 by Kajona, www.kajona.de                                                              *
*       Published under the GNU LGPL v2.1, see /system/licence_lgpl.txt                                 *
*-------------------------------------------------------------------------------------------------------*
*	$Id$                                            *
********************************************************************************************************/

namespace Kajona\Ldap\System\Usersources;

use Kajona\Ldap\System\Ldap;
use Kajona\System\System\Carrier;
use Kajona\System\System\Exception;
use Kajona\System\System\Logger;
use Kajona\System\System\Usersources\UsersourcesGroupInterface;
use Kajona\System\System\Usersources\UsersourcesUserInterface;
use Kajona\System\System\Usersources\UsersourcesUsersourceInterface;
use Kajona\System\System\UserUser;


/**
 * Global entry into the ldap-subsystem.
 * Mapps all calls and redirects them to the directory-services.
 * Since 4.8, the class is able to handle various ldap connections
 *
 * @author sidler@mulchprod.de
 * @since 3.4.1
 * @package module_ldap
 */
class UsersourcesSourceLdap implements UsersourcesUsersourceInterface
{

    private $objDB;


    /**
     * Default constructor
     */
    public function __construct()
    {
        $this->objDB = Carrier::getInstance()->getObjDB();
    }

    /**
     * Returns a readable name of the source, e.g. "Kajona" or "LDAP Company 1"
     *
     * @return mixed
     */
    public function getStrReadableName()
    {
        return Carrier::getInstance()->getObjLang()->getLang("usersource_ldap_name", "ldap");
    }

    /**
     * Tries to authenticate a user with the given credentials.
     * The password is unencrypted, each source should take care of its own encryption.
     *
     * @param UsersourcesUserInterface|UsersourcesUserLdap $objUser
     * @param string $strPassword
     *
     * @return bool
     */
    public function authenticateUser(UsersourcesUserInterface $objUser, $strPassword)
    {
        if ($objUser instanceof UsersourcesUserLdap) {
            foreach (Ldap::getAllInstances() as $objSingleLdap) {

                if ($objUser->getIntCfg() != $objSingleLdap->getIntCfgNr()) {
                    continue;
                }

                $objRealUser = new UserUser($objUser->getSystemid());

                $arrSingleUser = $objSingleLdap->getUserdetailsByName($objRealUser->getStrUsername());
                if ($arrSingleUser !== false && count($arrSingleUser) == 1) {
                    $arrSingleUser = $arrSingleUser[0];
                    $bitReturn = $objSingleLdap->authenticateUser($arrSingleUser['identifier'], $strPassword);


                    //synchronize the local data with the ldap-data
                    if ($objUser instanceof UsersourcesUserLdap) {
                        $objUser->setStrFamilyname($arrSingleUser["familyname"]);
                        $objUser->setStrGivenname($arrSingleUser["givenname"]);
                        $objUser->setStrEmail($arrSingleUser["mail"]);
                        $objUser->setStrDN($arrSingleUser["identifier"]);
                        $objUser->setIntCfg($objSingleLdap->getIntCfgNr());
                        $objUser->updateObjectToDb();
                        $this->objDB->flushQueryCache();

                    }

                    return $bitReturn;
                }


            }
        }

        return false;
    }

    /**
     * @return bool
     */
    public function getCreationOfGroupsAllowed()
    {
        return true;
    }

    /**
     * @return bool
     */
    public function getCreationOfUsersAllowed()
    {
        return false;
    }

    /**
     * @return bool
     */
    public function getMembersEditable()
    {
        return false;
    }

    /**
     * Loads the group identified by the passed id
     *
     * @param string $strId
     *
     * @return UsersourcesGroupInterface or null
     */
    public function getGroupById($strId)
    {
        $strQuery = "SELECT group_id FROM " . _dbprefix_ . "user_group WHERE group_id = ? AND group_subsystem = 'ldap'";

        $arrIds = $this->objDB->getPRow($strQuery, array($strId));
        if (isset($arrIds["group_id"]) && validateSystemid($arrIds["group_id"])) {
            return new UsersourcesGroupLdap($arrIds["group_id"]);
        }

        return null;
    }

    /**
     * Returns an empty group, e.g. to fetch the fields available and
     * in order to fill a new one.
     *
     * @return UsersourcesGroupInterface
     */
    public function getNewGroup()
    {
        return new UsersourcesGroupLdap();
    }

    /**
     * Returns an empty user, e.g. to fetch the fields available and
     * in order to fill a new one.
     *
     * @return UsersourcesUserInterface
     */
    public function getNewUser()
    {
        return new UsersourcesUserLdap();
    }

    /**
     * Loads the iser identified by the passed id
     *
     * @param string $strId
     *
     * @return UsersourcesUserInterface or null
     */
    public function getUserById($strId)
    {
        $strQuery = "SELECT user_id FROM " . _dbprefix_ . "user WHERE user_id = ? AND user_subsystem = 'ldap' AND (user_deleted = 0 OR user_deleted IS NULL)";

        $arrIds = Carrier::getInstance()->getObjDB()->getPRow($strQuery, array($strId));
        if (isset($arrIds["user_id"]) && validateSystemid($arrIds["user_id"])) {
            return new UsersourcesUserLdap($arrIds["user_id"]);
        }

        return null;
    }

    /**
     * Loads the user identified by the passed dn
     *
     * @param string $strUserDn
     *
     * @return UsersourcesUserInterface or null
     */
    public function getUserByDn($strUserDn)
    {
        $strQuery = "SELECT user_ldap_id FROM " . _dbprefix_ . "user_ldap WHERE user_ldap_dn = ?";

        $arrIds = Carrier::getInstance()->getObjDB()->getPRow($strQuery, array($strUserDn));
        if (isset($arrIds["user_ldap_id"]) && validateSystemid($arrIds["user_ldap_id"])) {
            return new UsersourcesUserLdap($arrIds["user_ldap_id"]);
        }

        return null;
    }


    /**
     * Loads the user identified by the passed name.
     * This method may be called during the authentication of users and may be used as a hook
     * in order to create new users in the central database not yet existing.
     *
     * @param string $strUsername
     *
     * @return UsersourcesUserInterface or null
     */
    public function getUserByUsername($strUsername)
    {
        $strQuery = "SELECT user_id FROM " . _dbprefix_ . "user WHERE user_username = ? AND user_subsystem = 'ldap' AND (user_deleted = 0 OR user_deleted IS NULL)";

        $arrIds = Carrier::getInstance()->getObjDB()->getPRow($strQuery, array($strUsername));
        if (isset($arrIds["user_id"]) && validateSystemid($arrIds["user_id"])) {
            return new UsersourcesUserLdap($arrIds["user_id"]);
        }

        //user not found. search for a matching user in the ldap and add a possible match to the system
        foreach (Ldap::getAllInstances() as $objSingleLdap) {
            $arrDetails = $objSingleLdap->getUserdetailsByName($strUsername);

            if ($arrDetails !== false && count($arrDetails) == 1) {
                $arrSingleUser = $arrDetails[0];
                $objUser = new UserUser();
                $objUser->setStrUsername($strUsername);
                $objUser->setStrSubsystem("ldap");
                $objUser->setIntActive(1);
                $objUser->setIntAdmin(1);
                $objUser->updateObjectToDb();

                /** @var $objSourceUser UsersourcesUserLdap */
                $objSourceUser = $objUser->getObjSourceUser();
                if ($objSourceUser instanceof UsersourcesUserLdap) {
                    $objSourceUser->setStrDN($arrSingleUser["identifier"]);
                    $objSourceUser->setStrFamilyname($arrSingleUser["familyname"]);
                    $objSourceUser->setStrGivenname($arrSingleUser["givenname"]);
                    $objSourceUser->setStrEmail($arrSingleUser["mail"]);
                    $objSourceUser->setIntCfg($objSingleLdap->getIntCfgNr());
                    $objSourceUser->updateObjectToDb();

                    $this->objDB->flushQueryCache();

                    return $objSourceUser;
                }

            }
        }

        return null;
    }

    /**
     * Returns an array of group-ids provided by the current source.
     *
     * @return string[]
     */
    public function getAllGroupIds()
    {
        $strQuery = "SELECT group_id
                       FROM " . _dbprefix_ . "user_group_ldap,
                            " . _dbprefix_ . "user_group
                      WHERE group_id = group_ldap_id
                      ORDER BY group_name";
        $arrRows = Carrier::getInstance()->getObjDB()->getPArray($strQuery, array());
        $arrReturn = array();
        foreach ($arrRows as $arrOneRow) {
            $arrReturn[] = $arrOneRow["group_id"];
        }

        return $arrReturn;
    }

    /**
     * Returns an array of user-ids provided by the current source.
     *
     * @return string[]
     */
    public function getAllUserIds()
    {
        $strQuery = "SELECT user_id
                       FROM " . _dbprefix_ . "user_ldap,
                            " . _dbprefix_ . "user
                      WHERE user_id = user_ldap_id
                        AND (user_deleted = 0 OR user_deleted IS NULL)
                      ORDER BY user_username";
        $arrRows = Carrier::getInstance()->getObjDB()->getPArray($strQuery, array());
        $arrReturn = array();
        foreach ($arrRows as $arrOneRow) {
            $arrReturn[] = $arrOneRow["user_id"];
        }

        return $arrReturn;
    }


    /**
     * Updates all user-data stored in the system.
     * This may be a long-running task, so execute this only explicitly
     * and not during common requests!
     *
     * @return bool
     */
    public function updateUserData()
    {
        //sync may take time -> increase the time available
        if (@ini_get("max_execution_time") < 500 && @ini_get("max_execution_time") > 0) {
            @ini_set("max_execution_time", "500");
        }

        $objLdap = Ldap::getInstance();

        //fill all groups - loads new members
        $arrGroups = $this->getAllGroupIds();

        $arrUserIds = array();

        foreach ($arrGroups as $strSingleGroupId) {
            $objGroup = new UsersourcesGroupLdap($strSingleGroupId);
            $arrUserIds = array_merge($arrUserIds, $objGroup->getUserIdsForGroup());
        }

        $arrUserIds = array_unique($arrUserIds);

        //parse all users
        $arrUsers = $this->getAllUserIds();
        foreach ($arrUsers as $strOneUserId) {
            $objUser = new UserUser($strOneUserId);
            /** @var $objSourceUser UsersourcesUserLdap */
            $objSourceUser = $objUser->getObjSourceUser();
            $arrUserDetails = false;
            try {
                $arrUserDetails = $objLdap->getUserdetailsByName($objUser->getStrUsername());
                if ($arrUserDetails != false && isset($arrUserDetails[0])) {
                    $arrUserDetails = $arrUserDetails[0];
                }
            } catch (Exception $objEx) {
            }
            if ($arrUserDetails !== false && in_array($strOneUserId, $arrUserIds)) {
                $objSourceUser->setStrDN($arrUserDetails["identifier"]);
                $objSourceUser->setStrFamilyname($arrUserDetails["familyname"]);
                $objSourceUser->setStrGivenname($arrUserDetails["givenname"]);
                $objSourceUser->setStrEmail($arrUserDetails["mail"]);
                $objSourceUser->updateObjectToDb();

                $this->objDB->flushQueryCache();
            } else {
                //user seems to be deleted, remove from system, too
                $objUser->deleteObject();
                Logger::getInstance("ldapsync.log")->addLogRow("Deleting user " . $strOneUserId . " / " . $objUser->getStrUsername() . " @ " . $objSourceUser->getStrDN(), Logger::$levelWarning);
            }
        }

        return true;

    }

}