LdapConnectionsTable.php 14 KB
<?php
namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Core\Exception\Exception;

class LdapConnectionsTable extends AppTable
{

    public $useTable = false;

    private $host;

    private $port;

    private $baseDn;

    private $authenticationType;

    private $filter;

    private $USE_LDAP = TRUE;

    private $fakeLDAPUsers = [];

    public function __construct()
    {
        parent::__construct();
    }

    // EP
    public function useFakeLdap()
    {
        return ! $this->useLdap();
    }

    public function useLdap()
    {
        $this->checkConfiguration();
        return $this->USE_LDAP;
    }

    private function buildFakeLdapUsers()
    {
        return $this->buildFakeLdapUsersFromDB();
    }

    private function buildFakeLdapUsersFromDB()
    {
        $users = TableRegistry::get('Users')->find();
        
        $ldapUsers = [];
        
        foreach ($users as $user) {
            $names = explode(" ", $user['nom']);
            if (isset($names[1])) {
                $ldapUsers[] = [
                    'sn' => [
                        $names[0]
                    ],
                    'mail' => [
                        $user['email']
                    ],
                    'givenname' => [
                        $names[1]
                    ],
                    $this->authenticationType => [
                        $user['username']
                    ],
                    'userpassword' => [
                        $user['password']
                    ]
                ];
            } else {
                $ldapUsers[] = [
                    'sn' => [
                        $names[0]
                    ],
                    'mail' => [
                        $user['email']
                    ],
                    'givenname' => " ",
                    $this->authenticationType => [
                        $user['username']
                    ],
                    'userpassword' => [
                        $user['password']
                    ]
                ];
            }
        }
        
        // EP (aout 2017)
        // ATTENTION : Utilisateur IMPORTANT.
        // Avec cet utilisateur, on simule un utilisateur qui n'est PAS dans la table utilisateurs
        // Il devrait donc se voir attribuer un role "Utilisateur" sans pour autant que ça soit écrit dans la table !!!
        // login = '_NouvelUtilisateur_username'
        // pass = '_NouvelUtilisateur_password'
        // $prefix = "_NouvelUtilisateur_";
        $ldapUsers[] = [
            'sn' => [
                'UTILISATEUR'
            ],
            'givenname' => [
                'FAKE_LDAP'
            ],
            // 'mail' => [$login.'email'],
            'mail' => [
                'fakeldapuser@domain.fr'
            ],
            // $this->authenticationType => [$prefix.'username'],
            $this->authenticationType => [
                $this->getTheFakeLdapUser()['login']
            ],
            // $this->authenticationType => ['usere'],
            'userpassword' => [
                $this->getTheFakeLdapUser()['pass']
            ]
            // 'userpassword' => ['toto'],
        ];
        
        return $ldapUsers;
    }

