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
You are using the
pam_unixmodule in the authentication stack for your service. That is useful only when the program invoking authentication through PAM is privileged, becausepam_unixneeds to access the system's secure credential store (the/etc/shadowfile, 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 viasudo, but not when you run it as an ordinary user.In a sense, then, running the application with
sudois 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
suorsudocommand 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.