2017-08-08 03:01:11 +08:00
< ? php
/**
* Simple LDAP object to interact with LDAP
*
* @ author Denis CLAVIER < clavierd at gmail dot com >
*/
require_once __DIR__ . '/LDAPInterface.php' ;
class LDAP implements LDAPInterface
{
protected $ldap_server ;
/**
* LDAP Resource
*
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_host
2017-08-08 03:01:11 +08:00
* Either a hostname or , with OpenLDAP 2. x . x and later , a full LDAP URI
2019-05-02 20:51:50 +08:00
* @ param int @ ldap_port
2018-05-20 00:04:13 +08:00
* An optional int to specify ldap server port , by default : 389
* @ param int @ ldap_version
* An optional int to specify ldap version , by default LDAP V3 protocol is used
2017-08-08 03:01:11 +08:00
*
* Initiate LDAP connection by creating an associated resource
*/
2019-05-02 20:51:50 +08:00
public function __construct ( $ldap_host , $ldap_port = 389 , $ldap_version = 3 )
2017-08-08 03:01:11 +08:00
{
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_host ))
2017-08-08 03:01:11 +08:00
{
throw new InvalidArgumentException ( 'First argument to LDAP must be the hostname of a ldap server (string). Ex: ldap//example.com/ ' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_int ( $ldap_port ))
2017-08-08 03:01:11 +08:00
{
throw new InvalidArgumentException ( 'Second argument to LDAP must be the ldap server port (int). Ex : 389' );
}
2019-05-02 20:51:50 +08:00
$ldap = ldap_connect ( $ldap_host , $ldap_port )
2017-08-08 03:01:11 +08:00
or die ( " Unable to connect to the ldap server : $ldaphost ! Please check your configuration. " );
2018-05-20 00:04:13 +08:00
// Support LDAP V3 since many users have encountered difficulties with LDAP V3.
if ( is_int ( $ldap_version ) && $ldap_version <= 3 && $ldap_version > 0 )
{
ldap_set_option ( $ldap , LDAP_OPT_PROTOCOL_VERSION , $ldap_version );
}
else
{
throw new InvalidArgumentException ( 'Third argument to LDAP must be the ldap version (int). Ex : 3' );
}
2017-08-08 03:01:11 +08:00
$this -> ldap_server = $ldap ;
}
/**
2017-08-26 21:54:24 +08:00
* @ param string @ user
* A ldap username or email or sAMAccountName
2017-08-08 03:01:11 +08:00
* @ param string @ password
2017-08-26 21:54:24 +08:00
* An optional password linked to the user , if not provided an anonymous bind is attempted
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_search_attribute
2017-08-26 21:54:24 +08:00
* The attribute used on your LDAP to identify user ( uid , email , cn , sAMAccountName )
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_filter
2017-08-26 21:54:24 +08:00
* An optional filter to search in LDAP ( ex : objectClass = person ) .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_base_dn
2017-08-26 21:54:24 +08:00
* The LDAP base DN .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_bind_dn
2017-08-26 21:54:24 +08:00
* The directory name of a service user to bind before search . Must be a user with read permission on LDAP .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_bind_pass
2017-08-26 21:54:24 +08:00
* The password associated to the service user to bind before search .
2017-08-08 03:01:11 +08:00
*
* @ return
* TRUE if the user is identified and can access to the LDAP server
* and FALSE if it isn ' t
*/
2019-05-02 20:51:50 +08:00
public function checkLogin ( $user , $password = null , $ldap_search_attribute , $ldap_filter = null , $ldap_base_dn , $ldap_bind_dn , $ldap_bind_pass ) {
2017-08-26 21:54:24 +08:00
if ( ! is_string ( $user ))
2017-08-08 03:01:11 +08:00
{
2017-08-26 21:54:24 +08:00
throw new InvalidArgumentException ( 'First argument to LDAP/checkLogin must be the username or email of a ldap user (string). Ex: jdupont or jdupont@company.com' );
2017-08-08 03:01:11 +08:00
}
if ( ! is_string ( $password ) && $password != null )
{
throw new InvalidArgumentException ( 'Second argument to LDAP/checkLogin must be the password associated to the relative directory name (string).' );
2017-08-26 21:54:24 +08:00
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_search_attribute ))
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Third argument to LDAP/checkLogin must be the attribute to identify users (ex : uid, email, sAMAccountName) (string).' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_filter ) && $ldap_filter != null )
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Fourth argument to LDAP/checkLogin must be an optional filter to search in LDAP (string).' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_base_dn ))
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Fifth argument to LDAP/checkLogin must be the ldap base directory name (string). Ex: o=Company' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_bind_dn ) && $ldap_bind_dn != null )
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Sixth argument to LDAP/checkLogin must be an optional service account on restrictive LDAP (string).' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_bind_pass ) && $ldap_bind_pass != null )
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Seventh argument to LDAP/checkLogin must be an optional password for the service account on restrictive LDAP (string).' );
}
// If LDAP service account for search is specified, do an ldap_bind with this account
2019-05-02 20:51:50 +08:00
if ( $ldap_bind_dn != '' && $ldap_bind_dn != null )
2017-08-26 21:54:24 +08:00
{
2019-05-02 20:51:50 +08:00
$bind_result = ldap_bind ( $this -> ldap_server , $ldap_bind_dn , $ldap_bind_pass );
2017-08-26 21:54:24 +08:00
// If authentification failed, throw an exception
if ( ! $bind_result )
{
throw new Exception ( 'An error has occured during ldap_bind execution. Please check parameter of LDAP/checkLogin, and make sure that user provided have read permission on LDAP.' );
}
}
2019-05-02 20:51:50 +08:00
if ( $ldap_filter != " " && $ldap_filter != null )
2017-08-26 21:54:24 +08:00
{
2019-05-02 20:51:50 +08:00
$search_filter = '(&(' . $ldap_search_attribute . '=' . $user . ')(' . $ldap_filter . '))' ;
2017-08-26 21:54:24 +08:00
}
else
{
2019-05-02 20:51:50 +08:00
$search_filter = $ldap_search_attribute . '=' . $user ;
2017-08-26 21:54:24 +08:00
}
2019-05-02 20:51:50 +08:00
$result = ldap_search ( $this -> ldap_server , $ldap_base_dn , $search_filter , array (), 0 , 1 , 500 );
2017-08-26 21:54:24 +08:00
if ( ! $result )
{
throw new Exception ( 'An error has occured during ldap_search execution. Please check parameter of LDAP/checkLogin.' );
2017-08-08 03:01:11 +08:00
}
2017-08-26 21:54:24 +08:00
$data = ldap_first_entry ( $this -> ldap_server , $result );
if ( ! $data )
{
throw new Exception ( 'An error has occured during ldap_first_entry execution. Please check parameter of LDAP/checkLogin.' );
}
$dn = ldap_get_dn ( $this -> ldap_server , $data );
if ( ! $dn )
{
throw new Exception ( 'An error has occured during ldap_get_values execution (dn). Please check parameter of LDAP/checkLogin.' );
}
return ldap_bind ( $this -> ldap_server , $dn , $password );
2017-08-08 03:01:11 +08:00
}
/**
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_base_dn
2017-08-08 03:01:11 +08:00
* The LDAP base DN .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_filter
2017-08-22 05:10:20 +08:00
* A filter to get relevant data . Often the user id in ldap ( uid or sAMAccountName ) .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_bind_dn
2017-08-22 05:10:20 +08:00
* The directory name of a service user to bind before search . Must be a user with read permission on LDAP .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_bind_pass
2017-08-26 21:54:24 +08:00
* The password associated to the service user to bind before search .
2019-05-02 20:51:50 +08:00
* @ param string @ ldap_search_attribute
2017-08-26 21:54:24 +08:00
* The attribute used on your LDAP to identify user ( uid , email , cn , sAMAccountName )
* @ param string @ user
* A ldap username or email or sAMAccountName
2017-08-08 03:01:11 +08:00
*
* @ return
2018-05-20 00:04:13 +08:00
* An array with the user ' s mail , complete name and directory name .
2017-08-08 03:01:11 +08:00
*/
2019-05-02 20:51:50 +08:00
public function getDataForMattermost ( $ldap_base_dn , $ldap_filter , $ldap_bind_dn , $ldap_bind_pass , $ldap_search_attribute , $user ) {
2017-08-08 03:01:11 +08:00
$attribute = array ( " cn " , " mail " );
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_base_dn ))
2017-08-08 03:01:11 +08:00
{
throw new InvalidArgumentException ( 'First argument to LDAP/getData must be the ldap base directory name (string). Ex: o=Company' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_filter ))
2017-08-08 03:01:11 +08:00
{
throw new InvalidArgumentException ( 'Second argument to LDAP/getData must be a filter to get relevant data. Often is the user id in ldap (string). Ex : uid=jdupont' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_bind_dn ) && $ldap_bind_dn != null )
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Third argument to LDAP/getData must be an optional service account on restrictive LDAP (string).' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_bind_pass ) && $ldap_bind_pass != null )
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Fourth argument to LDAP/getData must be an optional password for the service account on restrictive LDAP (string).' );
}
2019-05-02 20:51:50 +08:00
if ( ! is_string ( $ldap_search_attribute ))
2017-08-26 21:54:24 +08:00
{
throw new InvalidArgumentException ( 'Fifth argument to LDAP/getData must be the attribute to identify users (ex : uid, email, sAMAccountName) (string).' );
}
if ( ! is_string ( $user ))
{
throw new InvalidArgumentException ( 'Sixth argument to LDAP/getData must be the username or email of a ldap user (string). Ex: jdupont or jdupont@company.com' );
}
2017-08-08 03:01:11 +08:00
2017-08-22 05:10:20 +08:00
// If LDAP service account for search is specified, do an ldap_bind with this account
2019-05-02 20:51:50 +08:00
if ( $ldap_bind_dn != '' && $ldap_bind_dn != null )
2017-08-22 05:10:20 +08:00
{
2019-05-02 20:51:50 +08:00
$bind_result = ldap_bind ( $this -> ldap_server , $ldap_bind_dn , $ldap_bind_pass );
2017-08-22 05:10:20 +08:00
// If authentification failed, throw an exception
if ( ! $bind_result )
{
throw new Exception ( 'An error has occured during ldap_bind execution. Please check parameter of LDAP/getData, and make sure that user provided have read permission on LDAP.' );
}
}
2019-05-02 20:51:50 +08:00
if ( $ldap_filter != " " && $ldap_filter != null )
2017-08-26 21:54:24 +08:00
{
2019-05-02 20:51:50 +08:00
$search_filter = '(&(' . $ldap_search_attribute . '=' . $user . ')(' . $ldap_filter . '))' ;
2017-08-26 21:54:24 +08:00
}
else
{
2019-05-02 20:51:50 +08:00
$search_filter = $ldap_search_attribute . '=' . $user ;
2017-08-26 21:54:24 +08:00
}
2019-05-02 20:51:50 +08:00
$result = ldap_search ( $this -> ldap_server , $ldap_base_dn , $search_filter , array (), 0 , 1 , 500 );
2017-08-08 03:01:11 +08:00
if ( ! $result )
{
throw new Exception ( 'An error has occured during ldap_search execution. Please check parameter of LDAP/getData.' );
}
$data = ldap_first_entry ( $this -> ldap_server , $result );
if ( ! $data )
{
throw new Exception ( 'An error has occured during ldap_first_entry execution. Please check parameter of LDAP/getData.' );
}
$mail = ldap_get_values ( $this -> ldap_server , $data , " mail " );
if ( ! $mail )
{
throw new Exception ( 'An error has occured during ldap_get_values execution (mail). Please check parameter of LDAP/getData.' );
}
$cn = ldap_get_values ( $this -> ldap_server , $data , " cn " );
if ( ! $cn )
{
throw new Exception ( 'An error has occured during ldap_get_values execution (complete name). Please check parameter of LDAP/getData.' );
}
return array ( " mail " => $mail [ 0 ], " cn " => $cn [ 0 ]);
}
/*
* Destructor to close the LDAP connection
*/
public function __destruct ()
{
ldap_close ( $this -> ldap_server );
}
}