Install & Configure OpenLDAP in Linux

I’m doing this only because I’ve done this multiple times and never documented it and had to go through and do multiple google searches each time. Hopefully this is the last time.

First off, install the OpenLDAP server and clients. I’ll install the client on the server too so that I could easily troubleshoot. If you’re using IPtables, you’ll need to open up ports 389 and 636 as well.

yum -y install openldap-clients openldap-servers

Next, I want to do some logging so that I could get messages if I need to troubleshoot. Here’s how to enable the syslog side of logging. Configuring the details of logging from the LDAP server side comes from the cn=config information.

mkdir /var/log/openldap
echo "local4.* /var/log/openldap/openldap.log" >> /etc/rsyslog.conf
systemctl restart rsyslog

Configuring TLS for openldap. This just edits the /etc/sysconfig/slapd file and adds ldaps to it so that it will listen on that port.

sed -i "s,ldap:///,ldap:/// ldaps:///," /etc/sysconfig/slapd

Restart the LDAP server for ldaps to take effect.

systemctl start slapd
systemctl enable slapd

Extending schema of openldap so that it accepts a bunch of the common attributes that typical directory servers have. The adschema attached is to support the MemberOf attribute, commonly used by AD servers. You can put the file anywhere you want. I happened to do this in Vagrant, so my file was in /vagrant.

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /vagrant/adschema.ldif

I’m also extending the schema using some of the schema files provided by OpenLDAP itself.

Now it’s time to configuring rootdn. This is basically the top of the LDAP tree. You should download the file and edit it. Change your directory manager password and the rootdn to whatever you like. You can use dc=xxx or o=xxx.

ldapmodify -Y EXTERNAL -H ldapi:/// -f /vagrant/config.ldif

Now we can add the users. Here’s a sample ldif for the users. Obviously, you’ll need to change the directory to match your rootdn.

ldapadd -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -w password -f /vagrant/directory.ldif

Congratulations! Your LDAP server is now running. You can test by running this:

ldapsearch -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -b 'dc=poc,dc=segmentationpov,dc=com' objectclass=* -w password

It should return your entire directory that you uploaded in directory.ldif.

I enabled SSL earlier, but if you try an ldapsearch with SSL, you’ll get this:

[[email protected] certs]# ldapsearch -H ldaps:// -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -w password -b 'dc=poc,dc=segmentationpov,dc=com' objectclass=* -ZZ
ldap_start_tls: Can't contact LDAP server (-1)
additional info: TLS: hostname does not match CN in peer certificate

If you want to ignore this and move forward, the setting is on the client side. You can change it in /etc/openldap/ldap.conf. Just put in there:


If you get a message like this:

[[email protected] certs]# ldapsearch -H ldaps:// -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -w password -b 'dc=poc,dc=segmentationpov,dc=com' objectclass=* -ZZ
ldap_start_tls: Operations error (1)
additional info: TLS already started

The issue is that you’re trying to run StartTLS in 2 places. You can omit the -ZZ and run like this:

ldapsearch -H ldaps:// -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -w password -b 'dc=poc,dc=segmentationpov,dc=com' objectclass=*

or run with the -ZZ like this:

ldapsearch -H ldap:// -x -D cn=ldapadm,dc=poc,dc=segmentationpov,dc=com -w password -b 'dc=poc,dc=segmentationpov,dc=com' objectclass=* -ZZ

That’s just using the default certificate that comes with OpenLDAP. If you want to use your own certificate, you can put them in

ldapmodify -Y EXTERNAL -H ldapi:/// -f tls7.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
modifying entry "cn=config"
SV-LT-1361:Downloads altonyu$ openssl s_client -connect
depth=0 C = US, ST = CA, L = San Francisco, O = ShocKNetworK, CN =, emailAddress = [email protected]
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = CA, L = San Francisco, O = ShocKNetworK, CN =, emailAddress = [email protected]
verify error:num=21:unable to verify the first certificate
verify return:1
Certificate chain
0 s:/C=US/ST=CA/L=San Francisco/O=ShocKNetworK/[email protected]
i:/C=US/ST=California/O=ShocKNetworK/OU=Security/[email protected]
Server certificate

Sendmail routing through Microsoft Active Directory

Sendmail routing through Microsoft Active Directory

To give credit where credit is due, the attachment was sent to me from Randy Fox from csgsystems. There’s one bug with public folders. The workaround is to create a mailing list by the same name and make the public folder a member of the list.

If you’re reading this, you are probably running a Microsoft Exchange
Server or probably currently already have sendmail relaying to an Exchange
Server and want to improve your setup.

