LDAP support

Submitted by Valentino Ricci on 2020-12-11

Hello,

I needed LDAP support, so I modified the SessionManager in order to check the LDAP before the normal check and I added a new class to make LDAP autenthication.

SessionManager updates in bold:

    public function login( $login, $password, $newPassword = null )
    {
        $user = null;
        $isTemp = false;

        $transaction = $this->connection->beginTransaction( System_Db_Transaction::RepeatableRead, 'users' );

        try {
            $query = 'SELECT user_id, user_name, user_passwd, user_access, passwd_temp, user_email, user_language FROM {users}'
                . ' WHERE user_login = %s AND user_access > %d';

            $user = $this->connection->queryRow( $query, $login, System_Const::NoAccess );

            if ( $user != null ) {
                $userId = $user[ 'user_id' ];
                $hash = $user[ 'user_passwd' ];
                $isTemp = $user[ 'passwd_temp' ];

                $ldapHelper = new System_Api_TkLDAPHelper();
                if ( $ldapHelper->checkPassword( $login, $password ) == false) {

                    $passwordHash = new System_Core_PasswordHash();

                    if ( $passwordHash->checkPassword( $password, $hash ) ) {
                        if ( $newPassword != null ) {
                            if ( $newPassword == $password )
                                throw new System_Api_Error( System_Api_Error::CannotReusePassword );

                            if ( System_Core_Application::getInstance()->getSite()->getConfig( 'demo_mode' ) ) {
                                if ( $user[ 'user_access' ] != System_Const::AdministratorAccess )
                                    throw new System_Api_Error( System_Api_Error::AccessDenied );
                            }

                            $newHash = $passwordHash->hashPassword( $newPassword );

                            $query = 'UPDATE {users} SET user_passwd = %s, passwd_temp = 0 WHERE user_id = %d';
                            $this->connection->execute( $query, $newHash, $userId );

                            $isTemp = false;
                        } else if ( $passwordHash->isNewHashNeeeded( $hash ) ) {
                            $newHash = $passwordHash->hashPassword( $password );

                            $query = 'UPDATE {users} SET user_passwd = %s WHERE user_id = %d';
                            $this->connection->execute( $query, $newHash, $userId );
                        }
                    } else {
                        $user = null;
                    }
                } else {
                    $isTemp = false;
                }

            }

            $transaction->commit();
        } catch ( Exception $ex ) {
            $transaction->rollback();
            throw $ex;
        }

        if ( $user != null && $isTemp ) {
            $this->logout();
            throw new System_Api_Error( System_Api_Error::MustChangePassword );
        }

        $this->loginCommon( $login, $user );

        return $user;
    }

New class System_Api_TkLDAPHelper. I just need to get domain, host and port from configuration parameters.

<?php

//  File Location: /system/api/tkldaphelper.inc.php

if ( !defined( 'WI_VERSION' ) ) die( -1 );

class System_Api_TkLDAPHelper
{
    private static $ldapDomain = "@tekne.local";           // set here your ldap domain
    private static $ldapHost = "ldap://172.16.171.171";    // set here your ldap host
    private static $ldapPort = "389";                      // ldap Port (default 389)
    private static $ldapUser  = "";                        // ldap User (rdn or dn)
    private static $ldapPassword = "";                     // ldap associated Password  
    
    public function __construct(  )
    {
    }
    
   /**
    * Validate given password against the stored hash.
    * @param $password The plain text password.
    * @param $storedHash The stored hash.
    * @return @c true if the password is valid, @c false otherwise.
    */
    public function checkPassword( $user, $password )
    {
        if ( $user == null )
            return false;

        if ( $password == null )
            return false;

        $ldapConnection = ldap_connect(self::$ldapHost, self::$ldapPort);

        if ($ldapConnection) {
            self::$ldapUser = addslashes(trim($user));
            self::$ldapPassword = addslashes(trim($password));
            
            ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
            ldap_set_option($ldapConnection, LDAP_OPT_REFERRALS, 0);
            $ldapbind = @ldap_bind($ldapConnection, self::$ldapUser . self::$ldapDomain, self::$ldapPassword);

            // verify binding
            if ($ldapbind) {
                ldap_close($ldapConnection);    // close ldap connection
                return true;
            } 
        }
        return false;
    }
}
?>