Active Directory Authentication in Linux


Windows uses Active Directory for authentication, specifically Kerberos. Linux once used only the traditional Unix authentication methods (/etc/password), but eventually adopted Sun’s PAM (pluggable authentication modules). PAM provides a unified authentication API that decouples application-level authentication from whatever underlying, lower-level authentication mechanism(s) the system uses.

We want some AD users to be able to log into a Linux box using their AD password. This is a relatively modest goal. More complex and extensive integrations are possible. Red Hat’s Windows Integration Guide outlines what’s possible.

Linux systems ship with Kerberos and LDAP PAM modules than work with AD. However, SSSD (System Security Services Daemon) adds security and convenience when integrating with Active Directory. SSSD acts as a proxy between between PAM+NSS and AD. SSSD authenticates to AD by Kerberos, and fetches user and group info by LDAP.

Samba Winbind provides similar functionality to SSSD, but SSSD improves on Winbind in several ways, including the ability to integrate with FreeIPA in addition to Active Directory.

So, Linux has these basic components:

SSSD sits between PAM+NSS and Active Directory:

+--------+            +--------+           +--------------------+
|        |    LDAP    |        |    NSS    |                    |
|        |<---------->|        |<--------->|                    |
| AD DC  |            |  SSSD  |           | Linux Applications |
|        |<---------->|        |<--------->|                    |
|        |  Kerberos  |        |    PAM    |                    |
+--------+            +--------+           +--------------------+

What are the pieces we need on the Linux box?

In short, SSSD and realmd are very auto-magical. This is often sufficient to join the domain:

#  apt-get install sssd packagekit realmd adcli oddjob-mkhomedir
#  realm join


Linux has user and group ID’s. AD has security ID’s. One of the roles of SSSD is to map AD SID’s to Linux user and group ID’s. SSSD handles mapping ID’s like this:

  1. Reserve a range of Linux ID’s for each AD domain.
  2. When an AD user logs into the Linux box for the first time, SSSD creates ID’s in the domain’s range based on the user’s SID.
  3. Because SSSD does the above two things deterministically, a user should get the same ID’s on any Linux box.

It’s possible, though not necessary, to store user POSIX attributes in AD, including uidNumber, gidNumber, unixHomeDirectory, and loginShell. However, SSSD overrides such values unless we disable its automatic ID mapping.

Prerequisites for AD to Support SSSD ID Mapping

No configuration should be necessary, if the following things are properly configured.

Home Directories

The oddjob-mkhomedir package adds a helper to create home directories for AD users. Install the package, edit /etc/sssd/sssd.conf, and set:

override_homedir = /home/%d/%u
default_shell = /bin/bash

After making changes to /etc/sssd/sssd.conf:

#  systemctl restart sssd.service

Automatic Kerberos Host Keytab Renewal

Install the adcli package. It help SSSD automatically new the Kerberos host keytab.

SSSD complains about NSCD

NSCD socket was detected and seems to be configured to cache some of the databases controlled by SSSD [passwd,group,netgroup,services]. It is recommended not to run NSCD in parallel with SSSD, unles…ed not to cache these.

Edit /etc/nscd.conf:

enable-cache hosts yes
enable-cache passwd no
enable-cache group no
enable-cache netgroup no

Join the Linux box to the Domain (realmd)

realmd discovers the domain, configures SSSD (or Windbind), configures Kerberos, and generally automates a lot of stuff. It also sets which AD users can access the Linux box.

#  realm discover
#  realm discover
#  realm join
#  realm deny --all
#  realm permit 'EXAMPLE\paul'
#  realm permit -g 'EXAMPLE\linux users'
$  id


On Red Hat:

#  yum install oddjob-mkhomedir
#  systemctl enable oddjobd
#  systemctl start oddjobd
#  authconfig --enablemkhomedir --update

Debian doesn’t have authconfig, and (as of 2018) doesn’t enable oddjob-mkhomedir, even after installing it. So, enable it manually but editing /etc/pam.d/common-session:

session optional skel=/etc/skel/ umask=0022

Naive questions

Can local users always log in, even if the DC is unreachable?

Yes. We can configure what authentication methods PAM uses, and the order in which it consults them in /etc/nsswitch.conf. Furthermore, SSSD can cache credentials to permit offline authentication.

How do we avoid confusion between local and domain users?

For Winbind, set winbind use default domain = no in /etc/samba/smb.conf. This forces domain users to specify an account name qualified with the domain at login (e.g., “EXAMPLE.COM\paul”).

SSSD defaults to this behavior. See default_domain_suffix and iuse_fully_qualified_names in sssd.conf(5).

Do we need to manually create home directories each domain user?

No. With Winbind, Samba takes care of that, as configured in /etc/samba/smb.conf, like template homedir = /home/%U@%D.

Eh, no, it should (?) create home directories, but doesn’t seem to actually do so….

If we do:

#  mkdir -p /home/EXAMPLE/paul
#  chmod 775 /home/EXAMPLE
#  chown 'EXAMPLE\paul' /home/EXAMPLE/paul
#  chmod 700 /home/EXAMPLE/paul

… then Winbind will set the directory as the user’s home. It just won’t auto-create the directory for us.

Maybe oddjob-mkhomedir? Yes, see the “oddjob-mkhomedir” section in these notes.

Can any domain user log in?

By default, yes.

