Bug 14351 - getpwnam error in 32 bit version only - it cannot deal with LDAP accounts coupled with Active Directory
Summary: getpwnam error in 32 bit version only - it cannot deal with LDAP accounts cou...
Status: CLOSED WORKSFORME
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-11 14:43 UTC by Robert Klima
Modified: 2015-09-17 13:36 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Testprogram - source and 32-Bit version which produces the error on 32-Bit library (7.67 KB, application/zip)
2012-07-11 14:43 UTC, Robert Klima
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Klima 2012-07-11 14:43:28 UTC
Created attachment 6523 [details]
Testprogram - source and 32-Bit version which produces the error on 32-Bit library

getpwnam() of 32-Bit Library returns NULL pointer for valid user.
64-Bit Version seams to work correctly.

Situation: ActiveDirectory is coupled with LDAP to be accessed from Linux.

Here a Link where another user verifies: in 32-Bit Ubuntu getpwnam() returns a NULL-Pointer whereas the 64-Bit-Variante returns a valid passwd-structure:

http://stackoverflow.com/questions/2352373/getpwnam-on-ubuntu-behaves-differently-if-compiled-in-32-bit


Here a link where it says, user-IDs in Linux are 32-Bit in size (on 32-Bit-systems) whereas Windows-UserIDs are 'larger':

http://suacommunity.com/dictionary/getpwnam-entry.php
Original text: While ID's on Unix systems are typically 32-bit (16-bit on older systems) Windows's ID are larger (and may vary in size).


Test program:
---------------------------------


/*
*/

#	include		<pwd.h>
#	include		<grp.h>
#   include     <time.h>
#	include		<string.h>
#	include		<stdlib.h>
#	include		<unistd.h>
#	include		<stdio.h>
#	include		<shadow.h>

#	include		<errno.h>

#define _NUMBER_OF_CALL     5
#define __SLEEP_TIME        1
#define __MAX_SLEEP_TIME    60
#define TTRACE if ( __STDOUT )

/*
 * #####################################################################
 * #
 * #     g e t D a t e C h a r
 * #     ----------------------
 * #
 * #####################################################################
 */
