Setting up a lightweight authentication back end

Posted by Sven Kiljan on

Most self-hosted web services can authenticate against a back end server using LDAP or Kerberos. Hosting a server to handle authentication using these protocols can be a daunting task for the uninitiated. This guide explains how to configure Samba as a back end authentication server to allow each user to authenticate against multiple services with a single account. The authentication server will run Active Directory Domain Services as a domain controller to enable authentication over LDAP and Kerberos. This guide will also explain how to configure Nextcloud to authenticate users using LDAP. Users will be able to login and change their passwords through Nextcloud's web interface. The same (changed) password would also be usable for other (web) services.

All actions in this guide are written from the perspective that they are directly performed by the root user. Actually doing so is a bad practice. It is better to work with something like sudo when actually performing the actions in this guide. The sudo command has been avoided to keep commands short.

This guide will refer often to Windows and Microsoft's website. Samba's aim is to offer an implementation of Active Directory and the underlying protocols in such a way that they are compatible with Microsoft's original implementation. Therefore, the best source of technical background information is sometimes Microsoft.

A security warning: here be dragons

This guide aims to implement Active Directory using Samba as a domain controller. Samba, like Windows, stores passwords insecurely using a single MD4 hash without salt, referred to by Microsoft as NT hash. An example for generating an NT hash is given in Background: Active Directory account passwords.

In terms of security, the use of a one-way function without salt is one of the worst ways passwords can be stored. Stored NT hashes are vulnerable to brute-force attacks, which can be used to retrieve the original password. The required time can be shortened significantly on less powerful hardware through the use of rainbow tables due to a lack of salt. This makes realistic attacks viable using limited resources.

Note that this is not related to passwords in transit to a domain controller for verification. Over a network, passwords are protected by secure handshakes and connections (NTLMv2, Kerberos and/or SSL/TLS). The only way this weakness can be exploited in a brute-force attack is if an adversary gains access to the NT hashes stored on a domain controller.

