2016-03-06 14:45:15 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware API - LDAP server information
|
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Lars Kneschke <l.kneschke@metaways.de>
|
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package api
|
|
|
|
* @subpackage ldap
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace EGroupware\Api\Ldap;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class to store and retrieve information (eg. supported object classes) of a connected ldap server
|
|
|
|
*/
|
|
|
|
class ServerInfo
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Unknown LDAP server
|
|
|
|
*/
|
|
|
|
const UNKNOWN = 0;
|
|
|
|
/**
|
|
|
|
* OpenLDAP server
|
|
|
|
*/
|
|
|
|
const OPENLDAP = 1;
|
|
|
|
/**
|
2020-09-08 15:29:51 +02:00
|
|
|
* Samba4 Active Directory server
|
2016-03-06 14:45:15 +01:00
|
|
|
*/
|
|
|
|
const SAMBA4 = 2;
|
2020-09-08 15:29:51 +02:00
|
|
|
/**
|
|
|
|
* Windows Active Directory server
|
|
|
|
*/
|
|
|
|
const WINDOWS_AD = 4;
|
2016-03-06 14:45:15 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array $namingContext holds the supported namingcontexts
|
|
|
|
*/
|
|
|
|
var $namingContext = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string $version holds the LDAP server version
|
|
|
|
*/
|
|
|
|
var $version = 2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var integer $serverType holds the type of LDAP server(OpenLDAP, ADS, NDS, ...)
|
|
|
|
*/
|
|
|
|
var $serverType = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string $_subSchemaEntry the subschema entry DN
|
|
|
|
*/
|
|
|
|
var $subSchemaEntry = '';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array $supportedObjectClasses the supported objectclasses
|
|
|
|
*/
|
|
|
|
var $supportedObjectClasses = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array $supportedOIDs the supported OIDs
|
|
|
|
*/
|
|
|
|
var $supportedOIDs = array();
|
|
|
|
|
2020-09-05 13:11:07 +02:00
|
|
|
/**
|
|
|
|
* @var array OIDs of supported controls LDAP_CONTROL_*
|
|
|
|
*/
|
|
|
|
var $suportedControl = [];
|
|
|
|
|
2016-03-06 14:45:15 +01:00
|
|
|
/**
|
|
|
|
* Name of host
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
var $host;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $host
|
|
|
|
*/
|
|
|
|
function __construct($host)
|
|
|
|
{
|
2023-08-17 12:22:45 +02:00
|
|
|
$this->host = preg_match('#^ldaps?//([^:]+)#', $host, $matches) ? $matches[1] : $host;
|
2016-03-06 14:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gets the version
|
|
|
|
*
|
|
|
|
* @return integer the supported ldap version
|
|
|
|
*/
|
|
|
|
function getVersion()
|
|
|
|
{
|
|
|
|
return $this->version;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sets the namingcontexts
|
|
|
|
*
|
|
|
|
* @param array $_namingContext the supported namingcontexts
|
|
|
|
*/
|
|
|
|
function setNamingContexts($_namingContext)
|
|
|
|
{
|
|
|
|
$this->namingContext = $_namingContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sets the type of the ldap server(OpenLDAP, ADS, NDS, ...)
|
|
|
|
*
|
|
|
|
* @param integer $_serverType the type of ldap server
|
|
|
|
*/
|
|
|
|
function setServerType($_serverType)
|
|
|
|
{
|
|
|
|
$this->serverType = $_serverType;
|
|
|
|
}
|
|
|
|
|
2020-09-08 15:29:51 +02:00
|
|
|
/**
|
|
|
|
* @param ?bool $windows_ad true: check for windows AD, false: check for Samba4, null: check of any AD
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
function activeDirectory($windows_ad=null)
|
|
|
|
{
|
|
|
|
return !isset($windows_ad) ? in_array($this->serverType, [self::WINDOWS_AD, self::SAMBA4], true) :
|
|
|
|
$this->serverType === ($windows_ad ? self::WINDOWS_AD : self::SAMBA4);
|
|
|
|
}
|
|
|
|
|
2016-03-06 14:45:15 +01:00
|
|
|
/**
|
|
|
|
* sets the DN for the subschema entry
|
|
|
|
*
|
|
|
|
* @param string $_subSchemaEntry the subschema entry DN
|
|
|
|
*/
|
|
|
|
function setSubSchemaEntry($_subSchemaEntry)
|
|
|
|
{
|
|
|
|
$this->subSchemaEntry = $_subSchemaEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sets the supported objectclasses
|
|
|
|
*
|
|
|
|
* @param array $_supportedObjectClasses the supported objectclasses
|
|
|
|
*/
|
|
|
|
function setSupportedObjectClasses($_supportedObjectClasses)
|
|
|
|
{
|
|
|
|
$this->supportedOIDs = $_supportedObjectClasses;
|
|
|
|
$this->supportedObjectClasses = array_flip($_supportedObjectClasses);
|
|
|
|
}
|
|
|
|
|
2020-09-05 13:11:07 +02:00
|
|
|
/**
|
|
|
|
* sets the supported objectclasses
|
|
|
|
*
|
|
|
|
* @param array $_supportedControl LDAP_CONTROL_* values
|
|
|
|
*/
|
|
|
|
function setSupportedControl(array $_supportedControl)
|
|
|
|
{
|
|
|
|
unset($_supportedControl['count']);
|
|
|
|
$this->suportedControl = $_supportedControl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if given (multiple) LDAP_CONTROL_* args are (all) supported
|
|
|
|
*
|
|
|
|
* @param int $control LDAP_CONTROL_* value(s)
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
function supportedControl($control)
|
|
|
|
{
|
|
|
|
return count(array_intersect(func_get_args(), $this->suportedControl)) === func_num_args();
|
|
|
|
}
|
|
|
|
|
2016-03-06 14:45:15 +01:00
|
|
|
/**
|
|
|
|
* sets the version
|
|
|
|
*
|
|
|
|
* @param integer $_version the supported ldap version
|
|
|
|
*/
|
|
|
|
function setVersion($_version)
|
|
|
|
{
|
|
|
|
$this->version = $_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* checks for supported objectclasses
|
|
|
|
*
|
|
|
|
* @return bool returns true if the ldap server supports this objectclass
|
|
|
|
*/
|
|
|
|
function supportsObjectClass($_objectClass)
|
|
|
|
{
|
|
|
|
if($this->supportedObjectClasses[strtolower($_objectClass)])
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Query given ldap connection for available information
|
|
|
|
*
|
|
|
|
* @param resource $ds
|
|
|
|
* @param string $host
|
|
|
|
* @param int $version 2 or 3
|
2021-03-31 17:49:43 +02:00
|
|
|
* @return self
|
2016-03-06 14:45:15 +01:00
|
|
|
*/
|
|
|
|
public static function get($ds, $host, $version=3)
|
|
|
|
{
|
|
|
|
$filter='(objectclass=*)';
|
2020-09-08 15:29:51 +02:00
|
|
|
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry','vendorname','supportedControl','forestFunctionality');
|
2016-03-06 14:45:15 +01:00
|
|
|
if(($sr = @ldap_read($ds, '', $filter, $justthese)))
|
|
|
|
{
|
|
|
|
if(($info = ldap_get_entries($ds, $sr)))
|
|
|
|
{
|
|
|
|
$ldapServerInfo = new ServerInfo($host);
|
|
|
|
$ldapServerInfo->setVersion($version);
|
|
|
|
|
|
|
|
// check for naming contexts
|
|
|
|
if($info[0]['namingcontexts'])
|
|
|
|
{
|
|
|
|
for($i=0; $i<$info[0]['namingcontexts']['count']; $i++)
|
|
|
|
{
|
|
|
|
$namingcontexts[] = $info[0]['namingcontexts'][$i];
|
|
|
|
}
|
|
|
|
$ldapServerInfo->setNamingContexts($namingcontexts);
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for ldap server type
|
|
|
|
if($info[0]['structuralobjectclass'])
|
|
|
|
{
|
|
|
|
switch($info[0]['structuralobjectclass'][0])
|
|
|
|
{
|
|
|
|
case 'OpenLDAProotDSE':
|
2018-09-12 17:06:31 +02:00
|
|
|
$ldapServerType = self::OPENLDAP;
|
2016-03-06 14:45:15 +01:00
|
|
|
break;
|
|
|
|
default:
|
2018-09-12 17:06:31 +02:00
|
|
|
$ldapServerType = self::UNKNOWN;
|
2016-03-06 14:45:15 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
$ldapServerInfo->setServerType($ldapServerType);
|
|
|
|
}
|
2020-09-08 15:29:51 +02:00
|
|
|
// Check for ActiveDirectory by forestFunctionality and set Samba4 if vendorName includes samba
|
|
|
|
if(!empty($info[0]['forestfunctionality'][0]))
|
2016-03-06 14:45:15 +01:00
|
|
|
{
|
2020-09-08 15:29:51 +02:00
|
|
|
$ldapServerInfo->setServerType(!empty($info[0]['vendorname']) && stripos($info[0]['vendorname'][0], 'samba') !== false ?
|
|
|
|
self::SAMBA4 : self::WINDOWS_AD);
|
2016-03-06 14:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// check for subschema entry dn
|
|
|
|
if($info[0]['subschemasubentry'])
|
|
|
|
{
|
|
|
|
$subschemasubentry = $info[0]['subschemasubentry'][0];
|
|
|
|
$ldapServerInfo->setSubSchemaEntry($subschemasubentry);
|
|
|
|
}
|
|
|
|
|
2020-09-05 13:11:07 +02:00
|
|
|
if (!empty($info[0]['supportedcontrol']) && is_array($info[0]['supportedcontrol']))
|
|
|
|
{
|
|
|
|
$ldapServerInfo->setSupportedControl($info[0]['supportedcontrol']);
|
|
|
|
}
|
|
|
|
|
2016-03-06 14:45:15 +01:00
|
|
|
// create list of supported objetclasses
|
|
|
|
if(!empty($subschemasubentry))
|
|
|
|
{
|
|
|
|
$filter='(objectclass=*)';
|
|
|
|
$justthese = array('objectClasses');
|
|
|
|
|
|
|
|
if(($sr = ldap_read($ds, $subschemasubentry, $filter, $justthese)))
|
|
|
|
{
|
|
|
|
if(($info = ldap_get_entries($ds, $sr)))
|
|
|
|
{
|
|
|
|
if($info[0]['objectclasses']) {
|
|
|
|
for($i=0; $i<$info[0]['objectclasses']['count']; $i++)
|
|
|
|
{
|
|
|
|
$matches = null;
|
|
|
|
if(preg_match('/^\( (.*) NAME \'(\w*)\' /', $info[0]['objectclasses'][$i], $matches))
|
|
|
|
{
|
|
|
|
#_debug_array($matches);
|
|
|
|
if(count($matches) == 3)
|
|
|
|
{
|
|
|
|
$supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $ldapServerInfo;
|
|
|
|
}
|
2023-08-17 12:22:45 +02:00
|
|
|
}
|