I am working on a radius authentication solution composed of a PAM module and an NSS module.
The flow is like this:
- user
ben
login (via thelogin
command) - the user enters the username:
ben
- my NSS module is queried with that username and returns a default non privileged user
radius
, same behavior as libnss-ato - the user types the password
- my PAM module is called and will query the Radius server, if the auth is accepted, the PAM module will use Radius vendor attributes to pick a local username to map the Radius user to, this mapping is written to a database, for example
ben
->admin
- now, my NSS module will read that database and return the proper local username for the Radius user
- with the
login
command, the user is logged at the proper mapped useradmin
Now, my problem is as follow. OpenSSH server will read NSS before PAM.
This means the flow is like this:
- user
ben
ssh in - SSH query NSS and map
ben
to the default accountradius
- the user is presented with a password prompt and enters the password
- my PAM module is called and the mapping
ben
->admin
cached - SSH will spawn a session as
radius
instead ofadmin
because it uses the value it got from NSS before PAM was called
Now this bug happens only on first login, because on second login the NSS will have cached data and return correct user on first call.
But it is still a problem, firstly because I don’t want the first login to fall to the wrong user each time, second if ben
got admin rights dropped, his next login will still be mapped to admin by SSH because of NSS cache of my NSS module.
I cannot query the mapping on the first NSS call because querying mapping from radius requires a successful login.
I have a few leads, but I’d really love some insight on this issue.
My leads are:
- have the
radius
user use a special root setuid shell, this shell would read the my NSS database and change user, then exec the real shell, the problem is that I need to know which radius user is logged in. I can write env var in my PAM module, but as the shell will be setuid, I need a security mechanism to ensure that var is trusted. Only thing I see is to have a crypto signature in the var, and have the setuid shell verify that with a private key in root 0600. - call
setuid
in the PAM module, but that’s sound fishy
Advertisement
Answer
I ended up changing the shell for the user to a setuid wrapper that drop privileges to the intended user.
Code is here: https://github.com/kuon/radius-auth-virtual