yet another mod_shared_roster_ldap questions

I'm having issues with mod_shared_roster_ldap communicating with my Active Directory server. The IM server is communicating successfully with the AD server, users are authenticating properly, and queries seem to run appropriately (getting correct response of groups and users). However the client lists are not populating.

I'm sure there this is not an insurmountable problem, and at one point, I had this working. Unfortunately, probably due to an ejabberd update, it stopped working

. Here are the particulars of my
system:

Ubuntu 12.04.3 LTS (x86)
ejabberd v 2.1.10-2ubuntu1.1

My ejabberd.cfg file mod_shared_roster_ldap was primarily copied from http://lists.jabber.ru/pipermail/ejabberd/2013-August/008132.html, and looks like:
----ejabberd.cfg outtake-------------------------
{mod_shared_roster_ldap,[
% The next line may be redundant if you already have defined
% ldap_base at the higher level
{ldap_base, "cn=Users,dc=example,dc=com"},
% Disable, which is always added to the end.
{ldap_filter, ""},
{ldap_rfilter, "(&(objectclass=Group)(description=department))"},
% Here we take those objects taken in the previous step, examine this property,
% and build the list of unique strings that define your groups.
{ldap_groupattr, "cn"},
% This will look for users of a single group. It will be called for each group, with %g
% set to the name retrieved from above, e.g.
% "GHENRY Staff" from
% cn=GHENRY Staff,ou=Groups,dc=ghenry,dc=co,dc=uk
% It will give you the full list of users you want to see.
{ldap_gfilter, "(memberof=CN=%g,CN=Users,DC=example,DC=com)"},
% Where we get the roster item name from to show in the roster
{ldap_groupdesc, "mail"}, %this is requested from each user
{ldap_memberattr, "sAMAccountName"},
{ldap_memberattr_format, "CN=%u,CN=Users,DC=example,DC=com"},
% Use this to get the single user object
%{ldap_ufilter,
"(&(distinguishedName=%u)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"},
{ldap_ufilter, "distinguishedName=%u"},
% This holds the JID as per what we use to Auth
{ldap_useruid, "mail"},
% Use this to set the display name of the roster item
{ldap_userdesc, "cn"},
% Extra 'stuff'
%{ldap_auth_check, "off"},
{ldap_user_cache_validity, "10"},
{ldap_group_cache_validity, "10"}
]},
-------------------------------------

My ejabberd.log file queries the departments/groups and finds:
----ejabberd.log outtake-------------------------
=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=RYDD,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",
["RYDD"]}]}}

=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=RYDH,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",
["RYDH"]}]}}

=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=RYDP,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",
["RYDP"]}]}}

=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=RYDR,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",
["RYDR"]}]}}
-------------------------------------

That is great. It is finding the groups (RYDD, RYDH, RYDP, RYDR). Then it queries each of these, asking for the CN, the sAMAccountName, and mail:

----ejabberd.log outtake-------------------------
=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:696) : {searchRequest,
{'SearchRequest',"cn=Users,dc=example,dc=com",
wholeSubtree,neverDerefAliases,0,5,false,
{equalityMatch,
{'AttributeValueAssertion',"memberof",
"CN=RYDP,CN=Users,DC=example,DC=com"}},
["cn","mail","sAMAccountName"]}}

=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=Foo P. Bar,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",
["Foo P. Bar"]},
{'PartialAttributeList_SEQOF',
"sAMAccountName",
["barf"]},
{'PartialAttributeList_SEQOF',"mail",
["barf@example.com"]}]}}

=INFO REPORT==== 2014-08-12 17:36:36 ===
D(<0.548.0>:eldap:767) : {searchResEntry,
{'SearchResultEntry',
"CN=test,CN=Users,DC=example,DC=com",
[{'PartialAttributeList_SEQOF',"cn",["test"]},
{'PartialAttributeList_SEQOF',
"sAMAccountName",
["test"]},
{'PartialAttributeList_SEQOF',"mail",
["test@example.com"]}]}}
-------------------------------------

and so on...
According to my JID should be assigned to the mail (test@example.com).
However, nothing lists are populated in my client (Pidgin). I've tried so many different ways, I am not sure ejabberd is sending even the departments (RYDD, etc.) to the clients. I am fairly confident that isn't getting transmitted, and the people definitely are not getting transmitted.

Just for the sake of thoroughness, here is an example of my departments query using ldap:
-------------------------------------
me@sv10365:~/common_commands$ ldapsearch -x -h example.com -D "example\LDBD" -W -b 'CN=RYDP,CN=Users,DC=example,DC=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base with scope subtree # filter: (objectclass=*) # requesting: ALL #

# RYDP, Users, example.com
dn: CN=RYDP,CN=Users,DC=example,DC=com
objectClass: top
objectClass: group
cn: RYDP
description: department
member: CN=John M. User,CN=Users,DC=example,DC=com
member: CN=test,CN=Users,DC=example,DC=com
member: CN=Foo P. Bar,CN=Users,DC=example,DC=com
(and so on)
distinguishedName: CN=RYDP,CN=Users,DC=example,DC=com
instanceType: 4
whenCreated: 20140205181546.0Z
whenChanged: 20140811222923.0Z
uSNCreated: 324535
uSNChanged: 400395
name: RYDP
objectGUID:: GR+BQkGnj0igpvxBtBNDmA==
objectSid:: AQUAAAAAAAUVAAAAUctyIxK+e1oD4Ze5BgUAAA==
sAMAccountName: RYDP
sAMAccountType: 268435456
groupType: -2147483646
objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=example,DC=com
dSCorePropagationData: 16010101000000.0Z

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
-------------------------------------

