mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-25 08:09:02 +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)
|
* 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(),
|
* All values used to construct filters need to run through ldap::quote(),
|
||||||
* to be save against LDAP query injection!!!
|
* 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
|
class addressbook_ads extends addressbook_ldap
|
||||||
{
|
{
|
||||||
@ -37,6 +40,13 @@ class addressbook_ads extends addressbook_ldap
|
|||||||
*/
|
*/
|
||||||
var $accountsFilter = '(objectclass=user)';
|
var $accountsFilter = '(objectclass=user)';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for DN
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $dn_attribute='cn';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accounts ADS object
|
* Accounts ADS object
|
||||||
*
|
*
|
||||||
@ -44,6 +54,14 @@ class addressbook_ads extends addressbook_ldap
|
|||||||
*/
|
*/
|
||||||
protected $accounts_ads;
|
protected $accounts_ads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ADS is Samba4 (true), otherwise false
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
public $is_samba4 = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constructor of the class
|
* constructor of the class
|
||||||
*
|
*
|
||||||
@ -78,6 +96,7 @@ class addressbook_ads extends addressbook_ldap
|
|||||||
$this->connect();
|
$this->connect();
|
||||||
}
|
}
|
||||||
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $this->ldap_config['ads_host']);
|
$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
|
// AD seems to use user, instead of inetOrgPerson
|
||||||
$this->schema2egw['user'] = $this->schema2egw['inetorgperson'];
|
$this->schema2egw['user'] = $this->schema2egw['inetorgperson'];
|
||||||
@ -106,6 +125,25 @@ class addressbook_ads extends addressbook_ldap
|
|||||||
$this->ds = $this->accounts_ads->ldap_connection();
|
$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
|
* 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));
|
$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 = $GLOBALS['egw']->accounts->id2name($account_id, 'person_id');
|
||||||
}
|
}
|
||||||
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
|
$contact_id = !is_array($contact_id) ? $contact_id :
|
||||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
|
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']);
|
||||||
|
|
||||||
$rows = $this->_searchLDAP($this->allContactsDN, "(objectguid=$contact_id)", $this->all_attributes, ADDRESSBOOK_ALL);
|
|
||||||
|
|
||||||
|
$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;
|
return $rows ? $rows[0] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,4 +185,19 @@ class addressbook_ads extends addressbook_ldap
|
|||||||
|
|
||||||
$this->_inetorgperson2egw($contact, $data);
|
$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;
|
var $allContactsDN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for DN
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $dn_attribute='uid';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int $total holds the total count of found rows
|
* @var int $total holds the total count of found rows
|
||||||
*/
|
*/
|
||||||
@ -237,6 +244,13 @@ class addressbook_ldap
|
|||||||
*/
|
*/
|
||||||
private $ldap_config;
|
private $ldap_config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDAP connection
|
||||||
|
*
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
var $ds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constructor of the class
|
* constructor of the class
|
||||||
*
|
*
|
||||||
@ -256,10 +270,10 @@ class addressbook_ldap
|
|||||||
{
|
{
|
||||||
$this->ldap_config =& $GLOBALS['egw_info']['server'];
|
$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->accountContactsDN = $this->ldap_config['ldap_context'];
|
||||||
$this->allContactsDN = $this->ldap_config['ldap_contact_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)
|
if ($ds)
|
||||||
{
|
{
|
||||||
@ -303,7 +317,7 @@ class addressbook_ldap
|
|||||||
elseif (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-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_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();
|
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -340,6 +354,37 @@ class addressbook_ldap
|
|||||||
return array_values(array_unique($fields));
|
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
|
* reads contact data
|
||||||
*
|
*
|
||||||
@ -355,16 +400,30 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
|
if (is_array($contact_id)) $contact_id = isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid'];
|
||||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
|
$filter = $this->id_filter($contact_id);
|
||||||
$filter = "(|(entryUUID=$contact_id)(uid=$contact_id))";
|
|
||||||
}
|
}
|
||||||
$rows = $this->_searchLDAP($this->ldap_config['ldap_contact_context'],
|
$rows = $this->_searchLDAP($this->allContactsDN,
|
||||||
$filter, $this->all_attributes, ADDRESSBOOK_ALL);
|
$filter, $this->all_attributes, ADDRESSBOOK_ALL);
|
||||||
|
|
||||||
return $rows ? $rows[0] : false;
|
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
|
* saves the content of data to the db
|
||||||
*
|
*
|
||||||
@ -403,7 +462,7 @@ class addressbook_ldap
|
|||||||
$baseDN = $this->accountContactsDN;
|
$baseDN = $this->accountContactsDN;
|
||||||
$cn = false;
|
$cn = false;
|
||||||
// we need an admin connection
|
// 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!
|
// 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')
|
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']);
|
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!
|
return lang('Permission denied !!!'); // only admin or the user itself is allowd to write accounts!
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if $baseDN exists. If not create it
|
// check if $baseDN exists. If not create it
|
||||||
if (($err = $this->_check_create_dn($baseDN)))
|
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
|
// check the existing objectclasses of an entry, none = array() for new ones
|
||||||
$oldObjectclasses = array();
|
$oldObjectclasses = array();
|
||||||
$attributes = array('dn','cn','objectClass','uid','mail');
|
$attributes = array('dn','cn','objectClass',$this->dn_attribute,'mail');
|
||||||
|
|
||||||
$contactUID = $this->data[$this->contacts_id];
|
$contactUID = $this->data[$this->contacts_id];
|
||||||
if(!empty($contactUID) &&
|
if (!empty($contactUID) &&
|
||||||
($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
|
($result = ldap_search($this->ds, $base=$this->allContactsDN, $filter=$this->id_filter($contactUID), $attributes)) &&
|
||||||
'(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes)) &&
|
|
||||||
($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count'])
|
($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count'])
|
||||||
{
|
{
|
||||||
unset($oldContactInfo[0]['objectclass']['count']);
|
unset($oldContactInfo[0]['objectclass']['count']);
|
||||||
@ -438,13 +496,12 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
$isUpdate = true;
|
$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));
|
||||||
}
|
}
|
||||||
|
//error_log(__METHOD__."() contactUID='$contactUID', isUpdate=".array2string($isUpdate).", oldContactInfo=".array2string($oldContactInfo));
|
||||||
$ldapContact['uid'] = $contactUID;
|
|
||||||
|
|
||||||
// add for all supported objectclasses the objectclass and it's attributes
|
// add for all supported objectclasses the objectclass and it's attributes
|
||||||
foreach($this->schema2egw as $objectclass => $mapping)
|
foreach($this->schema2egw as $objectclass => $mapping)
|
||||||
{
|
{
|
||||||
@ -484,7 +541,7 @@ class addressbook_ldap
|
|||||||
$this->$egw2objectclass($ldapContact,$data,$isUpdate);
|
$this->$egw2objectclass($ldapContact,$data,$isUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($isUpdate)
|
if ($isUpdate)
|
||||||
{
|
{
|
||||||
// make sure multiple email-addresses in the mail attribute "survive"
|
// make sure multiple email-addresses in the mail attribute "survive"
|
||||||
if (isset($ldapContact['mail']) && $oldContactInfo[0]['mail']['count'] > 1)
|
if (isset($ldapContact['mail']) && $oldContactInfo[0]['mail']['count'] > 1)
|
||||||
@ -497,9 +554,6 @@ class addressbook_ldap
|
|||||||
// update entry
|
// update entry
|
||||||
$dn = $oldContactInfo[0]['dn'];
|
$dn = $oldContactInfo[0]['dn'];
|
||||||
$needRecreation = false;
|
$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
|
// add missing objectclasses
|
||||||
if($ldapContact['objectClass'] && array_diff($ldapContact['objectClass'],$oldObjectclasses))
|
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
|
// 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;
|
$newDN = $newRDN .','. $baseDN;
|
||||||
if(strtolower($dn) != strtolower($newDN) || $needRecreation)
|
if ($needRecreation)
|
||||||
{
|
{
|
||||||
$result = ldap_read($this->ds, $dn, 'objectclass=*');
|
$result = ldap_read($this->ds, $dn, 'objectclass=*');
|
||||||
$oldContact = ldap_get_entries($this->ds, $result);
|
$oldContact = ldap_get_entries($this->ds, $result);
|
||||||
@ -536,7 +590,7 @@ class addressbook_ldap
|
|||||||
$newContact[$key] = $value;
|
$newContact[$key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$newContact['uid'] = $contactUID;
|
$newContact[$this->dn_attribute] = $ldapContact[$this->dn_attribute];
|
||||||
|
|
||||||
if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0)
|
if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0)
|
||||||
{
|
{
|
||||||
@ -559,7 +613,21 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
$dn = $newDN;
|
$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))
|
if (!@ldap_modify($this->ds, $dn, $ldapContact))
|
||||||
{
|
{
|
||||||
@ -571,7 +639,7 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
else
|
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
|
unset($ldapContact['entryuuid']); // trying to write it, gives an error
|
||||||
|
|
||||||
if (!@ldap_add($this->ds, $dn, $ldapContact))
|
if (!@ldap_add($this->ds, $dn, $ldapContact))
|
||||||
@ -608,7 +676,7 @@ class addressbook_ldap
|
|||||||
foreach($keys as $entry)
|
foreach($keys as $entry)
|
||||||
{
|
{
|
||||||
$entry = ldap::quote(is_array($entry) ? $entry['id'] : $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))
|
"(|(entryUUID=$entry)(uid=$entry))", $attributes))
|
||||||
{
|
{
|
||||||
$contactInfo = ldap_get_entries($this->ds, $result);
|
$contactInfo = ldap_get_entries($this->ds, $result);
|
||||||
@ -715,6 +783,11 @@ class addressbook_ldap
|
|||||||
$searchFilter = '';
|
$searchFilter = '';
|
||||||
foreach($criteria as $egwSearchKey => $searchValue)
|
foreach($criteria as $egwSearchKey => $searchValue)
|
||||||
{
|
{
|
||||||
|
if (in_array($egwSearchKey, array('id','contact_id')))
|
||||||
|
{
|
||||||
|
$searchFilter .= $this->ids_filter($searchValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
foreach($this->schema2egw as $mapping)
|
foreach($this->schema2egw as $mapping)
|
||||||
{
|
{
|
||||||
if(($ldapSearchKey = $mapping[$egwSearchKey]))
|
if(($ldapSearchKey = $mapping[$egwSearchKey]))
|
||||||
@ -736,7 +809,6 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
$colFilter = $this->_colFilter($filter);
|
$colFilter = $this->_colFilter($filter);
|
||||||
$ldapFilter = "(&$objectFilter$searchFilter$colFilter)";
|
$ldapFilter = "(&$objectFilter$searchFilter$colFilter)";
|
||||||
|
|
||||||
if (!($rows = $this->_searchLDAP($searchDN, $ldapFilter, $this->all_attributes, $addressbookType)))
|
if (!($rows = $this->_searchLDAP($searchDN, $ldapFilter, $this->all_attributes, $addressbookType)))
|
||||||
{
|
{
|
||||||
return $rows;
|
return $rows;
|
||||||
@ -849,6 +921,11 @@ class addressbook_ldap
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'id':
|
||||||
|
case 'contact_id':
|
||||||
|
$filter .= $this->ids_filter($value);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!is_int($key))
|
if (!is_int($key))
|
||||||
{
|
{
|
||||||
@ -1020,7 +1097,7 @@ class addressbook_ldap
|
|||||||
/**
|
/**
|
||||||
* check if $baseDN exists. If not create it
|
* 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
|
* @return boolean/string false on success or string with error-message
|
||||||
*/
|
*/
|
||||||
function _check_create_dn($baseDN)
|
function _check_create_dn($baseDN)
|
||||||
@ -1042,8 +1119,8 @@ class addressbook_ldap
|
|||||||
|
|
||||||
list(,$ou) = explode(',',$baseDN);
|
list(,$ou) = explode(',',$baseDN);
|
||||||
foreach(array(
|
foreach(array(
|
||||||
'ou=contacts,'.$this->ldap_config['ldap_contact_context'],
|
'ou=contacts,'.$this->allContactsDN,
|
||||||
$ou.',ou=contacts,'.$this->ldap_config['ldap_contact_context'],
|
$ou.',ou=contacts,'.$this->allContactsDN,
|
||||||
$baseDN,
|
$baseDN,
|
||||||
) as $dn)
|
) 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
|
* @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/user-attributes-w2k8.htm
|
||||||
* @link http://www.selfadsi.org/attributes-e2k7.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
|
class accounts_ads
|
||||||
{
|
{
|
||||||
@ -298,6 +299,17 @@ class accounts_ads
|
|||||||
return $this->adldap->utilities()->decodeGuid(is_array($objectguid) ? $objectguid[0] : $objectguid);
|
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
|
* Reads the data of one account
|
||||||
*
|
*
|
||||||
@ -841,6 +853,8 @@ class accounts_ads
|
|||||||
}
|
}
|
||||||
if ($param['type'] == 'groups' || $param['type'] == 'both')
|
if ($param['type'] == 'groups' || $param['type'] == 'both')
|
||||||
{
|
{
|
||||||
|
$query = ldap::quote(strtolower($param['query']));
|
||||||
|
|
||||||
$filter = null;
|
$filter = null;
|
||||||
if(!empty($query) && $query != '*')
|
if(!empty($query) && $query != '*')
|
||||||
{
|
{
|
||||||
|
@ -193,83 +193,7 @@ class ldap
|
|||||||
//error_log("no ldap server info found");
|
//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']);
|
$ldapbind = @ldap_bind($this->ds, $GLOBALS['egw_info']['server']['ldap_root_dn'], $GLOBALS['egw_info']['server']['ldap_root_pw']);
|
||||||
|
|
||||||
$filter='(objectclass=*)';
|
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $host, $supportedLDAPVersion);
|
||||||
$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->saveSessionData();
|
$this->saveSessionData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
define('UNKNOWN_LDAPSERVER',0);
|
define('UNKNOWN_LDAPSERVER',0);
|
||||||
define('OPENLDAP_LDAPSERVER',1);
|
define('OPENLDAP_LDAPSERVER',1);
|
||||||
|
define('SAMBA4_LDAPSERVER',2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to store and retrieve information (eg. supported object classes) of a connected ldap server
|
* Class to store and retrieve information (eg. supported object classes) of a connected ldap server
|
||||||
@ -140,4 +141,92 @@ class ldapserverinfo
|
|||||||
}
|
}
|
||||||
return false;
|
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