mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 00:29:38 +01:00
accounts addressbook incl. working updates for active directory
This commit is contained in:
parent
5c63214e82
commit
d328af7cff
@ -12,12 +12,15 @@
|
||||
/**
|
||||
* Active directory backend for accounts (not yet AD contacts)
|
||||
*
|
||||
* We use ADS objectGUID as contact ID and UID.
|
||||
* We use ADS string representation of objectGUID as contact ID and UID.
|
||||
*
|
||||
* Unfortunatly Samba4 and active directory of win2008r2 differn on how to search for an objectGUID:
|
||||
* - Samba4 can only search for string representation eg. (objectGUID=2336A3FC-EDBD-42A2-9EEB-BD7A5DD2804E)
|
||||
* - win2008r2 can only search for hex representation eg. (objectGUID=\FC\A3\36\23\BD\ED\A2\42\9E\EB\BD\7A\5D\D2\80\4E)
|
||||
* We could use both filters or-ed together, for now we detect Samba4 and use string GUID for it.
|
||||
*
|
||||
* All values used to construct filters need to run through ldap::quote(),
|
||||
* to be save against LDAP query injection!!!
|
||||
*
|
||||
* @todo get saving of contacts working: fails while checking of container exists ...
|
||||
*/
|
||||
class addressbook_ads extends addressbook_ldap
|
||||
{
|
||||
@ -37,6 +40,13 @@ class addressbook_ads extends addressbook_ldap
|
||||
*/
|
||||
var $accountsFilter = '(objectclass=user)';
|
||||
|
||||
/**
|
||||
* Attribute used for DN
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $dn_attribute='cn';
|
||||
|
||||
/**
|
||||
* Accounts ADS object
|
||||
*
|
||||
@ -44,6 +54,14 @@ class addressbook_ads extends addressbook_ldap
|
||||
*/
|
||||
protected $accounts_ads;
|
||||
|
||||
/**
|
||||
* ADS is Samba4 (true), otherwise false
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $is_samba4 = false;
|
||||
|
||||
|
||||
/**
|
||||
* constructor of the class
|
||||
*
|
||||
@ -78,6 +96,7 @@ class addressbook_ads extends addressbook_ldap
|
||||
$this->connect();
|
||||
}
|
||||
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $this->ldap_config['ads_host']);
|
||||
$this->is_samba4 = $this->ldapServerInfo->serverType == SAMBA4_LDAPSERVER;
|
||||
|
||||
// AD seems to use user, instead of inetOrgPerson
|
||||
$this->schema2egw['user'] = $this->schema2egw['inetorgperson'];
|
||||
@ -106,6 +125,25 @@ class addressbook_ads extends addressbook_ldap
|
||||
$this->ds = $this->accounts_ads->ldap_connection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return LDAP filter for contact id
|
||||
*
|
||||
* @param string $contact_id
|
||||
* @return string
|
||||
*/
|
||||
protected function id_filter($contact_id)
|
||||
{
|
||||
// check that GUID eg. from URL contains only valid hex characters and dash
|
||||
// we cant use ldap::quote() for win2008r2 hex GUID, as it contains backslashes
|
||||
if (!preg_match('/^[0-9A-Fa-f-]+/', $contact_id))
|
||||
{
|
||||
throw new egw_exception_assertion_failed("'$contact_id' is NOT a valid GUID!");
|
||||
}
|
||||
|
||||
// samba4 can only search by string representation of objectGUID, while win2008r2 requires hex representation
|
||||
return '(objectguid='.($this->is_samba4 ? $contact_id : $this->accounts_ads->objectguid2hex($contact_id)).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* reads contact data
|
||||
*
|
||||
@ -120,11 +158,11 @@ class addressbook_ads extends addressbook_ldap
|
||||
$account_id = (int)(is_array($contact_id) ? $contact_id['account_id'] : substr($contact_id,8));
|
||||
$contact_id = $GLOBALS['egw']->accounts->id2name($account_id, 'person_id');
|
||||
}
|
||||
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
|
||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
|
||||
|
||||
$rows = $this->_searchLDAP($this->allContactsDN, "(objectguid=$contact_id)", $this->all_attributes, ADDRESSBOOK_ALL);
|
||||
$contact_id = !is_array($contact_id) ? $contact_id :
|
||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']);
|
||||
|
||||
$rows = $this->_searchLDAP($this->allContactsDN, $filter=$this->id_filter($contact_id), $this->all_attributes, ADDRESSBOOK_ALL);
|
||||
//error_log(__METHOD__."('$contact_id') _searchLDAP($this->allContactsDN, '$filter',...)=".array2string($rows));
|
||||
return $rows ? $rows[0] : false;
|
||||
}
|
||||
|
||||
@ -147,4 +185,19 @@ class addressbook_ads extends addressbook_ldap
|
||||
|
||||
$this->_inetorgperson2egw($contact, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove attributes we are not allowed to update
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
function sanitize_update(array &$ldapContact)
|
||||
{
|
||||
// not allowed and not need to update these in AD
|
||||
unset($ldapContact['objectguid']);
|
||||
unset($ldapContact['objectsid']);
|
||||
|
||||
parent::sanitize_update($ldapContact);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -75,6 +75,13 @@ class addressbook_ldap
|
||||
*/
|
||||
var $allContactsDN;
|
||||
|
||||
/**
|
||||
* Attribute used for DN
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $dn_attribute='uid';
|
||||
|
||||
/**
|
||||
* @var int $total holds the total count of found rows
|
||||
*/
|
||||
@ -237,6 +244,13 @@ class addressbook_ldap
|
||||
*/
|
||||
private $ldap_config;
|
||||
|
||||
/**
|
||||
* LDAP connection
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
var $ds;
|
||||
|
||||
/**
|
||||
* constructor of the class
|
||||
*
|
||||
@ -256,10 +270,10 @@ class addressbook_ldap
|
||||
{
|
||||
$this->ldap_config =& $GLOBALS['egw_info']['server'];
|
||||
}
|
||||
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
$this->accountContactsDN = $this->ldap_config['ldap_context'];
|
||||
$this->allContactsDN = $this->ldap_config['ldap_contact_context'];
|
||||
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->allContactsDN;
|
||||
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->allContactsDN;
|
||||
|
||||
if ($ds)
|
||||
{
|
||||
@ -303,7 +317,7 @@ class addressbook_ldap
|
||||
elseif (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
|
||||
{
|
||||
$this->ldap_config['ldap_contact_host'] = $this->ldap_config['ldap_host'];
|
||||
$this->ldap_config['ldap_contact_context'] = $this->ldap_config['ldap_context'];
|
||||
$this->allContactsDN = $this->ldap_config['ldap_context'];
|
||||
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
|
||||
}
|
||||
else
|
||||
@ -340,6 +354,37 @@ class addressbook_ldap
|
||||
return array_values(array_unique($fields));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return LDAP filter for contact id
|
||||
*
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
protected function id_filter($id)
|
||||
{
|
||||
return '(|(entryUUID='.ldap::quote($id).')(uid='.ldap::quote($id).'))';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return LDAP filter for (multiple) contact ids
|
||||
*
|
||||
* @param array|string $ids
|
||||
* @return string
|
||||
*/
|
||||
protected function ids_filter($ids)
|
||||
{
|
||||
if (!is_array($ids) || count($ids) == 1)
|
||||
{
|
||||
return $this->id_filter(is_array($ids) ? array_shift($ids) : $ids);
|
||||
}
|
||||
$filter = array();
|
||||
foreach($ids as $id)
|
||||
{
|
||||
$filter[] = $this->id_filter($id);
|
||||
}
|
||||
return '(|'.implode('', $filter).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* reads contact data
|
||||
*
|
||||
@ -355,16 +400,30 @@ class addressbook_ldap
|
||||
}
|
||||
else
|
||||
{
|
||||
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
|
||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
|
||||
$filter = "(|(entryUUID=$contact_id)(uid=$contact_id))";
|
||||
if (is_array($contact_id)) $contact_id = isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid'];
|
||||
$filter = $this->id_filter($contact_id);
|
||||
}
|
||||
$rows = $this->_searchLDAP($this->ldap_config['ldap_contact_context'],
|
||||
$rows = $this->_searchLDAP($this->allContactsDN,
|
||||
$filter, $this->all_attributes, ADDRESSBOOK_ALL);
|
||||
|
||||
return $rows ? $rows[0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove attributes we are not allowed to update
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
function sanitize_update(array &$ldapContact)
|
||||
{
|
||||
// never allow to change the uidNumber (account_id) on update, as it could be misused by eg. xmlrpc or syncml
|
||||
unset($ldapContact['uidnumber']);
|
||||
|
||||
unset($ldapContact['entryuuid']); // not allowed to modify that, no need either
|
||||
|
||||
unset($ldapContact['objectClass']);
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the content of data to the db
|
||||
*
|
||||
@ -403,7 +462,7 @@ class addressbook_ldap
|
||||
$baseDN = $this->accountContactsDN;
|
||||
$cn = false;
|
||||
// we need an admin connection
|
||||
$this->ds = $this->connect(true);
|
||||
$this->connect(true);
|
||||
|
||||
// for sql-ldap we need to account_lid/uid as id, NOT the contact_id in id!
|
||||
if ($GLOBALS['egw_info']['server']['contact_repository'] == 'sql-ldap')
|
||||
@ -416,7 +475,6 @@ class addressbook_ldap
|
||||
error_log("Permission denied, to write: data[owner]=$data[owner], data[account_id]=$data[account_id], account_id=".$GLOBALS['egw_info']['user']['account_id']);
|
||||
return lang('Permission denied !!!'); // only admin or the user itself is allowd to write accounts!
|
||||
}
|
||||
|
||||
// check if $baseDN exists. If not create it
|
||||
if (($err = $this->_check_create_dn($baseDN)))
|
||||
{
|
||||
@ -424,11 +482,11 @@ class addressbook_ldap
|
||||
}
|
||||
// check the existing objectclasses of an entry, none = array() for new ones
|
||||
$oldObjectclasses = array();
|
||||
$attributes = array('dn','cn','objectClass','uid','mail');
|
||||
$attributes = array('dn','cn','objectClass',$this->dn_attribute,'mail');
|
||||
|
||||
$contactUID = $this->data[$this->contacts_id];
|
||||
if (!empty($contactUID) &&
|
||||
($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
|
||||
'(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes)) &&
|
||||
($result = ldap_search($this->ds, $base=$this->allContactsDN, $filter=$this->id_filter($contactUID), $attributes)) &&
|
||||
($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count'])
|
||||
{
|
||||
unset($oldContactInfo[0]['objectclass']['count']);
|
||||
@ -438,13 +496,12 @@ class addressbook_ldap
|
||||
}
|
||||
$isUpdate = true;
|
||||
}
|
||||
if(!$contactUID)
|
||||
|
||||
if(empty($contactUID))
|
||||
{
|
||||
$this->data[$this->contacts_id] = $contactUID = md5($GLOBALS['egw']->common->randomstring(15));
|
||||
$ldapContact[$this->contacts_id] = $this->data[$this->contacts_id] = $contactUID = md5($GLOBALS['egw']->common->randomstring(15));
|
||||
}
|
||||
|
||||
$ldapContact['uid'] = $contactUID;
|
||||
|
||||
//error_log(__METHOD__."() contactUID='$contactUID', isUpdate=".array2string($isUpdate).", oldContactInfo=".array2string($oldContactInfo));
|
||||
// add for all supported objectclasses the objectclass and it's attributes
|
||||
foreach($this->schema2egw as $objectclass => $mapping)
|
||||
{
|
||||
@ -497,9 +554,6 @@ class addressbook_ldap
|
||||
// update entry
|
||||
$dn = $oldContactInfo[0]['dn'];
|
||||
$needRecreation = false;
|
||||
// never allow to change the uidNumber (account_id) on update, as it could be misused by eg. xmlrpc or syncml
|
||||
unset($ldapContact['uidnumber']);
|
||||
unset($ldapContact['entryuuid']); // not allowed to modify that, no need either
|
||||
|
||||
// add missing objectclasses
|
||||
if($ldapContact['objectClass'] && array_diff($ldapContact['objectClass'],$oldObjectclasses))
|
||||
@ -522,9 +576,9 @@ class addressbook_ldap
|
||||
}
|
||||
|
||||
// check if we need to rename the DN or need to recreate the contact
|
||||
$newRDN = 'uid='. ldap::quote($contactUID);
|
||||
$newRDN = $this->dn_attribute.'='. ldap::quote($ldapContact[$this->dn_attribute]);
|
||||
$newDN = $newRDN .','. $baseDN;
|
||||
if(strtolower($dn) != strtolower($newDN) || $needRecreation)
|
||||
if ($needRecreation)
|
||||
{
|
||||
$result = ldap_read($this->ds, $dn, 'objectclass=*');
|
||||
$oldContact = ldap_get_entries($this->ds, $result);
|
||||
@ -536,7 +590,7 @@ class addressbook_ldap
|
||||
$newContact[$key] = $value;
|
||||
}
|
||||
}
|
||||
$newContact['uid'] = $contactUID;
|
||||
$newContact[$this->dn_attribute] = $ldapContact[$this->dn_attribute];
|
||||
|
||||
if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0)
|
||||
{
|
||||
@ -559,7 +613,21 @@ class addressbook_ldap
|
||||
}
|
||||
$dn = $newDN;
|
||||
}
|
||||
unset($ldapContact['objectClass']);
|
||||
// try renaming entry if content of dn-attribute changed
|
||||
if (strtolower($dn) != strtolower($newDN) || $ldapContact[$this->dn_attribute] != $oldContactInfo[$this->dn_attribute])
|
||||
{
|
||||
if (@ldap_rename($this->ds, $dn, $newRDN, null, true))
|
||||
{
|
||||
$dn = $newDN;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_log(__METHOD__."() ldap_rename or $dn to $newRDN failed! ".ldap_error($this->ds));
|
||||
}
|
||||
}
|
||||
unset($ldapContact[$this->dn_attribute]);
|
||||
|
||||
$this->sanitize_update($ldapContact);
|
||||
|
||||
if (!@ldap_modify($this->ds, $dn, $ldapContact))
|
||||
{
|
||||
@ -571,7 +639,7 @@ class addressbook_ldap
|
||||
}
|
||||
else
|
||||
{
|
||||
$dn = 'uid='. ldap::quote($ldapContact['uid']) .','. $baseDN;
|
||||
$dn = $this->dn_attribute.'='. ldap::quote($ldapContact[$this->dn_attribute]) .','. $baseDN;
|
||||
unset($ldapContact['entryuuid']); // trying to write it, gives an error
|
||||
|
||||
if (!@ldap_add($this->ds, $dn, $ldapContact))
|
||||
@ -608,7 +676,7 @@ class addressbook_ldap
|
||||
foreach($keys as $entry)
|
||||
{
|
||||
$entry = ldap::quote(is_array($entry) ? $entry['id'] : $entry);
|
||||
if($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
|
||||
if($result = ldap_search($this->ds, $this->allContactsDN,
|
||||
"(|(entryUUID=$entry)(uid=$entry))", $attributes))
|
||||
{
|
||||
$contactInfo = ldap_get_entries($this->ds, $result);
|
||||
@ -715,6 +783,11 @@ class addressbook_ldap
|
||||
$searchFilter = '';
|
||||
foreach($criteria as $egwSearchKey => $searchValue)
|
||||
{
|
||||
if (in_array($egwSearchKey, array('id','contact_id')))
|
||||
{
|
||||
$searchFilter .= $this->ids_filter($searchValue);
|
||||
continue;
|
||||
}
|
||||
foreach($this->schema2egw as $mapping)
|
||||
{
|
||||
if(($ldapSearchKey = $mapping[$egwSearchKey]))
|
||||
@ -736,7 +809,6 @@ class addressbook_ldap
|
||||
}
|
||||
$colFilter = $this->_colFilter($filter);
|
||||
$ldapFilter = "(&$objectFilter$searchFilter$colFilter)";
|
||||
|
||||
if (!($rows = $this->_searchLDAP($searchDN, $ldapFilter, $this->all_attributes, $addressbookType)))
|
||||
{
|
||||
return $rows;
|
||||
@ -849,6 +921,11 @@ class addressbook_ldap
|
||||
}
|
||||
break;
|
||||
|
||||
case 'id':
|
||||
case 'contact_id':
|
||||
$filter .= $this->ids_filter($value);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!is_int($key))
|
||||
{
|
||||
@ -1020,7 +1097,7 @@ class addressbook_ldap
|
||||
/**
|
||||
* check if $baseDN exists. If not create it
|
||||
*
|
||||
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$this->ldap_config['ldap_contact_context']
|
||||
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$this->allContactsDN
|
||||
* @return boolean/string false on success or string with error-message
|
||||
*/
|
||||
function _check_create_dn($baseDN)
|
||||
@ -1042,8 +1119,8 @@ class addressbook_ldap
|
||||
|
||||
list(,$ou) = explode(',',$baseDN);
|
||||
foreach(array(
|
||||
'ou=contacts,'.$this->ldap_config['ldap_contact_context'],
|
||||
$ou.',ou=contacts,'.$this->ldap_config['ldap_contact_context'],
|
||||
'ou=contacts,'.$this->allContactsDN,
|
||||
$ou.',ou=contacts,'.$this->allContactsDN,
|
||||
$baseDN,
|
||||
) as $dn)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@ require_once EGW_API_INC.'/adldap/adLDAP.php';
|
||||
* @access internal only use the interface provided by the accounts class
|
||||
* @link http://www.selfadsi.org/user-attributes-w2k8.htm
|
||||
* @link http://www.selfadsi.org/attributes-e2k7.htm
|
||||
* @link http://msdn.microsoft.com/en-us/library/ms675090(v=vs.85).aspx
|
||||
*/
|
||||
class accounts_ads
|
||||
{
|
||||
@ -298,6 +299,17 @@ class accounts_ads
|
||||
return $this->adldap->utilities()->decodeGuid(is_array($objectguid) ? $objectguid[0] : $objectguid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string GUID to hex string used in filter
|
||||
*
|
||||
* @param string $strGUID
|
||||
* @return int
|
||||
*/
|
||||
public function objectguid2hex($strGUID)
|
||||
{
|
||||
return $this->adldap->utilities()->strGuidToHex($strGUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data of one account
|
||||
*
|
||||
@ -841,6 +853,8 @@ class accounts_ads
|
||||
}
|
||||
if ($param['type'] == 'groups' || $param['type'] == 'both')
|
||||
{
|
||||
$query = ldap::quote(strtolower($param['query']));
|
||||
|
||||
$filter = null;
|
||||
if(!empty($query) && $query != '*')
|
||||
{
|
||||
|
@ -193,83 +193,7 @@ class ldap
|
||||
//error_log("no ldap server info found");
|
||||
$ldapbind = @ldap_bind($this->ds, $GLOBALS['egw_info']['server']['ldap_root_dn'], $GLOBALS['egw_info']['server']['ldap_root_pw']);
|
||||
|
||||
$filter='(objectclass=*)';
|
||||
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry');
|
||||
|
||||
if(($sr = @ldap_read($this->ds, '', $filter, $justthese)))
|
||||
{
|
||||
if($info = ldap_get_entries($this->ds, $sr))
|
||||
{
|
||||
$this->ldapServerInfo = new ldapserverinfo($host);
|
||||
|
||||
$this->ldapServerInfo->setVersion($supportedLDAPVersion);
|
||||
|
||||
// check for naming contexts
|
||||
if($info[0]['namingcontexts'])
|
||||
{
|
||||
for($i=0; $i<$info[0]['namingcontexts']['count']; $i++)
|
||||
{
|
||||
$namingcontexts[] = $info[0]['namingcontexts'][$i];
|
||||
}
|
||||
$this->ldapServerInfo->setNamingContexts($namingcontexts);
|
||||
}
|
||||
|
||||
// check for ldap server type
|
||||
if($info[0]['structuralobjectclass'])
|
||||
{
|
||||
switch($info[0]['structuralobjectclass'][0])
|
||||
{
|
||||
case 'OpenLDAProotDSE':
|
||||
$ldapServerType = OPENLDAP_LDAPSERVER;
|
||||
break;
|
||||
default:
|
||||
$ldapServerType = UNKNOWN_LDAPSERVER;
|
||||
break;
|
||||
}
|
||||
$this->ldapServerInfo->setServerType($ldapServerType);
|
||||
}
|
||||
|
||||
// check for subschema entry dn
|
||||
if($info[0]['subschemasubentry'])
|
||||
{
|
||||
$subschemasubentry = $info[0]['subschemasubentry'][0];
|
||||
$this->ldapServerInfo->setSubSchemaEntry($subschemasubentry);
|
||||
}
|
||||
|
||||
// create list of supported objetclasses
|
||||
if(!empty($subschemasubentry))
|
||||
{
|
||||
$filter='(objectclass=*)';
|
||||
$justthese = array('objectClasses');
|
||||
|
||||
if($sr=ldap_read($this->ds, $subschemasubentry, $filter, $justthese))
|
||||
{
|
||||
if($info = ldap_get_entries($this->ds, $sr))
|
||||
{
|
||||
if($info[0]['objectclasses']) {
|
||||
for($i=0; $i<$info[0]['objectclasses']['count']; $i++)
|
||||
{
|
||||
$pattern = '/^\( (.*) NAME \'(\w*)\' /';
|
||||
if(preg_match($pattern, $info[0]['objectclasses'][$i], $matches))
|
||||
{
|
||||
#_debug_array($matches);
|
||||
if(count($matches) == 3)
|
||||
{
|
||||
$supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->ldapServerInfo);
|
||||
}
|
||||
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $host, $supportedLDAPVersion);
|
||||
$this->saveSessionData();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
define('UNKNOWN_LDAPSERVER',0);
|
||||
define('OPENLDAP_LDAPSERVER',1);
|
||||
define('SAMBA4_LDAPSERVER',2);
|
||||
|
||||
/**
|
||||
* Class to store and retrieve information (eg. supported object classes) of a connected ldap server
|
||||
@ -140,4 +141,92 @@ class ldapserverinfo
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query given ldap connection for available information
|
||||
*
|
||||
* @param resource $ds
|
||||
* @param string $host
|
||||
* @param int $version 2 or 3
|
||||
* @return ldapserverinfo
|
||||
*/
|
||||
public static function get($ds, $host, $version=3)
|
||||
{
|
||||
$filter='(objectclass=*)';
|
||||
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry','vendorname');
|
||||
if(($sr = @ldap_read($ds, '', $filter, $justthese)))
|
||||
{
|
||||
if($info = ldap_get_entries($ds, $sr))
|
||||
{
|
||||
$ldapServerInfo = new ldapserverinfo($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':
|
||||
$ldapServerType = OPENLDAP_LDAPSERVER;
|
||||
break;
|
||||
default:
|
||||
$ldapServerType = UNKNOWN_LDAPSERVER;
|
||||
break;
|
||||
}
|
||||
$ldapServerInfo->setServerType($ldapServerType);
|
||||
}
|
||||
if ($info[0]['vendorname'] && stripos($info[0]['vendorname'][0], 'samba') !== false)
|
||||
{
|
||||
$ldapServerInfo->setServerType(SAMBA4_LDAPSERVER);
|
||||
}
|
||||
|
||||
// check for subschema entry dn
|
||||
if($info[0]['subschemasubentry'])
|
||||
{
|
||||
$subschemasubentry = $info[0]['subschemasubentry'][0];
|
||||
$ldapServerInfo->setSubSchemaEntry($subschemasubentry);
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
$pattern = '/^\( (.*) NAME \'(\w*)\' /';
|
||||
if(preg_match($pattern, $info[0]['objectclasses'][$i], $matches))
|
||||
{
|
||||
#_debug_array($matches);
|
||||
if(count($matches) == 3)
|
||||
{
|
||||
$supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ldapServerInfo;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user