And here is what a single user looks like:
-------------------------------------
me@sv10365:~/common_commands$ ldapsearch -x -h example.com -D "example\LDBD" -W -b 'CN=Foo P. Bar,CN=Users,DC=example,DC=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base with scope subtree # filter: (objectclass=*) # requesting: ALL #

# Foo P. Bar, Users, example.com
dn: CN=Foo P. Bar,CN=Users,DC=example,DC=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Foo P. Bar
sn: Bar
c: US
l: City
st: State
description: RYDP
postalCode: 12345
physicalDeliveryOfficeName: 2BG416
telephoneNumber: 123-456-7890
givenName: Fooinitials: P
distinguishedName: CN=Foo P. Bar,CN=Users,DC=example,DC=com
instanceType: 4
whenCreated: 20121030143417.0Z
whenChanged: 20140717135214.0Z
displayName: Foo P. Bar
uSNCreated: 106489
memberOf: CN=RYDP,CN=Users,DC=example,DC=com
memberOf: CN=IMgroup,CN=Users,DC=example,DC=com
memberOf: CN=unita,CN=Users,DC=example,DC=com
memberOf: CN=FMUsers,CN=Users,DC=example,DC=com
uSNChanged: 390025
co: Country
department: RYDP
company: AFRL
streetAddress: 123 Carroway
name: Foo P. Bar
objectGUID:: Pf8uudJzQkS4tgUWntC4Yg==
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 840
badPasswordTime: 130500972231505004
lastLogoff: 0
lastLogon: 130500972392811072
pwdLastSet: 130398125792384544
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAAUctyIxK+e1oD4Ze5kAQAAA==
accountExpires: 9223372036854775807
logonCount: 93
sAMAccountName: barf
sAMAccountType: 805306368
userPrincipalName: barf@example.com
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=example,DC=com
dSCorePropagationData: 16010101000000.0Z
lastLogonTimestamp: 130500787348108915
mail: barf@example.com

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
-------------------------------------

I think I am close because in the log, it seems to be querying everything properly and getting appropriate responses (to the best of my understanding). However it doesn't seem to be properly populating the lists that are sent to users. I assume that means it is not assigning a valid JID. Right now, I think the jid should be barf@example.com, although maybe it is just barf. I've tried the latter by connecting the JID to the sAMAccountName, but no difference is seen.

Any thoughts?

Thanks for all of your help (whomever "you" are).

See comments in the quote

See comments in the quote below.

bedfordr wrote:

----ejabberd.cfg outtake-------------------------
{mod_shared_roster_ldap,[
{ldap_base, "cn=Users,dc=example,dc=com"},
{ldap_filter, ""},
{ldap_rfilter, "(&(objectclass=Group)(description=department))"}, -> Well, you seem to get the list of groups that have string "department" as their description. OK.
{ldap_groupattr, "cn"},
{ldap_gfilter, "(memberof=CN=%g,CN=Users,DC=example,DC=com)"},-> Now you find users that belong to those groups. OK.
{ldap_groupdesc, "mail"}, )"},-> Now you get the users' mails as their group names. Is this OK? They will likely go to individual groups... Well, that's not gonna prevent it from working, fix later.
{ldap_memberattr, "sAMAccountName"},)"}, -> User name is in this attribute. OK.
{ldap_memberattr_format, "CN=%u,CN=Users,DC=example,DC=com"}, -> Here it is! You tell ejabberd that the string in sAMAccountName looks like "CN=%u,CN=Users,DC=example,DC=com", and ask it to only use what is in place of "%u". Buth that's not like that! You need to omit this param, or use just "%u" here!
{ldap_ufilter, "distinguishedName=%u"}, -> This won't work either. There's no user that has DN that looks like "barf" or "test".
{ldap_useruid, "mail"}, -> This has to be sAMAccountName. Maybe there's something different now, but in some versions there had been a check that this value is the same as in ldap_memberattr.
{ldap_userdesc, "cn"},
{ldap_user_cache_validity, "10"},
{ldap_group_cache_validity, "10"}
]},
-------------------------------------

My goodness, @mikekaganski!

My goodness, @mikekaganski! It seems you're onto something! Every time I look at the documentation, I understand the purpose of each line differently. I settled on all of the above based on the feedback from the ldap, and trying to get the components to return (ldap_groupdesc, ldap_memberattr, ldap_groupattr, I guess). Clearly that was an incomplete understanding. Based on your description, I think I understand what is going on.

First, I thought the process went as follows:

  1. Search for groups and find members in that group
  2. Query each member of group (e.g. "RYDP") and get their JID and User Description
  3. Assign each of these query members to the group query (e.g. "RYDP")

Instead, the process seems to be:

  1. Search for groups and find members in that group
  2. Query each member of group (e.g. "RYDP") and get their JID and User Description and Group affiliation (again, need "RYDP")
  3. Assign each of these query members to their affiliation (e.g. "RYDP" in the above example)

My only annoyance is that because I have to query each user's affiliation (even after I search for the memberof), I have to retain their affiliation in two places (one in a group assignment, and one in a 'department'). I can't say I really understand this process, but for now, it seems to be populating properly.

Here is what my working mod_shared_roster_ldap now looks like:

{mod_shared_roster_ldap,[
{ldap_base, "cn=Users,dc=opto,dc=lab"},
{ldap_filter, ""},
{ldap_rfilter, "(&(objectclass=Group)(description=department))"},
{ldap_groupattr, "cn"},
{ldap_gfilter, "(memberof=CN=%g,CN=Users,DC=opto,DC=lab)"},
{ldap_groupdesc, "department"}, %this is requested from each user
{ldap_memberattr, "sAMAccountName"},
{ldap_useruid, "sAMAccountName"},
{ldap_userdesc, "cn"},
{ldap_user_cache_validity, "10"},
{ldap_group_cache_validity, "10"}
]},

Thank you for your help!

Syndicate content