getpwuid() returns NULL for LDAP user

7.9k views Asked by At

I'm having issues retrieving current user information of Red Hat Enterprise 6 where the user is an LDAP user?

I have some code (actually part of an installation tool) that needs to retrieve the user name, home directory and other details. It is using the getpwuid() call to do this based on the user id. A simplified breakdown:

uid_t uid = getuid();
printf("UID = %d\n", uid);

errno = 0;
struct passwd* udetails = getpwuid(uid);

if (udetails != NULL)
{
    printf("User name = %s\n", udetails->pw_name);
}
else
{
    printf("getpwuid returns NULL, errno=%d\n", errno);
}

This works without problems where the user is a local user (in that system's /etc/passwd).

When the user is an LDAP-authenticated user, the call the getuid returns the user ID or the current user, but the call to getpwuid returns 0, with no error code set in errno. According to the documentation, this means that the user doesn't exist.

Should this work? According to the getpwuid manpage:

The getpwnam() function returns a pointer to a structure containing the broken-out fields of the record in the password database (e.g., the local password file /etc/passwd, NIS, and LDAP) that matches the username name.

The getpwuid() function returns a pointer to a structure containing the broken-out fields of the record in the password database that matches the user ID uid.

Is an alternative call required to get the details if the current user was authenticated by LDAP? Is it necessary to open the LDAP database in an application, or should the system call handle that?

Additional: I have also now tried this on a RHEL 5 box authenticating against the same LDAP directory. Could this just be a configuration issue on the RHEL 6 box? Or a wider RHEL 6 issue?

Additional: /etc/nsswitch.conf as requested by Basile Starynkevitch (commented lines removed):

passwd:     files sss
shadow:     files sss
group:      files sss

hosts:      files dns

bootparams: nisplus [NOTFOUND=return] files

ethers:     files
netmasks:   files
networks:   files
protocols:  files
rpc:        files
services:   files sss

netgroup:   files sss

publickey:  nisplus

automount:  files ldap
aliases:    files nisplus

I'm guessing that some of these should mention ldap at some point? In fact this suggests that it's not using LDAP at all....

3

There are 3 answers

0
BunbySoft On

I had exactly the same problem on CentOS 8. The answer by @kriko helped me solve it, but I had to yum install nss_nis.i686 in order to fix it. Not sssd-client.i686

2
Tommaso On

I have a similar problem, I was trying to run Teamviewer9 on an x64 debian (also tried Ubuntu). It was not working for accounts in an active directory domain, Teamviewer was crashing because getpwuid() returns null. I solved installing nscd, as described in this ubuntu bug.

It took me a lot to fix this...

0
krico On

The problem seems to be missing nss_sss libraries for 32 bit (in my case). I think for redhat it is the rpm package: sssd-client.i686.rpm

I used the following makefile:

all: getpwuid_bug-32bit getpwuid_bug-64bit

getpwuid_bug-32bit: getpwuid_bug.c makefile
        $(CC) -Wall -m32 -o $@ $<

getpwuid_bug-64bit: getpwuid_bug.c makefile
        $(CC) -Wall -m64 -o $@ $<

and the following getpwuid_bug.c

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>

int main(argc, argv)
     int argc; char **argv;
{
  uid_t uid;
  struct passwd *udetails;

  uid = getuid();
  printf("UID = %d\n", uid);

  errno = 0;
  udetails = getpwuid(uid);

  if (udetails != NULL) {
    printf("User name = %s\n", udetails->pw_name);
  } else {
    printf("getpwuid returns NULL, errno=%d\n", errno);
    return 1;
  }
  return 0;
}

Now type make...

Then run both

$ ./getpwuid_bug-32bit
UID = 1234
getpwuid returns NULL, errno=0
$ ./getpwuid_bug-64bit
UID = 1234
User name = krico
$

Then if you strace both versions of the program, you will see that the 64 bit version finds nss_sss imediately

open("/lib64/libnss_sss.so.2", O_RDONLY) = 3

where as the 32 bit one fails miserably after going through many of these:

open("/lib/tls/i686/sse2/libnss_sss.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/sse2", 0xfffef338) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/libnss_sss.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

So, my conclusion is you need to install some rpm with that 32 bit version of the library (like for example sssd-client.i686.rpm)