Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions apps/user_ldap/lib/Group_LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,34 @@ public function inGroup($uid, $gid) {
return false;
}

if(strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'zimbramailforwardingaddress') {
// array containing domains
$dns = array();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these days you can use short notation $dns = []; :)

// loop througth array members
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

foreach($members as $mailOfMember) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this can take a lot of time on big groups with many members. Do you think it is possible to use the provided $uid attribute and attempt to look up the user directly?

// split the email of each member eg. [email protected]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intendentation here and the following four lines appears wrong

// once splitted ['member_name', 'zimbra.com'];
$memberEmailParts = explode("@", $mailOfMember);
// get the first part of email
$memberEmailName = $memberEmailParts[0];
// (&(&(objectclass=zimbraAccount)(!(objectclass=zimbraCalendarResource))(!(zimbraHideInGal=TRUE))(zimbraAccountStatus=active))(|(uid=%uid)(|(mailPrimaryAddress=%uid)(mail=%uid))))
// with the query above we need to replace each %uid for our $memberEmailName
// once replaced is done, we have this: assuming our $memberEmailName = "johuder"
// (&(&(objectclass=zimbraAccount)(!(objectclass=zimbraCalendarResource))(!(zimbraHideInGal=TRUE))(zimbraAccountStatus=active))(|(uid=johuder)(|(mailPrimaryAddress=johuder)(mail=johuder))))
$filter = str_replace('%uid', $memberEmailName, $this->access->connection->ldapLoginFilter);
// request query to LDAP
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn');
if(count($ldap_users) < 1) {
// if is not found any user, continue to the next user in the foreach loop
continue;
}
// if user were found, we push it into the array result
array_push($dns, $ldap_users[0]);
}
// update the last value in $members with the found users.
$members = $dns;
}

//extra work if we don't get back user DNs
if(strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'memberuid') {
$dns = array();
Expand Down Expand Up @@ -642,7 +670,21 @@ public function getUserGroups($uid) {
);
if ($userMatch !== false) {
// match found so this user is in this group
$pos = strpos($dynamicGroup['dn'][0], ',');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you test this against groups having a , in their cn?

//assuming $dynamicGroup['dn'][0] has: cn=myGroup,ou=people,dc=domain,dc=com
// we look for the first , into the string, in the string above
// $pos variable will contain 10
if ($pos !== false) {
$membershipGroup = substr($dynamicGroup['dn'][0], 3, $pos - 3);
// we need to extract the group name
// so we extracted from cn=myGroup,ou=people,dc=domain,dc=com
// we extract from position 3 to 7 in the string above, so we have: myGroup
$groups[] = $membershipGroup;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be dealt with $this->access->dn2groupname, because we rely on mappings here and avoid name collisions (e.g. with groups from other backends). Adding the group just like this won't have it mapped and further operations against this group might not work.

// then we add the group found to the array groups
}

$groupName = $this->access->dn2groupname($dynamicGroup['dn'][0]);

if(is_string($groupName)) {
// be sure to never return false if the dn could not be
// resolved to a name, for whatever reason.
Expand Down Expand Up @@ -697,6 +739,11 @@ public function getUserGroups($uid) {
$this->access->connection->ldapHost, \OCP\Util::DEBUG);
}
$uid = $result[0];
} else if(strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'zimbramailforwardingaddress'){
// if ldapGroupMemberAssocAttr match with zimbramailforwardingaddress
// we look into the zimbra LDAP
$result = $this->access->readAttribute($userDN, 'uid');
$uid = $result[0].'@*';
} else {
// just in case
$uid = $userDN;
Expand Down Expand Up @@ -814,6 +861,7 @@ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {

$groupUsers = array();
$isMemberUid = (strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'memberuid');
$isZimbraUid = (strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'zimbramailforwardingaddress');
$attrs = $this->access->userManager->getAttributes(true);
foreach($members as $member) {
if($isMemberUid) {
Expand All @@ -827,6 +875,26 @@ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
continue;
}
$groupUsers[] = $this->access->dn2username($ldap_users[0]['dn'][0]);
} else if($isZimbraUid) {
// if our LDAP config point to zimbra platform
$memberParts = explode('@', $member);
// extract the first part of email member
$member = $memberParts[0];

// replace all '%uid' with the value of $member and get the filter query
$filter = $this->access->combineFilterWidthAnd(array(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in method name, it should be combineFilterWithAnd

\OCP\Util::mb_str_replace('%uid', $member,
$this->access->connection->ldapLoginFilter, 'UTF-8'),
$this->access->getFilterPartForUserSearch($search)
));
// exec the query we got above
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn');
// if we not found any user, let's continue
if (count($ldap_users) < 1) {
continue;
}
// if we found the user, add it to the array
$groupUsers[] = $this->access->dn2username($ldap_users[0]);
} else {
//we got DNs, check if we need to filter by search or we can give back all of them
if ($search !== '') {
Expand Down
7 changes: 5 additions & 2 deletions apps/user_ldap/lib/Wizard.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,12 +776,15 @@ private function checkHost() {

/**
* tries to detect the group member association attribute which is
* one of 'uniqueMember', 'memberUid', 'member', 'gidNumber'
* one of 'uniqueMember', 'memberUid', 'member', 'gidNumber',
* 'zimbramailforwardingaddress'
* @return string|false, string with the attribute name, false on error
* @throws \Exception
*/
private function detectGroupMemberAssoc() {
$possibleAttrs = array('uniqueMember', 'memberUid', 'member', 'gidNumber');
// add the new zimbramailforwardingaddress option for zimbra LDAP support
$possibleAttrs = array('uniqueMember', 'memberUid', 'member', 'gidNumber',
'zimbramailforwardingaddress');
$filter = $this->configuration->ldapGroupFilter;
if(empty($filter)) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion apps/user_ldap/templates/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
<p><label for="ldap_group_display_name"><?php p($l->t('Group Display Name Field'));?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" data-default="<?php p($_['ldap_group_display_name_default']); ?>" title="<?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?>" /></p>
<p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" title="<?php p($l->t('Base Group Tree'));?>"></textarea></p>
<p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" title="<?php p($l->t('Group Search Attributes'));?>"></textarea></p>
<p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) p(' selected'); ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) p(' selected'); ?>>memberUid</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) p(' selected'); ?>>member (AD)</option><option value="gidNumber"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'gidNumber')) p(' selected'); ?>>gidNumber</option></select></p> <p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /></p>
<p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) p(' selected'); ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) p(' selected'); ?>>memberUid</option><option value="zimbraMailForwardingAddress"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'zimbraMailForwardingAddress')) p(' selected'); ?>>zimbraMailForwardingAddress</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) p(' selected'); ?>>member (AD)</option><option value="gidNumber"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'gidNumber')) p(' selected'); ?>>gidNumber</option></select></p> <p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /></p>
<p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /></p>
<p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /></p>
<p><label for="ldap_turn_on_pwd_change"><?php p($l->t('Enable LDAP password changes per user'));?></label><span class="inlinetable"><span class="tablerow left"><input type="checkbox" id="ldap_turn_on_pwd_change" name="ldap_turn_on_pwd_change" value="1" data-default="<?php p($_['ldap_turn_on_pwd_change_default']); ?>" title="<?php p($l->t('Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server.'));?>" /><span class="tablecell"><?php p($l->t('(New password is sent as plain text to LDAP)'));?></span></span>
Expand Down