Bind failed (port=389), OS error=(13)

This is the last line from $ORACLE_HOME/ldap/log/oidldapd01.log for a 10g AS R3 Oracle Internet Directory that isn’t responding to an ldapbind or an ldapsearch, but that opmnctl status shows as “Alive”(opmn is an inveterate liar, in case you didn’t know by now):

2011/05/05:13:31:37 * Main:0 * sgslunlListen: Bind failed (port=389), OS error=(13)

What should be there instead is something like:

2011/05/05:13:34:01 * DispatcherListener:2 * Listening on Non SSL port = 389 and SSL port = 636

So what’s the problem?

I’ll tell you: someone has been messing with the file ownership and permissions on the file system for your directory server, that’s what.

Mehendra Babu over on Online Apps DBA has a very good article on this problem entitled sgslunlListen: Bind failed (port=389), OS error=(13)” error in ldap log: Unable to bind to ldap. Thanks to my partner-in-crime, Anil Prakash for ferretting that one out.

The root of the problem is, well, that the oidldapd executable for the LDAP server daemon needs to be setuid root for anything to work. Of course a security conscious Oracle application setup is always going to run as someone else, like a system “oracle” user. The conflict arises because of a decision made back in the Stone Age of Unix computing that any daemon listening on TCP port lower that 1024 must be started by root. This Unix “feature” has always been a bit of a stumbling block for Java, which wasn’t originally designed to handle these kinds of things (it was only supposed to be run on toasters, refrigerators and other such devices, after all). That’s why new installations of Oracle’s directory server used to listen by default on port 3060, and why even today the “pure Java” Apache Directory Server wouldn’t run on the standard ports of 389/636.

But Oracle came up with a clever solution to the problem (which it also uses to get its version of the Apache HTTP server to run on port 80): it changes the permissions of the daemon executable to setuid root during the installation process. The script in the root of $ORACLE_HOME is the actual code that works this magic.

These permissions don’t change on their own. Someone has to deliberately reset permissions on the executable or the file system hierarchy where it lives. Look for something like “chown -R oracle:dba $ORACLE_HOME” or “chmod -R ugo+rwx $ORACLE_HOME” in root’s .bash_history. Either or both will mess things up for you.

The best way to fix this is to just run again, as root. While you’re at it, you may want to check permissions on any other infrastructure components you may have on the same machine (in our case we found someone had also changed things in the separate $ORACLE_HOME we have for OSSO).

This is what the permissions for the critical files mentioned in Mehendra’s article should look like in context:

-rwxr-xr--oracle dba 2025 Mar 2 20:28 oidadmin
-rwxr-xr--oracle dba 2447 Mar 2 20:29 oidca
-rwxr-xr--oracle dba 1668993 Mar 4 00:12 oidctl
-rwxr-xr--oracle dba 834 Mar 2 20:29 oidemdpasswd
-rws--x---root dba 2741453 Mar 4 00:12 oidldapd
-rws--x---oracle dba 1683507 Mar 4 00:12 oidmon
-rwxr-xr--oracle dba 1356 Mar 4 00:12 oidpatchca
-rwxr-xr--oracle dba 2757 Mar 4 00:12 oidprovtool
-rws--x---oracle dba 1839779 Mar 4 00:12 oidrepld

Note that oidldapd is owned by root and has the “s” bit set for “setuid”. In addition, although owned by the oracle system user, both oidmon and oidrepld are setuid (in this case setuid oracle).

Here are the relevant lines from

if [ -f oidmon ]; then
$ECHO "Setting oidmon file protections"
$CHMOD 0710 oidmon # only owner and group has execute permission
$CHMOD u+s oidmon

if [ -f  oidldapd ];then
$ECHO "Setting oidldapd file protections"
if [ "389" -eq $NONSSLPORT -o "636" -eq $SSLPORT ]; then
$CHOWN root oidldapd # make oidldapd setuid root for security
$CHMOD 4710 oidldapd # only owner and group has execute permission
$CHMOD 0710 oidldapd # only owner and group has execute permission
$CHMOD u+s oidldapd

if [ -f oidrepld ] ; then
$ECHO "Setting oidrepld file protections"
$CHMOD 0710 oidrepld # only owner and group has execute permission
$CHMOD u+s oidrepld

If you’re an experienced sysadmin by now you may be asking the question: why bother with the script, why not just set these ownerships and permissions on those specific files? Actually it probably would work if you did that. Here are the commands to do it (courtesy of Mehendra):

chown root:dba oidldapd
chmod 4710 oidldapd
chmod 4710 oidmon
chmod 4710 oidrepld

Of course there’s no guarantee that you won’t see other problems related to a mass change of file ownership and permissions (like a pid file that Anil found was owned by root). So go ahead and try the surgical route if you like, but keep in mind that Oracle’s prescription for this particular ailment is to run YMMV (Your Mileage May Vary).

Oh, by the way. If Oracle ever moves to some kind of performance-based testing for certification, like Red Hat, this would be a great test problem. Come to think of it, this could also be a good interview question!