Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Oh great ones, I had a perl module that worked great until recently. It verified username / passwords on my linux box. We recently migrated from NIS to LDAP, and now my call to getpwnam returns only an 'x' when before it would return the encrypted password. Is there an ldap'ized way to grab the encrypted password? My program runs as root, so that's not the problem. thanks, me

Replies are listed 'Best First'.
Re: LDAP & getpwnam
by Celada (Monk) on Dec 08, 2005 at 22:11 UTC

    It's a feature, not a bug: the sensitive information is protected :-)

    Remember that there are two different things going on with the passwd/shadow database: there is querying the database to find out what users exist and what information is associated with them, and there is authenticating a user. The former is the job of NSS (name service switch) and the latter is the job of PAM (pluggable authentication modules).

    It so happens that with flat files and also with NIS (because NIS and NIS+ were designed to work much like network versions of the flat files), the authentication (PAM) piece makes use of the same datbase as the database piece (NSS), i.e. it gets the username and crypted password out of the NSS database and checks if the credentials supplied by the user are good.

    But in general an authentication mechanism is not required to keep its authentication information located in the NSS database. LDAP does not because LDAP already has a way for users to authenticate against it that is independant of the UNIX specific information that can be found in the passwd file. Some authentication mechanisms could not store crypted hashes in the traditional passwd file fields even if they wanted to because they have no such concept! Examples are one time password schemes and SecurID.

    So LDAP stores a dummy value in the UNIX /etc/passwd style field of its database. You will have to get the passwords some other way. I don't know much about LDAP, but I actually suspect that it's quite secure and that it will actually not let you get at that information over the network.

    If you need to authenticate users from your Perl script, you probably need to use PAM to ask the system whether a username and password combination is valid. This is what all of the things on your system that need authentication (like the SSH server) do. There seems to be an Authen::PAM module on CPAN but I have never used it.

      I do know a bit about LDAP, but I'm rather stale in it, and most of my experience is with the Netscape/iPlanet/SunOne line, and a little bit of dealing with Novell's directory server.

      You're right, in that many directory servers don't want you to retrieve the password, for exactly the reasons you mentioned.

      Of course, the 'x' might also mean something else -- it could mean that whomever imported everyone imported a shadowed password file, but didn't actually load the passwords ... we'll hope that's not the case, however. Typically, LDAP does store a real password, and with the servers I've used, it'll even return the password if you have the right permissions (either you logged in as the user, you're the directory manager, or some other user w/ the necessary permissions ... but that has nothing to do with the program being run as 'root', it has to do with the user you're binding to the server as)

      Anyway, here's my normal process for authenticating users in LDAP:

      1. Bind as an application user, and search for the user's DN, in the appropriate tree.
      2. Try to bind as the user, using the found DN, with the password that the user supplied.

      In some cases, I might have some extra logic, if there were flags in the system for which services a user had access to ... eg, I might search for &(uid=username)(host=servicename)

      I also don't tend to use PAM for application security, as my PAM config tells it who's allowed to log into the machine, not log into the applications that are running on the machine ... I just use Net::LDAP ... um ... here's some really simplistic authentication logic (assumes the users are in a flat branch, so we don't need to look up their DN):

      (okay, I'm remembering why I don't go back and look at my 5+ year old code ... ack.)

Re: LDAP & getpwnam
by beachbum (Beadle) on Dec 08, 2005 at 21:45 UTC
    The ldap implementations I have worked with have always prevented password retrieval. You can however, create a new attribute on the user object that stores a synchronized version of the password. Although guilty, I can't condone this as a Good Thing to do, however, if you limit access to that attribute you can minimize the risk.