0

I tend to a number of computers running Ubuntu Linux. I want a central service to authenticate console users against. All user files (home) should be in one location. I am aware there are numerous sensible solutions to this, including (but not limited to) a file-server exporting shares via NFS and LDAP or Kerberos or even a Microsoft Active Directory. However, due to budget cuts, I am not granted any of those. Only thing I do have is a file-server with a samba share. On a single share, each user has a destinct directory only writable to them. Can I authenticate a console user against a samba share?

1 Answer 1

0

Considerations

There is different parts to this:

  1. The authentication itself ("may this user use the computer?").
  2. The account data including user information, ID mapping, group membership,… (the data of e.g. getent passwd).

Authentication

Checking credentials (user and password) against a samba share is relatively easy. You can use smbclient:

smbclient --user="$PAM_USER" --password="$password" --directory "$PAM_USER" --command="quit" "\\\\fileserver.example.com\\homes"

This command will succeed if the credentials are correct and fail if the server rejects them. You can use it with pam_exec. pam_exec will set $PAM_USER and also helps with obtaining $password. See the full example at the end of this answer. This question has a similar intent.

Adding this to the PAM auth stage will handle the authentication, but on its own will not make the login work.

Account

In order to actually use the system, the user must be known to the system. This is handled by the Name Service Switch (nss). I am not aware of any samba-specific module, though. Also, we do not really need one. Since we already know that a user provided credentials which have been validated by the samba server, we can simply create a local user on the fly and give it with the very same password. Also, I want to add the user to a special goup sambahome so I can easily differentiate between ordinary local users (such as root) and users with their home on the share.

adduser "$PAM_USER" --quiet --gecos "" --home "/home/$PAM_USER" --no-create-home --add_extra_groups --disabled-password &&
echo "$PAM_USER:$passwd" | chpasswd &&
adduser "$PAM_USER" "sambahome"

Storage

Since the user's home directory resides on a samba share, we can employ pam_mount to mount the share automatically during logon.

Implementation

Authentication

This is my default /etc/pam.d/common-auth, expanded by some lines:

auth    [success=3 default=ignore]  pam_unix.so nullok
auth    optional    pam_exec.so expose_authtok /usr/local/sbin/pam-addsmbuser
auth    [success=1 default=ignore]  pam_unix.so nullok
auth    requisite           pam_deny.so
auth    required            pam_permit.so

auth    [success=ok default=1] pam_succeed_if.so quiet_fail user ingroup sambahome
auth    optional    pam_mount.so 

The first line (with pam_unix) checks the credentials for a local user.
On success, the next 3 lines are skipped and pam_permit takes effect.
In case there is no local user, the second line will be considered. pam_exec will execute pam-addsmbuser which will create a new local user. Then pam_unix is queried again (in the third line).

In either case, pam_mount is executed, but only if the user actually has their home on the samba share. Guarding this with pam_succeed_if is optional, but keeps auth logs clean.

Account

In whole, /usr/local/sbin/pam-addsmbuser looks like this:

#!/bin/sh
read password
if smbclient --workgroup="AD.FH-WEDEL.DE" --user="$PAM_USER" --password="$password" --directory "$PAM_USER" --command="quit" "\\\\fs1.ad.fh-wedel.de\\tux-homes"
then
    adduser --disabled-password --gecos "" --home "/home/ad/$PAM_USER" --no-create-home --quiet --add_extra_groups "$PAM_USER" &&
    echo "$PAM_USER:$password" | chpasswd &&
    adduser "$PAM_USER" "sambahome"
fi

Please note that $PAM_USER is an environment variable whereas $password is read from standard input.

Storage

The relevant lines in /etc/security/pam_mount.conf.xml:

<volume fstype="cifs" server="fileserver.example.com" path="homes/%(USER)" mountpoint="/home/%(USER)" options="uid=%(USER),gid=%(USERGID),dir_mode=0700,file_mode=0700,nosuid,nodev,mfsymlinks" />
<mkmountpoint enable="1" remove="true" />

You might need to tweak the options at the end according to your needs. I have mixed feelings about mfsymlinks.

Session

In order to work, pam_mount also must be present in /etc/pam.d/common-session:

session [success=ok default=1] pam_succeed_if.so quiet_fail user ingroup sambahome
session optional    pam_mount.so

Results

I have been using this setup for months. So far it looks sufficiently reliable.

Caveats

As far as I can tell, this method of checking credentials only works for username and password. Password-less methods such as public-key authentication via SSH probably will not work. I did not check.

This system will not handle password changes gracefully. If the local password is changed, authentication will succeed via pam_unix, but the samba server will reject the password and pam_mount will fail. Similar problems arise with a server-side password change. This can probably be worked around with more intricatre scripts.

Local UIDs will not be the same across the systems. I do not see any problem with that, though.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .