Previously, we saw that Mozilla MCD can inspect a user’s environment using getEnv()
. It can also retrieve information from an LDAP directory. I use this feature to inform Firefox and Thunderbird of the user in detail. The corporate directory knows the user’s full name, mail server and authentication credentials. autoconfig takes this and, among other useful things, constructs an email account for Thunderbird without user intervention.
The javascript API to deal with LDAP is a bit hackish, however it is all we have. The first task is to define a function called processLDAPValues()
which accepts a queryResults
string as its only argument. Inside processLDAPValues
you extract return data from queryResults
.
Instead of invoking processLDAPValues()
directly, you call getLDAPAttributes()
which in turn gets you to your function. To illustrate, here is the code I use to query the corporate directory server and save the values for later use.
var userInfo = new Object(); // This will hold LDAP results userInfo.envUser = getenv("LOGNAME"); // Unix UID userInfo.envHome = getenv("HOME"); // User home directory var ldapHost = "ldap.example.com"; var ldapBase = "dc=example,dc=com"; if( userInfo.envUser ) { var ldapFilter = "uid=" + userInfo.envUser; } else { throw("Couldn't get UID from the environment"); } // LDAP attributes to retrieve from the server var ldapAttrs = new Array( "cn", "email", "employeenumber", "givenname", "mailhost", "sn", "uid" ); // Define how to process LDAP results before we make the call function processLDAPValues(queryResults) { if( queryResults ) { // Build the userInfo object for later use for( var attr in ldapAttrs ) { userInfo[ ldapAttrs[attr] ] = getLDAPValue( queryResults, ldapAttrs[attr] ); } } else { throw( "No LDAP results" ); } } // Call upon LDAP for the values in ldapAttrs array // Uses the previous processLDAPValues() getLDAPAttributes( ldapHost, ldapBase, ldapFilter, ldapAttrs.join(",") ); |
The first thing I do is create a userInfo
object that will hold LDAP results for use later in the autoconfig. To that object I add attributes for the user’s login name and home directory.
The next bit sets variables to contain the directory server’s hostname, base DN and the LDAP filter to use in the search. It’s a good idea to throw an error if there is no $LOGNAME
. (In a later post I will show how to enhance autoconfig error reporting.)
The ldapAttrs
array names the attributes I want to return from LDAP. Change this array to suit your environment. The last line of code joins the array together with commas and feeds it to getLDAPAttributes
along with the hostname, base DN and filter. getLDAPAttributes
is defined in MOZILLA_HOME/defaults/autoconfig/prefcalls.js
and does the work to perform the query, then call your predefined processLDAPValues()
function.
The example autoconfig script at developer.mozilla.org set preferences inside processLDAPValues
, however this is a bad convention. There are many preferences that require user information and separating pref()
calls away from the main block of preference setting can be confusing. As you can see here I simply run through the array of attributes I’m interested in and get the result from the LDAP query for that attribute, assigning it to the userInfo
object.
Later on in the script I ask the userInfo
object for those stored LDAP attributes. To set the hostname of the user’s mail server, for example, I call
// IMAP server name from corporate LDAP directory defaultPref("mail.server.server1.hostname", userInfo.mailhost ); |
LDAP directories are a great resource. What attributes could you store in your corporate server?
This works great at my site! I’ve been banging my head against the wall, however, with one more thing I’m trying to do. I want some of my settings to be conditional upon posixGroups that the user is a member of, i.e. (&(cn=”Admin Group”)(memberUid=userInfo.envUser)).
I’m no js expert, but it appears that getLDAPAttributes assumes that your query result is a single user record, and no way to look at attributes of pertinent groups.
Since processLDAPValues is a function, I don’t think I can define it twice and call getLDAPAttributes twice to do a second query.
Is there any way to get information from more than one entity in the LDAP database, or am I barking up the wrong tree?
Glad to it helps.
getLDAPAttributes
passesprocessLDAPValues
a string argument (queryResults
). I don’t remember the format of the string, but it may support multiple results. ThegetLDAPValue
function munches the string and returns the value of the attribute. Try usingdisplayError
orprint
insideprocessLDAPValues
to display thequeryResults
. Like I said, the LDAP handling is hackish. It’s enlightening to read$MOZ_HOME/defaults/autoconfig/prefcalls.js
.*zilla products support real LDAP queries and if I were still working with Thunderbird & Firefox I would be writing a more object-oriented way. Sadly, jobs change. Check the XPCOM reference.
Thank you for your work, this was really helpful for me!
You’re welcome. Thanks for sharing a link to this post on the tb-enterprise mailing list.
I run into a problem with mobile computers. If a user starts Thunderbird outside of our LAN, Thunderbird reads the failover.jsc, the local copy of the centralized settings, but of course can’t connect to the LDAP server. Then, all settings are available, but all LDAP Valures are “undefined”.
I helped myself to disable the use of failover.jsc wenn not in LAN with lockPref(“autoadmin.failover_to_cached”, false); but found that now only settings with pref are memorized (saved in the pref.js in the user profile). The use of defaultPref und lockPref in the global settings file was not possible this way.
Our corporate policy does not allow for anonymous binds to the LDAP server. Is there a way to pass the binddn and password to the array?
Hey Jason. It may be possible by adding the
binddn
toldapFilter
. If that fails I suggest asking on the Thunderbird enterprise mailing list.