Verifying a users password on AIX setup with LPA

Hello,

We're running AIX 6 & 7.

Previously we were using the old encryption techinique (DES/crypt)
I have a GUI application that has a verify button (the verify button is sort of a digital signature) - the user clicks it, enters his or her password and we then make a call to a C module, This grabs the hash value password from the shadow file.
We then grab the salt from the hashed value and make a to the crypt function, which returns an encrypted string that we compare to the shadow string to verify the user is valid.

We've now introduced LPA onto our server which has effectively broken our verification.

I've looked at the "authenticate" function provided by libc, however, I have been unable to make this work (doesnt seem to do anything).
The manpage for the crypt function seems to signify that you can use LPA, but again, I havent been able to make this work either. I believe I am passing in the correct salted value, but the string returned is always different so there's no way to match the hashed string with this one.

Would anyone know of an alternative way to verify a user on the system from within an application (without dropping them out to a commandline) ?

Thanks,

Chris

You can create password hashes with openssl.
For example:

echo test123 | openssl passwd -stdin
echo test123 | openssl passwd -stdin -1

And with a fixed salt

echo test123 | openssl passwd -stdin -1 -salt AB

There might be other crypt methods available, see

openssl enc -c -help

if only LPA was changed, authenticate() works quite well:

$ cat checkpw.c
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <userpw.h>

int main(int argc, char *argv[])
{
        char *username, *pw, *msg = (char *)NULL;
        struct userpw *up;
        int rc, reenter;

        if (argc > 2) {
                fprintf(stderr, "Usage: %s [username]\n", argv[0]);
                return 2;
        }

        if (argc == 2) {
                /* username is in argv[1] */
                username = (char *)calloc(strlen(argv[1])+1, 1);
                if (!username) {
                        fprintf(stderr, "can't allocate memory for username\n");
                        return 3;
                }
                strncpy(username, argv[1], strlen(argv[1]));
        }

        if (argc == 1) {
                /* get current user */
                username = (char *)calloc(PW_NAMELEN + 1, 1);
                if (!username) {
                        fprintf(stderr, "can't allocate memory for username\n");
                        return 3;
                }
                rc = getlogin_r(username, PW_NAMELEN);
                if (rc) {
                        fprintf(stderr, "can't get current user's name, RC=%d\n", rc);
                        return 4;
                }
        }

        printf("Checking password for user %s\n", username);

        pw = getpass("Enter password: ");
        if (!pw) {
                fprintf(stderr, "can't obtain password for user %s\n", username);
                return 5;
        }

        do {
                rc = authenticate(username, pw, &reenter, &msg);
                if (msg) {
                        if (!reenter) {
                                fputs(msg, stderr);
                        }
                        free(msg);
                        msg = (char *)NULL;
                }
        } while (reenter);
        return rc;
}

Compilation:

$ cc checkpw.c -o checkpw

Check:

$ grep -p user /etc/security/passwd
user:
        password = {ssha512}06$verylongpassword
        lastupdate = 1448619478

$ ./checkpw user
Checking password for user user
Enter password:
$ echo $?
0

Thanks very much for both replies - I was certainly looking into the authenticate function as an alternative, but was having difficulty getting it to return anything useful, or anything at all really.

As it turns out, I forgot to give the program the proper low-level ownership/permissions, so it would always fail.

For those interested, the program needs to be owned by a root-level user/group and have 4755 permissions for it to be able to access the authentication level calls.

Again, thanks a bunch!

Chris

---------- Post updated at 03:28 PM ---------- Previous update was at 10:09 AM ----------

Another update on this for enquiring minds!

Previously, our crypt() call was in a shared object - and this used to work (still does with the old encryption method, (non-LPA) ). However, from what i've been able to tell, calls to crypt() using LPA currently require that the program have a proper authoritative owner and permissions, meaning if you create a stand-alone executable and give it the same permissions as listed above (and the proper salt), the crypt() function will work without issue.

1 Like