Most sendmail to exchange setups will take mail and blindly relay the mail
over. If yours is like this, you will know that you get email bounces that
can go nowhere because most of the initial intentions of the emails were
for spam and they would just send messages to users that they don’t know
even exist. A major problem with this is that it will hold up your sendmail
queue and hinder your performance as it will try to send these emails just
as much as the ones that are important and need to be sent out immediately.
This article will show you how to use sendmail’s ldap features to look into
the Active Directory to see where the mail should go and have sendmail send
it there. By having sendmail look into the Active Directory, it will know
whether users exist and will stop immediately after the “RCPT TO” in the
envelope if users don’t exist, eliminating the useless, bounce emails that
never get anywhere.

This procedure is not fully supported by Sun support because of the amount
of customization required.

First off, you will need a version of sendmail that has ldap capabilities
compiled into it. You can check this with:

/usr/lib/sendmail -d0.11 < /dev/null

Version 8.12.8+Sun

When you see LDAPMAP, you know that it will work. Solaris 7-9 should all
work. Patches are available for those that don’t.

The Microsoft Active Directory is a different ldap server than your typical
ldap server, so you will want to browse the directory and learn more about
how it’s designed. You will need to find or create a user that can browse
the Active Directory.

For the sake of simplicity, this example will use the Administrator userid
and his password to bind to the Active Directory server and find view its

For Solaris 8-9, if you have the SUNWlldap package installed, you can use
the ldapsearch command located /usr/bin. Run something like:

/usr/bin/ldapsearch -L -D “cn=Administrator, cn=Users, dc=domain, dc=com” \
-h -b “dc=domain,dc=com” objectclass=* \
> /tmp/active_directory.ldif

It will ask you for a password. You want to input the Windows
Administrator’s password there. You can open the /tmp/active_directory.ldif
file and read it and you can find a lot of the information in the directory

If you do not have the ldapsearch command, while logged in as Administrator
on the Exchange server, you can achieve a similar result in Windows with

ldifde -f c:\temp\export.ldif -v

Upon knowing what’s in the Active Directory, you can proceed to plug this
data into your sendmail configuration.

Because the Active Directory is a little different from your standard ldap
server, some hacks are required to make sendmail work.

You want to go into your /usr/lib/mail/hack directory. You can create it if
the directory isn’t there. (The files are attached.) In there, you want to create a file called
AD_ldap_routing.m4 and inside of it have:

# Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
# All rights reserved.
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.

