LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-31-2011, 09:08 AM   #1
chesschi
Member
 
Registered: May 2011
Posts: 41

Rep: Reputation: 0
OpenSSH and PAM


Hello!

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?

Thanks a lot!!!!

Last edited by chesschi; 08-31-2011 at 09:10 AM.
 
Old 09-01-2011, 03:42 AM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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.)
 
Old 09-01-2011, 06:33 AM   #3
chesschi
Member
 
Registered: May 2011
Posts: 41

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
Which version of OpenSSH?
It's 5.2p1. But I tried the latest version and I got the same results.

Quote:
Originally Posted by Nominal Animal View Post
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 View Post
(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
 
Old 09-01-2011, 11:20 PM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by chesschi View Post
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:
Code:
auth       sufficient   /lib/security/pam_radius_auth.so
auth       required     /lib/security/pam_unix_auth.so
That (the required bit) does not look correct to me.

Based on LDAP configurations known to work, I personally would use
Code:
auth       sufficient   pam_unix.so
auth       sufficient   pam_radius_auth.so use_first_pass
auth       required     pam_deny.so
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?
 
Old 09-02-2011, 06:52 AM   #5
chesschi
Member
 
Registered: May 2011
Posts: 41

Original Poster
Rep: Reputation: 0
Thank you for your response! Unfortunately, I am still struggling how to make it work with your suggestion.

Quote:
Originally Posted by Nominal Animal View Post
Code:
auth       sufficient   pam_unix.so
auth       sufficient   pam_radius_auth.so use_first_pass
auth       required     pam_deny.so
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 View Post
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.
Code:
retval = pam_get_item(pamh, PAM_CONV, (CONST void **) &conv);
retval = conv->conv(1, msg, &resp,conv->appdata_ptr);
where *resp is the password.

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?

Thanks!!!
 
Old 09-02-2011, 11:42 PM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by chesschi View Post
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.

You could try inverting the stacking order, i.e.
Code:
auth       sufficient   pam_radius_auth.so
auth       sufficient   pam_unix.so use_first_pass
auth       required     pam_deny.so
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 View Post
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 View Post
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
Code:
auth      required   pam_radius_auth.so
account   required   pam_permit.so
session   required   pam_permit.so
password  required   pam_deny.so
(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
Code:
auth       sufficient   pam_radius_auth.so
auth       sufficient   pam_unix.so use_first_pass
auth       required     pam_deny.so
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.
 
Old 09-05-2011, 04:06 AM   #7
chesschi
Member
 
Registered: May 2011
Posts: 41

Original Poster
Rep: Reputation: 0
Thanks for your reply!

Quote:
Originally Posted by Nominal Animal View Post
You could try inverting the stacking order, i.e.
Code:
auth       sufficient   pam_radius_auth.so
auth       sufficient   pam_unix.so use_first_pass
auth       required     pam_deny.so
Code:
auth      required   pam_radius_auth.so
account   required   pam_permit.so
session   required   pam_permit.so
password  required   pam_deny.so
I tried the above settings but radius is still unable to get the password correctly.

Quote:
Originally Posted by Nominal Animal View Post
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
And the sshd_config setting is:
Code:
UsePAM yes
PasswordAuthentication yes
ChallengeResponseAuthentication yes
Quote:
Originally Posted by Nominal Animal View Post
id -u sshuser
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?

Thanks!!!

Last edited by chesschi; 09-05-2011 at 04:08 AM.
 
Old 09-05-2011, 06:14 AM   #8
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Just to verify, if you replace /etc/pam.d/sshd with
Code:
#%PAM-1.0
auth        required      pam_env.so
auth        required      pam_radius_auth.so
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     required      pam_nologin.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_radius_auth.so

session     optional      pam_keyinit.so force revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_permit.so

password    required      pam_deny.so
do SSH logins with Radius accounts work or not?

Quote:
Originally Posted by chesschi View Post
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.
 
1 members found this post helpful.
Old 09-06-2011, 06:20 AM   #9
chesschi
Member
 
Registered: May 2011
Posts: 41

Original Poster
Rep: Reputation: 0
Thanks for your great help! I had a better idea of OpenSSH now.

Quote:
Originally Posted by Nominal Animal View Post
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?

Thanks A LOT!!!
 
Old 09-06-2011, 10:01 AM   #10
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by chesschi View Post
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.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] OpenSSH and PAM julienr78 Linux - Security 4 10-02-2010 04:02 AM
passwordless OpenSSH with MIT-Kerberos and PAM dbalsige Linux - Software 1 11-12-2009 12:12 PM
OpenSSH, authentication, PAM haertig Linux - Security 3 03-27-2006 01:40 PM
openssh/PAM auth problem crippler909 Linux From Scratch 1 06-08-2003 11:51 AM
OpenSSH and PAM Authentication RyanP Linux - General 4 02-17-2001 12:08 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:05 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration