2006-06-24 17:13:29 +02:00
< ? php
2011-10-24 08:59:14 +02:00
/* Copyright ( C ) 2004 Rodolphe Quiedeville < rodolphe @ quiedeville . org >
* Copyright ( C ) 2004 Benoit Mortier < benoit . mortier @ opensides . be >
2021-10-28 12:13:28 +02:00
* Copyright ( C ) 2005 - 2021 Regis Houssin < regis . houssin @ inodbox . com >
* Copyright ( C ) 2006 - 2021 Laurent Destailleur < eldy @ users . sourceforge . net >
2006-06-24 17:13:29 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2006-06-24 17:13:29 +02:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2006-06-24 17:13:29 +02:00
*/
/**
2011-10-24 08:53:26 +02:00
* \file htdocs / core / class / ldap . class . php
2010-07-21 13:57:52 +02:00
* \brief File of class to manage LDAP features
2021-06-15 20:16:05 +02:00
*
* Note :
* LDAP_ESCAPE_FILTER is to escape char array ( '\\' , '*' , '(' , ')' , " \x00 " )
* LDAP_ESCAPE_DN is to escape char array ( '\\' , ',' , '=' , '+' , '<' , '>' , ';' , '"' , '#' )
2008-12-09 21:14:04 +01:00
*/
2010-07-21 13:57:52 +02:00
/**
2015-03-17 10:38:25 +01:00
* Class to manage LDAP features
2010-07-21 13:57:52 +02:00
*/
2006-11-21 18:38:28 +01:00
class Ldap
{
2018-08-22 10:37:16 +02:00
/**
* @ var string Error code ( or message )
*/
2020-04-10 10:59:32 +02:00
public $error = '' ;
2015-03-17 10:38:25 +01:00
2018-08-30 23:13:16 +02:00
/**
* @ var string [] Array of error strings
*/
public $errors = array ();
2018-09-02 23:44:53 +02:00
2008-12-09 21:14:04 +01:00
/**
2010-07-21 13:57:52 +02:00
* Tableau des serveurs ( IP addresses ou nom d ' hotes )
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public $server = array ();
2018-08-30 23:13:16 +02:00
2021-10-28 12:13:28 +02:00
/**
* Current connected server
*/
public $connectedServer ;
2008-12-09 21:14:04 +01:00
/**
* Base DN ( e . g . " dc=foo,dc=com " )
*/
2020-10-31 14:32:18 +01:00
public $dn ;
2008-12-09 21:14:04 +01:00
/**
* type de serveur , actuellement OpenLdap et Active Directory
*/
2020-10-31 14:32:18 +01:00
public $serverType ;
2008-12-09 21:14:04 +01:00
/**
* Version du protocole ldap
*/
2020-10-31 14:32:18 +01:00
public $ldapProtocolVersion ;
/**
* Server DN
*/
public $domain ;
2008-12-09 21:14:04 +01:00
/**
* User administrateur Ldap
* Active Directory ne supporte pas les connexions anonymes
*/
2020-10-31 14:32:18 +01:00
public $searchUser ;
2008-12-09 21:14:04 +01:00
/**
* Mot de passe de l ' administrateur
* Active Directory ne supporte pas les connexions anonymes
*/
2020-10-31 14:32:18 +01:00
public $searchPassword ;
2008-12-09 21:14:04 +01:00
/**
* DN des utilisateurs
*/
2020-10-31 14:32:18 +01:00
public $people ;
2008-12-09 21:14:04 +01:00
/**
* DN des groupes
*/
2020-10-31 14:32:18 +01:00
public $groups ;
2008-12-09 21:14:04 +01:00
/**
2009-12-21 09:02:25 +01:00
* Code erreur retourne par le serveur Ldap
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public $ldapErrorCode ;
2008-12-09 21:14:04 +01:00
/**
* Message texte de l ' erreur
*/
2020-10-31 14:32:18 +01:00
public $ldapErrorText ;
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
//Fetch user
2020-10-31 14:32:18 +01:00
public $name ;
public $firstname ;
public $login ;
public $phone ;
public $skype ;
public $fax ;
public $mail ;
public $mobile ;
2006-11-21 23:51:05 +01:00
2020-10-31 14:32:18 +01:00
public $uacf ;
public $pwdlastset ;
2006-11-21 23:51:05 +01:00
2020-10-31 14:32:18 +01:00
public $ldapcharset = 'UTF-8' ; // LDAP should be UTF-8 encoded
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
/**
2017-10-07 13:09:31 +02:00
* The internal LDAP connection handle
*/
2020-10-31 14:32:18 +01:00
public $connection ;
2008-12-09 21:14:04 +01:00
/**
* Result of any connections etc .
*/
2020-10-31 14:32:18 +01:00
public $result ;
2006-06-24 17:13:29 +02:00
2021-11-03 22:56:15 +01:00
/**
* No Ldap synchronization
*/
const SYNCHRO_NONE = 0 ;
/**
* Dolibarr to Ldap synchronization
*/
const SYNCHRO_DOLIBARR_TO_LDAP = 1 ;
/**
* Ldap to Dolibarr synchronization
*/
const SYNCHRO_LDAP_TO_DOLIBARR = 2 ;
2011-09-11 20:35:38 +02:00
2008-12-09 21:14:04 +01:00
/**
2011-09-11 20:35:38 +02:00
* Constructor
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function __construct ()
2008-12-09 21:14:04 +01:00
{
global $conf ;
2006-11-21 18:38:28 +01:00
2015-10-30 19:16:02 +01:00
// Server
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> LDAP_SERVER_HOST )) {
$this -> server [] = $conf -> global -> LDAP_SERVER_HOST ;
}
if ( ! empty ( $conf -> global -> LDAP_SERVER_HOST_SLAVE )) {
$this -> server [] = $conf -> global -> LDAP_SERVER_HOST_SLAVE ;
}
2021-10-28 15:40:05 +02:00
$this -> serverPort = getDolGlobalInt ( 'LDAP_SERVER_PORT' , 389 );
$this -> ldapProtocolVersion = getDolGlobalString ( 'LDAP_SERVER_PROTOCOLVERSION' );
$this -> dn = getDolGlobalString ( 'LDAP_SERVER_DN' );
$this -> serverType = getDolGlobalString ( 'LDAP_SERVER_TYPE' );
2021-06-15 20:16:05 +02:00
2021-10-28 15:40:05 +02:00
$this -> domain = getDolGlobalString ( 'LDAP_SERVER_DN' );
$this -> searchUser = getDolGlobalString ( 'LDAP_ADMIN_DN' );
$this -> searchPassword = getDolGlobalString ( 'LDAP_ADMIN_PASS' );
$this -> people = getDolGlobalString ( 'LDAP_USER_DN' );
$this -> groups = getDolGlobalString ( 'LDAP_GROUP_DN' );
2008-12-09 21:14:04 +01:00
2021-10-28 15:40:05 +02:00
$this -> filter = getDolGlobalString ( 'LDAP_FILTER_CONNECTION' ); // Filter on user
$this -> filtergroup = getDolGlobalString ( 'LDAP_GROUP_FILTER' ); // Filter on groups
$this -> filtermember = getDolGlobalString ( 'LDAP_MEMBER_FILTER' ); // Filter on member
2017-09-15 18:02:52 +02:00
2015-10-30 19:16:02 +01:00
// Users
2021-10-28 15:40:05 +02:00
$this -> attr_login = getDolGlobalString ( 'LDAP_FIELD_LOGIN' ); //unix
$this -> attr_sambalogin = getDolGlobalString ( 'LDAP_FIELD_LOGIN_SAMBA' ); //samba, activedirectory
$this -> attr_name = getDolGlobalString ( 'LDAP_FIELD_NAME' );
$this -> attr_firstname = getDolGlobalString ( 'LDAP_FIELD_FIRSTNAME' );
$this -> attr_mail = getDolGlobalString ( 'LDAP_FIELD_MAIL' );
$this -> attr_phone = getDolGlobalString ( 'LDAP_FIELD_PHONE' );
$this -> attr_skype = getDolGlobalString ( 'LDAP_FIELD_SKYPE' );
$this -> attr_fax = getDolGlobalString ( 'LDAP_FIELD_FAX' );
$this -> attr_mobile = getDolGlobalString ( 'LDAP_FIELD_MOBILE' );
2008-12-09 21:14:04 +01:00
}
2006-11-21 18:38:28 +01:00
2012-01-27 16:10:44 +01:00
// Connection handling methods -------------------------------------------
2008-12-09 21:14:04 +01:00
2020-10-31 14:32:18 +01:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Connect and bind
* Use this -> server , this -> serverPort , this -> ldapProtocolVersion , this -> serverType , this -> searchUser , this -> searchPassword
* After return , this -> connection and $this -> bind are defined
*
2012-03-12 15:09:46 +01:00
* @ return int < 0 if KO , 1 if bind anonymous , 2 if bind auth
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function connect_bind ()
2006-11-21 23:51:05 +01:00
{
2020-10-31 14:32:18 +01:00
// phpcs:enable
2020-06-22 09:26:42 +02:00
global $conf ;
2006-11-21 23:51:05 +01:00
2020-04-10 10:59:32 +02:00
$connected = 0 ;
$this -> bind = 0 ;
2021-11-07 17:43:17 +01:00
$this -> error = 0 ;
$this -> connectedServer = '' ;
2006-11-21 23:51:05 +01:00
2014-04-27 14:16:29 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( count ( $this -> server ) == 0 || empty ( $this -> server [ 0 ])) {
2020-04-10 10:59:32 +02:00
$this -> error = 'LDAP setup (file conf.php) is not complete' ;
2014-04-27 14:16:29 +02:00
dol_syslog ( get_class ( $this ) . " ::connect_bind " . $this -> error , LOG_WARNING );
2015-09-12 18:21:37 +02:00
return - 1 ;
2014-04-27 14:16:29 +02:00
}
2021-02-23 22:03:23 +01:00
if ( ! function_exists ( " ldap_connect " )) {
2020-04-10 10:59:32 +02:00
$this -> error = 'LDAPFunctionsNotAvailableOnPHP' ;
2015-09-12 18:21:37 +02:00
dol_syslog ( get_class ( $this ) . " ::connect_bind " . $this -> error , LOG_WARNING );
2020-04-10 10:59:32 +02:00
$return = - 1 ;
2015-09-12 18:21:37 +02:00
}
2006-11-21 23:51:05 +01:00
2021-02-23 22:03:23 +01:00
if ( empty ( $this -> error )) {
2016-06-04 14:50:32 +02:00
// Loop on each ldap server
2021-02-23 22:03:23 +01:00
foreach ( $this -> server as $host ) {
if ( $connected ) {
break ;
}
if ( empty ( $host )) {
continue ;
}
2017-09-15 18:02:52 +02:00
2018-03-19 17:59:23 +01:00
if ( $this -> serverPing ( $host , $this -> serverPort ) === true ) {
$this -> connection = ldap_connect ( $host , $this -> serverPort );
2021-02-23 22:03:23 +01:00
} else {
2021-09-11 02:48:28 +02:00
if ( preg_match ( '/^ldaps/i' , $host )) {
// With host = ldaps://server, the serverPing to ssl://server sometimes fails, even if the ldap_connect succeed, so
// we test this case and continue in suche a case even if serverPing fails.
$this -> connection = ldap_connect ( $host , $this -> serverPort );
} else {
continue ;
}
2021-02-23 22:03:23 +01:00
}
2017-09-15 18:02:52 +02:00
2021-02-23 22:03:23 +01:00
if ( is_resource ( $this -> connection )) {
2021-09-11 02:48:28 +02:00
// Upgrade connexion to TLS, if requested by the configuration
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> LDAP_SERVER_USE_TLS )) {
2021-09-11 02:48:28 +02:00
// For test/debug
2021-11-12 13:12:49 +01:00
//ldap_set_option($this->connection, LDAP_OPT_DEBUG_LEVEL, 7);
//ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3);
//ldap_set_option($this->connection, LDAP_OPT_REFERRALS, 0);
2021-09-11 02:48:28 +02:00
$resulttls = ldap_start_tls ( $this -> connection );
if ( ! $resulttls ) {
2017-09-16 17:12:51 +02:00
dol_syslog ( get_class ( $this ) . " ::connect_bind failed to start tls " , LOG_WARNING );
2021-09-11 02:48:28 +02:00
$this -> error = 'ldap_start_tls Failed to start TLS ' . ldap_errno ( $this -> connection ) . ' ' . ldap_error ( $this -> connection );
2017-09-16 17:12:51 +02:00
$connected = 0 ;
2021-11-03 22:56:15 +01:00
$this -> unbind ();
2017-09-16 17:12:51 +02:00
}
}
2017-09-15 18:02:52 +02:00
2016-06-04 14:50:32 +02:00
// Execute the ldap_set_option here (after connect and before bind)
$this -> setVersion ();
ldap_set_option ( $this -> connection , LDAP_OPT_SIZELIMIT , 0 ); // no limit here. should return true.
2017-09-15 18:02:52 +02:00
2021-02-23 22:03:23 +01:00
if ( $this -> serverType == " activedirectory " ) {
2020-04-10 10:59:32 +02:00
$result = $this -> setReferrals ();
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::connect_bind try bindauth for activedirectory on " . $host . " user= " . $this -> searchUser . " password= " . preg_replace ( '/./' , '*' , $this -> searchPassword ), LOG_DEBUG );
2020-04-10 10:59:32 +02:00
$this -> result = $this -> bindauth ( $this -> searchUser , $this -> searchPassword );
2021-02-23 22:03:23 +01:00
if ( $this -> result ) {
2020-04-10 10:59:32 +02:00
$this -> bind = $this -> result ;
$connected = 2 ;
2006-11-21 23:51:05 +01:00
break ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = ldap_errno ( $this -> connection ) . ' ' . ldap_error ( $this -> connection );
2006-11-21 23:51:05 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2016-06-04 14:50:32 +02:00
// Try in auth mode
2021-02-23 22:03:23 +01:00
if ( $this -> searchUser && $this -> searchPassword ) {
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::connect_bind try bindauth on " . $host . " user= " . $this -> searchUser . " password= " . preg_replace ( '/./' , '*' , $this -> searchPassword ), LOG_DEBUG );
2020-04-10 10:59:32 +02:00
$this -> result = $this -> bindauth ( $this -> searchUser , $this -> searchPassword );
2021-02-23 22:03:23 +01:00
if ( $this -> result ) {
2020-04-10 10:59:32 +02:00
$this -> bind = $this -> result ;
$connected = 2 ;
2016-06-04 14:50:32 +02:00
break ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = ldap_errno ( $this -> connection ) . ' ' . ldap_error ( $this -> connection );
2016-06-04 14:50:32 +02:00
}
2006-11-21 23:51:05 +01:00
}
2016-06-04 14:50:32 +02:00
// Try in anonymous
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2021-11-06 19:27:50 +01:00
dol_syslog ( get_class ( $this ) . " ::connect_bind try bind anonymously on " . $host , LOG_DEBUG );
2020-04-10 10:59:32 +02:00
$result = $this -> bind ();
2021-02-23 22:03:23 +01:00
if ( $result ) {
2020-04-10 10:59:32 +02:00
$this -> bind = $this -> result ;
$connected = 1 ;
2016-06-04 14:50:32 +02:00
break ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = ldap_errno ( $this -> connection ) . ' ' . ldap_error ( $this -> connection );
2016-06-04 14:50:32 +02:00
}
2006-11-21 23:51:05 +01:00
}
}
}
2017-09-15 18:02:52 +02:00
2021-02-23 22:03:23 +01:00
if ( ! $connected ) {
2021-11-03 22:56:15 +01:00
$this -> unbind ();
2021-11-07 17:43:17 +01:00
} else {
$this -> connectedServer = $host ;
2021-02-23 22:03:23 +01:00
}
2006-11-21 18:38:28 +01:00
}
2006-11-21 23:51:05 +01:00
}
2006-11-21 18:38:28 +01:00
2021-02-23 22:03:23 +01:00
if ( $connected ) {
2020-04-10 10:59:32 +02:00
$return = $connected ;
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::connect_bind return= " . $return , LOG_DEBUG );
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = 'Failed to connect to LDAP' . ( $this -> error ? ': ' . $this -> error : '' );
$return = - 1 ;
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::connect_bind return= " . $return . ' - ' . $this -> error , LOG_WARNING );
2008-01-11 11:25:26 +01:00
}
2021-11-07 17:43:17 +01:00
2006-11-21 23:51:05 +01:00
return $return ;
}
2006-11-21 18:38:28 +01:00
2008-12-09 21:14:04 +01:00
/**
2021-11-01 02:44:14 +01:00
* Simply closes the connection set up earlier . Returns true if OK , false if there was an error .
* This method seems a duplicate / alias of unbind () .
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ return boolean true or false
2021-10-28 15:40:05 +02:00
* @ deprecated ldap_close is an alias of ldap_unbind
2021-11-01 02:44:14 +01:00
* @ see unbind ()
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function close ()
2008-12-09 21:14:04 +01:00
{
2022-01-02 22:37:07 +01:00
$r_type = get_resource_type ( $this -> connection );
2022-01-06 16:02:47 +01:00
if ( $this -> connection && ( $r_type === " Unknown " || !@ ldap_close ( $this -> connection ))) {
2008-12-09 21:14:04 +01:00
return false ;
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
return true ;
}
}
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Anonymously binds to the connection . After this is done ,
2008-12-09 21:14:04 +01:00
* queries and searches can be done - but read - only .
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ return boolean true or false
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function bind ()
2008-12-09 21:14:04 +01:00
{
2021-02-23 22:03:23 +01:00
if ( ! $this -> result = @ ldap_bind ( $this -> connection )) {
2008-12-09 21:14:04 +01:00
$this -> ldapErrorCode = ldap_errno ( $this -> connection );
$this -> ldapErrorText = ldap_error ( $this -> connection );
2020-04-10 10:59:32 +02:00
$this -> error = $this -> ldapErrorCode . " " . $this -> ldapErrorText ;
2008-12-09 21:14:04 +01:00
return false ;
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
return true ;
}
}
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Binds as an authenticated user , which usually allows for write
2008-12-09 21:14:04 +01:00
* access . The FULL dn must be passed . For a directory manager , this is
* " cn=Directory Manager " under iPlanet . For a user , it will be something
* like " uid=jbloggs,ou=People,dc=foo,dc=com " .
2012-01-27 16:10:44 +01:00
*
* @ param string $bindDn DN
2012-03-19 17:18:11 +01:00
* @ param string $pass Password
2012-01-27 16:10:44 +01:00
* @ return boolean true or false
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function bindauth ( $bindDn , $pass )
2008-12-09 21:14:04 +01:00
{
2021-02-23 22:03:23 +01:00
if ( ! $this -> result = @ ldap_bind ( $this -> connection , $bindDn , $pass )) {
2008-12-09 21:14:04 +01:00
$this -> ldapErrorCode = ldap_errno ( $this -> connection );
$this -> ldapErrorText = ldap_error ( $this -> connection );
2020-04-10 10:59:32 +02:00
$this -> error = $this -> ldapErrorCode . " " . $this -> ldapErrorText ;
2008-12-09 21:14:04 +01:00
return false ;
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
return true ;
}
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
/**
2021-11-01 02:44:14 +01:00
* Unbind of LDAP server ( close connection ) .
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ return boolean true or false
2021-11-01 02:44:14 +01:00
* @ see close ()
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function unbind ()
2006-11-21 23:51:05 +01:00
{
2021-11-01 02:44:14 +01:00
$this -> result = true ;
if ( $this -> connection ) {
$this -> result = @ ldap_unbind ( $this -> connection );
}
if ( $this -> result ) {
2006-11-21 23:51:05 +01:00
return true ;
2021-11-01 02:44:14 +01:00
} else {
return false ;
2006-11-21 23:51:05 +01:00
}
}
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Verification de la version du serveur ldap .
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ return string version
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getVersion ()
2008-12-09 21:14:04 +01:00
{
$version = 0 ;
$version = @ ldap_get_option ( $this -> connection , LDAP_OPT_PROTOCOL_VERSION , $version );
return $version ;
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Change ldap protocol version to use .
2012-03-19 17:18:11 +01:00
*
2019-02-27 23:55:18 +01:00
* @ return boolean version
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function setVersion ()
{
2006-11-21 23:51:05 +01:00
// LDAP_OPT_PROTOCOL_VERSION est une constante qui vaut 17
2008-12-09 21:14:04 +01:00
$ldapsetversion = ldap_set_option ( $this -> connection , LDAP_OPT_PROTOCOL_VERSION , $this -> ldapProtocolVersion );
return $ldapsetversion ;
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* changement du referrals .
2012-03-19 17:18:11 +01:00
*
2019-02-27 23:55:18 +01:00
* @ return boolean referrals
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function setReferrals ()
{
2006-11-21 23:51:05 +01:00
// LDAP_OPT_REFERRALS est une constante qui vaut ?
2008-12-09 21:14:04 +01:00
$ldapreferrals = ldap_set_option ( $this -> connection , LDAP_OPT_REFERRALS , 0 );
return $ldapreferrals ;
}
2006-06-24 17:13:29 +02:00
2006-11-21 18:38:28 +01:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Add a LDAP entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2017-10-04 11:22:41 +02:00
* @ param string $dn DN entry key
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ param User $user Objet user that create
2017-10-04 11:22:41 +02:00
* @ return int < 0 if KO , > 0 if OK
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function add ( $dn , $info , $user )
2006-11-18 22:59:10 +01:00
{
2021-10-28 15:40:05 +02:00
dol_syslog ( get_class ( $this ) . " ::add dn= " . $dn . " info= " . json_encode ( $info ));
2006-11-26 01:24:10 +01:00
2009-08-11 22:16:58 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 3 ;
}
2008-12-09 21:14:04 +01:00
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $val ) {
if ( ! is_array ( $val )) {
$info [ $key ] = $this -> convFromOutputCharset ( $val , $this -> ldapcharset );
}
2006-11-19 05:56:10 +01:00
}
2006-11-21 23:51:05 +01:00
2019-01-27 11:55:16 +01:00
$this -> dump ( $dn , $info );
2008-12-09 21:14:04 +01:00
2006-11-18 22:59:10 +01:00
//print_r($info);
2020-04-10 10:59:32 +02:00
$result = @ ldap_add ( $this -> connection , $dn , $info );
2006-11-18 22:59:10 +01:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2012-05-12 12:32:24 +02:00
dol_syslog ( get_class ( $this ) . " ::add successfull " , LOG_DEBUG );
2006-11-26 08:00:14 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2015-03-17 10:38:25 +01:00
$this -> ldapErrorCode = @ ldap_errno ( $this -> connection );
$this -> ldapErrorText = @ ldap_error ( $this -> connection );
2020-04-10 10:59:32 +02:00
$this -> error = $this -> ldapErrorCode . " " . $this -> ldapErrorText ;
2015-03-17 10:38:25 +01:00
dol_syslog ( get_class ( $this ) . " ::add failed: " . $this -> error , LOG_ERR );
2006-11-26 08:00:14 +01:00
return - 1 ;
}
2006-11-18 22:59:10 +01:00
}
2009-08-11 22:16:58 +02:00
/**
2012-01-27 16:10:44 +01:00
* Modify a LDAP entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2020-06-30 13:20:46 +02:00
* @ param User $user Objet user that modify
2012-01-27 16:10:44 +01:00
* @ return int < 0 if KO , > 0 if OK
2009-08-11 22:16:58 +02:00
*/
2020-10-31 14:32:18 +01:00
public function modify ( $dn , $info , $user )
2009-08-11 22:16:58 +02:00
{
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::modify dn= " . $dn . " info= " . join ( ',' , $info ));
2009-08-11 22:16:58 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 3 ;
}
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $val ) {
if ( ! is_array ( $val )) {
$info [ $key ] = $this -> convFromOutputCharset ( $val , $this -> ldapcharset );
}
2009-08-11 22:16:58 +02:00
}
2019-01-27 11:55:16 +01:00
$this -> dump ( $dn , $info );
2009-08-11 22:16:58 +02:00
//print_r($info);
2020-06-28 21:19:11 +02:00
2020-10-31 14:32:18 +01:00
// For better compatibility with Samba4 AD
2020-06-21 19:52:15 +02:00
if ( $this -> serverType == " activedirectory " ) {
2020-09-29 13:28:22 +02:00
unset ( $info [ 'cn' ]); // To avoid error : Operation not allowed on RDN (Code 67)
2021-09-16 09:31:23 +02:00
2021-09-16 09:31:00 +02:00
// To avoid error : LDAP Error: 53 (Unwilling to perform)
2021-09-16 09:31:23 +02:00
if ( isset ( $info [ 'unicodePwd' ])) {
$info [ 'unicodePwd' ] = mb_convert_encoding ( " \" " . $info [ 'unicodePwd' ] . " \" " , " UTF-16LE " , " UTF-8 " );
2021-09-16 09:31:00 +02:00
}
2020-06-21 19:52:15 +02:00
}
2020-04-10 10:59:32 +02:00
$result = @ ldap_modify ( $this -> connection , $dn , $info );
2009-08-11 22:16:58 +02:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::modify successfull " , LOG_DEBUG );
2009-08-11 22:16:58 +02:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = @ ldap_error ( $this -> connection );
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::modify failed: " . $this -> error , LOG_ERR );
2009-08-11 22:16:58 +02:00
return - 1 ;
}
}
2017-10-04 11:22:41 +02:00
/**
* Rename a LDAP entry
* Ldap object connect and bind must have been done
*
* @ param string $dn Old DN entry key ( uid = qqq , ou = xxx , dc = aaa , dc = bbb ) ( before update )
* @ param string $newrdn New RDN entry key ( uid = qqq )
* @ param string $newparent New parent ( ou = xxx , dc = aaa , dc = bbb )
* @ param User $user Objet user that modify
2018-04-16 13:51:16 +02:00
* @ param bool $deleteoldrdn If true the old RDN value ( s ) is removed , else the old RDN value ( s ) is retained as non - distinguished values of the entry .
2017-10-04 11:22:41 +02:00
* @ return int < 0 if KO , > 0 if OK
*/
2020-10-31 14:32:18 +01:00
public function rename ( $dn , $newrdn , $newparent , $user , $deleteoldrdn = true )
2017-10-04 11:22:41 +02:00
{
2020-04-10 10:59:32 +02:00
dol_syslog ( get_class ( $this ) . " ::modify dn= " . $dn . " newrdn= " . $newrdn . " newparent= " . $newparent . " deleteoldrdn= " . ( $deleteoldrdn ? 1 : 0 ));
2017-10-04 11:22:41 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2017-10-04 11:22:41 +02:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2017-10-04 11:22:41 +02:00
return - 3 ;
}
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
$newrdn = $this -> convFromOutputCharset ( $newrdn , $this -> ldapcharset );
$newparent = $this -> convFromOutputCharset ( $newparent , $this -> ldapcharset );
2017-10-04 11:22:41 +02:00
//print_r($info);
2020-04-10 10:59:32 +02:00
$result = @ ldap_rename ( $this -> connection , $dn , $newrdn , $newparent , $deleteoldrdn );
2017-10-04 11:22:41 +02:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2017-10-04 11:22:41 +02:00
dol_syslog ( get_class ( $this ) . " ::rename successfull " , LOG_DEBUG );
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = @ ldap_error ( $this -> connection );
2017-10-04 11:22:41 +02:00
dol_syslog ( get_class ( $this ) . " ::rename failed: " . $this -> error , LOG_ERR );
return - 1 ;
}
}
2009-08-11 22:16:58 +02:00
/**
2012-01-27 16:10:44 +01:00
* Modify a LDAP entry ( to use if dn != olddn )
2019-02-27 23:55:18 +01:00
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2017-10-04 11:22:41 +02:00
* @ param string $dn DN entry key
* @ param array $info Attributes array
* @ param User $user Objet user that update
* @ param string $olddn Old DN entry key ( before update )
* @ param string $newrdn New RDN entry key ( uid = qqq ) ( for ldap_rename )
* @ param string $newparent New parent ( ou = xxx , dc = aaa , dc = bbb ) ( for ldap_rename )
* @ return int < 0 if KO , > 0 if OK
2009-08-11 22:16:58 +02:00
*/
2020-10-31 14:32:18 +01:00
public function update ( $dn , $info , $user , $olddn , $newrdn = false , $newparent = false )
2009-08-11 22:16:58 +02:00
{
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::update dn= " . $dn . " olddn= " . $olddn );
2009-08-11 22:16:58 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 3 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $olddn || $olddn != $dn ) {
if ( ! empty ( $olddn ) && ! empty ( $newrdn ) && ! empty ( $newparent ) && $this -> ldapProtocolVersion === '3' ) {
2017-10-04 11:22:41 +02:00
// This function currently only works with LDAPv3
2017-10-04 12:07:17 +02:00
$result = $this -> rename ( $olddn , $newrdn , $newparent , $user , true );
2020-10-31 14:32:18 +01:00
$result = $this -> modify ( $dn , $info , $user ); // We force "modify" for avoid some fields not modify
} else {
2017-10-04 11:22:41 +02:00
// If change we make is rename the key of LDAP record, we create new one and if ok, we delete old one.
$result = $this -> add ( $dn , $info , $user );
2021-02-23 22:03:23 +01:00
if ( $result > 0 && $olddn && $olddn != $dn ) {
$result = $this -> delete ( $olddn ); // If add fails, we do not try to delete old one
}
2017-10-04 11:22:41 +02:00
}
2020-05-21 15:05:19 +02:00
} else {
2009-08-12 01:42:21 +02:00
//$result = $this->delete($olddn);
2020-04-10 10:59:32 +02:00
$result = $this -> add ( $dn , $info , $user ); // If record has been deleted from LDAP, we recreate it. We ignore error if it already exists.
$result = $this -> modify ( $dn , $info , $user ); // We use add/modify instead of delete/add when olddn is received
2009-08-11 22:16:58 +02:00
}
2021-02-23 22:03:23 +01:00
if ( $result <= 0 ) {
2019-09-14 16:39:08 +02:00
$this -> error = ldap_error ( $this -> connection ) . ' (Code ' . ldap_errno ( $this -> connection ) . " ) " . $this -> error ;
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::update " . $this -> error , LOG_ERR );
2009-08-11 22:16:58 +02:00
//print_r($info);
return - 1 ;
2020-05-21 15:05:19 +02:00
} else {
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::update done successfully " );
2009-08-11 22:16:58 +02:00
return 1 ;
}
}
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Delete a LDAP entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param string $dn DN entry key
* @ return int < 0 if KO , > 0 if OK
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function delete ( $dn )
2006-11-18 22:59:10 +01:00
{
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::delete Delete LDAP entry dn= " . $dn );
2006-11-18 22:59:10 +01:00
2009-08-11 22:16:58 +02:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-08-11 22:16:58 +02:00
return - 3 ;
}
2008-12-09 21:14:04 +01:00
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2006-11-26 01:24:10 +01:00
2020-04-10 10:59:32 +02:00
$result = @ ldap_delete ( $this -> connection , $dn );
2006-11-18 22:59:10 +01:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
return 1 ;
}
2006-11-18 22:59:10 +01:00
return - 1 ;
}
2009-12-21 10:05:49 +01:00
2020-10-31 14:32:18 +01:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-12-21 10:05:49 +01:00
/**
2012-01-27 16:10:44 +01:00
* Build a LDAP message
2012-03-19 17:18:11 +01:00
*
2014-04-23 14:57:47 +02:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ return string Content of file
2009-12-21 10:05:49 +01:00
*/
2020-10-31 14:32:18 +01:00
public function dump_content ( $dn , $info )
2009-12-21 10:05:49 +01:00
{
2020-10-31 14:32:18 +01:00
// phpcs:enable
2020-04-10 10:59:32 +02:00
$content = '' ;
2009-12-21 10:05:49 +01:00
// Create file content
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^ldap/' , $this -> server [ 0 ])) {
2020-04-10 10:59:32 +02:00
$target = " -H " . join ( ',' , $this -> server );
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$target = " -h " . join ( ',' , $this -> server ) . " -p " . $this -> serverPort ;
2009-12-21 10:05:49 +01:00
}
2020-04-10 10:59:32 +02:00
$content .= " # ldapadd $target -c -v -D " . $this -> searchUser . " -W -f ldapinput.in \n " ;
$content .= " # ldapmodify $target -c -v -D " . $this -> searchUser . " -W -f ldapinput.in \n " ;
$content .= " # ldapdelete $target -c -v -D " . $this -> searchUser . " -W -f ldapinput.in \n " ;
2021-02-23 22:03:23 +01:00
if ( in_array ( 'localhost' , $this -> server )) {
$content .= " # If commands fails to connect, try without -h and -p \n " ;
}
2020-04-10 10:59:32 +02:00
$content .= " dn: " . $dn . " \n " ;
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $value ) {
if ( ! is_array ( $value )) {
2020-04-10 10:59:32 +02:00
$content .= " $key : $value\n " ;
2020-05-21 15:05:19 +02:00
} else {
2021-02-23 22:03:23 +01:00
foreach ( $value as $valuevalue ) {
2020-04-10 10:59:32 +02:00
$content .= " $key : $valuevalue\n " ;
2009-12-21 10:05:49 +01:00
}
}
}
return $content ;
}
/**
2012-01-27 16:10:44 +01:00
* Dump a LDAP message to ldapinput . in file
2012-03-19 17:18:11 +01:00
*
2014-04-23 14:57:47 +02:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ return int < 0 if KO , > 0 if OK
2009-12-21 10:05:49 +01:00
*/
2020-10-31 14:32:18 +01:00
public function dump ( $dn , $info )
2009-12-21 10:05:49 +01:00
{
global $conf ;
// Create content
2020-04-10 10:59:32 +02:00
$content = $this -> dump_content ( $dn , $info );
2009-12-21 10:05:49 +01:00
//Create file
2020-04-10 10:59:32 +02:00
$result = dol_mkdir ( $conf -> ldap -> dir_temp );
2009-12-21 10:05:49 +01:00
2020-04-10 10:59:32 +02:00
$outputfile = $conf -> ldap -> dir_temp . '/ldapinput.in' ;
$fp = fopen ( $outputfile , " w " );
2021-02-23 22:03:23 +01:00
if ( $fp ) {
2009-12-21 10:05:49 +01:00
fputs ( $fp , $content );
fclose ( $fp );
2021-02-23 22:03:23 +01:00
if ( ! empty ( $conf -> global -> MAIN_UMASK )) {
@ chmod ( $outputfile , octdec ( $conf -> global -> MAIN_UMASK ));
}
2009-12-21 10:05:49 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2009-12-21 10:05:49 +01:00
return - 1 ;
}
}
2017-09-15 18:02:52 +02:00
/**
* Ping a server before ldap_connect for avoid waiting
*
2021-09-11 02:48:28 +02:00
* @ param string $host Server host or address
2017-09-15 18:02:52 +02:00
* @ param int $port Server port ( default 389 )
2021-09-11 02:48:28 +02:00
* @ param int $timeout Timeout in second ( default 1 s )
2017-09-15 18:02:52 +02:00
* @ return boolean true or false
*/
2020-10-31 14:32:18 +01:00
public function serverPing ( $host , $port = 389 , $timeout = 1 )
2017-09-15 18:02:52 +02:00
{
2021-09-11 02:48:28 +02:00
$regs = array ();
2019-01-27 11:55:16 +01:00
if ( preg_match ( '/^ldaps:\/\/([^\/]+)\/?$/' , $host , $regs )) {
2021-09-11 02:48:28 +02:00
// Replace ldaps:// by ssl://
2018-03-19 12:11:59 +01:00
$host = 'ssl://' . $regs [ 1 ];
2021-09-11 02:48:28 +02:00
} elseif ( preg_match ( '/^ldap:\/\/([^\/]+)\/?$/' , $host , $regs )) {
// Remove ldap://
2018-03-19 17:59:23 +01:00
$host = $regs [ 1 ];
}
2021-09-11 02:48:28 +02:00
//var_dump($newhostforstream); var_dump($host); var_dump($port);
//$host = 'ssl://ldap.test.local:636';
//$port = 636;
$errno = $errstr = 0 ;
/*
if ( $methodtochecktcpconnect == 'socket' ) {
Try to use socket_create () method .
Method that use stream_context_create () works only on registered listed in stream stream_get_wrappers () : http , https , ftp , ...
}
*/
// Use the method fsockopen to test tcp connect. No way to ignore ssl certificate errors with this method !
2017-09-15 18:02:52 +02:00
$op = @ fsockopen ( $host , $port , $errno , $errstr , $timeout );
2021-09-11 02:48:28 +02:00
//var_dump($op);
2021-02-23 22:03:23 +01:00
if ( ! $op ) {
return false ; //DC is N/A
} else {
2017-09-15 18:31:22 +02:00
fclose ( $op ); //explicitly close open socket connection
2017-09-15 18:02:52 +02:00
return true ; //DC is up & running, we can safely connect with ldap_connect
}
}
2009-12-21 10:05:49 +01:00
2012-01-27 16:10:44 +01:00
// Attribute methods -----------------------------------------------------
2010-01-17 14:51:08 +01:00
2017-10-07 13:09:31 +02:00
/**
2012-01-27 16:10:44 +01:00
* Add a LDAP attribute in entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2014-04-23 14:57:47 +02:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ param User $user Objet user that create
* @ return int < 0 if KO , > 0 if OK
2009-12-21 09:02:25 +01:00
*/
2020-10-31 14:32:18 +01:00
public function addAttribute ( $dn , $info , $user )
2009-12-21 09:02:25 +01:00
{
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::addAttribute dn= " . $dn . " info= " . join ( ',' , $info ));
2009-12-21 09:02:25 +01:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 3 ;
}
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $val ) {
if ( ! is_array ( $val )) {
$info [ $key ] = $this -> convFromOutputCharset ( $val , $this -> ldapcharset );
}
2009-12-21 09:02:25 +01:00
}
2019-01-27 11:55:16 +01:00
$this -> dump ( $dn , $info );
2009-12-21 09:02:25 +01:00
//print_r($info);
2020-04-10 10:59:32 +02:00
$result = @ ldap_mod_add ( $this -> connection , $dn , $info );
2009-12-21 09:02:25 +01:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::add_attribute successfull " , LOG_DEBUG );
2009-12-21 09:02:25 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = @ ldap_error ( $this -> connection );
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::add_attribute failed: " . $this -> error , LOG_ERR );
2009-12-21 09:02:25 +01:00
return - 1 ;
}
}
2010-01-17 14:51:08 +01:00
2017-10-07 13:09:31 +02:00
/**
2012-01-27 16:10:44 +01:00
* Update a LDAP attribute in entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2014-04-23 14:57:47 +02:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ param User $user Objet user that create
* @ return int < 0 if KO , > 0 if OK
2009-12-21 09:02:25 +01:00
*/
2020-10-31 14:32:18 +01:00
public function updateAttribute ( $dn , $info , $user )
2009-12-21 09:02:25 +01:00
{
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::updateAttribute dn= " . $dn . " info= " . join ( ',' , $info ));
2009-12-21 09:02:25 +01:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 3 ;
}
2006-11-18 22:59:10 +01:00
2009-12-21 09:02:25 +01:00
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $val ) {
if ( ! is_array ( $val )) {
$info [ $key ] = $this -> convFromOutputCharset ( $val , $this -> ldapcharset );
}
2009-12-21 09:02:25 +01:00
}
2019-01-27 11:55:16 +01:00
$this -> dump ( $dn , $info );
2009-12-21 09:02:25 +01:00
//print_r($info);
2020-04-10 10:59:32 +02:00
$result = @ ldap_mod_replace ( $this -> connection , $dn , $info );
2009-12-21 09:02:25 +01:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::updateAttribute successfull " , LOG_DEBUG );
2009-12-21 09:02:25 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = @ ldap_error ( $this -> connection );
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::updateAttribute failed: " . $this -> error , LOG_ERR );
2009-12-21 09:02:25 +01:00
return - 1 ;
}
}
2010-01-17 14:51:08 +01:00
2017-10-07 13:09:31 +02:00
/**
2012-01-27 16:10:44 +01:00
* Delete a LDAP attribute in entry
* Ldap object connect and bind must have been done
2012-03-19 17:18:11 +01:00
*
2014-04-23 14:57:47 +02:00
* @ param string $dn DN entry key
2014-09-27 16:00:11 +02:00
* @ param array $info Attributes array
2014-04-23 14:57:47 +02:00
* @ param User $user Objet user that create
* @ return int < 0 if KO , > 0 if OK
2009-12-21 09:02:25 +01:00
*/
2020-10-31 14:32:18 +01:00
public function deleteAttribute ( $dn , $info , $user )
2009-12-21 09:02:25 +01:00
{
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::deleteAttribute dn= " . $dn . " info= " . join ( ',' , $info ));
2009-12-21 09:02:25 +01:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 2 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 09:02:25 +01:00
return - 3 ;
}
// Encode to LDAP page code
2020-04-10 10:59:32 +02:00
$dn = $this -> convFromOutputCharset ( $dn , $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
foreach ( $info as $key => $val ) {
if ( ! is_array ( $val )) {
$info [ $key ] = $this -> convFromOutputCharset ( $val , $this -> ldapcharset );
}
2009-12-21 09:02:25 +01:00
}
2019-01-27 11:55:16 +01:00
$this -> dump ( $dn , $info );
2009-12-21 09:02:25 +01:00
//print_r($info);
2020-04-10 10:59:32 +02:00
$result = @ ldap_mod_del ( $this -> connection , $dn , $info );
2009-12-21 09:02:25 +01:00
2021-02-23 22:03:23 +01:00
if ( $result ) {
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::deleteAttribute successfull " , LOG_DEBUG );
2009-12-21 09:02:25 +01:00
return 1 ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
$this -> error = @ ldap_error ( $this -> connection );
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::deleteAttribute failed: " . $this -> error , LOG_ERR );
2009-12-21 09:02:25 +01:00
return - 1 ;
}
}
2010-01-17 14:51:08 +01:00
2017-10-07 13:09:31 +02:00
/**
2009-12-21 10:05:49 +01:00
* Returns an array containing attributes and values for first record
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param string $dn DN entry key
* @ param string $filter Filter
2016-05-29 11:20:12 +02:00
* @ return int | array < 0 or false if KO , array if OK
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getAttribute ( $dn , $filter )
2010-01-17 14:51:08 +01:00
{
2009-12-21 10:05:49 +01:00
// Check parameters
2021-02-23 22:03:23 +01:00
if ( ! $this -> connection ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 10:05:49 +01:00
return - 2 ;
2007-05-01 18:26:12 +02:00
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> bind ) {
2020-04-10 10:59:32 +02:00
$this -> error = " NotConnected " ;
2009-12-21 10:05:49 +01:00
return - 3 ;
2007-05-01 18:26:12 +02:00
}
2010-01-17 14:51:08 +01:00
2021-11-01 11:13:44 +01:00
$search = @ ldap_search ( $this -> connection , $dn , $filter );
2008-12-09 21:14:04 +01:00
2009-12-21 10:05:49 +01:00
// Only one entry should ever be returned
2021-11-01 11:13:44 +01:00
$entry = @ ldap_first_entry ( $this -> connection , $search );
2008-12-09 21:14:04 +01:00
2021-02-23 22:03:23 +01:00
if ( ! $entry ) {
2009-12-21 10:05:49 +01:00
$this -> ldapErrorCode = - 1 ;
$this -> ldapErrorText = " Couldn't find entry " ;
2020-04-10 10:59:32 +02:00
return 0 ; // Couldn't find entry...
2007-05-01 18:26:12 +02:00
}
2009-12-21 10:05:49 +01:00
// Get values
2021-02-23 22:03:23 +01:00
if ( ! ( $values = ldap_get_attributes ( $this -> connection , $entry ))) {
2011-09-20 11:40:27 +02:00
$this -> ldapErrorCode = ldap_errno ( $this -> connection );
$this -> ldapErrorText = ldap_error ( $this -> connection );
2016-05-29 11:20:12 +02:00
return 0 ; // No matching attributes
2006-11-26 03:59:09 +01:00
}
2009-12-21 10:05:49 +01:00
// Return an array containing the attributes.
return $values ;
}
2006-11-19 05:56:10 +01:00
2008-12-09 21:14:04 +01:00
/**
2009-12-21 10:05:49 +01:00
* Returns an array containing values for an attribute and for first record matching filterrecord
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param string $filterrecord Record
* @ param string $attribute Attributes
* @ return void
2009-12-21 10:05:49 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getAttributeValues ( $filterrecord , $attribute )
2008-12-09 21:14:04 +01:00
{
2020-04-10 10:59:32 +02:00
$attributes = array ();
2008-12-09 21:14:04 +01:00
$attributes [ 0 ] = $attribute ;
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
// We need to search for this user in order to get their entry.
2019-01-27 11:55:16 +01:00
$this -> result = @ ldap_search ( $this -> connection , $this -> people , $filterrecord , $attributes );
2006-11-21 18:38:28 +01:00
// Pourquoi cette ligne ?
2008-12-09 21:14:04 +01:00
//$info = ldap_get_entries($this->connection, $this->result);
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
// Only one entry should ever be returned (no user will have the same uid)
$entry = ldap_first_entry ( $this -> connection , $this -> result );
2006-06-24 17:13:29 +02:00
2021-02-23 22:03:23 +01:00
if ( ! $entry ) {
2008-12-09 21:14:04 +01:00
$this -> ldapErrorCode = - 1 ;
$this -> ldapErrorText = " Couldn't find user " ;
2020-04-10 10:59:32 +02:00
return false ; // Couldn't find the user...
2008-12-09 21:14:04 +01:00
}
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
// Get values
2021-02-23 22:03:23 +01:00
if ( ! $values = @ ldap_get_values ( $this -> connection , $entry , $attribute )) {
2011-09-20 11:40:27 +02:00
$this -> ldapErrorCode = ldap_errno ( $this -> connection );
$this -> ldapErrorText = ldap_error ( $this -> connection );
2008-12-09 21:14:04 +01:00
return false ; // No matching attributes
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
// Return an array containing the attributes.
return $values ;
}
2006-06-25 01:15:46 +02:00
2008-12-09 21:14:04 +01:00
/**
2015-10-30 19:16:02 +01:00
* Returns an array containing a details or list of LDAP record ( s )
2012-01-27 16:10:44 +01:00
* ldapsearch - LLLx - hlocalhost - Dcn = admin , dc = parinux , dc = org - w password - b " ou=adherents,ou=people,dc=parinux,dc=org " userPassword
2012-03-19 17:18:11 +01:00
*
2021-05-24 22:11:24 +02:00
* @ param string $search Value of field to search , '*' for all . Not used if $activefilter is set .
2012-01-27 16:10:44 +01:00
* @ param string $userDn DN ( Ex : ou = adherents , ou = people , dc = parinux , dc = org )
* @ param string $useridentifier Name of key field ( Ex : uid )
2012-10-24 17:32:10 +02:00
* @ param array $attributeArray Array of fields required . Note this array must also contains field $useridentifier ( Ex : sn , userPassword )
2021-03-05 11:21:04 +01:00
* @ param int $activefilter '1' or 'user' = use field this -> filter as filter instead of parameter $search , 'group' = use field this -> filtergroup as filter , 'member' = use field this -> filtermember as filter
2013-02-25 11:57:52 +01:00
* @ param array $attributeAsArray Array of fields wanted as an array not a string
2012-01-27 16:10:44 +01:00
* @ return array Array of [ id_record ][ ldap_field ] = value
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getRecords ( $search , $userDn , $useridentifier , $attributeArray , $activefilter = 0 , $attributeAsArray = array ())
2008-12-09 21:14:04 +01:00
{
2020-04-10 10:59:32 +02:00
$fulllist = array ();
2008-12-09 21:14:04 +01:00
2019-01-27 11:55:16 +01:00
dol_syslog ( get_class ( $this ) . " ::getRecords search= " . $search . " userDn= " . $userDn . " useridentifier= " . $useridentifier . " attributeArray=array( " . join ( ',' , $attributeArray ) . " ) activefilter= " . $activefilter );
2008-12-09 21:14:04 +01:00
// if the directory is AD, then bind first with the search user first
2021-02-23 22:03:23 +01:00
if ( $this -> serverType == " activedirectory " ) {
2008-12-09 21:14:04 +01:00
$this -> bindauth ( $this -> searchUser , $this -> searchPassword );
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::bindauth serverType=activedirectory searchUser= " . $this -> searchUser );
2008-12-09 21:14:04 +01:00
}
// Define filter
2021-06-15 20:22:36 +02:00
if ( ! empty ( $activefilter )) { // Use a predefined trusted filter (defined into setup by admin).
2020-11-19 22:07:32 +01:00
if ((( string ) $activefilter == '1' || ( string ) $activefilter == 'user' ) && $this -> filter ) {
2008-12-09 21:14:04 +01:00
$filter = '(' . $this -> filter . ')' ;
2021-03-05 11:14:21 +01:00
} elseif ((( string ) $activefilter == 'group' ) && $this -> filtergroup ) {
2021-03-05 11:24:28 +01:00
$filter = '(' . $this -> filtergroup . ')' ;
2020-11-19 22:07:32 +01:00
} elseif ((( string ) $activefilter == 'member' ) && $this -> filter ) {
2015-10-30 19:16:02 +01:00
$filter = '(' . $this -> filtermember . ')' ;
2020-11-19 22:07:32 +01:00
} else {
2021-06-15 20:22:36 +02:00
// If this->filter/this->filtergroup is empty, make fiter on * (all)
$filter = '(' . ldap_escape ( $useridentifier , '' , LDAP_ESCAPE_FILTER ) . '=*)' ;
2008-12-09 21:14:04 +01:00
}
2021-06-15 20:22:36 +02:00
} else { // Use a filter forged using the $search value
$filter = '(' . ldap_escape ( $useridentifier , '' , LDAP_ESCAPE_FILTER ) . '=' . ldap_escape ( $search , '' , LDAP_ESCAPE_FILTER ) . ')' ;
2008-12-09 21:14:04 +01:00
}
2021-02-23 22:03:23 +01:00
if ( is_array ( $attributeArray )) {
2008-12-09 21:14:04 +01:00
// Return list with required fields
2020-04-10 10:59:32 +02:00
$attributeArray = array_values ( $attributeArray ); // This is to force to have index reordered from 0 (not make ldap_search fails)
dol_syslog ( get_class ( $this ) . " ::getRecords connection= " . $this -> connection . " userDn= " . $userDn . " filter= " . $filter . " attributeArray=( " . join ( ',' , $attributeArray ) . " ) " );
2012-10-24 16:25:09 +02:00
//var_dump($attributeArray);
2008-12-09 21:14:04 +01:00
$this -> result = @ ldap_search ( $this -> connection , $userDn , $filter , $attributeArray );
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
// Return list with fields selected by default
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::getRecords connection= " . $this -> connection . " userDn= " . $userDn . " filter= " . $filter );
2008-12-09 21:14:04 +01:00
$this -> result = @ ldap_search ( $this -> connection , $userDn , $filter );
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> result ) {
2008-12-09 21:14:04 +01:00
$this -> error = 'LDAP search failed: ' . ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
return - 1 ;
}
$info = @ ldap_get_entries ( $this -> connection , $this -> result );
2007-04-26 02:08:06 +02:00
2009-12-21 10:05:49 +01:00
// Warning: Dans info, les noms d'attributs sont en minuscule meme si passe
2007-04-26 02:08:06 +02:00
// a ldap_search en majuscule !!!
2006-11-26 01:24:10 +01:00
//print_r($info);
2007-04-26 02:08:06 +02:00
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i < $info [ " count " ]; $i ++ ) {
2020-04-10 10:59:32 +02:00
$recordid = $this -> convToOutputCharset ( $info [ $i ][ $useridentifier ][ 0 ], $this -> ldapcharset );
2021-02-23 22:03:23 +01:00
if ( $recordid ) {
2007-04-26 02:08:06 +02:00
//print "Found record with key $useridentifier=".$recordid."<br>\n";
2020-04-10 10:59:32 +02:00
$fulllist [ $recordid ][ $useridentifier ] = $recordid ;
2008-12-09 21:14:04 +01:00
2007-04-26 02:08:06 +02:00
// Add to the array for each attribute in my list
2011-09-20 18:12:52 +02:00
$num = count ( $attributeArray );
2021-02-23 22:03:23 +01:00
for ( $j = 0 ; $j < $num ; $j ++ ) {
2020-04-10 10:59:32 +02:00
$keyattributelower = strtolower ( $attributeArray [ $j ]);
2007-04-26 02:08:06 +02:00
//print " Param ".$attributeArray[$j]."=".$info[$i][$keyattributelower][0]."<br>\n";
2009-01-29 13:39:52 +01:00
2009-12-21 10:05:49 +01:00
//permet de recuperer le SID avec Active Directory
2021-02-23 22:03:23 +01:00
if ( $this -> serverType == " activedirectory " && $keyattributelower == " objectsid " ) {
2007-04-26 02:08:06 +02:00
$objectsid = $this -> getObjectSid ( $recordid );
2020-04-10 10:59:32 +02:00
$fulllist [ $recordid ][ $attributeArray [ $j ]] = $objectsid ;
2020-05-21 15:05:19 +02:00
} else {
2020-04-10 10:59:32 +02:00
if ( in_array ( $attributeArray [ $j ], $attributeAsArray ) && is_array ( $info [ $i ][ $keyattributelower ])) {
2013-02-25 11:57:52 +01:00
$valueTab = array ();
2020-04-10 10:59:32 +02:00
foreach ( $info [ $i ][ $keyattributelower ] as $key => $value ) {
2019-01-27 11:55:16 +01:00
$valueTab [ $key ] = $this -> convToOutputCharset ( $value , $this -> ldapcharset );
2013-02-25 11:57:52 +01:00
}
$fulllist [ $recordid ][ $attributeArray [ $j ]] = $valueTab ;
} else {
2019-01-27 11:55:16 +01:00
$fulllist [ $recordid ][ $attributeArray [ $j ]] = $this -> convToOutputCharset ( $info [ $i ][ $keyattributelower ][ 0 ], $this -> ldapcharset );
2013-02-25 11:57:52 +01:00
}
2007-04-26 02:08:06 +02:00
}
}
}
}
2006-06-24 17:13:29 +02:00
2008-12-09 21:14:04 +01:00
asort ( $fulllist );
return $fulllist ;
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
/**
* Converts a little - endian hex - number to one , that 'hexdec' can convert
2012-01-27 16:10:44 +01:00
* Required by Active Directory
*
2012-03-20 12:46:57 +01:00
* @ param string $hex Hex value
2012-04-16 12:01:32 +02:00
* @ return string Little endian
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function littleEndian ( $hex )
2012-01-27 16:10:44 +01:00
{
2020-11-19 22:07:32 +01:00
$result = '' ;
2020-04-10 10:59:32 +02:00
for ( $x = dol_strlen ( $hex ) - 2 ; $x >= 0 ; $x = $x - 2 ) {
2019-01-27 11:55:16 +01:00
$result .= substr ( $hex , $x , 2 );
2008-12-09 21:14:04 +01:00
}
return $result ;
}
/**
2012-03-19 17:18:11 +01:00
* Recupere le SID de l ' utilisateur
2012-01-27 16:10:44 +01:00
* Required by Active Directory
2012-03-19 17:18:11 +01:00
*
2012-04-16 12:01:32 +02:00
* @ param string $ldapUser Login de l ' utilisateur
2012-03-19 17:18:11 +01:00
* @ return string Sid
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getObjectSid ( $ldapUser )
2008-12-09 21:14:04 +01:00
{
2020-04-10 10:59:32 +02:00
$criteria = '(' . $this -> getUserIdentifier () . '=' . $ldapUser . ')' ;
2008-12-09 21:14:04 +01:00
$justthese = array ( " objectsid " );
2009-01-29 13:39:52 +01:00
2008-12-09 21:14:04 +01:00
// if the directory is AD, then bind first with the search user first
2021-02-23 22:03:23 +01:00
if ( $this -> serverType == " activedirectory " ) {
2008-12-09 21:14:04 +01:00
$this -> bindauth ( $this -> searchUser , $this -> searchPassword );
}
$i = 0 ;
$searchDN = $this -> people ;
2021-02-23 22:03:23 +01:00
while ( $i <= 2 ) {
2008-12-09 21:14:04 +01:00
$ldapSearchResult = @ ldap_search ( $this -> connection , $searchDN , $criteria , $justthese );
2009-01-29 13:39:52 +01:00
2021-02-23 22:03:23 +01:00
if ( ! $ldapSearchResult ) {
2008-12-09 21:14:04 +01:00
$this -> error = ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
return - 1 ;
}
$entry = ldap_first_entry ( $this -> connection , $ldapSearchResult );
2021-02-23 22:03:23 +01:00
if ( ! $entry ) {
2012-03-19 17:18:11 +01:00
// Si pas de resultat on cherche dans le domaine
2008-12-09 21:14:04 +01:00
$searchDN = $this -> domain ;
$i ++ ;
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
$i ++ ;
$i ++ ;
}
}
2021-02-23 22:03:23 +01:00
if ( $entry ) {
2012-03-19 17:18:11 +01:00
$ldapBinary = ldap_get_values_len ( $this -> connection , $entry , " objectsid " );
2008-12-09 21:14:04 +01:00
$SIDText = $this -> binSIDtoText ( $ldapBinary [ 0 ]);
return $SIDText ;
2020-05-21 15:05:19 +02:00
} else {
2008-12-09 21:14:04 +01:00
$this -> error = ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
return '?' ;
}
}
2009-01-29 13:39:52 +01:00
2008-12-09 21:14:04 +01:00
/**
* Returns the textual SID
* Indispensable pour Active Directory
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param string $binsid Binary SID
* @ return string Textual SID
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function binSIDtoText ( $binsid )
2012-01-27 16:10:44 +01:00
{
2020-04-10 10:59:32 +02:00
$hex_sid = bin2hex ( $binsid );
$rev = hexdec ( substr ( $hex_sid , 0 , 2 )); // Get revision-part of SID
$subcount = hexdec ( substr ( $hex_sid , 2 , 2 )); // Get count of sub-auth entries
$auth = hexdec ( substr ( $hex_sid , 4 , 12 )); // SECURITY_NT_AUTHORITY
2008-12-09 21:14:04 +01:00
$result = " $rev - $auth " ;
2021-02-23 22:03:23 +01:00
for ( $x = 0 ; $x < $subcount ; $x ++ ) {
2020-04-10 10:59:32 +02:00
$result .= " - " . hexdec ( $this -> littleEndian ( substr ( $hex_sid , 16 + ( $x * 8 ), 8 ))); // get all SECURITY_NT_AUTHORITY
2008-12-09 21:14:04 +01:00
}
return $result ;
}
2009-01-29 13:39:52 +01:00
2006-11-21 23:51:05 +01:00
2006-11-19 05:56:10 +01:00
/**
2012-01-27 16:10:44 +01:00
* Fonction de recherche avec filtre
* this -> connection doit etre defini donc la methode bind ou bindauth doit avoir deja ete appelee
* Ne pas utiliser pour recherche d ' une liste donnee de proprietes
* car conflit majuscule - minuscule . A n ' utiliser que pour les pages
* 'Fiche LDAP' qui affiche champ lisibles par defaut .
*
2014-11-15 15:19:37 +01:00
* @ param string $checkDn DN de recherche ( Ex : ou = users , cn = my - domain , cn = com )
* @ param string $filter Search filter ( ex : ( sn = nom_personne ) )
* @ return array | int Array with answers ( key lowercased - value )
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function search ( $checkDn , $filter )
2006-11-19 17:02:53 +01:00
{
2012-10-24 17:32:10 +02:00
dol_syslog ( get_class ( $this ) . " ::search checkDn= " . $checkDn . " filter= " . $filter );
2006-11-21 23:51:05 +01:00
2020-04-10 10:59:32 +02:00
$checkDn = $this -> convFromOutputCharset ( $checkDn , $this -> ldapcharset );
$filter = $this -> convFromOutputCharset ( $filter , $this -> ldapcharset );
2006-11-26 01:24:10 +01:00
2006-11-19 05:56:10 +01:00
// if the directory is AD, then bind first with the search user first
if ( $this -> serverType == " activedirectory " ) {
2006-11-26 03:59:09 +01:00
$this -> bindauth ( $this -> searchUser , $this -> searchPassword );
2006-11-19 05:56:10 +01:00
}
2006-11-21 23:51:05 +01:00
2006-11-19 17:02:53 +01:00
$this -> result = @ ldap_search ( $this -> connection , $checkDn , $filter );
2006-11-21 23:51:05 +01:00
2006-11-19 17:02:53 +01:00
$result = @ ldap_get_entries ( $this -> connection , $this -> result );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
2006-11-26 01:24:10 +01:00
$this -> error = ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
return - 1 ;
2020-05-21 15:05:19 +02:00
} else {
2006-11-19 05:56:10 +01:00
ldap_free_result ( $this -> result );
return $result ;
}
}
2006-06-25 16:29:29 +02:00
2008-12-09 21:14:04 +01:00
/**
2011-05-28 02:16:12 +02:00
* Load all attribute of a LDAP user
2012-03-19 17:18:11 +01:00
*
2012-01-27 16:10:44 +01:00
* @ param User $user User to search for . Not used if a filter is provided .
* @ param string $filter Filter for search . Must start with &.
* Examples : & ( objectClass = inetOrgPerson ) & ( objectClass = user )( objectCategory = person ) & ( isMemberOf = cn = Sales , ou = Groups , dc = opencsi , dc = com )
* @ return int > 0 if OK , < 0 if KO
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function fetch ( $user , $filter )
2008-01-25 23:13:25 +01:00
{
// Perform the search and get the entry handles
2006-11-21 23:51:05 +01:00
2008-01-25 23:13:25 +01:00
// if the directory is AD, then bind first with the search user first
if ( $this -> serverType == " activedirectory " ) {
$this -> bindauth ( $this -> searchUser , $this -> searchPassword );
}
2006-06-25 19:09:43 +02:00
2020-04-10 10:59:32 +02:00
$searchDN = $this -> people ; // TODO Why searching in people then domain ?
2008-12-09 21:14:04 +01:00
2008-01-25 23:13:25 +01:00
$result = '' ;
2020-04-10 10:59:32 +02:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
while ( $i <= 2 ) {
2017-10-07 13:09:31 +02:00
dol_syslog ( get_class ( $this ) . " ::fetch search with searchDN= " . $searchDN . " filter= " . $filter );
2008-01-25 23:13:25 +01:00
$this -> result = @ ldap_search ( $this -> connection , $searchDN , $filter );
2021-02-23 22:03:23 +01:00
if ( $this -> result ) {
2008-01-25 23:13:25 +01:00
$result = @ ldap_get_entries ( $this -> connection , $this -> result );
2021-02-23 22:03:23 +01:00
if ( $result [ 'count' ] > 0 ) {
dol_syslog ( 'Ldap::fetch search found ' . $result [ 'count' ] . ' records' );
} else {
dol_syslog ( 'Ldap::fetch search returns but found no records' );
}
2011-05-28 05:34:20 +02:00
//var_dump($result);exit;
2020-05-21 15:05:19 +02:00
} else {
2017-10-07 13:09:31 +02:00
$this -> error = ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
dol_syslog ( get_class ( $this ) . " ::fetch search fails " );
return - 1 ;
2008-01-25 23:13:25 +01:00
}
2009-01-29 13:39:52 +01:00
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
2009-12-21 10:05:49 +01:00
// Si pas de resultat on cherche dans le domaine
2008-01-25 23:13:25 +01:00
$searchDN = $this -> domain ;
$i ++ ;
2020-05-21 15:05:19 +02:00
} else {
2011-05-28 02:16:12 +02:00
break ;
2008-01-25 23:13:25 +01:00
}
}
2006-06-25 19:09:43 +02:00
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
2008-01-25 23:13:25 +01:00
$this -> error = ldap_errno ( $this -> connection ) . " " . ldap_error ( $this -> connection );
return - 1 ;
2020-05-21 15:05:19 +02:00
} else {
2019-01-27 11:55:16 +01:00
$this -> name = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_name ][ 0 ], $this -> ldapcharset );
$this -> firstname = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_firstname ][ 0 ], $this -> ldapcharset );
$this -> login = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_login ][ 0 ], $this -> ldapcharset );
$this -> phone = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_phone ][ 0 ], $this -> ldapcharset );
$this -> skype = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_skype ][ 0 ], $this -> ldapcharset );
$this -> fax = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_fax ][ 0 ], $this -> ldapcharset );
$this -> mail = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_mail ][ 0 ], $this -> ldapcharset );
$this -> mobile = $this -> convToOutputCharset ( $result [ 0 ][ $this -> attr_mobile ][ 0 ], $this -> ldapcharset );
2008-12-09 21:14:04 +01:00
2019-01-27 11:55:16 +01:00
$this -> uacf = $this -> parseUACF ( $this -> convToOutputCharset ( $result [ 0 ][ " useraccountcontrol " ][ 0 ], $this -> ldapcharset ));
2021-02-23 22:03:23 +01:00
if ( isset ( $result [ 0 ][ " pwdlastset " ][ 0 ])) { // If expiration on password exists
2020-04-10 10:59:32 +02:00
$this -> pwdlastset = ( $result [ 0 ][ " pwdlastset " ][ 0 ] != 0 ) ? $this -> convert_time ( $this -> convToOutputCharset ( $result [ 0 ][ " pwdlastset " ][ 0 ], $this -> ldapcharset )) : 0 ;
2020-05-21 15:05:19 +02:00
} else {
2008-01-25 23:13:25 +01:00
$this -> pwdlastset = - 1 ;
}
2021-02-23 22:03:23 +01:00
if ( ! $this -> name && ! $this -> login ) {
$this -> pwdlastset = - 1 ;
}
2019-01-27 11:55:16 +01:00
$this -> badpwdtime = $this -> convert_time ( $this -> convToOutputCharset ( $result [ 0 ][ " badpasswordtime " ][ 0 ], $this -> ldapcharset ));
2009-01-29 13:39:52 +01:00
2008-01-25 23:13:25 +01:00
// FQDN domain
2019-01-27 11:55:16 +01:00
$domain = str_replace ( 'dc=' , '' , $this -> domain );
$domain = str_replace ( ',' , '.' , $domain );
2008-01-25 23:13:25 +01:00
$this -> domainFQDN = $domain ;
2006-11-21 23:51:05 +01:00
2011-05-28 05:34:20 +02:00
// Set ldapUserDn (each user can have a different dn)
2017-10-07 13:09:31 +02:00
//var_dump($result[0]);exit;
2020-04-10 10:59:32 +02:00
$this -> ldapUserDN = $result [ 0 ][ 'dn' ];
2011-05-28 05:34:20 +02:00
2008-01-25 23:13:25 +01:00
ldap_free_result ( $this -> result );
return 1 ;
}
2007-04-28 14:57:13 +02:00
}
2006-06-24 17:13:29 +02:00
2006-11-21 23:51:05 +01:00
2012-01-27 16:10:44 +01:00
// helper methods
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
/**
2012-01-27 16:10:44 +01:00
* Returns the correct user identifier to use , based on the ldap server type
2012-03-19 17:18:11 +01:00
*
* @ return string Login
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getUserIdentifier ()
2012-01-27 16:10:44 +01:00
{
2008-12-09 21:14:04 +01:00
if ( $this -> serverType == " activedirectory " ) {
return $this -> attr_sambalogin ;
} else {
return $this -> attr_login ;
}
}
2006-11-21 23:51:05 +01:00
2020-10-31 14:32:18 +01:00
/**
* UserAccountControl Flgs to more human understandable form ...
*
* @ param string $uacf UACF
* @ return void
*/
public function parseUACF ( $uacf )
2012-01-27 16:10:44 +01:00
{
2008-12-09 21:14:04 +01:00
//All flags array
2017-10-02 08:43:53 +02:00
$flags = array (
" TRUSTED_TO_AUTH_FOR_DELEGATION " => 16777216 ,
" PASSWORD_EXPIRED " => 8388608 ,
" DONT_REQ_PREAUTH " => 4194304 ,
" USE_DES_KEY_ONLY " => 2097152 ,
" NOT_DELEGATED " => 1048576 ,
" TRUSTED_FOR_DELEGATION " => 524288 ,
" SMARTCARD_REQUIRED " => 262144 ,
" MNS_LOGON_ACCOUNT " => 131072 ,
" DONT_EXPIRE_PASSWORD " => 65536 ,
" SERVER_TRUST_ACCOUNT " => 8192 ,
" WORKSTATION_TRUST_ACCOUNT " => 4096 ,
" INTERDOMAIN_TRUST_ACCOUNT " => 2048 ,
" NORMAL_ACCOUNT " => 512 ,
" TEMP_DUPLICATE_ACCOUNT " => 256 ,
" ENCRYPTED_TEXT_PWD_ALLOWED " => 128 ,
" PASSWD_CANT_CHANGE " => 64 ,
" PASSWD_NOTREQD " => 32 ,
" LOCKOUT " => 16 ,
" HOMEDIR_REQUIRED " => 8 ,
" ACCOUNTDISABLE " => 2 ,
" SCRIPT " => 1
);
2006-06-25 16:29:29 +02:00
2008-12-09 21:14:04 +01:00
//Parse flags to text
$retval = array ();
2020-02-19 11:59:27 +01:00
//while (list($flag, $val) = each($flags)) {
foreach ( $flags as $flag => $val ) {
2008-12-09 21:14:04 +01:00
if ( $uacf >= $val ) {
$uacf -= $val ;
$retval [ $val ] = $flag ;
}
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
//Return human friendly flags
return ( $retval );
}
2006-11-21 23:51:05 +01:00
2020-10-31 14:32:18 +01:00
/**
* SamAccountType value to text
*
* @ param string $samtype SamType
* @ return string Sam string
*/
public function parseSAT ( $samtype )
2012-01-27 16:10:44 +01:00
{
2017-10-02 08:43:53 +02:00
$stypes = array (
805306368 => " NORMAL_ACCOUNT " ,
805306369 => " WORKSTATION_TRUST " ,
805306370 => " INTERDOMAIN_TRUST " ,
268435456 => " SECURITY_GLOBAL_GROUP " ,
268435457 => " DISTRIBUTION_GROUP " ,
536870912 => " SECURITY_LOCAL_GROUP " ,
536870913 => " DISTRIBUTION_LOCAL_GROUP "
);
2008-12-09 21:14:04 +01:00
$retval = " " ;
while ( list ( $sat , $val ) = each ( $stypes )) {
if ( $samtype == $sat ) {
$retval = $val ;
break ;
}
}
2021-02-23 22:03:23 +01:00
if ( empty ( $retval )) {
$retval = " UNKNOWN_TYPE_ " . $samtype ;
}
2006-11-21 23:51:05 +01:00
2008-12-09 21:14:04 +01:00
return ( $retval );
}
2006-11-21 23:51:05 +01:00
2020-10-31 14:32:18 +01:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2009-12-21 10:05:49 +01:00
/**
2012-01-27 16:10:44 +01:00
* Convertit le temps ActiveDirectory en Unix timestamp
*
* @ param string $value AD time to convert
2015-04-06 12:25:30 +02:00
* @ return integer Unix timestamp
2008-12-09 21:14:04 +01:00
*/
2020-10-31 14:32:18 +01:00
public function convert_time ( $value )
2006-11-26 01:24:10 +01:00
{
2020-10-31 14:32:18 +01:00
// phpcs:enable
2020-04-10 10:59:32 +02:00
$dateLargeInt = $value ; // nano secondes depuis 1601 !!!!
2008-12-09 21:14:04 +01:00
$secsAfterADEpoch = $dateLargeInt / ( 10000000 ); // secondes depuis le 1 jan 1601
2020-04-10 10:59:32 +02:00
$ADToUnixConvertor = (( 1970 - 1601 ) * 365.242190 ) * 86400 ; // UNIX start date - AD start date * jours * secondes
$unixTimeStamp = intval ( $secsAfterADEpoch - $ADToUnixConvertor ); // Unix time stamp
2008-12-09 21:14:04 +01:00
return $unixTimeStamp ;
2006-11-26 01:24:10 +01:00
}
2009-01-29 13:39:52 +01:00
2008-12-09 21:14:04 +01:00
/**
2011-12-07 18:10:24 +01:00
* Convert a string into output / memory charset
2017-10-07 13:09:31 +02:00
*
2012-01-27 16:10:44 +01:00
* @ param string $str String to convert
* @ param string $pagecodefrom Page code of src string
* @ return string Converted string
2009-08-11 22:16:58 +02:00
*/
2019-01-27 15:20:16 +01:00
private function convToOutputCharset ( $str , $pagecodefrom = 'UTF-8' )
2009-08-11 22:16:58 +02:00
{
global $conf ;
2021-02-23 22:03:23 +01:00
if ( $pagecodefrom == 'ISO-8859-1' && $conf -> file -> character_set_client == 'UTF-8' ) {
$str = utf8_encode ( $str );
}
if ( $pagecodefrom == 'UTF-8' && $conf -> file -> character_set_client == 'ISO-8859-1' ) {
$str = utf8_decode ( $str );
}
2008-12-09 21:14:04 +01:00
return $str ;
2009-08-11 22:16:58 +02:00
}
2006-11-26 01:24:10 +01:00
2008-12-09 21:14:04 +01:00
/**
2011-12-07 18:10:24 +01:00
* Convert a string from output / memory charset
2017-10-07 13:09:31 +02:00
*
2012-01-27 16:10:44 +01:00
* @ param string $str String to convert
* @ param string $pagecodeto Page code for result string
* @ return string Converted string
2009-08-11 22:16:58 +02:00
*/
2020-10-31 14:32:18 +01:00
public function convFromOutputCharset ( $str , $pagecodeto = 'UTF-8' )
2009-08-11 22:16:58 +02:00
{
global $conf ;
2021-02-23 22:03:23 +01:00
if ( $pagecodeto == 'ISO-8859-1' && $conf -> file -> character_set_client == 'UTF-8' ) {
$str = utf8_decode ( $str );
}
if ( $pagecodeto == 'UTF-8' && $conf -> file -> character_set_client == 'ISO-8859-1' ) {
$str = utf8_encode ( $str );
}
2008-12-09 21:14:04 +01:00
return $str ;
2009-08-11 22:16:58 +02:00
}
2011-12-07 18:10:24 +01:00
2011-10-23 20:02:15 +02:00
/**
2011-12-07 18:10:24 +01:00
* Return available value of group GID
2012-01-27 16:10:44 +01:00
*
2017-09-16 21:58:05 +02:00
* @ param string $keygroup Key of group
* @ return int gid number
2011-12-07 18:10:24 +01:00
*/
2020-10-31 14:32:18 +01:00
public function getNextGroupGid ( $keygroup = 'LDAP_KEY_GROUPS' )
2011-10-24 08:59:14 +02:00
{
2011-10-23 20:02:15 +02:00
global $conf ;
2011-12-07 18:10:24 +01:00
2021-02-23 22:03:23 +01:00
if ( empty ( $keygroup )) {
$keygroup = 'LDAP_KEY_GROUPS' ;
}
2017-09-16 17:51:18 +02:00
2020-04-10 10:59:32 +02:00
$search = '(' . $conf -> global -> $keygroup . '=*)' ;
2019-01-27 11:55:16 +01:00
$result = $this -> search ( $this -> groups , $search );
2021-02-23 22:03:23 +01:00
if ( $result ) {
2011-10-24 08:59:14 +02:00
$c = $result [ 'count' ];
$gids = array ();
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i < $c ; $i ++ ) {
2011-10-24 08:59:14 +02:00
$gids [] = $result [ $i ][ 'gidnumber' ][ 0 ];
}
rsort ( $gids );
2011-12-07 18:10:24 +01:00
2020-04-10 10:59:32 +02:00
return $gids [ 0 ] + 1 ;
2011-10-23 20:02:15 +02:00
}
2011-12-07 18:10:24 +01:00
return 0 ;
2011-10-23 20:02:15 +02:00
}
2006-11-26 01:24:10 +01:00
}