char * getDateChar()
{
    static char          xdat[32];
    time_t               tt;
    struct tm           *tm;

    tt = time((time_t *)NULL);
    tm = localtime(&tt);
    sprintf(xdat, "%.4d%.2d%.2d/%.2d%.2d%.2d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

    return (char *)xdat;
} /* Ende Funktion 'getDateChar' */










/*
 * #####################################################################
 * #
 * #     M a i n    -   Ticket Nr. 197218(Linux), 197115(Linux), 195542, ....
 * #     -------        Testprogramm
 * #
 * #
 * #####################################################################
 */
int main(int argc, char *argv[])
{
    int                  loopNr=0, s_errno;
    int                  sleepTime = __SLEEP_TIME;
    int                  maxLoop = _NUMBER_OF_CALL;
    char                 wUserName[256];
    char                 wProgName[256];
    struct passwd       *passwd;
    struct spwd         *sp_entry;
    char                *FName;

    if  ( (argc > 1 ) && ( strcmp( (argv[1]), "-help" ) == 0 ) )
    {
      printf("Usage %s <user> <loop> <sleep>\n", argv[0]);
      printf("     <user>  -    user name, standard login name - 'cuserid()'\n");
      printf("     <loop>  -    number of call getpwnam(), standard %i, endless -1\n", maxLoop);
      printf("     <sleep> -    sleep time (sec.) for loop, standard %i, max. %i\n", sleepTime, __MAX_SLEEP_TIME);
      exit (0);
    }

    /* -----------------------------------------------------------------
     *  Password-entry wird geholt
     */
    strcpy(wProgName, argv[0]);
    FName = (char *)strrchr((char *)wProgName, '/');
    if  (FName)   FName++;
    else          FName = wProgName;

    printf("%s --> Developer test program '%s' started.\n\n", getDateChar(), FName);

    strcpy(wUserName, (char *)cuserid(NULL));
    if  (argc > 1)     strcpy(wUserName, argv[1]);
    if  (argc > 2)     maxLoop = atoi(argv[2]);
    if  (argc > 3)     sleepTime = atoi(argv[3]);
    if  ( ( sleepTime < 0 ) || ( sleepTime > __MAX_SLEEP_TIME ) )   sleepTime = __SLEEP_TIME;

    printf("%s     %-30s : '%s'\n", getDateChar(), "user name", wUserName);
    printf("%s     %-30s : '%d'\n", getDateChar(), "defined max. loop number", maxLoop);
    printf("%s     %-30s : '%d'\n", getDateChar(), "sleep time for loop", sleepTime);
    printf("%s     CRYPTPW_TRUSTED_HP supported\n", getDateChar());

    /* -----------------------------------------------------------------
     *  Password-entry wird geholt
     *  Linux man page:
     *  The getpwnam() and getpwuid() functions return a pointer to a passwd structure,
     *  or NULL if the matching entry is not found or an error occurs. If an error occurs,
     *  errno is set appropriately.
     *  If one wants to check errno after the call, it should be set to zero before the call.
     */
    loopNr = 0;
    while(maxLoop)
    {
        loopNr++;

        /* -----------------------------------------------------------------
         *  get password file entry - call getpwnam()
         */
        printf("\n%s %04i get password file entry, call getpwnam(%s)\n", getDateChar(), loopNr, wUserName);
        errno = 0;
        passwd = getpwnam(wUserName);
        if  (passwd  == NULL)
        {
            if  ( errno )
                printf("%s      ---> . error '%s' in getpwnam(%s)-call\n", getDateChar(), (char *)strerror(errno), wUserName);
            else
                printf("%s      ---> . the matching password entry is for user '%s' not found, but errno not set!\n", getDateChar(), wUserName);
#ifdef __BLABLA
            printf("\n%s <--- Developer test program '%s' terminated abnormally.\n", getDateChar(), FName);
            exit(0);
#endif
        }
        else
        {
            printf("%s      user entry structure successfully determined : '%s'\n", getDateChar(), passwd->pw_name);
        }

        /* -----------------------------------------------------------------
         *  user passwort ermiiteln - getspnam()? oder getpwnam()?
         *  get shadow password file entry - call getspnam()
         */
        printf("%s      get shadow password file entry, call getspnam(%s)\n", getDateChar(), wUserName);
        errno = 0;
        sp_entry  = (struct spwd *)0;
        sp_entry  = getspnam(wUserName);
        if ( sp_entry )
            printf("%s      . %-20s --> '%s'\n", getDateChar(), "crypt-pw(sp_pwdp)", sp_entry->sp_pwdp);
        else
        {
            printf("%s      . shadow password entry could not be determined, getspnam()-entry NULL\n", getDateChar());
            if (errno)
                printf("%s      . error '%s' in getspnam(%s)-call\n", getDateChar(), (char *)strerror(errno), wUserName);
            else
                printf("%s      . no error in getspnam()-call, but the user password could not be determined\n", getDateChar());

            if  ( passwd )
                printf("%s      . %-20s --> '%s'\n", getDateChar(), "crypt-pw(pw_passwd)", passwd->pw_passwd);
            else
                printf("%s      ==> fatal error, user password could not be determined\n", getDateChar());
        }

        maxLoop--;
        sleep(sleepTime);

    }


    printf("\n%s <--- Developer test program '%s' terminated normally.\n", getDateChar(), FName);
    exit(0);
} /* Ende Funktion 'main' */
Comment 1 Andreas Jaeger 2012-07-11 14:54:25 UTC
The stackoverflow shows that no 32-bit ldap nss lib was installed:

"Obviously the same module cannot be used for both 64-bit and 32-bit. Ubuntu Karmic ships /lib32/libnss_ldap.so.2 in package ia32-libs – is this installed?"

Some questions:
1) Is this the case on your system?
2) What is the content of /etc/nscd.conf?
3) What kind of Linux are you running?
Comment 2 Florian Weimer 2014-06-17 19:02:51 UTC
Closing because of lack of response from the reporter.
Comment 3 Robert Klima 2015-09-17 13:30:34 UTC
For that reason, I provided a test program, which can be used to replay the error in that very environment.
Can you please try with the test program?


For your questions:
It is the environment of our customer.  Unfortunately it is hard to tell what his configuration is.
He has an AD coupled with LDAP.  The command su works fine.  However, a 32bit-executable (see testprogram attached) calling getpwnam() retrieves a NULL pointer.
The 64 bit variant of that testprogram works.

Is there a solution?
Comment 4 Florian Weimer 2015-09-17 13:36:13 UTC
(In reply to Robert Klima from comment #3)
> For your questions:
> It is the environment of our customer.  Unfortunately it is hard to tell
> what his configuration is.
> He has an AD coupled with LDAP.  The command su works fine.  However, a
> 32bit-executable (see testprogram attached) calling getpwnam() retrieves a
> NULL pointer.
> The 64 bit variant of that testprogram works.
> 
> Is there a solution?

The likely solution is to install 32-bit versions of the NSS LDAP support libraries (and perhaps of the PAM libraries, too).  This is a system setup issue and not something glibc changes can fix.