Linux LDAP authentication with Samba4

Given a fresh Samba4 domain setup and a bunch of Linux/Windows client machines, how do you configure them to allow logins from domain users–ideally with a shared userspace mounted from Samba4? In this post, I’m going to share my experience on how I setup Ubuntu clients to authenticate via Active Directory. The default behavior in Samba4 is to use winbind, which keeps a local flat file of uid/gid mappings. I prefer letting LDAP hold that data. It’s possible to edit user accounts in the Active Directory tree to include the posixAccount LDAP class with uidNumber/gidNumber/unixHomeDirectory/loginShell attributes, and setup each Linux client to talk to the Active Directory domain controller merely as a Kerberized LDAP server. As a result, we can have a single account and password for both Windows and Linux users across the domain. We don’t have to join the Linux machines to the domain, we just need to export the correct Kerberos credentials to each client. I learned about this technique primarily from this blog, although I also heavily referenced the Samba4 mailing list.

Note: If security is top priority for you, you may prefer the full domain join route for Linux machines. In fact, it’s probably best not to bother with Samba4 at all in that case…

Samba4

You’ll need to make some minor changes to Samba4. Under /usr/local/samba/etc/smb.conf (or wherever this file is stored), add the following line:

idmap_ldb:use rfc2307 = Yes

This instructs Samba4 to rely on LDAP for uid/gid mapping for users. Otherwise, it will use the local winbind flat file database.

Admittedly, I haven’t found a lot of information on how this works, so I’m speaking mainly from what I’ve observed. Take it with a grain of salt. If you want to be able to resolve usernames/groups on your Samba4 server, you’ll need to perform the following steps on the server machine as well as any clients.

nss-pam-ldap

The key package you will need to make this work is nss-pam-ldap. You can find it here. As stated on the website, this package provides a PAM module and daemon (nslcd) for querying and authenticating to an LDAP server. Follow the instructions here on how to set it up. I don’t want to reiterate everything that’s stated in the documentation, so I’ll just add some things.

  • If you want to connect to a remote LDAP server, make sure you specify the address in the form ldap://IP_ADDRESS. I made the mistake of using the hostname and got strange errors…it took me a while to track that one down.
  • The /etc/nsswitch.conf portion tells your machine where to look for user/group/host name resolution. It’s an essential step, so don’t forget it.
  • When I installed the package, I’m pretty sure it edited the pam configuration files for me. Check to be sure. Also, be careful editing these files because you could easily lock yourself out of the machine.

Active Directory requires Kerberos authenticated queries. You might be able to specify a domain user and password, but a kerberos keytab is probably better. The keytab is a principle/encryption key pair that grants the right to request keys without a password. I’ll explain more about this in a bit. Before we make changes to /etc/nslcd.conf to integrate that component, we need to do some Kerberos related setup.

Kerberos

I recommend reading up on Kerberos; it’s a really neat technology that Active Directory utilizes heavily. Here are some terms you’ll find thrown around a lot:

Realm – The Kerberos Realm identifies a specific Kerberos database stored on a single machine (KDC). It’s usually the same as the domain name, but it doesn’t have to be.

Principle – *A Kerberos principal is a unique identity to which Kerberos can assign tickets. Principals can have an arbitrary number of components. Each component is separated by a component separator, generally `/’. The last component is the realm, separated from the rest of the principal by the realm separator, generally `@’. If there is no realm component in the principal, then it will be assumed that the principal is in the default realm for the context in which it is being used.

Keytab – *All Kerberos server machines need a keytab file, called /etc/krb5.keytab, to authenticate to the KDC. The keytab file is an encrypted, local, on-disk copy of the host’s key.

*Taken straight from the MIT documentation.

Before messing with these though, we need to create a domain user.

samba-tool user add ldap-service
samba-tool user setexpiry ldap-service --noexpiry

We then need to export a keytab for this user, which will allow us to request keys without a password:

samba-tool domain exportkeytab /etc/nslcd.keytab --principal=ldap-service

You’ll need to copy this key to any of your clients that use nslcd. Keep in mind that this key grants domain user privileges without using a password, so limit the permissions on this file heavily.

Before continuing, you should make sure you having these packages installed: kstart, libsasl2-modules-gssapi-mit. If you forget the latter, you’ll get a “no suitable SASL mechanism found” error.

Once again, open up nslcd.conf and add the following lines:

# samAccountName holds the username in AD. It's a suitable substitute for uid. We can map it to avoid duplicating data.
map passwd uid samAccountName

# homeDirectory is already in use by AD for storing the Windows directory. We'll store ours in unixHomeDirectory
map passwd homeDirectory unixHomeDirectory

# Enable Kerberos authentication
sasl_mech GSSAPI
sasl_realm YOURREALM.DOMAIN.COM
krb5_ccname /var/run/nslcd/nslcd.tkt

The last line points at a ticket file that we haven’t done anything with yet. The keytab file just gives you the right to request tickets. A ticket actually gives you access to resources, and has an expiration date associated with it. We need to tell nslcd to request a tickets at a certain interval using this keytab file. To do this (in Ubuntu), edit /etc/default/nslcd to look like the following:

K5START_START="yes"
K5START_BIN=/usr/bin/k5start
K5START_KEYTAB=/etc/nslcd.keytab
K5START_PRINCIPLE=ldap-service

The nslcd service will use a daemon called k5start to request a new ticket at specified certain interval.

As an important sidenote, there is a service called nscd (not to be confused with nslcd) that caches name lookups. It’s good to have running on all your clients because it takes the load off your LDAP server. However, during testing you should turn it off via `service nscd stop` so that you’re actually talking to the LDAP server and not a local cache.

User Accounts

At this point, you should be able to start nslcd and run getent passwd without things hanging. Make sure to check your system log to verify that things are working. Keep in mind that you can run nslcd -d (with multiple d’s for more output) directly on the command line to see error output. You’ll want to check that LDAP binds are working. However, you won’t actually see any domain user accounts listed in the getent output because we haven’t added posixAccount classes to them yet.

The easiest way to do this is through the ldb* set of commands provided by samba. If you run kinit administrator, you should be able to connect to your Samba4 LDAP server with Kerberos authentication by using the “-k yes” flag. As an example:

 ldbsearch -H ldap://SERVER_HOSTNAME -k yes

should print the entire tree. I noticed that when using these utilities, I have to specify the hostname of my LDAP server. Using the IP address fails with NT_STATUS_INVALID_PARAMETER. I’m not sure why that’s the case.

In our case, we want to modify a user entry to include the posixAccount data. If you haven’t already, make a domain user using the samba-tool user add interface.

Next, create a .ldif file and add the following lines:

dn: USERCN
changetype: modify
add: objectClass
objectClass: posixAccount
-
add: uidNumber
uidNumber: UIDNUMBER
-
add: gidNumber
gidNumber: GIDNUMBER
-
add: unixHomeDirectory
unixHomeDirectory: HOMEDIRECTORY
-
add: loginShell
loginShell: /bin/bash

Obviously, you’ll need to replace the upper case entries with your specific data. Once you have this file, you can write it to the LDAP tree with the following command:

ldbmodify -H ldap://SERVER_HOSTNAME -k yes /tmp/YOURFILE.ldif

Now your user has all the data it needs to authenticate and login to a Linux client! If everything works, you should now be able to type getent passwd YOURUSER and see their entry in the output. You should also be able to su – YOURUSER and authenticate. If you’re lucky and it works, congrats! You’ve just logged in to your Linux client through Active Directory! It you’re like me, things probably didn’t work the first time. Make sure to check the logs and utilize debug mode for the nslcd and samba services. Good luck!