Creating a Samba-powered Active Directory


  • A fresh Linux installation. This guide has been tested with Arch Linux. Part of it is based on this article from ArchWiki. Most of the guide should be helpful for other distributions as well, but note that the used version should be relatively new. Use at least a current stable version.
  • A static IP address. How to configure a static IP differs based on the used network configuration daemon. ArchWiki has an example using systemd-networkd (the default network configuration daemon in Arch Linux) to configure a network interface with a static IP using a .network configuration file in /etc/systemd/network. An example configuration (run systemctl restart systemd-networkd to apply):

  • When using systemd-resolved for network name resolution (which Arch Linux does by default), edit /etc/systemd/resolved.conf to configure DNS. Point the first DNS server entry to the loopback interface ( and the second entry to the server that normally handles your DNS requests. For the second entry, see the existing value(s) in /etc/resolv.conf or your DHCP configuration. In most simple home networks, the IP address of the DNS server is the same as the default gateway. Also configure your future AD domain name as a search domain. An example configuration (run systemctl restart systemd-resolved to apply):
  • A configured hostname. Changing the hostname after an Active Directory has been set-up is not worth the trouble it brings. In this guide the server will be named 'addc01'. A hostname can often easily be configured using echo "addc01" > /etc/hostname, combined with a logout/login or a reboot.
  • For Active Directory (AD) you must have some idea about which DNS (sub)domain you want to use as the name of the realm and which NetBIOS name you want to use for the Windows NT domain name. It does not really matter much when only web services will be authenticated, but it will be important if you also would like to let other machines join the domain. This guide will assume that only one AD domain will ever be needed for all services hosted behind a single public DNS domain. Values for this guide:
    • Public domain:
    • DNS name of the AD Domain (not used on the Internet):
    • NetBIOS name of the NT domain: EXAMPLE

Install Samba and other required packages

This will be different for each Linux distribution. On an up-to-date Arch Linux installation this can be done in a single command:

pacman -S --needed bind-tools krb5 ntp samba

Debian-based distributions such as Ubuntu might use something like this:

apt-get update
apt-get install bind9utils krb5-user ntp samba

Create a domain controller

This process is similar to the installation of Active Directory Domain Services on a Windows Server. The old guard will remember dcpromo while kids these days use either Server Manager or PowerShell to set up a domain controller.

Run the command:

samba-tool domain provision --use-rfc2307 --interactive

Several values will be asked.

  • The realm is the DNS name of the domain in capital letters: AD.EXAMPLE.COM
  • The domain is the NetBIOS name of the NT domain in capital letters: EXAMPLE
  • The server role will be domain controller: dc
  • For the DNS backend we rely on Samba's own implementation: SAMBA_INTERNAL
  • DNS forwarder IP address: In a simple home network the IP of the default (Internet) gateway can be used. For more complex networks this should point to an existing DNS server.
  • Administrator password: This will be the password for the domain administrator. Make sure to pick a secure password, since this account will be able to do anything and everything, locally and remotely. The password should adhere to some complexity requirements.

Adjust password policies

The NIST SP 800-63 Digital Identity Guidelines state:

Verifiers SHOULD NOT impose other composition rules (e.g., requiring mixtures of different character types or prohibiting consecutively repeated characters) for memorized secrets. Verifiers SHOULD NOT require memorized secrets to be changed arbitrarily (e.g., periodically).

This means that authentication servers should not demand from users to have specific characters in their passwords, and that passwords should not expire based on how old they are.

User passwords in AD have to fulfill several complexity requirements. This includes the password for the domain administrator, which was entered in the previous step. These complexity requirements do not comply to the NIST guidelines. To disable the complexity rules, run:

samba-tool domain passwordsettings set --complexity=off

By default user passwords in AD expire. This is also against the NIST guidelines. In addition, this can create deadlock situations in which the user is unable to change the password after it has expired. To disable password expiration, run the following commands:

samba-tool domain passwordsettings set --min-pwd-age=0
samba-tool domain passwordsettings set --max-pwd-age=0
pdbedit -P "maximum password age" -C -1

The NIST guidelines do not state anything about reusing old passwords. By default, the user is not allowed to use a number of previous passwords. To disable this check, run:

samba-tool domain passwordsettings set --history-length=0

Configure the NTP server

Kerberos relies on sychronized clocks. To allow domain machines to synchronize their clocks securely, the NTP server must be configured. Run:

install -d /var/lib/samba/ntp_signd
chown root:ntp /var/lib/samba/ntp_signd
chmod 0750 /var/lib/samba/ntp_signd
echo -e "\nntpsigndsocket /var/lib/samba/ntp_signd/" >> /etc/ntp.conf
systemctl enable ntpd.service
systemctl start ntpd.service

Configure Kerberos

The configuration of the Kerberos client tools must align with Samba. Samba makes this easy by providing a prepared configuration file. To use this, run:

mv /etc/krb5.conf{,.default}
ln -s /var/lib/samba/private/krb5.conf /etc/krb5.conf

Prepare LDB tooling

LDB is the database engine used by Samba to store LDAP(-Like) data. Tools are provided to work with it, but these must be enabled before they can be used. Run:

echo 'export LDB_MODULES_PATH="${LDB_MODULES_PATH}:/usr/lib/samba/ldb"' \
  > /etc/profile.d/
chmod 0755 /etc/profile.d/
echo '. /etc/profile.d/' >> ~/.bashrc
. /etc/profile.d/

Start and test Samba

To enable samba to start at boot and to start it immediately, run:

systemctl enable samba
systemctl start samba

To test whether DNS is working correctly, run:

host -t SRV
host -t SRV
host -t A

All commands should return sensible values.

To test Kerberos ticketing support, run:

kinit administrator@AD.EXAMPLE.COM

The first command will ask for the domain administrator password before a ticket will be given, which is shown with the second command. If you receive the error kinit: Cannot contact any KDC for realm 'AD.EXAMPLE.COM while getting initial credentials', remove the second DNS server entry from /etc/systemd/resolved.conf and run systemctl restart systemd-resolved.

To test SMB support and authentication using the Kerberos ticket, run:

smbclient //addc01/netlogon -U administrator -k -c 'ls'

Without asking for a password it should return the file list of the (empty) netlogon directory.

Enable TLS support for LDAP connections

TLS protects confidentiality and integrity of in transit LDAP data between client and server. In addition, some LDAP operations might not be allowed using plain text connections, such as changing user passwords.

Edit /etc/samba/smb.conf. Add the following values to the [global] section:

        tls enabled  = yes
        tls cafile   = tls/ca.pem
        tls keyfile  = tls/key.pem
        tls certfile = tls/cert.pem
        tls verify peer = ca_and_name

The certificates and key file have been generated by Samba when the domain was provisioned. These files are located in /var/lib/samba/private/tls. Later you might need to add the certificate authority's certificate ca.pem to the list of trusted root certificate authorities on LDAP clients.

For reference:

  • LDAP uses TCP 389 and UDP 389 for incoming connections
  • LDAPS (LDAP over SSL/TLS) uses TCP 636 for incoming connections

Allow user password change over LDAP

Front end applications can use LDAP as a back end authentication server. Some of these applications also allow authenticated users to change their passwords.

AD allows password changes by manipulating the unicodePwd attribute of an account. Web applications such as Nextcloud only support password changes through manipulation of the more LDAP common userPassword attribute. By default the latter is not allowed in AD. This can be overridden by modifying the dSHeuristics attribute. Specifically, the fUserPwdSupport heuristic must be set to true. To do this, run:

ldbedit -e nano -H /var/lib/samba/private/sam.ldb \
  -b 'CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=ad,DC=example,DC=com' \

Add the following line to the bottom and save:

dSHeuristics: 000000001

This will set the 9th heuristic of dSHeuristics, fUserPwdSupport, to true.

Password changes are only allowed over secure connections, which is why TLS support for LDAP connections was enabled earlier.

Working with Active Directory users and computers

You can use Remote Server Administration Tools (RSAT) for Windows to manipulate AD users and computers. Make sure that the Windows machine is a domain member.

Alternatively, you can use the command-line in Linux on the domain controller. See Background: Samba user and group management. Also see Background: Samba LDAP user attribute manipulation for information on how to see and modify LDAP attributes of existing users on the command-line.

Connect Nextcloud to Active Directory

Nextcloud is a web server that can use LDAP for user authentication. This was tested using Nextcloud 12.

Prepare Active Directory

First a Nextcloud user account is necessary, so that Nextcloud can login to LDAP for information retrieval. Run on the domain controller:

samba-tool user create nextcloud

Note the password for this account. It must be configured in Nextcloud later.

For ease of management it is wise to place all web users in their own organizational unit (OU). Prepare the OU 'Web Hosting' by creating the file create-ou-webhosting.ldif with the following contents on the domain controller:

dn: OU=Web Hosting,DC=ad,DC=example,DC=com
changetype: add
objectClass: top
objectClass: organizationalUnit

Now run on the domain controller:

ldbadd -H /var/lib/samba/private/sam.ldb create-ou-webhosting.ldif

To create a user group called 'Nextcloud Users' in the Web Hosting OU, run:

samba-tool group add 'Nextcloud Users' --groupou='OU=Web Hosting'

You can now create your first Nextcloud user in the Web Hosting OU. Run on the domain controller:

samba-tool user create testuser \
  --given-name=Test --surname=User --userou='OU=Web Hosting'

The given attributes (name and mail) are mandatory for Nextcloud to function correctly. Make sure to give these attributes to every Nextcloud user in LDAP.

Make 'testuser' a member of the Nextcloud Users group. Run on the domain controller:

samba-tool group addmembers 'Nextcloud Users' testuser

Allow Nextcloud (admins) to reset LDAP user passwords

An LDAP account was created to allow Nextcloud to look up LDAP information for user logins. This account can be given permission to reset the passwords of Nextcloud LDAP users. This enables the following functionality:

  • Each LDAP user can change their own LDAP account password through Nextcloud's web interface.
  • In case an LDAP user forgets their password, they can request an email with a password reset link.
  • Nextcloud administrators can reset user passwords.

First, the account's security information descriptor (SID) has to be looked up. For this, run on the domain controller:

ldbsearch -H /var/lib/samba/private/sam.ldb '(samAccountName=nextcloud)' 'objectSid'

To allow the nextcloud user to reset passwords, run on the domain controller (as one command line, do not split it over multiple lines like this example does):

samba-tool dsacl set --action=allow --objectdn='OU=Web Hosting,DC=ad,DC=example,DC=com' \

See Background: Configuring AD DS ACLs in Samba for more information about this command and the used parameters.

Configure DNS on the Nextcloud server

This is similar to the configuration of the domain controller. The only difference is that the DNS server IP is that of the domain controller instead of localhost. An example configuration for systemd-resolved (/etc/systemd/resolved.conf):


Import the CA certificate on the Nextcloud server

To be able to make secure connections to Samba's LDAP server it is required to add the certificate authority certificate to the Nextcloud server's trusted root certificate store.

Copy from the Samba domain controller the file /var/lib/samba/private/tls/ca.pem to the Nextcloud server to /etc/ca-certificates/trust-source/anchors. You might want to rename ca.pem to ad-example-ca.crt to make the purpose of the file more explicit.

Before the import you can look on the Nextcloud server at the file sizes in /etc/ca-certificates/extracted/.

Now run on the Nextcloud server:

trust extract-compat

The file sizes in /etc/ca-certificates/extracted/ should have changed, indicating that the certificate was imported successfully.

Allow LDAP users to login in Nextcloud

Nextcloud must be configured to allow user authentication using credentials from LDAP. Go to the Nextcloud web interface and login using the admin account. Open Settings, Admin, LDAP / AD integration.

The Server tab of this page will be opened. The other tabs are initially disabled. Enter the values as follows:

After Nextcloud verifies the values, the other tabs will be enabled. Open the Users tab. Adjust the values as follows:

Now open the Login Attributes tab. Here the available login attributes (AD username and/or email address) can be chosen. If web users are not familiar with their usernames, it might be wise to only allow email addresses for login, as this example shows:
Enter testuser's email address ( in the 'Test Loginname' field and choose 'Verify settings' to verify that the value can be used.

Open the Advanced tab and the Directory Settings settings group. Enable the option 'Enable LDAP password changes per user':
This will allow users to change their passwords. They will only be able to do this when logged in or through a password reset email. The warning states that passwords are sent plain text to the server, which is why LDAPS (LDAP over SSL/TLS) is used to ensure confidentiality and integrity. Note that the above screenshot is simplified to reduce its size. There are many more settings, but they should be left untouched.

Finally, open the Special Attributes settings group on the same tab. Configure Nextcloud to retrieve the user's email address from the LDAP 'mail' attribute like this:

No other changes are necessary. The Groups tab was skipped for simplicity, but it can be configured to also import group information from LDAP. Note that LDAP groups support in Nextcloud is limited. LDAP groups can be used in Nextcloud to distinguish users and to assign them Nextcloud rights, but users cannot be assigned LDAP groups in Nextcloud's web interface.

The Expert tab was also skipped. It only contains settings that might be useful to change under special circumstances.

Try logging in with the testuser account (email address: that was created earlier.

Removing Nextcloud LDAP users

Removing LDAP users from Nextcloud is not as straightforward as local users. An LDAP user can only be deleted from Nextcloud if all following conditions are met:

  1. The user was deleted in LDAP (for example, by running samba-tool user delete <username> on the domain controller).
  2. The deleted user in LDAP was detected by Nextcloud. A Nextcloud background job is scheduled to run every 51 minutes (by default) to detect removed LDAP users. To see which removed users were detected, run on the Nextcloud server in the Nextcloud directory:
sudo -u http php occ ldap:show-remnants

Where 'http' is the account that runs Nextcloud (in PHP).

Users from that list can be removed by running:

sudo -u http php occ user:delete <nextcloudName>

An example:

The Nextcloud name (highlighted) is the value of the UUID attribute of the LDAP user (that was recently removed from LDAP). Nextcloud uses this value to uniquely identify users internally.

See the Nextcloud Administration Manual for more information about LDAP User Cleanup.

Background parts

This part of the guide contains more background information on different subjects. It provides more information about the technical context.

Background: Samba user management cheat sheet

Here are some useful Samba one-liners for user management. To keep them short, it is assumed all these commands are executed as root, directly on the domain controller.
Add user:

samba-tool user create <username> \
  --given-name=<givenname> --surname=<surname> --mail=<mailaddress>

Delete user: samba-tool user delete <username>
Disable user: samba-tool user disable <username>
Enable user: samba-tool user enable <username>
List users: samba-tool user list
Reset user password: smbpasswd <username>

In addition, here are several one-liners for groups. These can be useful for separating Note that group names can contain spaces.
Create group: samba-tool group add '<group name>'
Delete group: samba-tool group delete '<group name>'
List groups: samba-tool group list
Add user to group: samba-tool group addmembers '<group name>' <username>
Remove user from group: samba-tool group removemembers '<group name>' <username>
List users in group: samba-tool group listmembers '<group name>'

samba-tool is well documented. Use samba-tool --help for a list of commands and samba-tool <command> [subcommand] --help for more information about specific (sub)commands.

Background: Samba LDAP user attribute manipulation

By default a freshly created domain user's profile is quite empty, containing a minimum amount of information for AD to function (especially if smbpasswd -a <username> was used). Sometimes additional attributes might be necessary.

To see a user's current attributes through LDAP (sorted), run:

ldbsearch -H /var/lib/samba/private/sam.ldb -S '(samAccountName=<username>)'

To edit a user's attributes in a text editor, run:

ldbedit -e nano -H /var/lib/samba/private/sam.ldb '(samAccountName=<username>)'

This allows you to add the attributes displayName (containing the user's full name) and mail (containing the user's email address) if you used smbpasswd -a <username> to create a user account.

It is also possible to script LDAP changes using ldbmodify. Read more about that on the SambaWiki

Background: Active Directory account passwords

Passwords are stored using (non-salted) one-way hashes. To get the hash from an account, run:

ldbsearch -H /var/lib/samba/private/sam.ldb '(samAccountName=<username>)' 'unicodePwd'

Note that the NT hash can only be revealed by directly interacting with the Samba Security Accounts Manager (SAM) LDAP-Like database, locally on the domain controller. The same query will not work over a network connection. One can test this by running on a (remote) computer (with OpenLDAP installed and the self-signed certificate authority's certificate imported) by running:

ldapsearch -Z -h -D 'CN=Administrator,CN=Users,DC=ad,DC=example,DC=com' -W \
  -b 'CN=Users,DC=ad,DC=example,DC=com' '(samAccountName=<username>)' 'unicodePwd'

The user will be found, but unicodePwd is not part of the answer.

To create an NT hash manually, use:

printf '%s' "MyPassword" | \
iconv -t utf16le | \
openssl md4 | \
sed "s/^.*= //" | \
sed 's/\([0-9a-f]\{2\}\)/\\\\\\x\1/gI' | xargs printf | \

A brief explanation:
printf prints the password (without any newline characters).
iconv converts the password to a unicode string as used in Windows.
openssl hashes the unicode string using MD4.
The first sed line removes irrelevant openssl output.
The second sed line, together with xargs, converts the hex string to binary.
base64 encodes the binary data to Base64 and prints the output.

As noted in the security warning at the beginning of this guide, this form of password storage is hardly secure. Keep your domain controller up-to-date and keep the attack surface to a minimum by not installing additional software.

Background: Configuring AD DS ACLs in Samba

In the guide the following command is used to grant the nextcloud account the right to reset passwords of users in the User organizational unit:

samba-tool dsacl set --action=allow --objectdn='OU=Web Hosting,DC=ad,DC=example,DC=com' \

Since the samba-tool dsacl command is quite obscure and not well-documented I will give an explanation of its use here.

DS stands for Directory Services, and ACL stands for Access Control List(s). dsacl set can be used to manipulate AD DS permissions. Unfortunately, there is no get subcommand to read AD DS permissions.

Traditionally, AD DS permissions are configured through Microsoft's Remote Server Administration Tools (RSAT) for Windows. RSAT provides a graphical user interface (GUI) and a command-line interface (CLI) tool to read and manipulate AD DS permissions. The GUI is the well known 'Active Directory Users and Computers' window, and the command-line interface tool is dsacls.exe.

Of course the GUI is very user friendly. Allowing the svc_nextcloud user to reset passwords is as easy as:

Of course, GUIs are not efficient for automation. The CLI tool is much more useful for this. To set the same permission for svc_nextcloud using the CLI in Windows, run:

dsacls "CN=Users,DC=ad,DC=example,DC=com" /G "svc_nextcloud:CA;Reset password;user" /I:S

This is quite friendly to read. An explanation of the parameters:

dsacls "CN=Users,DC=ad,DC=example,DC=com" /G "svc_nextcloud:CA;Reset password;user" /I:S
       1                                  2   3             4  5              6     7
  1. The AD DS object to modify permissions of. LDAP notation.
  2. Parameter that indicates that specified permission(s) should be granted to specified group/user.
  3. The group or user who is granted the permission. domain\user notation, user@domain notation, FQDN notation, or SID notation.
  4. Permission bits. See dsacls.exe /? for a list.
  5. The object or property to grant permission over. Display name notation.
  6. Inherited object type. Determines over what type of objects the group/user is granted the permission. Display name notation.
  7. Parameter that indicates that specified inheritance flags apply. See dsacls.exe /? for a list. The S flag indicates that the granted permission is only inherited by sub objects and not to the applied object itself. This is logical, since organizational units (such as 'CN=Users,DC=ad,DC=example,DC=com') do not have passwords to reset, but they do contain objects which do (which are limited to the 'User' type by parameter 6).

Now compare this to the samba-tool command (lines with parameter numbers are marked with # and are not part of the input):

samba-tool dsacl set --action=allow --objectdn='OU=Web Hosting,DC=ad,DC=example,DC=com' \
#          1     2   3              4
# 5
#    6  7    8  9                                    10
#   11
  1. Samba-tool command. See samba-tool --help for a list.
  2. Samba-tool subcommand. See samba-tool <command> --help for a list. For dsacl, set is the only available subcommand. See samba-tool dsacl set --help for more information on its use.
  3. Parameter that states whether the permission(s) is/are granted (allow) or denied (deny).
  4. Parameter that specifies of which AD DS object the security descriptor will be modified. The AD DS object is given in LDAP notation.
  5. Parameter that states that one or more access control entry (ACE) strings will be provided in security descriptor definition language (SDDL), each separated by parentheses. See this MSDN page for more information about SDDL.
  6. First parameter of the ACE string (ace_type). Specifies the ACE type. See this MSDN page for a list of all possible values. For the granted permission the value is OA (ACCESS_ALLOWED_OBJECT_ACE_TYPE), which states that the ACE will use the ACCESS_ALLOWED_OBJECT_ACE structure (defines an access control entry (ACE) that controls allowed access to an object, a property set, or property).
  7. Second parameter of the ACE string (ace_flags). Specifies a set of ACE type-specific control flags. See this MSDN page for a list of all possible values. For the granted permission these flags are CI (CONTAINER_INHERIT_ACE, ACE is inherited by containers) and IO (INHERIT_ONLY_ACE, ACE does not control access to the object to which it is attached).
  8. Third parameter of the ACE string (rights). Specifies access rights controlled by the ACE. See this MSDN page for a list of possible values. For the granted permission this value is CR (ADS_RIGHT_DS_CONTROL_ACCESS, the right to perform an operation controlled by an extended access right).
  9. Fourth parameter of the ACE string (object_guid). Specifies the right to be granted by its GUID. See this MSDN page for a list of possible values. Another list can be found on this Technet page. For the granted permission this value is 00299570-246d-11d0-a768-00aa006e0529, which represents the reset password permission.
  10. Fifth parameter of the ACE string (inherit_object_guid). Specifies what type of object will inherit the permission. The object type is specified using its schema ID GUID. See this MSDN page for a list of possible values. For the granted permission this is bf967aba-0de6-11d0-a285-00aa003049e2, which represents the 'User' type.
  11. Sixth parameter of the ACE string (account_sid). Specifies the account that will be granted the right by its security identifier (SID). To get the SID of an Active Directory user through LDAP, run: ldbsearch -H /var/lib/samba/private/sam.ldb '(samAccountName=<username>)' 'objectSid'

Effectively dsacls.exe and samba-tool do the same in this scenario. What makes samba-tool much more complex is not only the number of parameters, but also their non-intuitive values. dsacls.exe abstracts most of these values away by using display names and deduction.