[Samba] query account expired state

Kees van Vloten keesvanvloten at gmail.com
Sat Oct 28 11:50:31 UTC 2023


Op 28-10-2023 om 13:22 schreef Rowland Penny via samba:
> On Sat, 28 Oct 2023 11:54:34 +0200
> Kees van Vloten via samba <samba at lists.samba.org> wrote:
>
>> Op 28-10-2023 om 09:37 schreef Rowland Penny via samba:
>>> On Fri, 27 Oct 2023 23:48:22 +0200
>>> Kees van Vloten via samba <samba at lists.samba.org> wrote:
>>>
>>>> Hi Team,
>>>>
>>>> Is it possible to make a LDAP-query that returns whether an account
>>>> is expired or not?
>>>>
>>>> I am aware that it is possible to do the maths against the
>>>> "accountExpires" attribute, but that requires some scripting around
>>>> the query.
>>>>
>>>> - Kees.
>>>>
>>>>
>>> Would that it was so simple.
>>>
>>> There is a flag 'ADS_UF_PASSWORD_EXPIRED' in the userAccountControl
>>> attribute, but you would have to obtain the value from that
>>> attribute and check if '8388608' is set, I am not sure if Samba
>>> uses this.
>>>
>>> Windows has replaced the above with the aptly named
>>> 'ms-DS-User-Password-Expired' attribute which, as far as I can tell,
>>> Samba knows nothing about.
>> The unfortunate situation is that Samba (4.19.2) does not implement
>> the 'ADS_UF_PASSWORD_EXPIRED' flag. It does support
>> 'msDS-UserPasswordExpiry', but that returns and LDAP time value so it
>> requires computation by the querier to figure out expiry.
> I am on 4.18.8 and that doesn't have 'msDS-UserPasswordExpiry' or
> 'ms-DS-User-Password-Expired', but if it did, then the time stored
> would be, as you say, in Windows format.
You mention 2 other attributes: 'msDS-UserPasswordExpiry' and 
DS-User-Password-Expired'. I just check them, both are not supported in 
4.19.2.
>
>> Another suggestion from ldapwiki.com: "All expired user accounts:
>> '(&(objectCategory=Person)(objectClass=User)(!accountExpires=0)(!accountExpires=9223372036854775807))'"
>> does not work either. Accounts on Samba always have the value
>> '9223372036854775807'.
> accountExpires != the password expiry.
> An account can expiry for other reasons than the password expiring and
> if the password does expire, then it can be reset and the account
> hasn't expired.
Fair point, so this is not a good query anyway.
>
>> Some output to show all this:
>>
>> ldapsearch -x -W -ZZ -H ldap://dc.samdom.com -D 'CN=test 1
>> user,OU=User Accounts,DC=samdom,DC=com' -b 'CN=test 1 user,OU=User
>> Accounts,DC=samdom,DC=com' '(objectClass=user)'
>> Enter LDAP Password:
>> ldap_bind: Invalid credentials (49)
>>           additional info: 80090308: LdapErr: DSID-0C0903A9, comment:
>> AcceptSecurityContext error, data 532, v1db1
>> # Apparently this seems to mean "expired"...
> Perhaps, perhaps not, it could just be an incorrect password.
>
>> /var/log/samba/audit_auth.log:
>> {
>>     "timestamp":"2023-10-28T11:38:53.865118+0200",
>>     "type":"Authentication",
>>     "Authentication":{
>>       "version":{
>>         "major":1,
>>         "minor":3
>>       },
>>       "eventId":4625,
>>       "logonId":"0",
>>       "logonType":8,
>>       "status":"NT_STATUS_PASSWORD_EXPIRED",
>>       "serviceDescription":"LDAP",
>>       "authDescription":"simple bind/TLS",
>>       "clientDomain":"SAMDOM",
>>       "clientAccount":"CN=test 1 user,OU=User
>> Accounts,DC=samdom,DC=com", "workstation":"DC1",
>>       "mappedAccount":"test1",
>>       "mappedDomain":"SAMDOM"
>> # Shortend output, removed irrelevant key/values
>>     }
>> }
>>
>> ldbsearch -H /var/lib/samba/private/sam.ldb -s sub -b 'CN=test 1
>> user,OU=User Accounts,DC=samdom,DC=com' '(objectClass=user)'
>> userAccountControl accountExpires accountExpires
>> msDS-UserPasswordExpiryTimeComputed 2> /dev/null
>> # record 1
>> dn: CN=test 1 user,OU=User Accounts,DC=samdom,DC=com
>> accountExpires: 9223372036854775807
>> userAccountControl: 512
>> msDS-UserPasswordExpiryTimeComputed: 133364804925898560
>>
>> # returned 1 records
>> # 1 entries
>> # 0 referrals
>>
>> 'userAccountControl' and 'accountExpires' do not show a clue about
>> the expiry!
>>
>>> So, you are left with a couple of options:
>>> Check if the 'computed' attribute
>>> 'msDS-UserPasswordExpiryTimeComputed' exists and if it does, turn
>>> that into a Unix date. Or calculate the expiry time from the
>>> contents of the 'maxPwdAge' and the accounts 'pwdLastSet'
>>> attributes.
>> This is not an option in applications that just allow a ldap filter
>> (which is basically all applications with the exception of scripts).
>>
>> I consider this a big security omission: if  Samba is the source of
>> information but not the the authenticator of the user, that
>> application cannot block expired users !
> But, Samba when running as an AD DC is the source of information AND
> the source of authentication. A user with an expired password will not
> be allowed to logon.

You are right, this is preferable, but not always the case.

For example Samba does not support  MFA, an application that does this 
can use Samba as its user database but has to perform the MFA 
authentication with its own mechanism.

The situation I have is that you can login with MFA (from internet) 
while you are blocked with normal authentication (when in the office) 
when your password is expired. That is definitely not alright!

>
>> How to proceed from here?
>>
>> I guess the real fix to update 'userAccountControl' and/or
>> 'accountExpires' need changes in Samba's C code. In the meantime I
>> would like to close this gap, so I am tempted to write a cron-script
>> to check expiry and then update 'userAccountControl' every minute or
>> so.
>>
>> Any other thoughts?
> I am not sure if Unix can use 'userAccountControl' and even if it can,

You can, I used it in the past to set 512 / 514 for enabled / disabled 
account. Now I am using samba-tool for it because that is easier with a 
bit-field (because other values than 512/ 514 can be there and you just 
want to toggle bit-1 (the 2), which would make the code a bit complexer).

As an alternative the cron-script you set / reset some value in another 
(used) attribute, which can then be used in queries.

> you are still going to need a script to check if it contains '8388608'.

This is easy, there is a special LDAP function to query bit-values, the 
same as for account disabled:

(!(userAccountControl:1.2.840.113556.1.4.803:=2)) # for not disabled

(!(userAccountControl:1.2.840.113556.1.4.803:=8388608)) # for not expired

- Kees.

>
> Rowland
>



More information about the samba mailing list