According to what smb.conf(5) says about valid users, by default, yes. For Winbind, specify an allowed AD group (and exclude others) in /etc/samba/smb.conf, like:

valid users = @"Linux Users"

With SSSD, use realm:

#  realm deny --all
#  realm permit 'EXAMPLE\paul'
#  realm permit -g 'EXAMPLE\linux users'

Do mounted Windows shares have the right user mappings?

If we just do:

#  mount -t cifs -o cifsacl,username=Administrator, // /mnt/public
#  getcifsacl /mnt/public/

…no, the mount shows up with everything owned by root (the mounting user).

#  apt-get install libwbclient-sssd cifs-utils
--- 20180725170729-Debian-9 ~ $  sudo update-alternatives --config idmap-plugin
There is only one alternative in link group idmap-plugin (providing /etc/cifs-utils/idmap-plugin): /usr/lib/x86_64-linux-gnu/cifs-utils/
Nothing to configure.
--- 20180725170729-Debian-9 ~ $  ls -l /etc/cifs-utils/idmap-plugin
lrwxrwxrwx 1 root root 30 Jul 27 16:10 /etc/cifs-utils/idmap-plugin -> /etc/alternatives/idmap-plugin
--- 20180725170729-Debian-9 ~ $  ls -l /etc/alternatives/idmap-plugin
lrwxrwxrwx 1 root root 47 Jul 27 16:10 /etc/alternatives/idmap-plugin -> /usr/lib/x86_64-linux-gnu/cifs-utils/
--- 20180725170729-Debian-9 ~ $  ls -l /usr/lib/x86_64-linux-gnu/cifs-utils/
-rw-r--r-- 1 root root 10368 Feb  4  2017 /usr/lib/x86_64-linux-gnu/cifs-utils/

[Older stuff and things related to Winbind below….]

Samba Configuration

apt-get install winbind samba-common-bin realmd policykit-1 packagekit libnss-winbind libpam-winbind


The “winbind use default domain” parameter is useful in single-domain enterprises and causes winbind to treat any username that isn’t qualified with a domain name as a username in the domain to which winbind is joined. Omit this parameter if you are concerned about confusion between local accounts on your systems and accounts in the default domain.

workgroup = EXAMPLE
security = ads
encrypt passwords = yes
idmap config * : backend = tdb
idmap config * : range = 1000000-1999999
template homedir = /home/%D/%U
template shell = /bin/bash
restrict anonymous = 2
winbind enum groups = yes
winbind enum users = yes
valid users = @"Linux Users"

NSS Configuration

Edit /etc/nsswitch.conf:

passwd:         compat systemd winbind
group:          compat systemd winbind
shadow:         compat
gshadow:        compat

PAM Configuration

The /etc/pam.d/ directory contains PAM configurations for various applications. See pam.conf(5) and PAM(7).

Debian and Red Hat organize these files slightly differently. On Debian, for example, /etc/pam.d/sshd includes the general file /etc/pam.d/common-auth. On CentOS, /etc/pam.d/sshd includes the file /etc/pam.d/password-auth.

PAM consults configuration files for individual services before falling back to the generic /etc/pam.d/other.

N.B. Red Hat and Debian both include utilities to configure PAM: pam-auth-update and authconfig/authconfig-tui. Manual changes to the files in /etc/pam.d/ may get overwritten on such systems!

Possibly, with libpam-winbind installed, just run pam-auth-update to auto-magically configure PAM?

--- falstaff ~ %  cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Debian GNU/Linux buster/sid"
--- falstaff ~ %  ls /etc/pam.d/
chfn             common-session                 gdm-password  ppp        sudo
chpasswd         common-session-noninteractive  i3lock        runuser    systemd-user
chsh             cron                           login         runuser-l  xscreensaver
cockpit          cups                           newusers      samba
common-account   gdm-autologin                  other         slock
common-auth      gdm-fingerprint                passwd        sshd
common-password  gdm-launch-environment         polkit-1      su
--- inky ~ $  cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="CentOS Linux 7 (Core)"
--- inky ~ $  ls /etc/pam.d/
chfn                 login             postlogin     setup              su              systemd-user
chsh                 other             postlogin-ac  smartcard-auth     sudo            vlock
config-util          passwd            remote        smartcard-auth-ac  sudo-i
crond                password-auth     runuser       smtp               su-l
fingerprint-auth     password-auth-ac  runuser-l     smtp.postfix       system-auth
fingerprint-auth-ac  polkit-1          screen        sshd               system-auth-ac

Joining the Domain

Once PAM, Samba, and NSS are configured and restarted, join the domain.

#  realm join --client-software=winbind

(Or, manually configure Kerberos, and pull a TGT.)

#  kinit Administrator@EXAMPLE.COM
#  net ads join

Check it worked:

$  getent passwd -s winbind
$  getent group -s winbind
$  wbinfo -u
$  wbinfo -g
$  net ads info

Using Winbind Instead of SSSD

Winbind sits between PAM+NSS and Active Directory, taking the place of SSSD:

+--------+            +---------+           +--------------------+
|        |    LDAP    |         |    NSS    |                    |
|        |<---------->|         |<--------->|                    |
| AD DC  |            | Winbind |           | Linux Applications |
|        |<---------->|         |<--------->|                    |
|        |  Kerberos  |         |    PAM    |                    |
+--------+            +---------+           +--------------------+