mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-27 00:58:55 +01:00
* ActiveDirectory: fix account-selection type groupmembers (applies only to non-admins!) and ignore Domain Users group
not setting caseIgnoreMatch for sorting, as its not supported for Windows ActiveDirectory
This commit is contained in:
parent
5afe7ddbca
commit
9f9cce88b2
@ -246,6 +246,7 @@ class Accounts
|
|||||||
$members = array();
|
$members = array();
|
||||||
foreach((array)$this->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $grp)
|
foreach((array)$this->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $grp)
|
||||||
{
|
{
|
||||||
|
if (isset($this->backend->ignore_membership) && in_array($grp, $this->backend->ignore_membership)) continue;
|
||||||
$members = array_unique(array_merge($members, (array)$this->members($grp,true,$param['active'])));
|
$members = array_unique(array_merge($members, (array)$this->members($grp,true,$param['active'])));
|
||||||
if ($param['type'] == 'groupmembers+memberships') $members[] = $grp;
|
if ($param['type'] == 'groupmembers+memberships') $members[] = $grp;
|
||||||
}
|
}
|
||||||
@ -313,6 +314,7 @@ class Accounts
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* $options['filter']['group'] only return members of that group
|
* $options['filter']['group'] only return members of that group
|
||||||
* $options['account_type'] "accounts", "groups", "both" or "groupmembers"
|
* $options['account_type'] "accounts", "groups", "both" or "groupmembers"
|
||||||
|
* $options['tag_list'] true: return array of values for keys "value", "label" and "icon"
|
||||||
* @return array with id - title pairs of the matching entries
|
* @return array with id - title pairs of the matching entries
|
||||||
*/
|
*/
|
||||||
public static function link_query($pattern, array &$options = array())
|
public static function link_query($pattern, array &$options = array())
|
||||||
@ -367,8 +369,24 @@ class Accounts
|
|||||||
'order' => $order,
|
'order' => $order,
|
||||||
)) as $account)
|
)) as $account)
|
||||||
{
|
{
|
||||||
$accounts[$account['account_id']] = self::format_username($account['account_lid'],
|
$displayName = self::format_username($account['account_lid'],
|
||||||
$account['account_firstname'],$account['account_lastname'],$account['account_id']);
|
$account['account_firstname'],$account['account_lastname'],$account['account_id']);
|
||||||
|
|
||||||
|
if (!empty($options['tag_list']))
|
||||||
|
{
|
||||||
|
$accounts[] = [
|
||||||
|
'value' => $account['account_id'],
|
||||||
|
'label' => $displayName,
|
||||||
|
'icon' => Framework::link('/api/avatar.php', [
|
||||||
|
'account_id' => $account['account_id'],
|
||||||
|
'modified' => $account['account_modified'],
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$accounts[$account['account_id']] = $displayName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $accounts;
|
return $accounts;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,14 @@ class Ads
|
|||||||
*/
|
*/
|
||||||
const MIN_ACCOUNT_ID = 1000;
|
const MIN_ACCOUNT_ID = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore group-membership of following groups, when compiling group-members
|
||||||
|
*
|
||||||
|
* We ignore "Domain Users" group with RID 513, as it contains all users!
|
||||||
|
*
|
||||||
|
* @var int[]
|
||||||
|
*/
|
||||||
|
public $ignore_membership = [ -513 ];
|
||||||
/**
|
/**
|
||||||
* Timestamps ldap => egw used in several places
|
* Timestamps ldap => egw used in several places
|
||||||
*
|
*
|
||||||
@ -1081,6 +1088,20 @@ class Ads
|
|||||||
{
|
{
|
||||||
$type_filter .= $this->frontend->config['ads_user_filter'];
|
$type_filter .= $this->frontend->config['ads_user_filter'];
|
||||||
}
|
}
|
||||||
|
// for non-admins and account_selection "groupmembers" we have to filter by memberOf attribute
|
||||||
|
if ($GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] === 'groupmembers' &&
|
||||||
|
(!isset($GLOBALS['egw_info']['user']['apps']['admin'])))
|
||||||
|
{
|
||||||
|
$type_filter .= '(|';
|
||||||
|
foreach($GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $group_id)
|
||||||
|
{
|
||||||
|
if (!in_array($group_id, $this->ignore_membership) && ($dn = Api\Accounts::id2name($group_id, 'account_dn')))
|
||||||
|
{
|
||||||
|
$type_filter .= '(memberOf='.$dn.')(primaryGroupID='.abs($group_id).')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$type_filter .= ')';
|
||||||
|
}
|
||||||
$type_filter .= ')';
|
$type_filter .= ')';
|
||||||
if ($account_type === 'u') break;
|
if ($account_type === 'u') break;
|
||||||
$user_filter = $type_filter;
|
$user_filter = $type_filter;
|
||||||
@ -1103,9 +1124,11 @@ class Ads
|
|||||||
/**
|
/**
|
||||||
* Get value(s) for LDAP_CONTROL_SORTREQUEST
|
* Get value(s) for LDAP_CONTROL_SORTREQUEST
|
||||||
*
|
*
|
||||||
|
* Sorting by multiple criteria is supported in LDAP RFC 2891, but - at least with Univention Samba - gives wired results,
|
||||||
|
* Windows AD does NOT support it and gives an error if the oid is specified!
|
||||||
|
*
|
||||||
* @param ?string $order_by sql order string eg. "contact_email ASC"
|
* @param ?string $order_by sql order string eg. "contact_email ASC"
|
||||||
* @return array of arrays with values for keys 'attr', 'oid' (caseIgnoreMatch='2.5.13.3') and 'reverse'
|
* @return array of arrays with values for keys 'attr', 'oid' (caseIgnoreMatch='2.5.13.3') and 'reverse'
|
||||||
* @todo sorting by multiple criteria is supported in LDAP RFC 2891, but - at least with Univention - gives wired results
|
|
||||||
*/
|
*/
|
||||||
protected function sort_values($order_by)
|
protected function sort_values($order_by)
|
||||||
{
|
{
|
||||||
@ -1122,14 +1145,17 @@ class Ads
|
|||||||
}
|
}
|
||||||
elseif (($attr = array_search('account_'.$matches[2], $this->attributes2egw)))
|
elseif (($attr = array_search('account_'.$matches[2], $this->attributes2egw)))
|
||||||
{
|
{
|
||||||
$values[] = [
|
$value = [
|
||||||
'attr' => $attr,
|
'attr' => $mapping[$matches[2]],
|
||||||
'oid' => '2.5.13.3', // caseIgnoreMatch
|
'oid' => '2.5.13.3', // caseIgnoreMatch
|
||||||
'reverse' => strtoupper($matches[3]) === ' DESC',
|
'reverse' => strtoupper($matches[3]) === ' DESC',
|
||||||
];
|
];
|
||||||
|
// Windows AD does NOT support caseIgnoreMatch sorting, only it's default sorting
|
||||||
|
if ($this->serverinfo->activeDirectory(true)) unset($value['oid']);
|
||||||
|
$values[] = $value;
|
||||||
}
|
}
|
||||||
$order_by = substr($order_by, strlen($matches[0]));
|
$order_by = substr($order_by, strlen($matches[0]));
|
||||||
if ($values) break; // sorting by multiple criteria gives wired results
|
if ($values) break; // sorting by multiple criteria gives no result for Windows AD and wired result for Samba4
|
||||||
}
|
}
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ class Ads extends Ldap
|
|||||||
$filter = '';
|
$filter = '';
|
||||||
if ($gid < 0 && ($dn = $GLOBALS['egw']->accounts->id2name($gid, 'account_dn')))
|
if ($gid < 0 && ($dn = $GLOBALS['egw']->accounts->id2name($gid, 'account_dn')))
|
||||||
{
|
{
|
||||||
$filter .= '(memberOf='.$dn.')';
|
$filter .= '(|(memberOf='.$dn.')(primaryGroupID='.abs($gid).'))';
|
||||||
}
|
}
|
||||||
return $filter;
|
return $filter;
|
||||||
}
|
}
|
||||||
|
@ -1096,9 +1096,11 @@ class Ldap
|
|||||||
/**
|
/**
|
||||||
* Get value(s) for LDAP_CONTROL_SORTREQUEST
|
* Get value(s) for LDAP_CONTROL_SORTREQUEST
|
||||||
*
|
*
|
||||||
|
* Sorting by multiple criteria is supported in LDAP RFC 2891, but - at least with Univention Samba - gives wired results,
|
||||||
|
* Windows AD does NOT support it and gives an error if the oid is specified!
|
||||||
|
*
|
||||||
* @param ?string $order_by sql order string eg. "contact_email ASC"
|
* @param ?string $order_by sql order string eg. "contact_email ASC"
|
||||||
* @return array of arrays with values for keys 'attr', 'oid' (caseIgnoreMatch='2.5.13.3') and 'reverse'
|
* @return array of arrays with values for keys 'attr', 'oid' (caseIgnoreMatch='2.5.13.3') and 'reverse'
|
||||||
* @todo sorting by multiple criteria is supported in LDAP RFC 2891, but - at least with Univention - gives wired results
|
|
||||||
*/
|
*/
|
||||||
protected function sort_values($order_by)
|
protected function sort_values($order_by)
|
||||||
{
|
{
|
||||||
@ -1119,17 +1121,20 @@ class Ldap
|
|||||||
{
|
{
|
||||||
if (isset($mapping[$matches[2]]))
|
if (isset($mapping[$matches[2]]))
|
||||||
{
|
{
|
||||||
$values[] = [
|
$value = [
|
||||||
'attr' => $mapping[$matches[2]],
|
'attr' => $mapping[$matches[2]],
|
||||||
'oid' => '2.5.13.3', // caseIgnoreMatch
|
'oid' => '2.5.13.3', // caseIgnoreMatch
|
||||||
'reverse' => strtoupper($matches[3]) === ' DESC',
|
'reverse' => strtoupper($matches[3]) === ' DESC',
|
||||||
];
|
];
|
||||||
|
// Windows AD does NOT support caseIgnoreMatch sorting, only it's default sorting
|
||||||
|
if ($this->ldapServerInfo->activeDirectory(true)) unset($value['oid']);
|
||||||
|
$values[] = $value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$order_by = substr($order_by, strlen($matches[0]));
|
$order_by = substr($order_by, strlen($matches[0]));
|
||||||
if ($values) break; // sorting by multiple criteria gives wired results
|
if ($values) break; // sorting by multiple criteria gives no result for Windows AD and wired result for Samba4
|
||||||
}
|
}
|
||||||
//error_log(__METHOD__."('$order_by') returning ".json_encode($values));
|
//error_log(__METHOD__."('$order_by') returning ".json_encode($values));
|
||||||
return $values;
|
return $values;
|
||||||
|
@ -26,9 +26,13 @@ class ServerInfo
|
|||||||
*/
|
*/
|
||||||
const OPENLDAP = 1;
|
const OPENLDAP = 1;
|
||||||
/**
|
/**
|
||||||
* Samba4 LDAP server
|
* Samba4 Active Directory server
|
||||||
*/
|
*/
|
||||||
const SAMBA4 = 2;
|
const SAMBA4 = 2;
|
||||||
|
/**
|
||||||
|
* Windows Active Directory server
|
||||||
|
*/
|
||||||
|
const WINDOWS_AD = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $namingContext holds the supported namingcontexts
|
* @var array $namingContext holds the supported namingcontexts
|
||||||
@ -112,6 +116,16 @@ class ServerInfo
|
|||||||
$this->serverType = $_serverType;
|
$this->serverType = $_serverType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the DN for the subschema entry
|
* sets the DN for the subschema entry
|
||||||
*
|
*
|
||||||
@ -190,7 +204,7 @@ class ServerInfo
|
|||||||
public static function get($ds, $host, $version=3)
|
public static function get($ds, $host, $version=3)
|
||||||
{
|
{
|
||||||
$filter='(objectclass=*)';
|
$filter='(objectclass=*)';
|
||||||
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry','vendorname','supportedControl');
|
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry','vendorname','supportedControl','forestFunctionality');
|
||||||
if(($sr = @ldap_read($ds, '', $filter, $justthese)))
|
if(($sr = @ldap_read($ds, '', $filter, $justthese)))
|
||||||
{
|
{
|
||||||
if(($info = ldap_get_entries($ds, $sr)))
|
if(($info = ldap_get_entries($ds, $sr)))
|
||||||
@ -222,9 +236,11 @@ class ServerInfo
|
|||||||
}
|
}
|
||||||
$ldapServerInfo->setServerType($ldapServerType);
|
$ldapServerInfo->setServerType($ldapServerType);
|
||||||
}
|
}
|
||||||
if ($info[0]['vendorname'] && stripos($info[0]['vendorname'][0], 'samba') !== false)
|
// Check for ActiveDirectory by forestFunctionality and set Samba4 if vendorName includes samba
|
||||||
|
if(!empty($info[0]['forestfunctionality'][0]))
|
||||||
{
|
{
|
||||||
$ldapServerInfo->setServerType(self::SAMBA4);
|
$ldapServerInfo->setServerType(!empty($info[0]['vendorname']) && stripos($info[0]['vendorname'][0], 'samba') !== false ?
|
||||||
|
self::SAMBA4 : self::WINDOWS_AD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for subschema entry dn
|
// check for subschema entry dn
|
||||||
|
Loading…
Reference in New Issue
Block a user