As I described in bug 114, OpenSSH makes assumptions about how PAM operates, and denies it acess to potentially critical information about failed logins. This problem occurs if you want to use PAM to obtain a consistant audit history across all system deamons - OpenSSH traditionally would not even start PAM, and now starts it specifying 'NOUSER' as the login name. I feel that the correct behaviour is to always call PAM. There are two particular reasons: Firstly, it ensures that PAM gets to decide that a user is invalid, and log it appropriatly. OpenSSH can add its own checks to the top, but the first decision should be with PAM. The second is to prevent username guessing attacks - by always calling PAM the system should always suffer the same timeouts/delays no matter the existance of the attempted login. Another (almost certainly less convincing) reason is that it would make it easier for sombody to write an OpenSSH based deamon that didn't service logins - like an authenticated proxy service that uses SSH for secure transport to the firewall. In this case the user almost certainly doesn't exist locally, but PAM can still be useful for authenticaion. (OK, so this is really oddball, but my main concern is the first two reasons).
> OpenSSH traditionally would not even start PAM, and > now starts it specifying 'NOUSER' as the login name. We have always used NOUSER, the recent patch just makes it consistent between protocols 1 and 2. > The second is to prevent username guessing attacks - by > always calling PAM the system should always suffer the > same timeouts/delays no matter the existance of the > attempted login. I don't think this is the case: the auth code attempts all authentications with the fake username anyway, so this should not be an issue unless the PAM modules themselves are broken. We rely on getpwnam() working in lots of places, so changing this would be a fair amount of work.
There is nothing wrong with calling pam_set_item to set an item to NULL and in fact there are modules on Solaris that do exactly that for PAM_AUTHTOK. PAM on Solaris would not have syslogged the pam_set_item message that is described in bug 114 There is nothing wrong in having a syslog message for pam_set_item being called with the item value as NULL, however since it is perfectly valid to do so this should be a debug only syslog message and either the case being reported had pam framework debugging enabled or there is a bug in the Linux PAM framework library. It is perfectly valid to pass NULL as the user into pam_start; pam_start ultimately calls pam_set_item to setup the PAM_USER. If the application does that then it should use pam_get_item(pamh, PAM_USER, &user) to find out which user was authenticated if pam_authenticate returned PAM_SUCCESS. I would rather that OpenSSH passed NULL to pam_start than passing NOUSER. There could potentially be modules on the stack that will prompt for a user name if PAM_USER is empty - this is perfectly valid PAM according to the XSSO spec (which Linux PAM does not comply with - it has extended and embraced in an incompatible way in some areas). Passing the string "NOUSER" takes a way a valid username out of the namespace, what if there really was a user called nouser (The user account for some subsystem called 'no' for example or someone called Neil Ouser) the pam_authenticate call might actually succeed - this probably isn't what you were expecting to happen in this case. PAM_USER == NULL means I the application don't know the user name, anything else is taken to mean you the application are trying to authenticate the named user. I believe the correct fix is for OpenSSH to pass NULL to pam_start when it doesn't know the username and pass the username when it does.
The problem is that OpenSSH knows the username perfectly well at this stage. It just refuses to pass it on to PAM! This means that PAM cannot log the fact that an invalid login was attempted - which is my primary issue here. I am doing some work on a product that is hoping to use PAM to log all authenticaion failures in a consistant manner across all system deamons. I see know reason why PAM cannot be told the truth, allowing this kind of thing without ugly hacks to OpenSSH itself (the current way this is done). auth_sia_password() doesn't take a 'struct passwd' argument, why should PAM have to? (The bits of auth_pam_password() and auth_password() that deal with the pw->uid feild should really be in a single function, elsewhere)
sshd should definitely not be using 'NOUSER'. The correct thing is to use the username, regardless of whether (pw) exists. I can't understand why you would substitute the value 'NOUSER'.
You do see the username, auth2.c line 193-197: log("input_userauth_request: illegal user %s", user); #ifdef USE_PAM start_pam("NOUSER"); #endif We fake a username with PAM to mitigate timing attacks.
Yes "YOU" see the username but PAM doesn't. How about a comment in the code about the timing attack you are trying to mitigate? You are eliminating the possibility that sshd might want to authenticate someone without a local account (requesting a non-login service?). Also, I think this is counter-productive with PAM. PAM has it's own ability to do this.
> You are eliminating the possibility that sshd might want to authenticate > someone without a local account (requesting a non-login service?). PAM shouldn't be abused to to be a getpw* replacement. Quoth http://www.opengroup.org/tech/rfc/mirror-rfc/rfc86.0.txt: ] (c) We do not address the source of information obtained from the ] "`getXbyY()'" family of calls (e.g., `getpwnam()').
While there are varying ideas on the interesting ways OpenSSH could be modified for usage without login accounts (and I see some real usful ideas here actually) this isn't the main issue. OpenSSH should always forward the correct username to PAM. Forwarding the incorrect username achives nothing - and prevents PAM from logging 'attempted login for user _____' in a consistant way across all system deamons.
Forwarding a fake username also means there is an undocumented username that has side effects caused by sshd; although all caps probably makes this a non-concern, to me it still smacks of special names like COM. This will be my last comment on the matter: - You are not doing anything by using 'NOUSER', at least nothing I can figure out. If this is to prevent some kind of attack, please add comments in the code. - You *are* causing problems. eg, my sshd w/ PAM uses a RADIUS backend. On my RADIUS server I get logs for 'NOUSER' failing. I would like to know what the attempted username was, and I would like to get this from a central source (the RADIUS server). I will admit, on the level of "problems" this is minor if 'NOUSER' actually prevents some attack. - The protocol 1 code path does not call PAM at all for invalid users. This would be acceptable for the protocol 2 code path, and better than using 'NOUSER', but eliminate the possibility of non-login services.
Created attachment 245 [details] Use supplied username in pam_start calls always Make sshd always use supplied username (even if it is invalid) in calls to PAM
I'm still not sure whether supplying a bad username to PAM is a good idea, but at least there is a patch that people can try timing attacks against.
Patch applied
Mass change of RESOLVED bugs to CLOSED