mod_shared_roster_ldap - LDAP Shared Roster Management

This module is included in ejabberd since the release of ejabberd 2.1.6.

Name: mod_shared_roster_ldap
Purpose: LDAP shared roster management
Author: Marcin Owsiany (porridge), Evgeniy Khramtsov and Realloc
Type: Module
Requirements:
Download: integrated into the proper ejabberd distribution

For historical information only (outdated): ejabberd-msrl project, documentation for old releases, an early mod_shared_roster_ldap.erl file.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Попробуйте описать фильтр

Попробуйте описать фильтр следующим образом:
(&(postalAddress)|(postOfficeBox))"},
Подробнее тут

Use with AD

I am unable to get mod_shared_roster_ldap working properly with Active Directory.

I am able to get it to query my user objects for sAMAccountName to find the user objects but each user is in his/her own roster group.

Can the module put all users in a single static roster group or somehow look to the OU for roster group name?

You'd need an attribute whose

You'd need an attribute whose value is the same across all your users.

ldap_userdesc - multiple attributes?

I would like the roster to be displayed as:

FirstName LastName

Where Firstname=givenName and LastName=sn in an LDAP directory.

I don't see any way that I can specify multiple attributes to ldap_userdesc. Any suggestions?

Static AD Group Roster

I have found many issues with configuring dynamic AD groups for population of shared rosters. Seems that the features required to resolve CN's to SamAccountnames is not working or cannot be filtered within the module. However I have yet to find just a simple single static group setup for AD that would just query a single group, or even just pull all the users from an OU, and populate a shared roster. Does anyone have any examples or a similar idea?

conf doesnt work for my ldap case

Hello everyone,

I am really confused to get mod_share_roster_ldap to work on my server. I am running Version 2.1.6 of ejabberd and wrote my mod conf as quoted below:

  {mod_shared_roster_ldap,[
  {ldap_base, "dc=mydomain,dc=com"},
  {ldap_rfilter, "(objectClass=posixGroup)"},
  {ldap_filter, ""},
  {ldap_gfilter, "(&(objectClass=posixGroup)(cn=%g))"},
  {ldap_groupdesc, "description"},
  {ldap_memberattr, "memberUid"},
  {ldap_memberattr_format, "memberUid=%u"},
  {ldap_ufilter, "(&(objectClass=inetOrgPerson)(uid=%u))"},
  {ldap_userdesc, "displayName"}
  ]},

My Directory looks like this:

dc=mydomain,dc=com

>ou=groups

>>ou=orga

>>>cn=office1

description=User of office1
objectClass=posixgroup
memberUid=user1
memberUid=user2

>>>cn=office2

description=User of office2
objectClass=posixgroup
memberUid=user3

>ou=people

>>uid=user1

displayName=John Smith
objectClass=inetOrgPerson

>>uid=user2

displayName=Peter Smith
objectClass=inetOrgPerson

>>uid=user3

displayName=Michael Smith
objectClass=inetOrgPerson

Can anyone help me with the right configuration. My brain is overheating at this moment. :)
I'd prefer to get all Users in office1 in one shared roster. office2 is not supposed to have a shared roster.

Thanks.

try removing format

Try removing the following:

bademeister wrote:
  {ldap_memberattr_format, "memberUid=%u"},

or set it to "%u"

Hey, thanks for the response.

Hey,

thanks for the response. Didn't see it till now. I tried it out. Didn't work for me.
Guess I have to spend a lot more time with LDAP. :)

Registered Users List from LDAP in database, not in clients

Hello everyone,

I've been beating my head against the keyboard for a couple of days on this, and I think it is time to ask for help. I am running ejabberd 2.1.6 with ldap auth and mod_shared_roster_ldap. I am using a Windows 2008 AD backend. ldap auth is working and I can login via the client and chat, get presence, etc.

The issue is the roster. I see no groups or users. I have set the log level to 5 and can see the ldap queries grabbing a list of ldap groups, and then enumerating users out of these groups. When I run the command ejabberdctl registered-users "domain.com" I get a list of all of my users. I'm stumped as to why this isn't working!

Here are some relevant sections of my config:

{auth_method, ldap}.
{ldap_servers, ["kxdc01", "kxdc02"]}.
{ldap_port, 3268}.
{ldap_uids, [{"sAMAccountName"}]}.
{ldap_filter, "(memberOf=*)"}.
{ldap_base, "dc=domain,dc=com"}.
{ldap_rootdn, "svn.authenticator@domain.com"}.
{ldap_password, "************"}.
{host_config, "domain.com", [{auth_method, ldap}]}.

.........

{mod_shared_roster_ldap, [
        {ldap_servers, ["kxdc01"]},
        {ldap_port, 3268},
        {ldap_encrypt, none},
        {ldap_rootdn, "svn.authenticator@domain.com"},
        {ldap_password, "*************"},
        {ldap_base, "CN=Users,DC=domain,DC=com"},
        {ldap_auth_check, off},
        {ldap_user_cache_validity, 10},
        {ldap_group_cache_validity, 10},
        {ldap_rfilter, "(&(objectClass=group)(|(cn=Finance)(cn=Systems)(cn=Executives)
(cn=Account Services)(cn=Coaching)(cn=Creative)(cn=Business Development)))"},
        {ldap_groupattr, "cn"},
        {ldap_filter, ""},
        {ldap_gfilter, "(&(objectClass=group)(CN=%g))"},
        {ldap_groupdesc, "name"},
        {ldap_memberattr, "member"},
        {ldap_memberattr_format, "CN=%u,CN=Users,DC=domain,DC=com"},
        {ldap_ufilter, "(&(objectClass=user)(CN=%u))"},
        {ldap_useruid, "sAMAccountName"},
        {ldap_userdesc, "displayName"}
  ]},

