Tuesday, June 1, 2010

using openLDAP for addressbook

By now I have got exhausted answering folks 'Why IndiMail does not have a shared addressbook'

IndiMail is a pure messaging platform. It does not attempt to do things which can be done better by other software like openLDAP etc.

However, things can get bit tricky setting up an address book using openLDAP. This tutorial should make it easy for you to install your own shared address book. The commands below have worked for me on my linux laptop which is proudly powered by Fedora 12. The commands / configuration may slightly vary for your Linux distro / openLDAP version.


Install openldap


% sudo yum install openldap openldap-servers openldap-clients

Configure openldap

You need to start slapd to implement openldap. slapd uses configurion
file /etc/openldap/slapd.conf

The following slapd.conf file contains the basic configurations required to establish a shared address book on a secure network, however there are no access controls yet defined; security is covered later on. The encrypted root password (rootpw) should be substituted where necessary. You can use slappasswd to generate the password

% slappasswd -s secret
{SSHA}gDPX3cS87+B31mAF5zHCGtEJBYSuqrN/


#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/duaconf.schema
include /etc/openldap/schema/dyngroup.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/java.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/ppolicy.schema
include /etc/openldap/schema/collective.schema

#######################################################################
# ldbm and/or bdb database definitions
#######################################################################

database bdb
suffix "dc=indimail,dc=org"
checkpoint 1024 15
rootdn "cn=Manager,dc=indimail,dc=org"
rootpw {SSHA}gDPX3cS87+B31mAF5zHCGtEJBYSuqrN/
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory /var/lib/ldap

# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!

access to dn.subtree="ou=addressbook,dc=indimail,dc=org"
by anonymous auth
by self write
by users read
access to *
by anonymous auth
by self read
by users read

# Indices to maintain for this database
index objectClass eq,pres
#index ou,cn,mail,surname,givenname eq,pres,sub
#index uidNumber,gidNumber,loginShell eq,pres
#index uid,memberUid eq,pres,sub
#index nisMapName,nisMapEntry eq,pres,sub

Make user that /etc/openldap/slapd.conf is owned by ldap and has write permissions for ldap user.

As of now I prefer openldap using slapd.conf and not slapd.d for configuration.

% sudo /bin/rm -r /etc/openldap/slapd.d

slapd Startup

My favourite method happens to be using djb's supervise and hence is one of the core compoment of the IndiMail package

% cat > /tmp/run1
#!/bin/sh
exec /usr/sbin/slapd -u ldap -f /etc/openldap/slapd.conf -d 0 2>&1
cntrl-d

% cat > /tmp/run2
#!/bin/sh
exec /var/indimail/bin/setuidgid qmaill \
/var/indimail/bin/multilog t /var/log/indimail/slapd.389
cntrl-d

# create /service/.slapd.389 so that svscan does not discover this new service yet
% sudo mkdir -p /service/.slapd.389/log
% sudo mv /tmp/run2 /service/.slapd.389/log/run
% sudo mv /tmp/run1 /service/.slapd.389/run
% sudo chmod +x /service/.slapd.389/run /service/.slapd.389/log/run

# rename .slapd.389 to slapd.389 for svscan to discover and start slapd
% sudo mv /service/.slapd.389 /service/slapd.389

% svstat /service/slapd.389
/service/slapd.389/: up (pid 4069) 4 seconds

AddressBook Entries

Information can be imported and exported into an LDAP directory service using the LDAP Data Interchange Format (LDIF) as defined in RFC2849. An LDIF file specifies the contents of a directory entry in a human readable text format, this allows quick manipulation of a file to re-import similar entries into the directory.

Now that the LDAP server has been configured and is running, we can conduct a simple search of the naming context to see our directory information before we start to import our entries.

The "namingContexts" should be similar to the example below.

% ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
# extended LDIF
#
# LDAPv3
# base <> with scope base
# filter: (objectclass=*)
# requesting: namingContexts

dn:
namingContexts: dc=indimail,dc=org

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

The following LDIF file will create the hierarchical directory service structure that we will be using for indimail's address book. The first entry is that of the base directory and the second entry is for the Manager's (administrator) account. The last two entries are the two organisational units that we will use to store the authorised users (for adding security later) and the address book entries.

The bolded entries should be changed to suit your configuration requirements.

% cat > addressbook.ldif
# Domain entry
dn: dc=indimail,dc=org
o: IndiMail LDAP Server
dc: indimail
objectclass: dcObject
objectclass: organization

# Manager entry
dn: cn=Manager,dc=indimail,dc=org
cn: Manager
objectclass: organizationalRole

# Users
dn: ou=users,dc=indimail,dc=org
ou: users
objectClass: top
objectClass: organizationalUnit

