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!

Advertisements

Joining Samba4 to an Existing Windows Domain.

Note: See my first post for more context.

I am developing an small Active Directory infrastructure for the Computer Science Department Linux/Windows lab environment at Taylor University. Lab users have a central user space shared by both the Linux and Windows profiles, which authenticate from to Active Directory. Our Windows profile setup utilizes folder redirection to the network share for most profile folders (Desktop, Music, Pictures, Downloads, AppData/Roaming, etc), while our Linux space is NFS mounted by clients. Since we favor Linux administration, we prefer to keep our user files stored on a Linux file system. The Samba4 server grants CIFS access to Windows users, while Linux users can automount via NFS. LDAP authentication is handled through Kerberos on both the Windows and Linux clients. While Windows clients are joined to the Domain, Linux treats Active Directory merely as a Kerberized LDAP server. Finally, each user account is extended with a posixAccount class allowing us to give each user the uid, gid, unix home directory, and login shell attributes they need to properly interface with nslcd (the ldap client daemon) for Linux logins.

Prerequisites

I started by setting up two Windows Server 2008 R2 machines. I created a new domain, installed the Active Directory Domain Services and DNS roles via the dcpromo.exe utility, configured both machines as domain controllers. This process is very well documented by Microsoft so I won’t describe it here. It’s important to ensure that directory and DNS replication is happening between these machines. I chose two Windows domain controllers for a few reasons:

  1. Demoting any DC appears to fail when a Samba4 DC exists in the domain. I’m not sure if this is specific to my setup, but it’s just one of the many bugs I’ve found so far (I hope they fix it soon). As such, I don’t really trust S4 to keep my production directory data intact, and if I have to demote (read: manually delete) my Windows DC for any reason, I want the directory data housed within Windows DC.
  2. Related to the above comment, I’m not comfortable yet entrusting S4 with master roles, thus I need two Windows boxes in case I need to bring one down.
  3. Active Directory is highly reliant on DNS. As such, I strongly prefer the Windows DNS to a hacked up BIND solution or S4’s brand new internal system. Having a two replicating Windows DNS servers is even better.
  4. Apparently, the Samba4 DNS doesn’t play well with Windows DNS yet. Once again, if I have to choose…

Anyway, after configuring the Windows machines, the next step was to create an Ubuntu Linux server (I chose Ubuntu because it’s heavily favored by the Samba4 team) and join it as a DC to the existing Windows domain. You first need to prepare your server for Samba4. Then, you need to setup Samba to join an existing domain.

Rather than regurgitate what is already stated on that Wiki, I’ll just note some things.

Kerberos

When you setup the Kerberos configuration file as stated in the Wiki, it’s important to test it out via kinit administrator@YOURREALM. By authenticating, you’ve requested a ticket from the Kerberos server, which is then placed in the default ticket cache, located at /tmp/krb5cc_0. If this isn’t working properly, the provision step will fail–probably with an LDAP authentication error.

Domain Name Service

If you’ve followed the Wiki instructions correctly up to this point, the provision step should work. After doing lots of test provisions, I’ve noticed that the DNS replication doesn’t always work (this is actually a known documented issue I guess). You can run the test commands they give you in the Wiki, or use the Windows DNS GUI to check that entries exist–my preferred approach. The Active Directory DNS tree heavily utilizes SRV records for services. The main ones we care about are Kerberos, LDAP, and GC (Global Catalog). Browse the DNS tree and make sure that you can see your Samba4 server listed along with the other Windows DC’s. In my configuration I noticed that under DomainDNSZones and ForestDNSZones, my Samba4 server is not listed. I think this is intended behavior because the Windows DNS and Samba4 DNS don’t work together quite yet.
If you notice that those entries don’t exist, there’s a handy script called samba_dnsupdate, located in INSTALL_DIR/samba/sbin/. That should replicate the DNS entries you need to the Windows DC’s. In the cases where the provision step failed to do this for me, running that script fixed the problem. Your mileage may vary.

Directory Replication Service

You can view the replication status by running the following command: samba-tool drs showrepl. If things don’t look like they’re working, first make sure you’ve started Samba! It may take it a few minutes to “warm up.” You can force replication by running:

samba-tool drs replicate <destinationDC> <sourceDC> <NC>

The NC term is your LDAP naming context; to replicate the whole tree, use your base Distinguished Name, e.g. DC=SOMETHING,DC=TEST,DC=COM. Under the Active Directory Sites and Services subtree in the Windows Server Manager GUI, you can view the connections between servers (Sites -> Default-First-Site-Name -> Servers -> YourS4Server). I’ve done several test configurations, and every one of them throws an error when I try and replicate to the Samba4 server from a Windows DC. This is the error I get:

The following error occurred during the attempt to synchronize naming context DomainDNSZones.<DOMAINNAME> from Domain Controller <Samba DC> to Domain Controller <Windows DC>: The naming context is in the process of being removed or is not replicated from the specific server. The operation will not continue.