Some output from the log file:

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:675) : {searchRequest,
                          {'SearchRequest',"CN=Users,DC=domain,DC=com",
                           wholeSubtree,neverDerefAliases,0,5,false,
                           {'and',
                            [{equalityMatch,
                              {'AttributeValueAssertion',"objectClass",
                               "group"}},
                             {'or',
                              [{equalityMatch,
                                {'AttributeValueAssertion',"cn","Finance"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn","Systems"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn","Executives"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn",
                                 "Account Services"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn","Coaching"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn","Creative"}},
                               {equalityMatch,
                                {'AttributeValueAssertion',"cn",
                                 "Business Development"}}]}]},
                           ["cn"]}}


=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Finance,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Finance"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Systems,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Systems"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Executives,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Executives"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Account Services,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Account Services"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Coaching,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Coaching"]}]}}


=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Creative,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Creative"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Business Development,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Business Development"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResDone,
                             {'LDAPResult',success,[],[],asn1_NOVALUE}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:675) : {searchRequest,
                          {'SearchRequest',"CN=Users,DC=domain,DC=com",
                           wholeSubtree,neverDerefAliases,0,5,false,
                           {'and',
                            [{equalityMatch,
                              {'AttributeValueAssertion',"objectClass",
                               "group"}},
                             {equalityMatch,
                              {'AttributeValueAssertion',"CN",
                               "Account Services"}}]},
                           ["cn","name","member"]}}


=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResEntry,
                             {'SearchResultEntry',
                                 "CN=Account Services,CN=Users,DC=domain,DC=com",
                                 [{'PartialAttributeList_SEQOF',"cn",
                                      ["Account Services"]},
                                  {'PartialAttributeList_SEQOF',"member",
                                      ["CN=Tori Wadzita,CN=Users,DC=domain,DC=com",
                                       "CN=Melissa Rasmussen,CN=Users,DC=domain,DC=com",
                                       "CN=Erin Keegan,CN=Users,DC=domain,DC=com",
                                       "CN=Cynthia Marias,CN=Users,DC=domain,DC=com",
                                       "CN=Claire Reinert,CN=Users,DC=domain,DC=com"]},
                                  {'PartialAttributeList_SEQOF',"name",
                                      ["Account Services"]}]}}

=INFO REPORT==== 2010-12-30 22:44:00 ===
D(<0.365.0>:eldap:746) : {searchResDone,
                             {'LDAPResult',success,[],[],asn1_NOVALUE}}

etc etc etc etc etc

Output from ejabberdctl:

# ejabberdctl registered-users domain.com

=INFO REPORT==== 31-Dec-2010::01:31:04 ===
D(<4837.404.0>:ejabberd_commands:314) : Executing command ejabberd_admin:registered_users 
with Args=["domain.com"]
** at node ejabberd@localhost **
aaron.dixon
administrator
amanda.schaer
ben.reid
calvin.buhler
camille.primous
caresse.schaff
claire.reinert
cynthia.marias
darshan.bugeaud
deb.king
emily.isett
erin.keegan
gerry.bernabe
greg.toledo
hannah.schultz
heather.gray
heather.mcdermott
hollyce.snyder
jack.valko
james.kaing
james.wojinski
jamie.brunner
jeff.hart
jenny.zenner
jeremy.kinney
john.chorlton
justin.white
kamie.callen
kelsey.teel
krbtgt
laurel.trujillo
lisa.bartel
lou.maxon
maggie.tonkin
marcie.aker
meagan.brunner
melissa.rasmussen
mike.viles
phillip.sherman
printuser
rich.finlay
ryan.dixon
sibyl.adams
svn.authenticator
teresa.greiner
terry.brashem
test.user
thor.radford
tori.wadzita

Any help would be great. Thanks!!

Jack

user IDs are not valid nodenames

Hi Jack,

Thanks for the clear and complete debugging information.

jackvalko wrote:

Hello everyone,

I've been beating my head against the keyboard for a couple of days on this, and I think it is time to ask for help. I am running ejabberd 2.1.6 with ldap auth and mod_shared_roster_ldap. I am using a Windows 2008 AD backend. ldap auth is working and I can login via the client and chat, get presence, etc.

The issue is the roster. I see no groups or users. I have set the log level to 5 and can see the ldap queries grabbing a list of ldap groups, and then enumerating users out of these groups. When I run the command ejabberdctl registered-users "domain.com" I get a list of all of my users. I'm stumped as to why this isn't working!

Here are some relevant sections of my config:

        {ldap_memberattr, "member"},
        {ldap_memberattr_format, "CN=%u,CN=Users,DC=domain,DC=com"},