# Addressbook entry
dn: ou=AddressBook,dc=indimail,dc=org
ou: AddressBook
objectClass: top
objectClass: organizationalUnit
cntrl-d

% ldapadd -x -D 'cn=Manager,dc=indimail,dc=org' -W -f addressbook.ldif
Enter LDAP Password:
adding new entry "dc=indimail,dc=org"
adding new entry "cn=Manager,dc=indimail,dc=org"
adding new entry "ou=users,dc=indimail,dc=org"
adding new entry "ou=addressbook,dc=indimail,dc=org"

The following LDAP search is requesting a listing of all entries starting from the base "dc=indimail,dc=org". This should return all of the entries that where added in the previous step.

% ldapsearch -x -b 'dc=indimail,dc=org' '(objectclass=*)'

# indimail.com
dn: dc=indimail,dc=org
objectClass: top
objectClass: dcObject
objectClass: organization
o: Home LDAP Network
dc: indimail

# Manager, indimail.com
dn: cn=Manager,dc=indimail,dc=org
objectClass: organizationalRole
cn: Manager

# users, indimail.com
dn: ou=users,dc=indimail,dc=org
ou: users
objectClass: top
objectClass: organizationalUnit

# addressbook, indimail.com
dn: ou=addressbook,dc=indimail,dc=org
ou: addressbook
objectClass: top
objectClass: organizationalUnit

Now that we have defined and imported our directory scheme, we are able to create user entries to populate the addressbook. The following is a simple example LDIF entry for a contact.

You can gain use slappasswd to generate a user password

% slappasswd -h {MD5} -s manny
{MD5}j+eKwOqr8vR0sN46lo4WXg==

The first line (dn:) designates where about in the directory the entry will belong when its imported, this should be changed to suit your needs.

% cat > newcontact.ldif
dn:uid=mbhangui,ou=addressbook,dc=indimail,dc=org
uid: mbhangui
cn: Manvendra Bhangui
gn: Manvendra
sn: Bhangui
o: Consim Info Pvt. Ltd.
l: Mandaivelli
street: #94 Coconut Republic
st: TN
postalCode: 600028
pager: +91 44 5555 1111
homePhone: +91 44 5555 1234
telephoneNumber: +91 44 5555 1235
facsimileTelephoneNumber: +91 44 5555 1236
mobile: +91 99401xxxxx
mail: m.bhangui@gmail.com
objectClass: top
objectClass: inetOrgPerson
userPassword: {MD5}j+eKwOqr8vR0sN46lo4WXg==
cntrl-d

The contents of the LDIF file can be added into the directory service using the "ldapadd" command below.

% ldapadd -x -D 'cn=Manager,dc=indimail,dc=org' -W -f newcontact.ldif
Enter LDAP Password:
adding new entry "uid=mbhangui,ou=addressbook,dc=indimail,dc=org"

If you do not require an address book and just require a basic user object to use for authenticaton, a basic user object can be created and imported into the LDAP server. This file uses the "UID" (User ID) string to distinguish the object and the contents are all that we need to create a basic authentication mechanism.

It should also be noted that this object is stored in the "users" organisational unit, which is located outside of the address book directory.=

% cat > useraccount.ldif
dn:uid=postmaster,ou=users,dc=indimail,dc=org
uid: postmaster
userPassword: {MD5}j+eKwOqr8vR0sN46lo4WXg==
objectClass: top
objectClass: account
objectClass: simpleSecurityObject
cntrl-d

% ldapadd -x -D 'cn=Manager,dc=indimail,dc=org' -W -f useraccount.ldif
Enter LDAP Password:
adding new entry "uid=postmaster,ou=users,dc=indimail,dc=org"

For mbhangui to authenticate to the server, one needs to pass
"uid=mbhangui,ou=users,dc=indimail,dc=org" as username along with the the plain text value of password, the hashed value is only for storage purposes.

% ldapsearch -x -b 'ou=AddressBook,dc=indimail,dc=org' \
-D "uid=mbhangui,ou=users,dc=indimail,dc=org" '(objectclass=*)' \
-s sub -w manny

Backing up LDAP Database

To export
% sudo /var/indimail/bin/svc -d /service/slapd.389
% slapcat -vl /etc/openldap/backup_slapd.ldif
% sudo /var/indimail/bin/svc -u /service/slapd.389