Interestingly enough, if I replicate via samba-tool using the same source and destination servers, everything works. I’m assuming there’s some incompatibility there that hasn’t been addressed yet by the Samba team. If anyone has a solution for this please let me know. So far it hasn’t caused any problems.
Another good test of replication is to create a user account and see if it transfers across domain controllers. You can do this via samba-tool user add.

Distributed File System Replication

Samba4 does not yet support DFS replication. For our purposes, the main issue this causes is group policy synchronization issues; namely, the SYSVOL folder–which houses group policy objects–is not replicated from the Windows domain controllers to the Samba server. As a result, you’ll need to manually mount the SYSVOL share, copy the data over, and then run samba-tool ntacl sysvolreset to fix the permissions. Ideally, you should write a script to do it. This only needs to be updated when you’ve changed a group policy object. This is a bit annoying, but it’s not a show stopper. If you don’t do this, then your clients will apply different group policy settings based on which controller they happen to talk to, which is bad.

Coming Up

At this point in the setup process, I had my two Windows and Samba4 domain controllers communicating pretty happily. In my next post I’ll talk about how I setup my Linux and Windows clients to authenticate, login, and access user data from the Samba server. Stay tuned!

Samba 4: A Case Study (Part 1)

I work in the IT department for the Computer Science Department at Taylor University. We do things a little differently here in terms of our lab machine setup. We dual boot Ubuntu Linux and Windows 7, but we centralize our file serving and domain controlling through Samba on Linux–as opposed to a Windows Active Directory Solution. Currently, we use Samba 3.5.x as our Primary Domain Controller with an OpenLDAP backend to host user accounts. This has been working, but it has issues. Samba 3 was designed for the NT style domain, which is really starting to show its age when compared to modern Active Directory. For instance, to edit a group policy setting, we currently have to manually edit our Windows OS image and push it out to every machine (alternatively, we have an updater script that allows us to do it without re-imaging, but it’s still a pain).

I started following Samba 4 development late last year, which just had its first official release a couple months ago, and I’m now in the process of building a production active directory cluster to replace the Samba 3 server. The official HOWTO is a little skimpy (listed here: http://wiki.samba.org/index.php/Samba_AD_DC_HOWTO), so I thought  I would add some of my experience setting this stuff up. As a disclaimer, I’m no expert, so this just my understanding based on messing around with it. If you notice something that’s not correct, please leave a comment or email me.

System Architecture

Before I go into details, I wanted to give a bit of an overview of the server architecture I went with. Although the Samba team would love for you to use Samba 4 exclusively, my personal experience tells me that it really should have a Windows DC attached to it (two would be better). I guess it depends on your specific needs, but one big reason we’re opting for Samba is the unification of file space and permissions between Linux and Windows.

One key thing to know about Active Directory is that it’s deeply tied into DNS. You can’t query for anything in the domain without a working DNS configuration. For a Linux-only solution, there are two options: use a heavily modified Bind configuration integrated with Samba (which has issues), or just choose the new default internal DNS server built by the Samba team.

Messing with Bind isn’t my cup of tea, and if you’re looking for help there, I’m not your guy. I’m not really excited about using the custom DNS solution either, for a couple reasons. For one, it’s brand new, so it’s a security risk, and it lacks the stability of industry standard DNS solutions. It seems like the Samba team just got fed up hacking Bind to match their needs, so they just wrote their own. That’s all well and good, but I’d rather use the Windows DNS solution. It’s turnkey, stable, and still allows for Linux integration I need.

I fiddles around with a couple different server configurations. I first tried using S4 as the initial DC. I built a Windows Server 2008 R2 machine (sidenote: don’t bother with Windows Server 2012, it’s not supported yet), and tried joining it to the Samba domain. I kept running into strange errors in dcpromo.exe, so that didn’t work.

In my second attempt, I built a Windows server box and joined the S4 server to it, using the instructions listed here: http://wiki.samba.org/index.php/Samba4/HOWTO/Join_a_domain_as_a_DC

This worked pretty well. I was able to join successfully and get replication working; I really like having the Windows GUI for DNS and Group Policy settings accessible from Windows. Because I don’t quite trust S4 yet, I added  a second Windows DC to the cluster. I’ve noticed that the S4 server screws up some features. For instance, I can’t demote any of the domain controllers (I get weird errors), so I have to manually remove the connections and DNS entries. This isn’t the end of the world for us because we have a small cluster. For larger clusters this would be a big show stopper. I’ve seen some chatter about this on the samba news list, but no solutions.  There are other minor issues I’ve run into, but I won’t list them here. I’ll probably make a separate post for that.

Those hiccups aside, I’m able to replicate the directory entries between all domain controllers. I can also create accounts on either the S4 or Windows machines successfully. I created a couple fresh Windows 7 builds and configured some group policy settings for them (including folder redirection and roaming profiles). It didn’t take too long to get that working.

There’s a lot of details I’ve come across in setting this up, so I’m going to try and spread it out over a few posts. Stay tuned for updates! If you have any questions about things, feel free to comment or email me.