It took me a while, but finally I removed all bugs (hopefully) and it works as a charm.
Since I'm using Ubuntu 16, I'll provide complete manual for others who get
lost. Note that in new versions of LDAP us usually used cn=config format,
so I'll show how to create database in this format.
1) Install dev packages to be able compile sources (maybe you will need to
install some additional packages)
$ sudo apt install gcc libdb-dev libsasl2-dev make libltdl-dev && echo "OK"
2) Make sure you do not have Ubuntu's LDAP server. If you're not sure sure,
simply try following command and if it FAIL, it is OK. Otherwise you need
to uninstall Ubuntu's LDAP, or change port settings in your custom LDAP
server
$ sudo service slapd stop
slapd: unrecognized service # This is OK, else uninstall slapd package
3) Simply remove (3A) or configure (3B) "apparmor" to avoid strange start
failure and another "permission denied" errors. Choice is up to you
(security vs convenience)
3A) Remove apparrmor
$ sudo apt remove apparmor
3B) Configure apparmor
Create new file and add following lines (without "====" separator):
$ sudo vim /etc/apparmor.d/opt.openldap.libexec.slapd
==============================================================================
# vim:syntax=apparmor
# Last Modified: Fri Jan 4 15:18:13 2008
# Author: Jamie Strandboge <jamie@ubuntu.com>
#include <tunables/global>
/opt/openldap/libexec/slapd {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/p11-kit>
#include <abstractions/ssl_certs>
/etc/ssl/private/ r,
/etc/ssl/private/* r,
/etc/sasldb2 r,
capability dac_override,
capability net_bind_service,
capability setgid,
capability setuid,
/etc/gai.conf r,
/etc/hosts.allow r,
/etc/hosts.deny r,
# ldap files
/opt/openldap/etc/openldap/** kr,
/opt/openldap/etc/openldap/slapd.d/** rw,
# kerberos/gssapi
/dev/tty rw,
/etc/gss/mech.d/ r,
/etc/gss/mech.d/* kr,
/etc/krb5.keytab kr,
/opt/openldap/var/tmp/ rw,
/opt/openldap/var/tmp/** rw,
# the databases and logs
/opt/openldap/var/openldap-data/ r,
/opt/openldap/var/openldap-data/** rwk,
# lock file
/opt/openldap/lib/alock kw,
# pid files and sockets
/opt/openldap/var/run/* w,
/opt/openldap/var/run/ldapi rw,
/opt/openldap/var/run/socket rw,
/opt/openldap/lib/ r,
/opt/openldap/lib/* mr,
/opt/openldap/libexec/slapd mr,
# Site-specific additions and overrides. See local/README for details.
# #include <local/opt.openldap.libexec.slapd>
}
==============================================================================
And restart "apparmor" service ($ sudo service apparmor restart)
4) configure - Enable "meta" and "ldap" backend + specific environment
settings and install it.
sudo mkdir -p /opt/openldap/ && \
./configure --enable-meta --enable-ldap --enable-spasswd \
--prefix=/opt/openldap/ && \
echo "Configure OK" && \
make -j4 depend && echo "Make depend OK" && make -j4 && echo "Make OK" && \
su root -c 'make install' && echo "Install OK"
5) Create new group "ldap_mod" for example and change rights.
$ sudo useradd -rMU ldap_mod && \
sudo touch /opt/openldap/var/run/slapd.pid \
/opt/openldap/var/run/slapd.m.args && \
sudo mkdir /opt/openldap/etc/openldap/slapd.d && \
sudo chown -R ldap_mod /opt/openldap/ && \
ls -l /opt/openldap/ && echo "All OK"
6) Create new service. Simply put following text to "/etc/init.d/ldap_mod"
==============================================================================
#!/bin/sh
### BEGIN INIT INFO
# Provides: slapd
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: OpenLDAP standalone server (Lightweight Directory Access Protocol)
### END INIT INFO
# Specify path variable
PATH=/opt/openldap/bin:/opt/openldap/libexec:/opt/openldap/sbin:/bin/:/usr/bin/:/sbin/
. /lib/lsb/init-functions
# Kill me on all errors
set -e
# Set the paths to slapd as a variable so that someone who really
# wants to can override the path in /etc/default/slapd.
SLAPD=/opt/openldap/libexec/slapd
# Stop processing if slapd is not there
[ -x $SLAPD ] || exit 0
# debconf may have this file descriptor open and it makes things work a bit
# more reliably if we redirect it as a matter of course. db_stop will take
# care of this, but this won't hurt.
exec 3>/dev/null
# Source the init script configuration
#if [ -f "/etc/default/slapd" ]; then
# . /etc/default/slapd
#fi
# Instead of file, define it here.
#SLAPD_CONF="/opt/openldap/etc/openldap/slapd.conf"
SLAPD_CONF="/opt/openldap/etc/openldap/slapd.d"
SLAPD_USER="ldap_mod"
SLAPD_GROUP="ldap_mod"
SLAPD_PIDFILE="/opt/openldap/var/run/slapd.pid" # Check ldap.conf
SLAPD_SERVICES="ldap:/// ldapi:///"
# Additional options to pass to slapd
#SLAPD_OPTIONS=" -d 0xFFFFFFFF -s 7"
SLAPD_OPTIONS=" "
# Load the default location of the slapd config file
if [ -z "$SLAPD_CONF" ]; then
if [ -e /opt/openldap/etc/openldap/slapd.d ]; then
SLAPD_CONF=/opt/openldap/etc/openldap/slapd.d
else
SLAPD_CONF=/opt/openldap/etc/openldap/slapd.conf
fi
fi
# Stop processing if the config file is not there
if [ ! -r "$SLAPD_CONF" ]; then
log_warning_msg "No configuration file was found for slapd at $SLAPD_CONF."
# if there is no config at all, we should assume slapd is not running
# and exit 0 on stop so that unconfigured packages can be removed.
[ "x$1" = xstop ] && exit 0 || exit 1
fi
# extend options depending on config type
if [ -f "$SLAPD_CONF" ]; then
SLAPD_OPTIONS="-f $SLAPD_CONF $SLAPD_OPTIONS"
elif [ -d "$SLAPD_CONF" ] ; then
SLAPD_OPTIONS="-F $SLAPD_CONF $SLAPD_OPTIONS"
fi
# Find out the name of slapd's pid file
if [ -z "$SLAPD_PIDFILE" ]; then
# If using old one-file configuration scheme
if [ -f "$SLAPD_CONF" ] ; then
SLAPD_PIDFILE=`sed -ne 's/^pidfile[[:space:]]\+\(.\+\)/\1/p' \
"$SLAPD_CONF"`
# Else, if using new directory configuration scheme
elif [ -d "$SLAPD_CONF" ] ; then
SLAPD_PIDFILE=`sed -ne \
's/^olcPidFile:[[:space:]]\+\(.\+\)[[:space:]]*/\1/p' \
"$SLAPD_CONF"/'cn=config.ldif'`
fi
fi
# XXX: Breaks upgrading if there is no pidfile (invoke-rc.d stop will fail)
# -- Torsten
if [ -z "$SLAPD_PIDFILE" ]; then
log_failure_msg "The pidfile for slapd has not been specified"
exit 1
fi
# Make sure the pidfile directory exists with correct permissions
piddir=`dirname "$SLAPD_PIDFILE"`
if [ ! -d "$piddir" ]; then
mkdir -p "$piddir"
[ -z "$SLAPD_USER" ] || chown -R "$SLAPD_USER" "$piddir"
[ -z "$SLAPD_GROUP" ] || chgrp -R "$SLAPD_GROUP" "$piddir"
fi
# Pass the user and group to run under to slapd
if [ "$SLAPD_USER" ]; then
SLAPD_OPTIONS="-u $SLAPD_USER $SLAPD_OPTIONS"
fi
if [ "$SLAPD_GROUP" ]; then
SLAPD_OPTIONS="-g $SLAPD_GROUP $SLAPD_OPTIONS"
fi
# Check whether we were configured to not start the services.
check_for_no_start() {
if [ -n "$SLAPD_NO_START" ]; then
echo 'Not starting slapd: SLAPD_NO_START set in /etc/default/slapd' >&2
exit 0
fi
if [ -n "$SLAPD_SENTINEL_FILE" ] && [ -e "$SLAPD_SENTINEL_FILE" ]; then
echo "Not starting slapd: $SLAPD_SENTINEL_FILE exists" >&2
exit 0
fi
}
# Tell the user that something went wrong and give some hints for
# resolving the problem.
report_failure() {
log_end_msg 1
if [ -n "$reason" ]; then
log_failure_msg "$reason"
else
log_failure_msg "The operation failed but no output was produced."
if [ -n "$SLAPD_OPTIONS" -o \
-n "$SLAPD_SERVICES" ]; then
if [ -z "$SLAPD_SERVICES" ]; then
if [ -n "$SLAPD_OPTIONS" ]; then
log_failure_msg "Command line used: slapd $SLAPD_OPTIONS"
fi
else
log_failure_msg "Command line used: slapd -h '$SLAPD_SERVICES' $SLAPD_OPTIONS"
fi
fi
fi
}
# Start the slapd daemon and capture the error message if any to
# $reason.
start_slapd() {
if [ -z "$SLAPD_SERVICES" ]; then
echo "Running command: "$SLAPD" "$SLAPD_OPTIONS""
reason="`start-stop-daemon --start --verbose --oknodo \
--pidfile "$SLAPD_PIDFILE" \
--exec $SLAPD -- $SLAPD_OPTIONS 2>&1`"
else
echo "Running command: "$SLAPD" -h '"$SLAPD_SERVICES"' "$SLAPD_OPTIONS""
reason="`start-stop-daemon --start --verbose --oknodo \
--pidfile "$SLAPD_PIDFILE" \
--exec $SLAPD -- -h "$SLAPD_SERVICES" $SLAPD_OPTIONS 2>&1`"
fi
echo "$reason"
# Backward compatibility with OpenLDAP 2.1 client libraries.
#if [ ! -h /var/run/ldapi ] && [ ! -e /var/run/ldapi ] ; then
# ln -s slapd/ldapi /var/run/ldapi
#fi
}
# Stop the slapd daemon and capture the error message (if any) to
# $reason.
stop_slapd() {
reason="`start-stop-daemon --stop --quiet --oknodo --retry TERM/10 \
--pidfile "$SLAPD_PIDFILE" \
--exec $SLAPD 2>&1`"
}
# Start the OpenLDAP daemons
start_ldap() {
trap 'report_failure' 0
log_daemon_msg "Starting OpenLDAP (custom)" "slapd"
start_slapd
trap "-" 0
log_end_msg 0
}
# Stop the OpenLDAP daemons
stop_ldap() {
trap 'report_failure' 0
log_daemon_msg "Stopping OpenLDAP (custom)" "slapd"
stop_slapd
trap "-" 0
log_end_msg 0
}
case "$1" in
start)
check_for_no_start
start_ldap ;;
stop)
stop_ldap ;;
restart|force-reload)
check_for_no_start
stop_ldap
start_ldap
;;
status)
status_of_proc -p $SLAPD_PIDFILE $SLAPD slapd
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
;;
esac
==============================================================================
9) Create old-style slapd-meta_test.conf for example at your home directory.
At sources is slapd-meta.conf, which can be your reference. Replace
variables @SOMETHING@ with real data. There is my example which I save to
my home directory:
==============================================================================
# master slapd config -- for testing
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2016 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
include ./servers/slapd/schema/core.schema
include ./servers/slapd/schema//cosine.schema
include ./servers/slapd/schema/inetorgperson.schema
include ./servers/slapd/schema/openldap.schema
include ./servers/slapd/schema/nis.schema
include ./servers/slapd/schema/ppolicy.schema
pidfile /opt/openldap/var/run/slapd.pid
argsfile /opt/openldap/var/run/slapd.m.args
#ldapmod#modulepath ../servers/slapd/back-ldap/
#ldapmod#moduleload back_ldap.la
#metamod#modulepath ../servers/slapd/back-meta/
#metamod#moduleload back_meta.la
#monitormod#modulepath ../servers/slapd/back-monitor/
#monitormod#moduleload back_monitor.la
# seems to improve behavior under very heavy load
# (i.e. it alleviates load on target systems)
threads 8
#######################################################################
# database definitions
#######################################################################
database meta
suffix "dc=company,dc=com"
rootdn "cn=binder,dc=company,dc=com"
rootpw bind
chase-referrals yes
#nretries forever
nretries 100
# 1 sec timeout for binds
bind-timeout 1000000
#norefs true
# remote1
uri "ldap://somewhere.eu:389/ou=cz,dc=company,dc=com"
# ubtree-exclude "ou=Excluded,ou=Meta,o=Example,c=US"
suffixmassage "ou=cz,dc=company,dc=com" "dc=cz,dc=company,dc=eu"
###pseudorootdn "cn=manager,ou=meta,dc=example,dc=com"
###pseudorootpw secret
idassert-bind bindmethod=simple
binddn="cn=binder for CZ,dc=cz,dc=company,dc=eu"
credentials="binders's secret password"
mode=none
flags=non-prescriptive
#idassert-authzFrom "dn.exact:cn=Manager,o=Local"
# remote2
uri "ldap://somewhere.else.eu:389/ou=de,dc=company,dc=com"
#subtree-include "dn.subtree:o=Example,c=US"
suffixmassage "ou=de,dc=company,dc=com" "dc=company,dc=eu"
###pseudorootdn "cn=manager,dc=example,dc=com"
###pseudorootpw secret
idassert-bind bindmethod=simple
binddn="cn=binder for DE,dc=de,dc=company,dc=eu"
credentials="binders's secret password2"
mode=none
flags=non-prescriptive
#idassert-authzFrom "dn.exact:cn=Manager,o=Local"
#limits dn.exact="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example,c=US" time=1 size=8
# This is only for binding as the rootdn
#database meta
#suffix "o=Local"
#rootdn "cn=Manager,o=Local"
#rootpw secret
#uri "ldap://127.3.3.3:389/o=Local"
#monitor#database monitor
==============================================================================
7) Create new (void) directory:
$ mkdir -p /tmp/slapd.d
8) Move/stay in directory with LDAP sources (so your modified paths will
work) and convert old style-syntax to new one:
$ rm -rf /tmp/slapd.d/* && \
sudo touch /opt/openldap/var/run/slapd.pid \
/opt/openldap/var/run/slapd.m.args && \
./servers/slapd/slaptest -f ~/slapd-meta_test.conf -F /tmp/slapd.d/ && \
echo "Conversion OK"
9) If conversion is OK, copy database to slapd.d
$ sudo rm -rf /opt/openldap/etc/openldap/slapd.d/* && \
sudo cp -r /tmp/slapd.d/* /opt/openldap/etc/openldap/slapd.d/ && \
sudo chmod 700 /opt/openldap/etc/openldap/slapd.d/ && \
sudo chown -R ldap_mod:ldap_mod /opt/openldap/ && \
echo "All right"
7) Update rc.d. This should be problem-less. Run it only once. It is enough.
$ sudo update-rc.d ldap_mod defaults && \
sudo update-rc.d ldap_mod enable && echo "All OK"
8) Try to run service. If it fails, you need to find out reason. Good start
might be /var/log/syslog.
$ sudo service ldap_mod restart && echo OK
##############################################################################
I know that configuration files could be more flexible thanks to variables,
but I wanted to keep it simple. Hopefully it will help someone and save some
time.
Thanks again for great support!
Best regards
Martin Stejskal