diff --git a/README.md b/README.md index a4a5bc8..2370a84 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,9 @@ binding. (It has been tested with eJabberd 2.1.10 and OpenLDAP 2.4.31.) Configuration ------------- -Edit the file `etc/ejabberd-auth.yaml` and configure: - - - At a minimum, the base context for your server. - - Any other settings where the default is inappropriate. +For OpenLDAP the default settings may suffice, assuming anonymous +searches are allowed. Edit the file `etc/ejabberd-auth.yaml` to +review the default configuration and adjust anything necessary. *Note that installing globally (below) will copy this file to global location.* diff --git a/etc/ejabberd-auth.yaml b/etc/ejabberd-auth.yaml index cbb2ec8..d8da2df 100644 --- a/etc/ejabberd-auth.yaml +++ b/etc/ejabberd-auth.yaml @@ -6,9 +6,11 @@ # The method to use for authentication. # (At the moment 'ldap' is the only supported method.) # Default: ldap -#method: ldap +method: ldap -ldap: +# Uncomment if any of the following LDAP properties need +# to be set. +#ldap: # URL to use to connect to the server. # Default: ldap://localhost #uri: ldap://localhost @@ -22,8 +24,8 @@ ldap: # password: guessmeifyoucan # Base for searching. - # Default: none - base: dc=example,dc=com + # Default: autodetect + #base: dc=example,dc=com # Attribute to match against the username. # Default: uuid diff --git a/lib/auth-ldap.js b/lib/auth-ldap.js index fd3d7e6..f31176a 100644 --- a/lib/auth-ldap.js +++ b/lib/auth-ldap.js @@ -5,6 +5,37 @@ var ldap = require('ldapjs'), assert = require('assert'), auth = require('./auth'); +function listRoots(client, callback) { + client.search("", { + filter: '(namingContexts=*)', + scope: 'base', + attributes: 'namingContexts', + attrsOnly: true + }, function(err, res) { + if (err) { + console.warn("Error searching for base contexts: " + err); + callback(); + } else { + var roots = []; + res.on('searchEntry', function(entry) { + roots.push(entry.object.namingContexts) + }); + res.on('error', function(err) { + console.warn("Error while searching for base contexts: " + err); + callback(); + }); + res.on('end', function(result) { + if (result.status === ldap.LDAP_SUCCESS) { + callback(roots); + } else { + console.error("LDAP error searching for base contexts: " + result.status); + callback(); + } + }); + } + }); +} + function start(options) { var base = options.base, admin = options.admin, @@ -14,7 +45,7 @@ function start(options) { objectFilter = ldap.parseFilter(filter), client = ldap.createClient({ url: url }); - function bindEvents() { + function bindChannel(base) { function findJabberUser(user, callback) { client.search(base, { filter: new ldap.AndFilter({ @@ -103,13 +134,36 @@ function start(options) { }); } + function bindChannelWithSearchBase(base) { + if (base) { + bindChannel(base); + } else { + listRoots(client, function(bases) { + switch (bases.length) { + case 0: + console.error("Cannot detect root naming context. Please configure manually."); + break; + case 1: + var base = bases[0]; + console.warn("Auto-detected base context: " + base); + bindChannel(base); + break; + case 2: + console.error("Multiple bases detected. Please configure manually."); + break; + + } + }); + } + } + if (admin) { client.bind(admin.dn, admin.password, function(err) { assert.ifError(err); - bindEvents(); + bindChannelWithSearchBase(base); }); } else { - bindEvents(); + bindChannelWithSearchBase(base); } }