[moon] home
IPv4

Erlkönig: Service lookups fail

Settings in /etc/nsswitch.conf can cripple network apps.
parent
[parent webpage]

server
[webserver base]

search
[search erlkonig webpages]

trust
[import certificates]


homes
[talisman]
[zoion]

Problem

In this scenario, getservent() and related library calls fail, even though /etc/services is present, correct, and appropriately permissioned. Side effects include the failure of utilities such as telnet, syslogd, and various daemons which configuring listener ports defined by service name.

By extension, this problem may also affect other NSS lookups, including but not limited to: hosts, passwd, group, shadow, ethers, netmask, protocols, rpc, netgroup, publickey, automount, aliases, bootparams, etc. In most cases problems relating to user, automounts, and aliases information will be more obvious.

Affected

  • Probably affects most Unixes based on the GNU C Library
  • Seen in Debian 3.1 (Sarge) with GNU Libc 2.3.2 (libc6)

Cause

The manual page for nsswitch.conf provides an example based on NIS which does not translate directly to the best one for LDAP for most environments. The use of [NOTFOUND=return] is generally only applicable to scenarios where the appropriate NSS database was known to exist and be the sole authoritive source, such as seen in many NIS deployments. However, many LDAP deployments serve solely user account information, and would first need to have more schemas activated and entries added to support the additional NSS lookups.

Reproduction

You have the problem if the following code, when run, outputs “getservbyname - failed”.

#include <stdio.h>
#include <netdb.h>

int main(void)
{
    int succp = 1;
    
    struct servent *service = getservbyname("ssh", "tcp");

    if(service) {
        int i = 0;
        printf("found service \"%s\"\n", service->s_name);
        while(service->s_aliases[i]) 
            printf("with alias \"%s\"\n", service->s_aliases[i++]);
        printf(" on port %d\n", service->s_port);
        printf(" protocol \"%s\"\n", service->s_proto);
    } else {
        fprintf(stderr, "getservbyname - failed\n");    
        succp = 0;
    }

    return succp ? 0 : -1;
}

Solution

The documentation for /etc/nsswitch.conf recommends an advanced syntax to allow multiple database services to be involved in lookups. This syntax may not work in some cases. A line such as:

services:   ldap [NOTFOUND=return] files   # can break getserv*()

may totally disable lookups if LDAP is enabled but missing services data, where any of the following should work just fine:

services:   files ldap
services:   ldap files
services:   ldap [NOTFOUND=continue] files
encrypt lang [de jp fr] diff backlinks (sec) validate printable
Walk without rhythm and you won't attract the worm.
[ Your browser's CSS support is broken. Upgrade! ]
alexsiodhe, christopher north-keys, christopher alex north-keys