    private function checkConfiguration()
    {
        $config = TableRegistry::get('Configurations')->find()
            ->where([
            'id =' => 1
        ])
            ->first();
        
        $this->USE_LDAP = $config->use_ldap ? TRUE : FALSE;
        
        if (! $this->USE_LDAP) {
            $this->authenticationType = $config->authentificationType_ldap;
            if (empty($this->fakeLDAPUsers))
                $this->fakeLDAPUsers = $this->buildFakeLdapUsers();
            return true;
        }
        // debug($this->fakeLDAPUsers);
        
        $ldapConfig = $config->toArray();
        
        if (! empty($config->host_ldap) && ! empty($config->port_ldap) && ! empty($config->baseDn_ldap) && ! empty($config->authentificationType_ldap) && ! empty($config->filter_ldap)) {
            $this->host = $config->host_ldap;
            $this->port = $config->port_ldap;
            $this->baseDn = $config->baseDn_ldap;
            $this->filter = $config->filter_ldap;
            $this->authenticationType = $config->authentificationType_ldap;
            
            return true;
        }
        
        throw new Exception('The ldap configuration is not valid : <br />
			<ul>
				<li>host = ' . @$ldapConfig['host'] . '</li>
				<li>port = ' . @$ldapConfig['port'] . '</li>
				<li>baseDn = ' . @$ldapConfig['baseDn'] . '</li>
				<li>filter = ' . @$ldapConfig['filter'] . '</li>
				<li>authenticationType = ' . @$ldapConfig['authenticationType'] . '</li>
			</ul>');
    }

    public function getAllLdapUsers()
    {
        try {
            if ($this->checkConfiguration()) {
                // REAL LDAP
                if ($this->USE_LDAP) {
                    $ldapConnection = ldap_connect($this->host, $this->port);
                    ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
                    
                    $results = ldap_search($ldapConnection, $this->baseDn, $this->filter);
                    
                    $res = ldap_get_entries($ldapConnection, $results);
                }                // FAKE LDAP
                else {
                    $res = $this->fakeLDAPUsers;
                }
                return $res;
            }
        } catch (Exception $e) {}
        return false;
    }

    // $userName = login
    public function getUserAttributes($userName, $LDAP_ANONYMOUS=true, $filter='', $just_these=[])
    {
        try {
            
            if ($this->checkConfiguration()) {
                if ($this->USE_LDAP) {
                    /*
                    $ldapConnection = ldap_connect($this->host, $this->port);
                    ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
                    */
                    /* CRAL
                    */
                    //$results = ldap_search($ldapConnection, $this->baseDn, $filter);
                    $results = ldap_search($ldapConnection, $this->baseDn, $filter, $just_these) or die("Could not search to LDAP server  response was: " . ldap_error($ldapconn) );
                    $info = ldap_get_entries($ldapConnection, $results);
                    //echo $info["count"]." entries returned\n";
                    return $info;
                } else
                    return array(
                        $this->getFakeLdapUser($userName)
                    );
            }
        } catch (Exception $e) {}
        
        return false;
    }

    public function getAuthenticationType()
    {
        return $this->authenticationType;
    }

    // EP added
    public function getFakeLdapUser($login)
    {
        foreach ($this->fakeLDAPUsers as $user) {
            if ($login == $user[$this->authenticationType][0])
                return $user;
        }
        return FALSE;
    }

    /**
     * Return a list of Users with key = username & value = username
     */
    public function getListUsers()
    {
        $u = $this->getAllLdapUsers();
        $utilisateurs = [];
        
        if ($this->USE_LDAP) {
            for ($i = 0; $i < $u['count']; $i ++) {
                $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0];
            }
        } else {
            for ($i = 0; $i < sizeof($u) - 1; $i ++) {
                $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0];
            }
        }
        
