Issues with LDAP backend in OpenLDAP

openldapreplicationslapd

Good Morning;

After working on setting up an LDAP proxy server to replicate LDAP data, I keep getting the following message:

52a0b5ca send_ldap_result: conn=-1 op=0 p=3

52a0b5ca send_ldap_result: err=32 matched="" text=""

52a0b5ca ==> ldap_back_add("dc=basecorp,dc=net")

52a0b5ca =>ldap_back_getconn: conn 0x7f40ea0 fetched refcnt=1.

/usr/libexec/slapd: symbol lookup error:
/usr/libexec/openldap/back_ldap-2.4.so.2: undefined symbol:
ldap_add_ext

This is with OpenLDAP 2.4.37 on both a Solaris 10 x86 host as well as a RedHat 5.5 host. Both are installed from sources, including the latest BDB distro. sourceserver is the machine I wish to pull data from and sync to destserver (see configs below).

So, the only thing the two machines I've tried running the proxy on have in common is me (ugh!). Is the issue that I've setup the proxy backwards? Perhaps I'm not allowed to add an entry to an LDAP backend? Hopefully, one of y'all can examine my configs below and answer my question as well as many others out there.

My slapd.conf for the proxy:

database ldap
hidden on
suffix "dc=basecorp,dc=net"
rootdn "cn=Manager"
uri    ldaps://destserver01.dest.net:636

lastmod on


acl-bind  bindmethod=simple
          binddn="cn=Manager"
          credentials=mypassword

syncrepl  rid=500
          provider=ldaps://sourceserver01.dest.net:636
          binddn="cn=Manager"
          bindmethod=simple
          credentials=mypassword
          searchbase="dc=basecorp,dc=net"
          filter="(objectClass=*)"
          scope=sub
          schemachecking=on
          type=refreshAndPersist
          retry="5 5 300 5"

overlay   syncprov

Lastly, allow me to throw mud in the water:

I used nm:

[root@buildtest01 ~]# nm  /usr/libexec/openldap/back_ldap-2.4.so.2 | grep ldap_add
                 U ldap_add_ext

And there's my missing symbol. Wth!?

Best Answer

As surmised @c4f4t0r, you're not (yet) having configuration problems -- you're having build related problems.

TL;DR: don't use dynamic backends, they're mostly broken unless you fiddle with the build process. Skip to the update below for the gruesome details...


You probably have old or non-OpenLDAP LDAP libraries in the default system locations. I do not believe the configure script is smart enough to test for this condition, or that the build process is sufficiently robust to handle it. For example if an old libldap.so is found in a system library location then it will be used in preference to the correct and freshly installed libldap.so at runtime. Running ldd against back_ldap-2.4.so should show this.

You may be able to fix this (without rebuilding) by adding the relevant directory to the environment variable LD_LIBRARY_PATH so that the directory with the newest OpenLDAP libraries is searched first (make sure to export the variable).

Or, fix it (preferably) at build time, by running configure with the LDFLAGS environment variable set with an RPATH which will hard-code a library search path into the binaries you build.

You haven't given your configure options or installation path etc. I have used variations on this in the past:

export LDFLAGS="-L/usr/local/ssl/lib -Wl,-rpath,/usr/local/ssl/lib"

in the case where I want to use a non-system OpenSSL, the same applies for using a non-system version of BerkeleyDB. On Solaris you may need to use "-R" instead of "-rpath" (if you're using gcc with the Sun linker rather than the GNU linker):

export LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib"

In your case you probably just need to set the rpath (-Wl,-rpath or -R), not -L (though I recommend using both when for the cases of OpenSSL and BerkeleyDB).


Update You are building with:

/configure --prefix=/usr --sysconfdir=/etc --enable-slapd --enable-crypt \
    --enable-modules --enable-bdb=mod --enable-hdb=mod --enable-ldap=yes \
    --enable-perl=mod --enable-overlays=mod --with-tls --with-gnu-ld

Note "--enable-ldap=yes", this builds the LDAP-backend statically into slapd, it does not create a dynamically loadable back_ldap.so (i.e. --enable-ldap=mod). One possibility is that you have a stray back_ldap.so that you are trying to load into your server, and an un-needed moduleload back_ldap. However, slapd will not allow you to load a dynamic module when a static module of the same name exists, so your slapd binary does not appear to be as you have described.

Run slapd -VVV to confirm static backends.

Assuming back_ldap is static you should be able to work around this problem, and remove any errant moduleload and stale .so for good measure.

I have a strong suspicion there is some libtool, dependency error or linker issue lurking here. I can reproduce this with a dynamic back_ldap. ldap_add_ext is indeed an unresolved symbol which isn't necessarily a problem (due to explicit dlopen() for modules), but that symbol is not exported by slapd. It is exported by libldap.so, but that's not a dependency of back_ldap.so and nothing else causes libldap to be loaded. (This also means the advice I gave above won't solve the problem, since it's not simply as simple as a library path problem.)

What's happening (i.e. the error you're seeing) is that the symbol ldap_add_ext isn't being resolved until it's required ("lazy" binding). When you try to add an LDAP object it is finally required of course. Then the wheels come off. (Should you feel the urge, you can break it at start-time by exporting LD_BIND_NOW=1 which turns off lazy binding, then start slapd, though odds are a different symbol will trip it.)

Right now the simplest option is to work with a static back_ldap (--enable-ldap=yes, and perhaps make clean && make depend && make install to be certain that slapd is correctly built). A less simple option is to use LD_PRELOAD=/usr/lib/libldap.soLD_PRELOAD=/usr/lib/libldap_r.so to work around the dependency problem, and cross-your fingers hoping that doesn't have some odd side-effects.


OK, this ancient email covers the problem: http://www.openldap.org/lists/openldap-software/200211/msg00469.html slapd is linked against a static libldap_r.a by default, this limits the symbols that will be available to those known at link time. Since the dynamic modules are loaded at run time with dlopen() the linker doesn't have visibility of their requirements (symbols/libraries).

One might reasonably conclude that dynamic building of (some) backends has been pretty much broken for some time.

So, either don't use dynamic backends (recommended), or fudge the build (not so recommended) with something like:

make depend && make
rm servers/slapd/slapd
LTSTATIC="" make -e     # alternative to editing the Makefile
make install

This links slapd against the libldap_r.so you just built instead of the .a, so all symbols can be loaded when needed (it also makes slapd about 15% smaller on disk). I haven't run an operational LDAP server with this, YMMV. There must be some similar or alternative solutions used by distros...