clinuxauthenticationubuntupam

Use PAM to authenticate UserB when program launched from userA


I've build a program in C, I run it on Ubuntu. I'm using PAM to authenticate users, e.g. I launch a client, the client sends username and password, the server authenticate the user. The problem is that if I launch, from userA, the program that makes the PAM authentication, I can only authenticate userA, while if I try to authenticate userB I get:

Failure in pam authentication: Authentication service cannot retrieve authentication info

I can solve this only if I run the program with sudo, but I don't think that's the appropriate approach?

Here's a summary of how I use PAM as of now:

pam_handle_t *handle = NULL;
const char *service_name = "myservice";
int retval;
char *username;

retval = pam_start(service_name, NULL, &conv, &handle); // &conv is a pointer to the struct with the standard/default misc_conv function
if (retval != PAM_SUCCESS){
    ...
}

retval = pam_authenticate(handle, 0);
if (retval != PAM_SUCCESS) {
    ...
}

I've also this file in pam.d folder:

auth        required        pam_unix.so
auth        required        pam_listfile.so onerr=fail item=group sense=allow file=/etc/login.group.allowed
account     required        pam_unix.so

Solution

  • I can solve this only if I run the program with sudo, but I don't think that's the appropriate approach?

    You are using the pam_unix module in the authentication stack for your service. That is useful only when the program invoking authentication through PAM is privileged, because pam_unix needs to access the system's secure credential store (the /etc/shadow file, or a secure authentication service such as sssd) -- with the possible exception of authenticating the already-authenticated user associated with the current session. That's why it works when you run the application via sudo, but not when you run it as an ordinary user.

    In a sense, then, running the application with sudo is the right approach. You need privilege to authenticate a user against the system's authentication database, and that's a good way to get it.

    Another, more risky, way to obtain the needed privilege would be to make the program SUID-root, or to give it the appropriate capabilities. If you went this way then you would want the program to drop unneeded privileges as soon as possible. This is the way a system service with such a need would normally do it.

    But if you're not writing a system service then the best answer is probably just don't. A regular user who wants to assume the identity of a different user should use the su or sudo command to do so, or should just log in as that user in the first place. That would moot the need for your application to authenticate a different user.