SSSD, LDAP and Kerberos
Finally, we can mix it all together in a setup that is very similar to Active Directory in terms of the technologies used: use LDAP for users and groups, and Kerberos for authentication.
Prerequisites, Assumptions, and Requirements
For this setup, we will need:
- an existing OpenLDAP server using the RFC2307 schema for users and groups. SSL support is recommended, but not strictly necessary because authentication in this setup is being done via Kerberos, and not LDAP.
- a Kerberos server. It doesn’t have to be using the OpenLDAP backend
- a client host where we will install and configure SSSD
On the client host, install the following packages:
sudo apt install sssd-ldap sssd-krb5 ldap-utils krb5-user
You may be asked about the default Kerberos realm. For this guide, we are using
At this point, you should alreaedy be able to obtain tickets from your Kerberos server, assuming DNS records point at it like explained elsewhere in this guide:
$ kinit ubuntu Password for ubuntu@EXAMPLE.COM: ubuntu@ldap-krb-client:~$ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: ubuntu@EXAMPLE.COM Valid starting Expires Service principal 04/17/20 19:51:06 04/18/20 05:51:06 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 04/18/20 19:51:05
But we want to be able to login as an LDAP user, authenticated via Kerberos. Let’s continue with the configuration.
/etc/sssd/sssd.conf configuration file, with permissions 0600 and ownership root:root, and this content:
[sssd] config_file_version = 2 domains = example.com [domain/example.com] id_provider = ldap ldap_uri = ldap://ldap01.example.com ldap_search_base = dc=example,dc=com auth_provider = krb5 krb5_server = kdc01.example.com,kdc02.example.com krb5_kpasswd = kdc01.example.com krb5_realm = EXAMPLE.COM cache_credentials = True
This example uses two KDCs, which made it necessary to also specify the krb5_kpasswd server because the second KDC is a replica and is not running the admin server.
Start the sssd service:
sudo systemctl start sssd.service
Automatic home directory creation
To enable automatic home directory creation, run the following command:
sudo pam-auth-update --enable mkhomedir
In this example, the LDAP server has the following user and group entry we are going to use for testing:
dn: uid=john,ou=People,dc=example,dc=com uid: john objectClass: inetOrgPerson objectClass: posixAccount cn: John Smith sn: Smith givenName: John mail: email@example.com uidNumber: 10001 gidNumber: 10001 loginShell: /bin/bash homeDirectory: /home/john dn: cn=john,ou=Group,dc=example,dc=com cn: john objectClass: posixGroup gidNumber: 10001 memberUid: john dn: cn=Engineering,ou=Group,dc=example,dc=com cn: Engineering objectClass: posixGroup gidNumber: 10100 memberUid: john
Note how the john user has no userPassword attribute.
The user john should be known to the system:
ubuntu@ldap-client:~$ getent passwd john john:*:10001:10001:John Smith:/home/john:/bin/bash ubuntu@ldap-client:~$ id john uid=10001(john) gid=10001(john) groups=10001(john),10100(Engineering)
Let’s try a login as this user:
ubuntu@ldap-krb-client:~$ sudo login ldap-krb-client login: john Password: Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-24-generic x86_64) (...) Creating directory '/home/john'. john@ldap-krb-client:~$ klist Ticket cache: FILE:/tmp/krb5cc_10001_BOrxWr Default principal: john@EXAMPLE.COM Valid starting Expires Service principal 04/17/20 20:29:50 04/18/20 06:29:50 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 04/18/20 20:29:50 john@ldap-krb-client:~$
We logged in using the kerberos password, and user/group information from the LDAP server.
SSSD and KDC spoofing
When using SSSD to manage kerberos logins on a Linux host, there is an attack scenario you should be aware of: KDC spoofing.
The objective of the attacker is to login on a workstation that is using Kerberos authentication. Let’s say he knows
john is a valid user on that machine.
The attacker first deploys a rogue KDC server in the network, and creates the
john principal there with a password of his choosing. What he has to do now is to have his rogue KDC respond to the login request from the workstation, before (or instead of) the real KDC. If the workstation isn’t authenticating the KDC, it will accept the reply from the rogue server and let
There is a configuration parameter that can be set to protect the workstation from this attack. It will have SSSD authenticate the KDC, and block the login if the KDC cannot be verified. This option is called
krb5_validate, and it’s
false by default.
To enable it, edit
/etc/sssd/sssd.conf and add this line to the domain section:
[sssd] config_file_version = 2 domains = example.com [domain/example.com] id_provider = ldap ... krb5_validate = True
The second step is to create a
host principal on the KDC for this workstation. This is how the KDC’s authenticity is verified. It’s like a “machine account”, with a shared secret that the attacker cannot control and replicate in his rogue KDC…The
host principal has the format
After the host principal is created, its keytab needs to be stored on the workstation. This two step process can be easily done on the workstation itself via
kadmin.local) to contact the KDC remotely:
$ sudo kadmin -p ubuntu/admin kadmin: addprinc -randkey host/ldap-krb-client.example.com@EXAMPLE.COM WARNING: no policy specified for host/ldap-krb-client.example.com@EXAMPLE.COM; defaulting to no policy Principal "host/ldap-krb-client.example.com@EXAMPLE.COM" created. kadmin: ktadd -k /etc/krb5.keytab host/ldap-krb-client.example.com Entry for principal host/ldap-krb-client.example.com with kvno 6, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5.keytab. Entry for principal host/ldap-krb-client.example.com with kvno 6, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5.keytab.
Then exit the tool and make sure the permissions on the keytab file are tight:
sudo chmod 0600 /etc/krb5.keytab sudo chown root:root /etc/krb5.keytab
You can also do it on the KDC itself using
kadmin.local, but you will have to store the keytab temporarily in another file and securely copy it over to the workstation.
Once these steps are complete, you can restart sssd on the workstation and perform the login. If the rogue KDC picks the attempt up and replies, it will fail the host verification. With debugging we can see that happening on the workstation:
==> /var/log/sssd/krb5_child.log <== (Mon Apr 20 19:43:58 2020) [[sssd[krb5_child]]] [validate_tgt] (0x0020): TGT failed verification using key for [host/ldap-krb-client.example.com@EXAMPLE.COM]. (Mon Apr 20 19:43:58 2020) [[sssd[krb5_child]]] [get_and_save_tgt] (0x0020): 1741: [-1765328377][Server host/ldap-krb-client.example.com@EXAMPLE.COM not found in Kerberos database]
And the login is denied. If the real KDC picks it up, however, the host verification succeeds:
==> /var/log/sssd/krb5_child.log <== (Mon Apr 20 19:46:22 2020) [[sssd[krb5_child]]] [validate_tgt] (0x0400): TGT verified using key for [host/ldap-krb-client.example.com@EXAMPLE.COM].
And the login is accepted.