Hello everyone,
I am currently facing some issues regarding the migration of my Dovecot authentication backend from OpenLDAP to Samba-DC.
Since both are LDAP-based directories, I assumed the migration would be straightforward, but that turned out not to be the case. I am fairly certain it is just a minor configuration detail, but I have been searching for a solution for three days now without success.
I would like to share my current configuration, which is working flawlessly with OpenLDAP.
The directory entry:
# extended LDIF
#
# LDAPv3
# base <dc=domain1,dc=tld> with scope subtree
# filter: (mail=user@domain3.tld)
# requesting: ALL
#
# user.surname, users, domain1.tld
dn: uid=user.surname,ou=users,dc=domain1,dc=tld
uid: user.surname
sn: surname
givenName: user
cn: user surname
displayName: user surname
mail: user@domain1.tld
mail: user@domain2.tld
mail: user@domain3.tld
uidNumber: 13113
gidNumber: 13000
homeDirectory: /home/user.surname
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: sambaSamAccount
sambaSID: S-1-5-21-2286081015-3344157248-104006538-1009
sambaNTPassword: [REDACTED]
sambaPasswordHistory: [REDACTED]
sambaPwdLastSet: 1753387770
sambaAcctFlags: [U ]
initials: 10000G
My Dovecot auth-ldap.conf.ext configuration for this setup looks like this:
# Global LDAP connection settings
ldap_version = 3
ldap_uris = ldap://[SERVER_IP]
ldap_auth_dn = cn=admin,dc=domain1,dc=tld
ldap_auth_dn_password = [PASSWORD]
ldap_base = dc=domain1,dc=tld
# --- Password Database (passdb) ---
# Handles the password verification (Authentication Bind)
passdb ldap {
ldap_bind = yes
uid=%{user},ou=users,dc=domain1,dc=tld
ldap_filter = (&(objectClass=posixAccount)(mail=%{user}))
}
# --- User Database (userdb) ---
# Retrieves user details for mailbox location and access rights.
userdb ldap {
ldap_filter = (&(objectClass=posixAccount)(mail=%{user}))
fields {
home = /srv/vmail/%{user|domain|lower}/%{user|username|lower}
uid = vmail
gid = vmail
quota_rule = *:storage=%{ldap:initials}
quota_rule2 = Trash:storage=500G
quota_rule3 = Spam:storage=50M
quota_storage_size = %{ldap:initials}
quota_mailbox_message_count = 30000
quota_mailbox_message_count = 5000
}
}
The setup is straightforward and works perfectly. The mail attribute is multivalued, containing the three email addresses associated with my three domains. The username remains consistent across all of them.
Now, here is a directory entry from my Samba-DC (Active Directory) for comparison:
# extended LDIF
#
# LDAPv3
# base <dc=domain1,dc=tld> with scope subtree
# filter: (mail=user@domain1.tld)
# requesting: ALL
#
# User Name, Users, domain1.tld
dn: CN=User Name,OU=Users,DC=domain1,DC=tld
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: User Name
sn: Surname
givenName: User
instanceType: 4
whenCreated: 20260510123059.0Z
displayName: User Name
uSNCreated: 4168
name: User Name
objectGUID:: [REDACTED]
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
primaryGroupID: 513
objectSid:: [REDACTED]
accountExpires: 9223372036854775807
sAMAccountName: username
sAMAccountType: 805306368
userPrincipalName: user@domain1.tld
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=domain1,DC=tld
mail: user@domain1.tld
pwdLastSet: 134228898599390930
userAccountControl: 512
memberOf: CN=MailUsers,CN=Users,DC=domain1,DC=tld
lastLogonTimestamp: 134250693872343440
logonCount: 9
msDS-cloudExtensionAttribute1: 10000G
proxyAddresses: user@domain2.tld
proxyAddresses: user@domain3.tld
proxyAddresses: user@domain1.tld
msDS-cloudExtensionAttribute2: user@domain2.tld
msDS-cloudExtensionAttribute3: user@domain3.tld
msDS-cloudExtensionAttribute4: user@domain1.tld
whenChanged: 20260609104109.0Z
uSNChanged: 5875
distinguishedName: CN=User Name,OU=Users,DC=domain1,DC=tld
For testing purposes, I have used proxyAddresses as a multivalued field, as well as msDS-cloudExtensionAttribute2 through msDS-cloudExtensionAttribute4.
My Dovecot auth-ldap.conf.ext configuration for this setup looks like this:
# Global LDAP connection settings
ldap_version = 3
ldap_uris = ldaps://dc1.domain1.tld
ldap_auth_dn = "administrator@domain1.tld"
ldap_auth_dn_password = [PASSWORD]
ldap_base = dc=domain1,dc=tld
# IMPORTANT: Samba DC / AD often requires disabling referrals
# referral = no
# --- Password Database (passdb) ---
# Handles the password verification (Authentication Bind)
passdb ldap {
driver = ldap
# Search filter
ldap_filter = (&(objectClass=user)(|(msDS-cloudExtensionAttribute4=%{user|username|lower}@%{user|domain|lower})(msDS-cloudExtensionAttribute3=%{user|username|lower}@%{user|domain|lower})(msDS-cloudExtensionAttribute2=%{user|username|lower}@%{user|domain|lower})))
# AD/Samba allows direct bind with the user's mail address
bind_userdn = %{user|username|lower}@domain1.tld
bind = yes
fields {
user = %{user|username}@domain1.tld
}
}
# --- User Database (userdb) ---
# Retrieves user details for mailbox location and access rights.
userdb ldap {
driver = ldap
ldap_filter = (&(objectClass=user)(|(mail=%{user})(userPrincipalName=%{user})))
fields {
home = /srv/vmail/%{original_user|domain|lower}/%{original_user|username|lower}
uid = vmail
gid = vmail
quota_rule = *:storage=%{ldap:msDS-cloudExtensionAttribute1}
quota_rule2 = Trash:storage=500G
quota_rule3 = Spam:storage=50M
quota_storage_size = %{ldap:msDS-cloudExtensionAttribute1}
quota_message_count = 30000
quota_mailbox_message_count = 5000
}
}
The password authentication works flawlessly, but no fields attributes are being returned, causing the entire connection to fail.
Here are a few lines from the log:
Jun 09 17:49:44 auth: Debug: Loading modules from directory: /usr/lib/dovecot/modules/auth
Jun 09 17:49:44 auth: Debug: Loading modules from directory: /usr/lib/dovecot/modules/auth
Jun 09 17:49:44 auth: Debug: Module loaded: /usr/lib/dovecot/modules/auth/libauthdb_ldap.so
Jun 09 17:49:44 auth: Debug: Read auth token secret from /run/auth-token-secret.dat
Jun 09 17:49:44 auth: Debug: ldap(ldaps://dc1.domain1.tld:636): initialization took 15 msecs
Jun 09 17:49:44 auth: Debug: conn unix:/run/auth-userdb (pid=20421,uid=0): Server accepted connection (fd=20)
Jun 09 17:49:44 auth: Debug: master in: USER 1 user1@domain1.tld protocol=doveadm debug
Jun 09 17:49:44 auth(user1@domain1.tld): Debug: ldap: Performing userdb lookup
Jun 09 17:49:44 auth(user1@domain1.tld): Debug: ldap: userdb cache miss
Jun 09 17:49:44 auth(user1@domain1.tld): Debug: ldap: user search: base=dc=domain1,dc=tld scope=subtree filter=(&(objectClass=user)(|(mail=user1@domain1.tld)(msDS-cloudExtensionAttribute2=user1@domain1.tld)(msDS-cloudExtensionAttribute3=user1@domain1.tld)(msDS-cloudExtensionAttribute4=user1@domain1.tld)))
Jun 09 17:51:01 auth: Debug: conn unix:/run/auth-userdb (pid=20432,uid=0): Server accepted connection (fd=22)
Jun 09 17:51:01 auth: Debug: master in: USER 1 user2@domain2.tld protocol=doveadm
Jun 09 17:51:01 auth(user2@domain2.tld): Debug: ldap: Performing userdb lookup
Jun 09 17:51:01 auth(user2@domain2.tld): Debug: ldap: userdb cache miss
Jun 09 17:51:01 auth(user2@domain2.tld): Debug: ldap: user search: base=dc=domain1,dc=tld scope=subtree filter=(&(objectClass=user)(|(mail=user2@domain2.tld)(msDS-cloudExtensionAttribute2=user2@domain2.tld)(msDS-cloudExtensionAttribute3=user2@domain2.tld)(msDS-cloudExtensionAttribute4=user2@domain2.tld)))
Jun 09 17:51:01 auth(user1@domain1.tld): Debug: ldap: Finished userdb lookup
Jun 09 17:51:01 auth(user1@domain1.tld): Debug: ldap: userdb cache miss
Jun 09 17:51:01 auth: Debug: ldap(ldaps://dc1.domain1.tld:636): initialization took 6 msecs
Jun 09 17:51:03 auth: Debug: userdb out: FAIL 1
Jun 09 17:51:03 auth: Debug: conn unix:/run/auth-userdb (pid=20421,uid=0): auth-master client: Disconnected: Connection closed (fd=20)
If anyone has any experience or insights into this mapping issue, I would be extremely grateful for any guidance. I am currently running Dovecot version 2.4 on an Ubuntu Server environment.
Thank you
Nicky