Can't get auth token for non-local users with PAM module
I've wrote a PAM module that should provide authentication for linux hosts with user accounts that are managed from a central site. Reading the username works fine, but the password is some garbage when the specified username is not existing on the local system, for example:
Code:
May 15 23:59:10 localhost sshd[24920]: pam_test[24920] NOTICE: got username 'test' The code for my PAM module: Code:
#include <stdio.h> |
pam_get_authtok() is OpenPAM shorthand.
If the password is supposed to have been asked already by a prior module in the chain, you can obtain it via retval = pam_get_item(pamh, PAM_AUTHTOK, password);. Normally, though, you need to start a PAM conversation, and ask the user for a password instead. For details, see Linux-PAM:modules/pam_unix/support.c:_unix_read_password() (at the end of the file). |
I've tried pam_get_authtok(), pam_prompt() and pam_get_item() since then, they all return "INCORRECT garbage" in the response variable. This only happens when I'm trying to use a username that does not exist on the local system, otherwise these functions return the correct password.
|
Quote:
I have actually discussed exactly the same issue in an earlier thread, where chesschi wanted to use FreeRadius for authentication. The problem is that Linux PAM will replace the password with "\b\n\r\177INCORRECT" if it cannot obtain information regarding the user from the system databases (Name Service Switch, see man nsswitch.conf). That cannot be simply edited out, either. You must have some way of providing the user information -- basically everything except the password -- to the system databases. You can write a dynamic nss library, use NIS+, or use LDAP to provide the remote user information, but it has to be provided somehow. A PAM module alone is not enough. Can you set up an LDAP server (say, as a frontend for your user database) for providing the public information on your users? If not, I am afraid you'll have to write user information daemon (one for client-side machines, and maybe one for your user database side), and a dynamic nss library that connects to the local user information daemon. Trust me, LDAP is much simpler. |
That seems to be reasonable. Thank you for your hint.
|
So now I've gone a step further and writed a simple NSS module. According to this thread, it shouldn't be a problem to do so. While my NSS module seems to work when using su(do), id etc., its debug functions don't get called when trying to login via ssh. Seems like sshd does not use NSS to lookup system users?
What I've done so far:
I've also tried to set a static local user account for whatever username is entered when trying to log in (via pam_set_item(pamh, PAM_USER, (const void **)"some_static_user") - but that didn't work too. To explain what I want to achieve with that: I want to grant a set of users access to specific servers. The UNIX user account they've access on the target server is stored in a central database and they should be logged in using that user name when they try to login with their personal username/password combination. Code for the actual NSS module: Code:
#include <stdio.h> |
Quote:
Edited to add: If you use nscd, you'll have to clear its cache too by running nscd -i passwd as root. |
After hours of trying and such, I'll figured it out. The function names were wrong. For some reason I've wrote the functions to be like _nss_NAME_getpwby*_r() instead of _nss_NAME_getpw*_r(). That's why _nss_NAME_endpwent() and _nss_NAME_setpwent() were called but the actual Nevertheless I've got it working and I am now able to read the password correctly even for users who don't exist locally.
Again, thank you for your efforts! |
Quote:
Anyway, it's very nice to hear that it works now. I take it that this solves your original problem? Would you mind recapping your findings in a final post, and marking the thread solved? I'm certain it would be very useful for others reading this thread in the future. |
All times are GMT -5. The time now is 12:10 AM. |