Some output from the log file:

                                  {'PartialAttributeList_SEQOF',"member",
                                      ["CN=Tori Wadzita,CN=Users,DC=domain,DC=com",

The issue is that the code assumes that the part of memberattr which "%u" matches is a valid nodename (i.e. something you can put ahead of "@" in a Jabber ID). In this case it's "Tori Wadzita" which is not a valid nodename, so it just silently ignores the user.

This is actually a known feature request, as non-nodename user IDs seem to be popular in Active Directory:
https://alioth.debian.org/tracker/index.php?func=detail&aid=312703&group...

There is a patch there, but I haven't taken a close look at it yet.

There is currently no ETA on when I'm going to implement such functionality. So unless someone else does it, or you manage to reference your users by a nodename, you're out of luck.

still not resolved or usable workaround???

Hi,

for me it looks like I have the same problem:
Using ejabberd 2.1.9 on OpenLDAP
My cn shows "firstname surname" (in fact "givenname sn").
I have a special attribute ecaIM in OpenLDAP which holds the NodeID "firstname.surname".
The groupmembership is represented by member: uid=Uxxxx,ou=users,... I think this is my problem! But how can I solve it?

I´m able to login using this NodeID with different clients (Miranda, PSI).
However I was not able to show up any roster information, weather groups nor users.

This is one of my configs (I tried a lot of other versions)

{ldap_memberattr, "member"},
%%only use groups as roster beginning with ka
{ldap_rfilter, "(&(objectClass=groupOfNames)(cn=ka*))"},
{ldap_filter, ""},
{ldap_gfilter, "(&(objectClass=groupOfNames)(cn=%g))"},
%% {ldap_groupdesc, "description"},
%% ecaPerson = inetorgPerson and additional attributes eg ecaIM
{ldap_ufilter, "(&(objectClass=ecaPerson)(ecaIM=%u))"},
{ldap_useruid, "imECA"},
{ldap_userdesc, "cn"}

*SOS* - any help would be more than appreciated!

regards
Jos

Consider this:

AD and mod_shared_roster_ldap

porridge wrote:

There is currently no ETA on when I'm going to implement such functionality. So unless someone else does it, or you manage to reference your users by a nodename, you're out of luck.

Well there's not much of a chance for me to get AD to bend to my will, and that's probably going to break a bunch of other stuff if I start messing with it. I was looking at get_user_part_re, and it seems to me that if it would allow a substitution (s/ / /) you could pretty much do whatever you wanted. I don't know erlang so I have a learning curve to climb. Let me know if there's any way to us to prioritize your stack (cash, beer, snacks, etc), this is a feature that many enterprises would love to have.

Thanks,

jack

I'm assuming that

I'm assuming that substitution would make it work for you because you have a simple mapping of user's CN to nodename by stripping whitespace?
Note that it's not going to save the day for every AD user. Or am I misunderstanding?

As for prioritization, it's just that recent OS upgrade has destroyed my testbed VM and merging of the module by ejabberd folks requires me to first have a look at how things changed and possibly revive the unit tests. Together this makes any ejabberd-msrl hacking a relatively big chunk of work compared to my other pet projects.

A proposition to consider

Hello porridge,

Thank you for your hard work on this module.
Hope you have managed to restore your development environment.

As to the topic,
I wanted to recall my post to this page dated Tue, 2010-01-12 12:13. Unfortunately, I didn't track the changes to the code for some time, and I cannot be sure that my proposition still makes sense, but maybe it's worth consideration.

In the AD, the user object has no fields specifying groups that the user belongs to. Instead, group object holds the multi-value property which items are full qualified LDAP name of the member (it may be a user or another group). Of course, this information doesn't nesessarily contain the user part of the jid.

After the mod_shared_roster_ldap finds the users that belong to a group, it looks for their display names. (The caching mechanism doesn't change things - the logic remains). The object that contains the display name MUST contain the user part of the jid (or jid itself) - the current implementation already searches for the jid. Let it look for both display name AND jid in one query - and if the jid field is the same as the search key field, then the result will be the same as it is now, and if the fields are different, we will have extra flexibility.

I want to apologize if my post is based on incorrect assumptions.
Keep up the great work.

eJabberd, mod_shared_roster_ldap and Active Directory

Hi all,

I just implemented an extension to query the "sAMAccountName" from LDAP in case there is a space in the CN.

I am sure there is a better way to do it (as I already have set user_uid to "sAMAccountName" - but somehow this module only works with the cn). I had to change the function group_entries_to_dict/7 to group_entries_to_dict/8 to include the complete Status record - in mod_shared_roster_ldap_helpers.erl and the call to this function in mod_shared_roster_ldap.erl...

group_entries_to_dict(State, GroupIDAttr, GroupDescAttr, GroupMemberAttr, Host, ExtractProcessor, AuthProcessor, Entries) ->
    lists:foldl(
        fun(#eldap_entry{attributes=Attrs}, Dict) ->
            case {eldap_utils:get_ldap_attr(GroupIDAttr, Attrs),
                  eldap_utils:get_ldap_attr(GroupDescAttr, Attrs),
                  lists:keysearch(GroupMemberAttr, 1, Attrs)}
            of
                {ID, Desc, {value, {GroupMemberAttr, Members}}} when ID =/= "" ->
                    JIDs = lists:foldl(
                        fun({ok, UID}, L) ->
                            FirstSpace = string:str(UID, " "),
                            Filter = [eldap_filter:do_sub(State#state.ufilter, [{"%u", UID}])],
                            if
                                FirstSpace > 0 ->
                                        Ret = eldap_search(State,Filter, [State#state.user_uid]),
                                        if
                                           Ret /= [] ->
                                                {eldap_entry, _, Attribs} = lists:last(Ret),
                                                [NewUID] = proplists:get_value(State#state.user_uid, Attribs);
                                        true ->
                                                NewUID = UID
                                        end;
                                true ->
                                        NewUID = UID
                            end,
                            %%io:fwrite("NewUID ~s~n", [NewUID]),
                            PUID = jlib:nodeprep(NewUID),
                                                       case PUID of
                                error -> L;
                                _ ->
                                    case AuthProcessor(PUID, Host) of
                                        true ->  [{PUID, Host} | L];
                                        _ -> L
                                    end
                            end;
                           (_, L) ->
                               L
                        end,
                        [],
                        lists:map(ExtractProcessor, Members)
                    ),
                    NewInfo = #group_info{desc = Desc, members = lists:usort(JIDs)},
                    dict:update(ID,
                        fun(OldInfo) ->
                            OldMembers = OldInfo#group_info.members,
                            NewMembers = NewInfo#group_info.members,
                            OldInfo#group_info{members = lists:umerge(OldMembers, NewMembers)}
                        end,
                        NewInfo, Dict);
                _ ->
                    Dict
            end
        end,
        dict:new(),
        Entries
    ).

Inefficient, I know - especially since userid value is already loaded before, but somehow not transmitted to this function. But it works for me. Here for everyone with the same problem.

It took me a while to get into the functional programming again.

Cheers, beasti.

EDIT: To test this you also need to change line 589-592 of mod_shared_roster_ldap to

RetrievedDict = mod_shared_roster_ldap_helpers:group_entries_to_dict(
                      State,
                      State#state.group_attr, State#state.group_desc, State#state.uid,
                      State#state.host, Extractor, Checker, Retrieved
                ),

and have the options for this module as following:

{ldap_memberattr_format_re, "CN=([,=]*),(OU=.*,)*DC=xxxxx,DC=yyy"},

Note: This last regexp is used to capture the cn of this active directory user.

Group membership based on gidNumber?

Hi,

I've been looking for an example config where the jabber roster group membership is based on only the gidNumber attribute of the posixAccount schema.

E.g. In the following entry, the jabber group would be 10251 (Systems), but that group does not have a corresponding memberUid for user jbloggs (as gidNumber already does this). We use gidNumber as the users primary group and would like them to show up in that group in the jabber roster. We use memberUid only for secondary groups, and do not want the user to appear in this group in the jabber roster.

Is this confuration supported by this module? I can't seem to find any examples of how it would be configured if it is?

dn: uid=jbloggs,ou=people,dc=domain,dc=org
shadowMin: 1
cn: Joe Bloggs
objectClass: ldapPublicKey
objectClass: shadowAccount
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: eduPerson
shadowMax: 365
uid: jbloggs
title: Developer
mail: jbloggs@domain.org
loginShell: /bin/bash
displayName: Joe Bloggs
shadowWarning: 10
shadowInactive: 10
o: DOM
gecos: Joe Bloggs
sn: Bloggs
homeDirectory: /home/jbloggs
givenName: Joe
uidNumber: 10161
gidNumber: 10251

dn: cn=systems,ou=group,dc=domain,dc=org
sambaGroupType: 2
displayName: Systems
cn: systems
objectClass: posixGroup
gidNumber: 10251
description: Systems

Try the flat schema example?

I think the flat DIT (http://ejabberd-msrl.alioth.debian.org/doc/0.5.3/msrl.html#htoc17) should work for you.
"ou" in that example maps to "gidNumber" in yours. However I don't think the code would be able to use your "human-readable" group name ("Systems") in that case, so your group name would be numeric, which is probably less than ideal.

New mod_shared_roster_ldap version: 0.5.3

The changes are:

  • changed group_entries_to_dict/7 to ignore (rather than crash on) UIDs which cause jlib:nodeprep/1 to return atom error — for example junk entries which are over 1KiB long.
  • added support for TLS connections to the LDAP server, consistent with the support in other ldap-based modules.

No longer work properly attribute "ldap_userdesc" in v 0.5.2

I used the module mod_shared_roster_ldap v 0.3.0 with ejabberd-2.1.3 on freebsd 7.3-RELEASEp2 with openldap-server-2.4.23. Design was used as the first example of documentation (3.4.1 Flat DIT):

ejabberd.cfg
...
{mod_shared_roster_ldap,[
{ldap_base, "ou=mailusers,dc=domain,o=org"},
{ldap_rfilter, "(mail=*)"},
{ldap_groupattr, "ou"},
{ldap_memberattr, "uid"},
{ldap_userdesc, "cn"},
{ldap_port, 389},
{ldap_servers, ["ldap.server.address"]},
{ldap_password, "xxxxxxxxx"},
{ldap_rootdn, "cn=xxxxxxxx,dc=domain,o=org"}
]},
...
ldif:
...

dn: uid=eugene, ou=MailUsers, dc=domain, o=org
...
objectClass: inetOrgPerson
userPassword: 1234567890
ou: Our Depatment
uid: eugene
mail: eugene@domain.ru
cn: Eugene V. Boontseff
...

In the roster contact was visible in the match, with (ldap_userdesc, "cn") as "Eugene V. Boontseff"
After I updated version of ejabberd to 2.1.4, a version mod_shared_roster_ldap to 0.5.2,
contact in the roster was seen as: "eugene". Ie attribute "uid" instead of "cn", regardless of what is set to "ldap_userdesc".

And ldap log records are no longer visible form:

slapd[1157]: SRCH "ou=mailusers,dc=domain,o=org" 2 0
slapd[1157]: 0 0 0
mail slapd[1157]: filter: (&(&(uid=username)(ou=*))(objectClass=inetOrgPerson))
mail slapd[1157]: attrs:
mail slapd[1157]: cn

After a rollback to previous versions all working again normally.

I beg your forgiveness.

I do not carefully read the "release notes". I had to determine "ldap_userid == ldap_memberattr.
As they say: if all else fails, read the last documentation.

repeated LDAP errors and msrl crash

ejabberd 2.1.4 w/ mod_shared_roster_ldap 0.5.2. LDAP auth and vcard work just fine, but when I enable mod_shared_roster_ldap I get the errors below. I have double checked all LDAP settings (similar to Deep DIT example).

Any help would be greatly appreciated.

=INFO REPORT==== 2010-09-01 00:55:43 ===
I(<0.371.0>:eldap:967) : LDAP connection on ad5.private:636

=ERROR REPORT==== 2010-09-01 00:55:43 ===
W(<0.371.0>:eldap:589) : LDAP server closed the connection: ad5.private:636
In State: wait_bind_response

=INFO REPORT==== 2010-09-01 00:55:43 ===
I(<0.371.0>:eldap:967) : LDAP connection on ad5.private:636

=ERROR REPORT==== 2010-09-01 00:55:43 ===
W(<0.371.0>:eldap:589) : LDAP server closed the connection: ad5.private:636
In State: wait_bind_response

=ERROR REPORT==== 2010-09-01 00:55:44 ===
'mod_shared_roster_ldap_private' crashed: {timeout,
                                            {gen_server,call,
                                             ['mod_shared_roster_ldap_private',
                                              {get_user_displayed_groups,
                                               "as375097"},
                                              10000]}}

Timeouts are usually a sign

Timeouts are usually a sign that the queries needed to process a single call to the module take too long when added up.

Try disabling ldap_auth_check.

Disabling ldap_auth_check

Disabling ldap_auth_check made no difference.

It seems connection is dropped by the LDAP server

Looking at the message:

Quote:

LDAP server closed the connection: ad5.private:636
In State: wait_bind_response

it seems that the LDAP server is dropping the connection while the module is awaiting bind response. Perhaps you've exceeded some resource limit on the server side?
Unfortunately I don't have any more ideas other than "go look at the LDAP server logs".

New mod_shared_roster_ldap version: 0.5.2

This release makes the module compatible with ejabberd 2.1.4 (bug #312628)

mod_shared_roster_ldap crashes on with 2.1.4 bundle

Hello guys,

I've downloaded ejabberd 2.1.4 and compiled mod_shared_roster_ldap with the bundled erlc without any warnings.
But the module crashes with the following trace in the log:

ERROR: "~p crashed: ~p~n" - ['mod_shared_roster_ldap_mydomain.net',
                                                     {noproc,
                                                      {gen_server,call,
                                                       ['mod_shared_roster_ldap_mydomain.net',
                                                        {get_user_displayed_groups,
                                                         "joedowy"},
                                                        10000]}}]

Please give me a hint on what I'm missing.
(The system is Debian Lenny)

Also I only copied config from 2.0.5 version. LDAP syslog shows only login BINDs but nothing queried by the module.

Thank you in advance!

This looks like a consequence

This looks like a consequence of the module crash. Please show the log before that message.

I guess nothing interesting here

Thank you for the prompt answer Marcin!

I guess nothing interesting here:

=INFO REPORT==== 2010-06-24 15:54:40 ===
I(<0.341.0>:ejabberd_listener:232) : (#Port<0.534>) Accepted connection {{xxx,xxx,xxx,xxx},40319}
-> {{xxx,xxx,xxx,xxx},5222}

=INFO REPORT==== 2010-06-24 15:54:41 ===
I(<0.1080.0>:ejabberd_c2s:580) : ({socket_state,tls,{tlssock,#Port<0.534>,#Port<0.536>},<0.1079.0>})
Accepted authentication for joedowy by ejabberd_auth_ldap

=INFO REPORT==== 2010-06-24 15:54:41 ===
I(<0.1080.0>:ejabberd_c2s:839) : ({socket_state,tls,{tlssock,#Port<0.534>,#Port<0.536>},<0.1079.0>})
Opened session for joedowy@mydomain.net/Home

=ERROR REPORT==== 2010-06-24 15:54:41 ===
ERROR: "~p crashed: ~p~n" - ['mod_shared_roster_ldap_mydomain.net',
                                                     {noproc,
                                                      {gen_server,call,
                                                       ['mod_shared_roster_ldap_mydomain.net',
                                                        {get_user_displayed_groups,
                                                         "joedowy"},
                                                        10000]}}]

=ERROR REPORT==== 2010-06-24 15:54:42 ===
ERROR: "~p crashed: ~p~n" - ['mod_shared_roster_ldap_mydomain.net',
                                                     {noproc,
                                                      {gen_server,call,
                                                       ['mod_shared_roster_ldap_mydomain.net',
                                                        {get_user_displayed_groups,
                                                         "joedowy"},
                                                        10000]}}]

This is from ejabberd.log. erlang.log is silent.

Still, this does not show the

Still, this does not show the root cause. Have a look earlier, perhaps when the module initializes or when the first user connects. If you can't find anything, increase log verbosity, restart ejabberd and retry.
If you still cannot find anything then, send the whole log to my email address.

Replying here for other

Replying here for other people's benefit.

We've found the following crash report in erlang.log:

=CRASH REPORT==== 25-Jun-2010::16:57:04 ===
  crasher:
    pid: <0.340.0>
    registered_name: 'eldap_mod_shared_roster_ldap_secondarydomain.net'
    exception exit: {function_clause,
                        [{proplists,get_value,[encrypt,none,undefined]},
                         {eldap,init,1},
                         {gen_fsm,init_it,6},
                         {proc_lib,init_p,5}]}
      in function  gen_fsm:init_it/6
    initial call: gen:init_it(gen_fsm,<0.339.0>,<0.339.0>,
                              {local,'eldap_mod_shared_roster_ldap_secondarydomain.net'},
                              eldap,
                              {["localhost"],
                               389,
                               "uid=admin,cn=admin,dc=primarydomain,dc=net",
                               "********",none},
                              [])
    ancestors: ['mod_shared_roster_ldap_secondarydomain.net',ejabberd_sup,
                  <0.36.0>]
    messages: []
    links: [<0.339.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 610
    stack_size: 23
    reductions: 180
  neighbours:
    neighbour: [{pid,<0.339.0>},
                  {registered_name,'mod_shared_roster_ldap_secondarydomain.net'},
                  {initial_call,
                   {gen,init_it,
                    [gen_server,<0.216.0>,<0.216.0>,
                     {local,'mod_shared_roster_ldap_secondarydomain.net'},
                     mod_shared_roster_ldap,
                     ["secondarydomain.net",
                      [{ldap_servers,["localhost"]},
                       {ldap_port,389},
                       {ldap_rootdn,
                        "uid=admin,cn=admin,dc=primarydomain,dc=net"},
                       {ldap_password,"********"},
                       {ldap_base,"dc=primarydomain,dc=net"},
                       {ldap_rfilter,
                        "(&(objectClass=organizationalUnit)(ou=Team))"},
                       {ldap_ufilter,"(&(objectClass=inetOrgPerson)(cn=*))"},
                       {ldap_gfilter,"(objectClass=inetOrgPerson)"},
                       {ldap_groupattr,"ou"},
                       {ldap_memberattr,"uid"},
                       {ldap_useruid,"uid"},
                       {ldap_groupdesc,"ou"},
                       {ldap_userdesc,"cn"}]],
                     []]}},
                  {current_function,{proc_lib,sync_wait,2}},
                  {ancestors,[ejabberd_sup,<0.36.0>]},
                  {messages,
                   [{ack,<0.340.0>,
                     {error,
                      {function_clause,
                       [{proplists,get_value,[encrypt,none,undefined]},
                        {eldap,init,1},
                        {gen_fsm,init_it,6},
                        {proc_lib,init_p,5}]}}}]},
                  {links,[<0.216.0>,<0.340.0>]},
                  {dictionary,[]},
                  {trap_exit,false},
                  {status,runnable},
                  {heap_size,987},
                  {stack_size,18},
                  {reductions,263}]

After having a look at eldap:init function, it's obvious that it has changed in an incompatible fashion in 2.1.4. It is now:

init({Hosts, Port, Rootdn, Passwd, Opts}) ->

where is used to be:

init({Hosts, Port, Rootdn, Passwd, Encrypt}) ->

since msrl is calling it with "none" as the last arg, then proplists:get_value crashes as none is not a valid list.

Perhaps "none" is not the best value to use, as it basically forces the module to not use TLS even if it's supported.

It would be great if someone could come up with a working patch for that. I might not be able to produce one before I come back from holidays in the middle of July.

Look at the changes in mod_vcard_ldap

porridge wrote:

After having a look at eldap:init function, it's obvious that it has changed in an incompatible fashion in 2.1.4.

since msrl is calling it with "none" as the last arg, then proplists:get_value crashes as none is not a valid list.

Perhaps "none" is not the best value to use, as it basically forces the module to not use TLS even if it's supported.

It would be great if someone could come up with a working patch for that. I might not be able to produce one before I come back from holidays in the middle of July.

Right, the function API changed between 2.1.3 and 2.1.4:
https://support.process-one.net/browse/EJAB-1229

You can see in the same commit that mod_vcard_ldap changed, too:
https://git.process-one.net/ejabberd/mainline/commit/f58d03c12e1160f40a7...
You can do a similar change; instead of passing 'none', or '[]', you can get the ldap tions from the module Opts, fallback to global options, and then pass a list [{encrypt, ...}, {...}]

THANK YOU!

Marcin!

I owe you one!
I've changed none argument to Opts at mod_shared_roster_ldap.erl:145 and it works now!
AFAIU, that should be enough for a patch, isn't it?

Thank you!

Well, I'm not sure it's a

Well, I'm not sure it's a proper fix - potentially passing Opts there is no different than passing an empty list, but I'd say it's good enough for now if it does not crash.

I've changed none argument to

I've changed none argument to Opts at mod_shared_roster_ldap.erl:145 but mod_shared_roster_ldap still crash :

=CRASH REPORT==== 16-Aug-2010::14:14:06 ===
crasher:
initial call: eldap:init/1
pid: <0.338.0>
registered_name: 'eldap_mod_shared_roster_ldap_mydomian'
exception exit: {function_clause,[{inet_tcp,getserv,["389"]},
{gen_tcp,connect1,4},
{gen_tcp,connect,4},
{eldap,connect_bind,1},
{eldap,connecting,2},
{gen_fsm,handle_msg,7},
{proc_lib,init_p_do_apply,3}]}
in function gen_fsm:terminate/7
ancestors: ['mod_shared_roster_ldap_mydomain',ejabberd_sup,
<0.37.0>]
messages: []
links: [<0.337.0>]
dictionary: []
trap_exit: false
status: running
heap_size: 1597
stack_size: 24
reductions: 329
neighbours:
neighbour: [{pid,<0.337.0>},
{registered_name,'mod_shared_roster_ldap_mydomian'},
{initial_call,{mod_shared_roster_ldap,init,['Argument__1']}},
{current_function,{proc_lib,sync_wait,2}},
{ancestors,[ejabberd_sup,<0.37.0>]},
{messages,[{ack,<0.338.0>,{ok,<0.338.0>}}]},
{links,[<0.222.0>,<0.338.0>]},
{dictionary,[]},
{trap_exit,false},
{status,runnable},
{heap_size,1597},
{stack_size,17},
{reductions,839}]

looks like TCP connection failure

amberovsky wrote:

I've changed none argument to Opts at mod_shared_roster_ldap.erl:145 but mod_shared_roster_ldap still crash :

=CRASH REPORT==== 16-Aug-2010::14:14:06 ===
crasher:
initial call: eldap:init/1
pid: <0.338.0>
registered_name: 'eldap_mod_shared_roster_ldap_mydomian'
exception exit: {function_clause,[{inet_tcp,getserv,["389"]},
{gen_tcp,connect1,4},
{gen_tcp,connect,4},
{eldap,connect_bind,1},
{eldap,connecting,2},
{gen_fsm,handle_msg,7},
{proc_lib,init_p_do_apply,3}]}

This one looks to me like a TCP connection (to your LDAP server) failure.

Have you managed to get this

Have you managed to get this to work? I struggle with the same thing.

New mod_shared_roster_ldap version: 0.5.1

The only important change this time is that using ``Display Names'' for usernames which are not all-lower-case now actually works.

Another thing I would like to ask the admin of this page for, is to replace the note about lack of documentation with a link to https://alioth.debian.org/docman/?group_id=100433 - I feel the module is now quite well documented there.

Link to doc, and change authorship

porridge wrote:

replace the note about lack of documentation

Done. And you are now the 'author' of this page, so you can edit it when needed :)

Thanks!

badlop wrote:
porridge wrote:

replace the note about lack of documentation

Done. And you are now the 'author' of this page, so you can edit it when needed :)

Thanks!

Although I cannot figure out how to edit the page? Do I just hit "Quote" and then remove the quote markers?

Also for some reason the forum starts talking to me in Spanish when I click "Create content" :-)

Edit node solved

porridge wrote:

Although I cannot figure out how to edit the page? Do I just hit "Quote" and then remove the quote markers?

Ah, my mistake. Try again now: between the node title and the "Submitted by" line, it should display you links to view and edit the node.

porridge wrote:

Also for some reason the forum starts talking to me in Spanish when I click "Create content" :-)

Yes, seems the English strings table got some Spanish sentences, and now I don't know how to fix it :S

Thanks!

badlop wrote:
porridge wrote:

Although I cannot figure out how to edit the page? Do I just hit "Quote" and then remove the quote markers?

Ah, my mistake. Try again now: between the node title and the "Submitted by" line, it should display you links to view and edit the node.

Seems to work now, thanks!

My opinion about mod_shared_roster_ldap

This project is very necessary for operation in the corporate environment.

IMHO

I consider that this project should be divided into two projects:
1. Only shared roster with data storage in database (as much as possible simple table) +
may be possible API for service of the data in roster
(as variant: to add record, to remove record, to change record,
to remove all records, to receive version number roster, to change version number roster)

2 Connectors set for the data recording in th rosters table in database.
Connectors realises logic of data acquisition from external
sources and updating of the rosters table.
Necessary connectors(as variant):
- LDAP
- File csv
- HTTP

/IMHO

Thanks for your comments. I

Thanks for your comments. I agree that having this kind of functionality is important for a company. That's why I'm working on it :-)

Can you explain what kind of data management API technology do you have in mind? Do you mean internal ejabberd API, or exposing it as a kind of web service?

As for the split between shared roster and connectors - until recently there was not that much connector-independent logic to warrant a separate connector-independent part. This might change now that "msrl" has caching capabilities. But first I think it would have to catch up with the original "msr" in terms of feature set. For example all roster groups are shown to all users, while in mod_shared_roster the administrator can choose which groups to expose to which group members.

Also, why do you feel an RDBMS-specific connector should be built into the base shared roster module? I would think a connector-agnostic architecture would be cleaner.

I am sorry for long term of

I am sorry for long term of the answer.

I imagines the following architecture:

The roster module <->Intermediate long-term storehouse <->Connectors for storehouse filling.

Data which are displayed by a roster, are the structured information.It makes sense to store them in RDBMS.
Simultaneously this storehouse serves for caching to the information from sources with high-cost access (for example, LDAP). Additional efforts for connection of this storehouse it is not required, as ejabberd already uses DBMS.

The roster module is responsible for logic of display of this structured information. Rules of display can be rigidly defined at once, or be modified at runtime. As the roster is views of the structured data, in this module it makes sense to define rules of views for various users (to what user what to show). This module should have a set of filters. Views is formed from local storehouse that raises speed and gives the chance to optimization (create indexes, tuning query, and etc.).

Modules of connectors receive the information from external sources (any), make its structurization and put into storehouse by rules. Rules can be or are rigidly defined, or flexibly to be modified. Connector should know how to obtain the raw data from a source, to structure them and to place in storehouse. The logic of connector should be as much as possible simple. Possibly, the module of connector also should contain logic of processing of the out-of-date data from the given source (to delete or keep).

As the information in storehouse is structured, it makes sense to abstract from physical structure of storage of the information and to give to it access through API. (export a set of functions for addition, updating, removal, etc.) Connectors (and other modules) can use API for work with the information in storehouse. In my opinion, given API should belong to the roster module.

At such scheme
- Displaying and functions of mining of the data is divided.
- We have an additional layer where the data caching and can be in addition processed

In my opinion it raises reliability of system and simplifies a code.
At such scheme the user can bring the additional information in a roster and if rules of change and processing of the out-of-date data do not result in loss of this information the given roster will possess interesting possibilities.

What do You name connector-agnostic architecture? Probably I have slightly lagged behind a life…

P.S. I apologise for my English.

Sorry for the late reply. It

Sorry for the late reply.
It seems to me you're proposing to have a mandatory RDBMS-based layer between the module and any possible data store. I don't think that overhead would be practical for anyone except those who already use an RDBMS, in which case even they would see that as an extra layer without any merit (why have a separate database if they already have one?).

New mod_shared_roster_ldap version: 0.5.0

Now available at https://alioth.debian.org/projects/ejabberd-msrl/

Most important changes:

  • the ldap_groupdesc parameter now defaults to whatever ldap_groupattr is set to, rather than to cn. You will need to set it manually if you relied on the previous default.
  • from this release on, both the user and group “display names” as well as group membership information is each retrieved with a single query and cached in memory as a dictionary which improves lookup performance when there is a large number of users. The list of group names is still queried on every roster retrieval.
  • note that a change in this release makes the module incompatible with ejabberd versions below 2.0 (in case it was compatible before).
  • fixed a bug where retrieving a group “display name” would only work for “Flat DIT” setups for groups with exactly one member.
  • introduced a new option ldap_group_cache_validity which defaults to 5 minutes and lets you specify the time for which group membership and group display name information is cached.
  • added upgrade instructions to documentation

See the Changes on the released files page for more information.

Need help on getting AD to work

Has anyone succeed in getting this to work with AD ?

Here is my current config any hints would be nice
{mod_shared_roster_ldap, [
{ldap_groupattr, "cn"},
{ldap_memberattr, "member"},
{ldap_filter, ""},
{ldap_memberattr_format_re, "CN=(\[^,\]*),(OU=.*,)*DC=corenagroup,DC=local"},
{ldap_ufilter, "(&(objectClass=person)(CN=%u))"},
{ldap_rfilter, "(&(objectClass=group)(CN=*_dev))"},
{ldap_user_cache_validity, 1},
{ldap_auth_check,off},
{ldap_useruid, "cn"},
{ldap_userdesc, "sAMAccountName"}

some hints

Some hints based on how version 0.5.0 (just released) works:

  1. run the (&(objectClass=group)(CN=*_dev)) query manually and see if the returned entries have a "member" attribute.
  2. run the Group filter (which would be (&(member=*)(cn=*)) since you did not specify one) and see if the returned entries have attributes "cn" and "member" and their values are sane-looking group name and member list, respectively
  3. match (case-sensitively!) the member list items from the previous query against CN=(\[^,\]*),(OU=.*,)*DC=corenagroup,DC=local

These are the basics. Show us example data from of the above steps before you go any further.

New mod_shared_roster_ldap version: 0.4.0

Now available at https://alioth.debian.org/projects/ejabberd-msrl/

Most important changes:

  • added two new source files, now the software is distributed in a tgz or zip archive
  • added regex support for member ID matching
  • added caching support for user names and another way to skip one query per user, improving performance

Credits:

  • The patch adding support for the ldap_memberattr_format_re and ldap_auth_check options was contributed by Denis Kurochkin.

See the Changes at the released files page for more information.

Syndicate content