Table of Contents
|
Written by Ben Chavet (ben [at] horde [dot] org)
This document is intended to help administrators configure various parts of horde to use an existing LDAP directory. Please feel free to fill in any gaps or to clarify any existing information presented here.
In this document, we assume the following, please adjust accordingly for your LDAP directory
The Horde authentication setup should look something like the following:
These are the minimum LDAP directory permissions needed by horde to authenticate against LDAP
access to dn.children="ou=Users,dc=example,dc=com"
attrs=entry,objectClass,uid
by dn="cn=horde,ou=DSA,dc=example,dc=com" read
by self read
by * none
access to dn.children="ou=Users,dc=example,dc=com"
attrs=userPassword
by self write
by anonymous auth
by * none
With a little tweaking, Horde can be used to do basic user management for a Posix system, such as adding and removing users.
We have to have a place to keep track of the next user id number. If you are already using LDAP for user management, chances are, you already have an object doing this, and you can skip this section. If you do not, we need to create one with the following ldif file:
dn: cn=NextFreeUnixId,dc=example,dc=com
homeDirectory: /dev/null
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
uid: NextFreeUnixId
gidNumber: 1000
uidNumber: 1000
sn: NextFreeUnixId
cn: NextFreeUnixId
And add this object to the directory:
ldapadd -x -h localhost -D "cn=root,dc=example,dc=com" -f filename.ldif -W
<?php if (!function_exists('_horde_hook_authldap')) { function _horde_hook_authldap($userID, $credentials = null) { $entry['dn'] = 'uid=' . $userID . ',ou=horde,dc=example,dc=com'; if (isset($credentials) && isset($credentials['user_fullname'])) { $entry['cn'] = $credentials['user_fullname']; } else { $entry['cn'] = $userID; } $entry['sn'] = $userID; $entry['objectclass'][0] = 'top'; $entry['objectclass'][1] = 'posixAccount'; $entry['objectclass'][2] = 'shadowAccount'; $entry['objectclass'][3] = 'inetOrgPerson'; $entry['uid'] = $userID; $entry['homeDirectory'] = '/home/' . $userID; $entry['gidNumber'] = 100; // get the next available uid and increment it if we're adding a user if (isset($credentials)) { $ds = @ldap_connect($GLOBALS['conf']['auth']['params']['hostspec']); @ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $GLOBALS['conf']['auth']['params']['version']); @ldap_bind($ds, $GLOBALS['conf']['auth']['params']['binddn'], $GLOBALS['conf']['auth']['params']['password']); $searchResults = @ldap_search($ds, 'dc=example,dc=com', 'cn=NextFreeUnixId'); $information = @ldap_get_entries($ds, $searchResults); ldap_modify($ds, 'cn=NextFreeUnixId,dc=example,dc=com', array('uidnumber' => $information[0]['uidnumber'][0] + 1)); @ldap_close($ds); $entry['uidNumber'] = $information[0]['uidnumber'][0]; } // need to check for new users (password) and edited users (user_pass_2) if (isset($credentials) && isset($credentials['password'])) { $entry['userPassword'] = '{MD5}' . base64_encode(mHash(MHASH_MD5, $credentials['password'])); } else if (isset($credentials) && isset($credentials['user_pass_2'])) { $entry['userPassword'] = '{MD5}' . base64_encode(mHash(MHASH_MD5, $credentials['user_pass_2'])); } return $entry; } } ?>
Another example for this code using a ou to store the next available uid information can be found at: http://heinous.org/wiki/Horde_Notes#Authentication
If you are using Horde to manage your user accounts, the horde account needs more priveleges in order to make the proper changes.
access to dn.base="cn=NextFreeUnixId,dc=example,dc=com"
by dn="cn=horde,ou=DSA,dc=example,dc=com" write
by * none
access to dn.children="ou=Users,dc=example,dc=com"
attrs=entry,objectClass,uid
by dn="cn=horde,ou=DSA,dc=example,dc=com" write
by self read
by * none
access to dn.children="ou=Users,dc=example,dc=com"
attrs=userPassword
by dn="cn=horde,ou=DSA,dc=example,dc=com" write
by self write
by anonymous auth
by * none
Storing Horde preferences in the LDAP directory adds a large number of attribute entries to every user DN. If this is something you do not want, you should look into using some other preference backend.
To use LDAP to store Horde preferences, set the preference system to use LDAP as its backend. The field values here are very simular to the Horde configuration.
These are the suggested LDAP directory permissions needed by Horde to store user preferences. The explicit write permission for the Horde DN can be omitted if the LDAP driver is configured to bind to LDAP as the logged-in user. However it remains necessary if you use a "root" DN. The "attrs=@hordePerson" syntax means this rule applies to all attributes included in the "hordePerson" objectClass.
# Access to Horde attributes
access to attrs="@hordePerson"
by dn="cn=horde,ou=DSA,dc=example,dc=com" write
by self write
by users none
by * none
Patch /etc/openldap/schema/core.schema with /horde/turba/scripts/ldap/core.schema.patch
Turba ships with an example LDAP address book, so we will use that here as our base. This example assumes that we are providing an address book containing all of the users who have access to this horde installation.
<?php $cfgSources['localldap'] = array( 'title' => _("Shared Directory"), 'type' => 'ldap', 'params' => array( 'server' => 'localhost', 'port' => 389, 'root' => 'ou=Users,dc=example,dc=com', 'bind_dn' => 'cn=horde,ou=Users,dc=example,dc=com', 'bind_password' => '********', 'sizelimit' => 200, 'dn' => array('cn'), 'objectclass' => array('top', 'person', 'organizationalPerson', 'inetOrgPerson', 'turbaContact', ), 'charset' => 'iso-8859-1', 'checkrequired' => false, 'version' => 3 ), 'map' => array( '__key' => 'dn', 'name' => 'cn', 'email' => 'mail', 'workPhone' => 'telephonenumber', 'cellPhone' => 'mobile', 'office' => 'roomNumber', 'employeeType' => 'employeeType', 'pgpPublicKey' => 'userCertificate', 'freebusyUrl' => 'calFBURL', ), 'search' => array( 'name', 'email', 'homePhone', 'workPhone', 'cellPhone', 'homeAddress' ), 'public' => true, 'readonly' => true, 'admin' => array(), 'export' => true ); ?>
The amount of information you can store is not by any means limited by what we have configured here. Any number of LDAP fields can be added to the 'map' array.
In order to use the calFBURL field, we have to include the rfc2739 schema in our LDAP configuration file.
include /etc/openldap/schema/rfc2739.schema
These are the minimum LDAP permissions required for the address book we defined above. If you included extra fields, be sure to add them here.
access to dn.children="ou=Users,dc=example,dc=com"
attrs=entry,cn,objectClass,mail,telephoneNumber,mobile,roomNumber,employeeType,userCertificate,calFBURL,displayName
by dn="cn=horde,ou=Users,dc=example,dc=com" read
by self read
by * none
To pass credentials used to log in Horde to IMP, modify the file ./horde/imp/config/servers.php (from your webroot). Here is the explanation given in the file :
hordeauth :
If this parameter is present and true, then IMP will attempt to use the user's existing credentials (the username/password they used to log in to Horde) to log in to this source. If this parameter is 'full', the username will be used unmodified; otherwise everything after and including the first @ in the username will be stripped off before attempting authentication.