VERSIONID(`$Id: ldap_routing.m4,v 8.8 2001/06/27 21:46:31 gshapiro Exp $')

# Check first two arguments. If they aren't set, may need to warn in proto.m4
ifelse(len(X`'_ARG1_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')')
ifelse(len(X`'_ARG2_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')')

# Check for third argument to indicate how to deal with non-existant
# LDAP records
ifelse(len(X`'_ARG3_), `1', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')',
 _ARG3_, `passthru', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')',
 `define(`_LDAP_ROUTING_', `_MUST_EXIST_')')

# Check for fouth argument to indicate how to deal with +detail info
ifelse(len(X`'_ARG4_), `1', `',
 _ARG4_, `strip', `define(`_LDAP_ROUTE_DETAIL_', `_STRIP_')',
 _ARG4_, `preserve', `define(`_LDAP_ROUTE_DETAIL_', `_PRESERVE_')')

# LDAP routing maps
Kldapmh ifelse(len(X`'_ARG1_), `1',
 `ldap -1 -v msExchHomeServerName,msExchExpansionServerName -k (|(mail=%0)(proxyaddresses=smtp:%0))',

Kldapmra ifelse(len(X`'_ARG2_), `1',
 `ldap -1 -v targetAddress -k (|(mail=%0)(proxyaddresses=smtp:%0))',

The next step is to make the modifications to your .mc file.

The first feature we should add is a mailertable to tell sendmail where to
send mail with different ldapsearch results.

So we add the line:

To add the ldap features into sendmail. Add the lines (of course, you put
in your domains):
LDAPROUTE_DOMAIN(`')dnl # what domain to do ldap lookups for.
LDAPROUTE_DOMAIN(`')dnl # alternate domain to do ldap lookups for.

You then need to specify your Active Directory settings (this all fits on
one line). You will also need to create the file /etc/mail/ldap.passwd. (We
will do this later)

define(`confLDAP_DEFAULT_SPEC',`-h -M simple -d "cn=Administrator, cn=Users, dc=domain, dc=com" -P /etc/mail/ldap.passwd -p 389 -b "dc=domain, dc=com"')

We will now have to add some custom rulesets. There’s also one line you need to change here:

R<> </ o=CSG Systems , Inc . / ou=CSG / cn=Configuration / cn=Servers / $+> <$+> <$+> <$*> $>LDAPMailertable <$1> $2

Make it match your organzation. You can find this by looking at your
active_directory.ldif file and seeing
the msExchHomeServerName attribute. Every user entry should have something

msExchHomeServerName: /o=Domain/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=domaincontroller

With that, you just strip off the last cn= and make spaces in between.

R$* < @ $=m . > $* $#esmtp [email protected] $2 $: $1 < @ $2 . > $3 internal addr delivered to host
R$* < @ $+ . $=m . > $* $#esmtp [email protected] $2 . $3 $: $1 < @ $2 .$3 . > $4 internal w/host

# Begin custom LDAP rule set.
# the following lines are essentually copied from the proto.m4 file. They are entered here to maintain the proper,
# original flow control but process the Active Directory response properly.
# pass names that still have a host to a smarthost (if defined)
R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name

# deal with other remote names
R$* < @$* > $* $#esmtp [email protected] $2 $: $1 < @ $2 > $3 [email protected]

# handle locally delivered names
R$=L $#local $: @ $1 special local names
R$+ $#local $: $1 regular local names

#do the LDAP lookup for the Exchange Mail Host
R<$+><$+><$*> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> <$3>

# if mailRoutingAddress (targetAddress) and local or non-existant mailHost,
# return the new mailRoutingAddress
R<$+> <$=w> <$+> <$+> <$*> [email protected] $>Parse0 $>canonify $1
R<$+> <> <$+> <$+> <$*> [email protected] $>Parse0 $>canonify $1

# fix hostname in Mailertable, relay from there
R<$+> <$+> <$+> <$+> <$*> $>LDAPMailertable <$2> $>canonify $1

# if no mailRoutingAddress and local mailHost,
# return original address
R<> <$=w> <$+> <$+> <$*> [email protected] $2

# if no mailRoutingAddress and non-local mailHost,
# relay to mailHost (Exchange Server) with original address
# "de-AD" response at same time
# You'll need to do the query manually the find the proper stuff to pull out
R<> </ o=CSG Systems , Inc . / ou=CSG / cn=Configuration / cn=Servers / $+> <$+> <$+> <$*> $>LDAPMailertable <$1> $2

# if still no mailRoutingAddress and no mailHost,
# try @domain
R<> <> <$+> <$+ @ $+> <$*> [email protected] $>LDAPExpand <$1> <@ $3> <$4>

# if no mailRoutingAddress and no mailHost and this was a domain attempt,
# return the original address
R<> <> <$+> <@ $+> <$*> [email protected] $1
# End of custom LDAPExpand rule set

You now want to create your cf file.

/usr/ccs/bin/m4 ../m4/cf.m4 >

Now that we’re done with the cf file, we need to supply the other files to
the configuration.
Create the ldap.passwd file:
echo “activedirectorypassword” > /etc/mail/ldap.passwd

Create the mailertable to tell sendmail where to send the mail. When we
stripped the last cn= off of the msExchHomeServerName, we will take that
and put it here. So my /etc/mail/mailertable will look like:

After you create this file, you will need to put it in the database for
sendmail to read it. Do this by running the command:
makemap -v hash /etc/mail/mailertable < /etc/mail/mailertable

You will also need to tell sendmail that you take mail for the domain as
well, so you want to put your domain in /etc/mail/local-host-names.
echo “” > /etc/mail/local-host-names

Now we will need to restart sendmail and test it. Run a command like this
for a user in the Active Directory:
/usr/lib/sendmail -bv [email protected]

You should see: [email protected]… deliverable: mailer esmtp, host, user [email protected]

If you run the same command on a user that’s not in the Active Directory,
you should get:
/usr/lib/sendmail -bv [email protected]
[email protected]… User unknown

Once you’ve got this, you’re all set!

Some ideas on troubleshooting:

If you see
/usr/sbin/sendmail -bv [email protected]
[email protected]… deliverable: mailer relay, host cn=exchangeserver, user
[email protected]

You probably forgot the mailertable. The mailertable translates the cn=host
to the actual host and tells it which protocol to use to send the mail. In
our case, we use esmtp.

If you see something like this:
/usr/sbin/sendmail -bv [email protected]
[email protected]… deliverable: mailer esmtp, host, user
>/o=domain/ou=First.Administrative.Group/cn=Configuration/cn=Servers/[email protected]<

You have the wrong data in the area where it says:
# relay to mailHost (Exchange Server) with original address
# “de-AD” response at same time
in the file.


Because it’s hard to read the .mc file stuff in the text, you can download the files here: AD_Routing.tar