        return $utilisateurs;
    }

    /**
     * Return a list of login ofUsers with key = username & value = login
     */
    public function getListLoginUsers()
    {
        $u = $this->getAllLdapUsers();
        $utilisateurs = [];
        
        if ($this->USE_LDAP) {
            for ($i = 0; $i < $u['count']; $i ++) {
                $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i][$this->authenticationType][0];
            }
        } else {
            for ($i = 0; $i < sizeof($u) - 1; $i ++) {
                $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i][$this->authenticationType][0];
            }
        }
        
        return $utilisateurs;
    }

    /**
     * Return a list of mail of Users with key = username & value = mail
     */
    public function getListEmailUsers()
    {
        $u = $this->getAllLdapUsers();
        $utilisateurs = [];
        
        if ($this->USE_LDAP) {
            for ($i = 0; $i < $u['count']; $i ++) {
                if (isset($u[$i]['mail'][0])) {
                    $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['mail'][0];
                } else {
                    $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = 'N/A';
                }
            }
        } else {
            for ($i = 0; $i < sizeof($u) - 1; $i ++) {
                $utilisateurs[$u[$i]['sn'][0] . ' ' . $u[$i]['givenname'][0]] = $u[$i]['mail'][0];
            }
        }
        
        return $utilisateurs;
    }

    /**
     * Return size of list users
     */
    public function getNbUsers()
    {
        $u = $this->getAllLdapUsers();
        
        if ($this->USE_LDAP) {
            $nbUsers = $u['count'];
        } else {
            $nbUsers = sizeof($u) - 1;
        }
        return $nbUsers;
    }

    // Utilisateur du ldap qui n'est pas dans la table utilisateurs
    // => il a donc le role "Utilisateur" PAR DEFAUT
    private function getTheFakeLdapUser()
    {
        return [
            'login' => '_fake_ldap_user_',
            'pass' => '_fake_ldap_user_pass'
        ];
    }

    public function ldapAuthentication($user_login, $user_password)
    {
        try {
            if ($this->checkConfiguration()) {
                
                // We are using LDAP
                if ($this->USE_LDAP) {
                    $LDAP_ANONYMOUS = true;
                    
                    // No connexion allowed without password
                    if (strlen(trim($user_password)) == 0) return FALSE;

                    // Set LDAP parameters
                    // - Anonymous connection (IRAP, IAS, LATMOS)
                    if ($LDAP_ANONYMOUS) {
                        //$dn = $this->baseDn; // "ou=users,dc=irap,dc=omp,dc=eu"
                        $auth_dn = ''; //= $this->authDn;
                        $binddn = $this->authenticationType . '=' . $user_login;
                        $ldappass = $user_password;
                        $filter = '('.$binddn.')';
                        //$just_these = array();
                        $just_these = [];
                    }
                    // - Authentified connection (CRAL)
                    else {
                        //$dn = $this->baseDn; // "dc=univ-lyon1,dc=fr";
                        //$binddn="CN=svc_ldap_cral,OU=users,OU=27,OU=sim,OU=univ-lyon1,DC=univ-lyon1,DC=fr";
                        //$binddn = "CN=svc_ldap_cral,OU=users,OU=27,OU=sim,OU=univ-lyon1,".$dn;
                        $auth_dn = "CN=svc_ldap_cral,OU=users,OU=27,OU=sim,OU=univ-lyon1"; //= $this->authDn;
                        $binddn = $auth_dn;
                        $ldappass = "lemotdepasse";
                        $filter = "(&(objectClass=person)(memberOf:1.2.840.113556.1.4.1941:=cn=ucbl.osu.cral,ou=groups,ou=27,ou=sim,ou=univ-lyon1,dc=univ-lyon1,dc=fr))";
                        $just_these = array("cn");
                    }
                    $binddn .= ','.$this->baseDn;
                    
                    // Connection
                    $ldapConnection = ldap_connect($this->host, $this->port) or die("Could not connect to $this->host (port $this->port)");
                    if ($ldapConnection) {
                        ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
                        // Binding
                        //if (@ldap_bind($ldapConnection, $this->authenticationType . '=' . $login . ',' . $this->baseDn, $password)) {
                        $ldapbind = ldap_bind($ldapConnection, $binddn, $ldappass) or die( "Could not bind to LDAP server.". ldap_error($ldapConnection) );
                        if ($ldapbind) {
                            //return $this->getUserAttributes($login, $LDAP_ANONYMOUS, $filter, $just_these)[0];
                            $search = $this->getUserAttributes($user_login, $LDAP_ANONYMOUS, $filter, $just_these) or die("Could not search in LDAP server, response was: " . ldap_error($ldapConnection) );
                            return $search[0];
                            /*
                             * } else {
                             * return false;
                             */
                        }
                    }
                    
                // We are not using LDAP (use FAKE LDAP instead)
                } else {
                    $user = $this->getFakeLdapUser($user_login);
                    // debug($user);
                    if ($user === false)
                        return FALSE;
                    // $this->authenticationType peut valoir "uid" ou "cn"... (par défaut "uid" pour le fake ldap, à confirmer...)
                    // if ($user['uid'][0] == "_NouvelUtilisateur_username" && $user['userpassword'][0] == "_NouvelUtilisateur_password") return $user;
                    // if ($user[$this->authenticationType][0] == "_NouvelUtilisateur_username" && $user['userpassword'][0] == "_NouvelUtilisateur_password") return $user;
                    if ($user[$this->authenticationType][0] == $this->getTheFakeLdapUser()['login'] && $user['userpassword'][0] == $this->getTheFakeLdapUser()['pass'])
                        return $user;
                    if ((new DefaultPasswordHasher())->check($user_password, $user['userpassword'][0]))
                        return $user;
                    // if ($user != false && $user['userpassword'][0] == $password) {
                }
            }
        } catch (Exception $e) {}
        return FALSE;
    }
}
?>