To import
% sudo /var/indimail/bin/svc -d /service/slapd.389
% slapadd -vl /etc/openldap/backup_slapd.ldif
% chown ldap.ldap /var/lib/ldap/*
% sudo /var/indimail/bin/svc -u /service/slapd.389

Email Client Settings

The last steps in setting up the shared address book is to configure the users email clients to access the LDAP server.

The following table contains some of the information needed to configure the client applications. Note the username will need to be written as the complete "distinguished name" value so the server knows which object to authenticate.

LDAP Server : your_host_IP:389
Search Base : ou=addressbook,dc=indimail,dc=org
Login Method : use distinguished name (if listed)
Username : uid=user,ou=addressbook,dc=indimail,dc=org
Password : As entered in newcontact.ldif file (plain text version)
Secure Connection: Never (unless encryption has been configured)

In the above 'user' is the actual user created in ldap by using ldapadd

References
  1. http://www.brennan.id.au/20-Shared_Address_Book_LDAP.html
  2. http://www.wains.be/mirrors/feldt.com/
  3. http://linsec.ca/Using_OpenLDAP_as_an_Address_Book

21 comments:

Chetanneo said...

I have go thorough this configuration but I cann't get success to configure. I think some of configuration are missing.

whenever i started the service an error of schema appears.

cprogrammer said...

what is the error you are getting?

Chetanneo said...

@400000004c161d3a021d197c supervise: fatal: unable to start slapd.389/run: exec format error

Chetanneo said...

/etc/init.d/ldap configtest
Checking configuration files for slapd: could not stat config file "/etc/openldap/schema/duaconf.schema": No such file or directory (2)
slaptest: bad configuration file!
[FAILED]

cprogrammer said...

do chmod +x /service/slapd.389/run /service/slapd.389/log/run

cprogrammer said...

check your openldap version which you have installed. It is probably not the latest. In that case comment out the schema which is giving error.

cprogrammer said...

You are getting exec format error. Show me the output of cat /service/slapd.389/run

Chetanneo said...

/service/slapd.389/run /service/slapd.389/log/run already have x permission & have already commented this schemas

my openldap ver is 2.3.43 n i think it's latest

I am using centos as OS

Chetanneo said...

output is
exec /usr/sbin/slapd -u ldap -f /etc/openldap/slapd.conf -d 0 2>&1

cprogrammer said...

have you managed to set it up?

Chetanneo said...

I am trying to compile openldap 2.4.21, but dependencies have big problem.

cprogrammer said...

then use your existing ldap installation and attempt to start by removing the schema that give error.

Also hope that you have put
#!/bin/sh in the first line of the run file

Chetanneo said...

Result of
ldapsearch2.4 -x -b 'dc=indimail,dc=org' '(objectclass=*)'

are

# extended LDIF
#
# LDAPv3
# base with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 50 Insufficient access

# numResponses: 1

cprogrammer said...

It means you don't have access to do anonymous bind. You need to do man on slapd.conf and put the right access control.

In my ldap version, I had to put the following at the right place (just after the database definition)

access to dn.subtree="ou=addressbook,dc=indimail,dc=org"
by anonymous auth
by self write
by users read
access to *
by anonymous auth
by self read
by users read

Chetanneo said...

I am not getting any single success to configure LDAP address book.

which version of ldap you are using ?

is it necessary to integrate with indimail.

this time I got following error

result: 50 Insufficient access

cprogrammer said...

LDAP and indimail are not at all related.

LDAP is Light Weight Directory Access Protocol and it has nothing to do with IndiMail. You do not require LDAP to be configured for IndiMail to work. Neither do you require IndiMail for LDAP to work.

You still have not configured access for anonymous bind and anonymous read. Unless you do that, you will continue to get

result: 50 Insufficient access

google and man slapd.conf(5) will be your friends. You need to define appropriate access in your slapd.conf

I tried multiple resources on the web using google and all of them worked. Please use google to find results on "How to use LDAP for addressbook"

I use openldap-2.4.21

Chetanneo said...

Thanks Sir,

I am trying all resources.

I am again let you know if getting problem

Chetanneo said...

yes, I have done it.

but as obvious issue remains. My email client is not showing addresses without searching.

What could be the issue ?

help me?

cprogrammer said...

Good and well done!!. Now you should do man on ldapsearch(1) and learn how to do ldapsearch and search for an addressbook entry. If ldapsearch works, then your email client will also work.

Chetanneo said...

Out put of
ldapsearch2.4 -x -b 'dc=cvteam,dc=local' '(objectclass=*)'
is showing like this :

# extended LDIF
#
# LDAPv3
# base with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 50 Insufficient access

# numResponses: 1

is Result: 50 Insufficient access generating any problem.

I am not adding contacts because of this error

cprogrammer said...

if you are getting access error, it means that you have not put the correct access lines in your slapd.conf for anon access. The access directives are discussed in detail in slapd.access(5) man page

IndiMail Queue Mechanism

Indimail has the ability of configuring multiple local and remote queues. A queue is a location on your hard disk where email are deposited ...