Hi,
there is an environment in which I have to use MS Active Directory for authentication and mail server user database, and I've run into a problem.
I. The problem
I want to retrieve the objectGUID attribute for the homedir path of the users. This attribute does never change, even when the username does or the account gets moved to another AD domain.
However, the objectGUID is returned as binary gibberish when using the following setting:
user_attrs =
=home=/var/vmail/example.com/%LT{ldap:objectGUID}, \
It results in
# doveadm user uTesting field value user utesting home /var/vmail/example.com/d ��n�aa_ o�� mail maildir:~/mail
Can someone reproduce this or offer a workaround?
The only idea I had was hashing the value using =%M{ldap:objectGUID}. However, this approach would become problematic if the behavior changes and a proper string representation is returned, as expected, instead of the binary data. Therefore, I'm hesitant to use this method for now.
A better approach would be encoding it as Base64, but I was unsuccessful to identify a fitting modifier at https://doc.dovecot.org/configuration_manual/config_file/config_variables/#m.... Any ideas?
II. Additional info
Using other attributes for LDAP/Active Directory works as expected. E.g.
=home=/var/vmail/example.com/%LT{ldap:sAMAccountName}
results in
# doveadm user uTesting field value user utesting home /var/vmail/example.com/utesting mail maildir:~/mail
The objectGUID is indeed binary data, but IHMO, it should be handled differently when returned. E.g. there is a defined string representation, [MS-DTYP] section 2.3.4.3: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/222af2... which links to:
curly braced GUID string: The string representation of a 128-bit globally unique identifier (GUID) using the form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}, where X denotes a hexadecimal digit. The string representation between the enclosing braces is the standard representation of a GUID as described in [RFC4122] section 3. Unlike a GUIDString, a curly braced GUID string includes enclosing braces.
Some libs simply decide to return the data Base64 encoded (which would be OK, too). E.g. openldap-clients / ldapsearch does so with objectGUID and objectSid:
$ ldapsearch [...] [...] # uTesting, common, user, managed, example.com dn: CN=uTesting,OU=common,OU=user,OU=managed,DC=example,DC=com [...] name: uTesting objectGUID:: RCDirQPvGU6KQUFfIE/i2Q== [...] objectSid:: AQUAAAAAAAUVAAAALenCqsullBUfFoubWQQAAA== [...] sAMAccountName: uTesting [...]
Other software had comparable bugs or behavior , e.g.
sssd ("Properly handle AD's binary objectGUID"): https://bugzilla.redhat.com/show_bug.cgi?id=1205382 https://github.com/SSSD/sssd/issues/3629
owncloud ("ensure that objectguid or guid really return binary data before converting it"): https://github.com/owncloud/core/issues/8317
III. Software versions, config
I can reproduce the issue on Fedora Server 38
# cat /etc/redhat-release Fedora release 38 (Thirty Eight)
# uname -r 6.4.15-200.fc38.x86_64
# dovecot --version 2.3.20 (80a5ac675d)
and CentOS 9 Stream:
# cat /etc/redhat-release CentOS Stream release 9
# uname -r 5.14.0-364.el9.x86_64
# dovecot --version 2.3.16 (7e2e900c1a)
I did not try a Debian-based distro yet.
The config itself works fine, relevant settings just for reference (as there are not many examples on the internet, maybe useful for somebody):
auth_username_format = %Lu
passdb { driver = ldap args = /etc/dovecot/dovecot-ldap.conf.ext } userdb { driver = ldap args = /etc/dovecot/dovecot-ldap-userdb.conf.ext }
with the following options to exclude inactive accounts, search smtp proxy addresses and having a mandatory group membership in SERVICE_EmailUsers:
base = OU=common,OU=user,OU=managed,DC=example,DC=com scope = subtree
user_filter =
(&
(objectClass=user)
(objectCategory=Person)
(|(sAMAccountName=%{username})(mail=%{username})(proxyAddresses=smtp:%{username}@%{domain}))
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
(memberOf:1.2.840.113556.1.4.1941:=SERVICE_EmailUsers)
) pass_filter =
(&
(objectClass=user)
(objectCategory=Person)
(|(sAMAccountName=%{username})(mail=%{username})(proxyAddresses=smtp:%{username}@%{domain}))
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
(memberOf:1.2.840.113556.1.4.1941:=SERVICE_EmailUsers)
)
I will blog about the config in more detail at https://foundata.com/en/blog/ soon, especially when the objectGUID is solved (maybe hashing it really the way to go). :-)
Regards, Andreas
-- foundata GmbH Steinhäuserstr. 20 76135 Karlsruhe
Sitz der Gesellschaft: Karlsruhe Registergericht: Amtsgericht Mannheim, HRB 714807 Geschäftsführer: Andreas Haerter USt-IdNr.: DE284122682