ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I try to authenticate the ssh user via PAM using FreeRadius. So the setup is:
SSH client --> [SSH server <- PAM -> FreeRadius Client] --> FreeRadius Server (storing user accounts)
I found that Openssh will set the password to "\b\n\r\177INCORRECT" if the user is not specified in /etc/passwd (see auth-pam.c). So when the FreeRadius client attempts to retrieve the password using pam_get_item, it will get the hardcoded bad password.
All of the user accounts are stored in the FreeRadius server. I don't want to have another set of username stored in the Radius client machine. Is there an easy way to workaround on this?
Which version of OpenSSH? In 5.8p2, there are two places where the hardcoded bad password is assigned. In both auth-pam.c:839:sshpam_respond() and auth-pam.c:1200:sshpam_auth_passwd() it happens only if the context is invalid (!authctxt->valid) or if the account is root but root login is not permitted. As far as I can see, OpenSSH 5.8p2 uses getpwnam() to determine the user account; and that of course uses PAM. I cannot see the behaviour you describe; the authentication context is based on information correctly obtained via PAM, and not from local files. Are you sure you have the correct OpenSSH port?
The majority of systems I use would not work if OpenSSH required the user to be in /etc/passwd. (Typically, only service user accounts are in /etc/passwd, local administration groups in /etc/group, and all users defined and authenticated via PAM (usually LDAP and AD).)
I suspect you have a problem in the PAM config on the SSH server machine. Does e.g. id -u someuser output the user ID for a FreeRadius user? It should. I'm personally not that familiar with Radius authentication, so hopefully someone with experience with FreeRadius can help you with that. (On the other hand, the documentation and config example at the FreeRadius web site does look relatively straightforward.)
It's 5.2p1. But I tried the latest version and I got the same results.
Quote:
Originally Posted by Nominal Animal
In 5.8p2, there are two places where the hardcoded bad password is assigned. In both auth-pam.c:839:sshpam_respond() and auth-pam.c:1200:sshpam_auth_passwd() it happens only if the context is invalid (!authctxt->valid) or if the account is root but root login is not permitted. As far as I can see, OpenSSH 5.8p2 uses getpwnam() to determine the user account; and that of course uses PAM. I cannot see the behaviour you describe; the authentication context is based on information correctly obtained via PAM, and not from local files. Are you sure you have the correct OpenSSH port?
Here is the experiment that I tested:
If the username is specified in /etc/passwd, e.g. sshuser::638:638::/home/sshuser:/bin/bash. The username and password entered by the user in the SSH client will be passed to the FreeRadius server (use pam_get_item to get the password) to authenticate and we can successfully login if the user credential exists.
Otherwise, the username entered by the user and the hardcoded password "\b\n\r\177INCORRECT" will be passed to the FreeRadius server and thus the login fails.
Quote:
Originally Posted by Nominal Animal
(On the other hand, the documentation and config example at the FreeRadius web site does look relatively straightforward.)
Yes it is straightforward. That is why I can make it work if I specify the user in /etc/passwd
If the username is specified in /etc/passwd, e.g. sshuser::638:638::/home/sshuser:/bin/bash. The username and password entered by the user in the SSH client will be passed to the FreeRadius server (use pam_get_item to get the password) to authenticate and we can successfully login if the user credential exists.
You know, I just really read the example configuration:
but note that as I said, I don't have Radius experience, so I'm basically assuming that Radius and LDAP work in a similar manner.
In my config, local user accounts are sufficient. pam_unix.so should prompt for a password if necessary (if no password has been supplied to the PAM stack yet).
FreeRadius user accounts are sufficient too (although local users are checked first). use_first_pass tells pam_radius_auth.so to use the already prompted for password, and not prompt for yet another one.
If neither of the above succeeded, the auth fails.
Could you try this modified configuration, and see if this works?
As expected, if I use the above configuration, it will not use pam_radius_auth.so in the first place when username is entered. However, when the user enters the passwords, pam_radius_auth.so obtains a (null) password using pam_get_item.
Quote:
Originally Posted by Nominal Animal
but note that as I said, I don't have Radius experience, so I'm basically assuming that Radius and LDAP work in a similar manner.
Forget about Radius if you are not familiar with it
What Radius does is fairly straight-forward, i.e.:
1. Get the username using pam_get_user
2. Get the password using pam_get_item
3. If the password is provided in the first place, it will use those username and password
4. If the password is NOT provided, it will wait for the user to enter the password using pam_conv, i.e.
So the configuration you suggested will get to step 1, 2 and 3 where password is null.
I am not familiar with SSH source code at all. I don't understand at which point in time SSH server will update the password if the user is not in /etc/passwd. Do you have any other suggestions?
As expected, if I use the above configuration, it will not use pam_radius_auth.so in the first place when username is entered. However, when the user enters the passwords, pam_radius_auth.so obtains a (null) password using pam_get_item.
That should not happen, it really should get the password the user entered.
but that should not change anything. PAM modules are stackable, and it should not matter which module does the conversation with the application doing the authentication.
Quote:
Originally Posted by chesschi
What Radius does is fairly straight-forward
Yeah, I just downloaded and browsed through the sources. It seems pretty usual for a PAM module, and appears to work just like the other PAM modules. (For comparison, see Linux-PAM, modules/pam_unix/pam_unix_auth.c.)
Quote:
Originally Posted by chesschi
I am not familiar with SSH source code at all. I don't understand at which point in time SSH server will update the password if the user is not in /etc/passwd.
OpenSSH is not at issue here. It uses the PAM interface to converse with the authentication modules. The user name is obtained from the SSH connection, but password is only prompted for if and when the PAM module asks for it (and challenge-response authentication is allowed in sshd_config). From OpenSSH's point of view, it does not matter which PAM module it is using; that's the point of using PAM.
Your problem is that your PAM configuration, for some reason, is not satisfied by the pam_radius module alone. Have you noted that the configuration files may contain @include diretives? While the configuration for the OpenSSH daemon is in /etc/pam.d/sshd, the file usually contains @include common-auth to include /etc/pam.d/common-auth file, which contains the authentication for all services. I apologise if I am repeating things you already know well; I only wish to make sure we both have the entire picture.
What I do not know, is whether the FreeRadius server provides the user information (user ID, group IDs, GECOS or attributes) like UNIX user accounts and LDAP do. If it does, then you could start by replacing /etc/pam.d/sshd with just
(no @include's at all!) to see if the FreeRadius authentication works. account and session are always allowed, so that an authenticated user is permitted by default (as long as they are authenticated).Denying password means that this config does not allow passwords to be changed. This configuration should work, because it only uses the Radius authentication and nothing else. If this does not work, then the Radius authentication has a problem (or the FreeRadius server does not provide the user information).
After the above works, you can continue by replacing the auth line with
and so on, going closer to the default configuration one directive at a time.
Finally, when you are sure it works, move the auth config from /etc/pam.d/sshd to the common files, so that all services use the same configuration by default. It might not seem like very important right now, but it is; one uses PAM services surprisingly often. Consider sudo for example: if it does not share the auth config, your Radius users cannot use sudo. (Furthermore, the superuser cannot do operations via sudo as a Radius user.)
I would be extremely interested in whether the basic four-line /etc/pam.d/sshd configuration works. Also, you did not yet tell me whether id -u sshuser works when sshuser is a Radius user not mentioned in /etc/passwd nor /etc/shadow? If it does, then the user information is obtained from the Radius service. If it does not work, then user information is not obtained from the Radius service.
I tried the above settings but radius is still unable to get the password correctly.
Quote:
Originally Posted by Nominal Animal
Have you noted that the configuration files may contain @include diretives?
My linux distro is CentOS 5.5. Once I installed OpenSSH with PAM enabled, the default setting in /etc/pam.d/sshd include system-auth. Then I added the radius module in the configuration file, i.e.
Code:
#%PAM-1.0
auth sufficient pam_radius_auth.so
auth include system-auth
account required pam_nologin.so
account include system-auth
password include system-auth
session optional pam_keyinit.so force revoke
session include system-auth
session required pam_loginuid.so
And the setting for /etc/init.d/system-auth is:
Code:
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password requisite pam_cracklib.so try_first_pass retry=3
password sufficient pam_unix.so md5 shadow nis nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
This returns no such user. So user information is not obtained from the Radius service. So what is the implication of this?
Does it mean that the pam_radius_auth module uses linux pam incorrectly?
This returns no such user. So user information is not obtained from the Radius service. So what is the implication of this?
The user information (UID, GID, and additional groups) must be obtained from somewhere for SSH login to be possible. This is a technical requirement; it is how access (to filesystem objects for example) is controlled in Linux. Each process runs under a specific user-ID and group-ID (and possibly additional groups). If there is no such information, OpenSSH can not let the user proceed. To make sure the supplied password is not leaked, it will replace the password (with "\b\n\r\177INCORRECT" as you have already seen) supplied to the PAM stack. Remember, it does not matter what the PAM stack responds at that point; the login is not going to happen anyway. User name and password alone simply is not enough.
According to a recent post by the developer, I think pam_auth_radius alone cannot provide the necessary information. I could be wrong, though. It may be that you just have not specified the user ID, group ID, and optional supplementary group IDs to the FreeRadius server.
Everything I've seen thus far indicates you should consider using LDAP instead. If you need Radius for something specific, you can always use FreeRadius with the same LDAP configured as a backend: basically, you can still use FreeRadius for passwords and accounting, but keep the user information (posixAccount) in LDAP. This seems to be quite a common configuration, but if you do not specifically need the Radius accounting stuff, you could simplify things and go with LDAP alone. Personally, I find the Radius network protocol dangerous (the passwords are only secured by the static secret); I believe SSL/TLS-secured LDAP connections are orders of magnitude more secure.
Another option is to write a set of simple scripts to "push" the Radius user account information (/etc/{passwd,group,shadow,gshadow} from a centralized location. You do not want to simply replace the files, you need a merge script on the receiving end to modify only the Radius entries. It's not too complicated with Bash and awk, for example. Basically, you "reserve" (logically, not technically) a range of user and group ID's for Radius users, say 30000-40000. Periodically, or when the user set changes, each machine retrieves the user and group lists from a centralized server, then modifies their local files accordingly. (Retrieving is easiest to do using scp and a dedicated user account, using public keys to authenticate between machines.) I'm sure I and others can help you with this, if you decide to go this route; just start a new topic in the Programming forum.
Thanks for your great help! I had a better idea of OpenSSH now.
Quote:
Originally Posted by Nominal Animal
The user information (UID, GID, and additional groups) must be obtained from somewhere for SSH login to be possible. This is a technical requirement; it is how access (to filesystem objects for example) is controlled in Linux. Each process runs under a specific user-ID and group-ID (and possibly additional groups). If there is no such information, OpenSSH can not let the user proceed. To make sure the supplied password is not leaked, it will replace the password (with "\b\n\r\177INCORRECT" as you have already seen) supplied to the PAM stack. Remember, it does not matter what the PAM stack responds at that point; the login is not going to happen anyway. User name and password alone simply is not enough.
I also don't think pam_radius_auth can provide the necessary information. Since my current setup is:
PC1: OpenSSH server and PAM-capable FreeRadius client
PC2: FreeRadius Server (with user accounts)
If the user accounts are not specified in PC1, I am just curious normally how a FreeRadius client or PAM-capable client should provide the user ID, group ID, and optional supplementary group IDs so that SSH can pick them up.
Is that once the FreeRadius client receives the user ID from SSH server, it should create a user temporarily in /etc/{passwd,group,shadow,gshadow} in runtime? If so, would it be "too late" because SSH cannot find the user information until the pam_radius_auth kicks in? What is the proper way to deal with this?
Is that once the FreeRadius client receives the user ID from SSH server, it should create a user temporarily in /etc/{passwd,group,shadow,gshadow} in runtime? If so, would it be "too late" because SSH cannot find the user information until the pam_radius_auth kicks in? What is the proper way to deal with this?
It would be too late; OpenSSH would already have replaced the password with the invalid one, since the account does not exist.
Check out this post by the pam_auth_radius maintainer (Alan DeKok) on the freeradius-users mailing list: The missing bit is a Radius NSS module (Name Service Switch module) that would provide the necessary account information. NSS is implemented as a dynamic library (even for static binaries!) in systems using the GNU C library. For proper privilege separation (and keeping the shared secret secret) the module would have to be in two parts: a dynamic library part, which connects to a locally-running daemon. The daemon would know the shared secrets, and do the communication with the Radius server.
However, Radius and NSS designs are at odds. Radius basically keys everything off based on the user name, but NSS identifies users and groups based on ID (numbers); names are just string labels. It might be workable to just cache and occasionally re-query the Radius server about users that have ever logged in to a machine, but it would be pretty much a hack: it would not work well if there are shared filesystems (since the cached user information may not contain all users). Technically, the Radius server would need to have a special Login-Service that would always succeed (ignoring the supplied password), but would specify the user information in Vendor-Specific attribute in the response, say format UID:GID:Supplementary-GID(s):GECOS: where the UID and GID(s) can be either numeric or local user/group names for mapping.
In other words, Radius alone is not going to cut it. Even if you invested (time) to develop an NSS module, it would be limited compared to LDAP. It is therefore no surprise that many use LDAP in addition to (or as a backed to) FreeRadius, at least storing the user account information in the LDAP database (posixAccount objects). Or, as I stated earlier, use scripts to maintain the user account information in files, from a centralized location. My suggestion to you is therefore to install OpenLDAP alongside FreeRadius, and perhaps modify FreeRadius to use LDAP as the backend. Or, if you do not need Radius features, just discard FreeRadius altogether for a simpler LDAP scheme.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.