Bug 32014 - S4 Connector does not sync account locking state
S4 Connector does not sync account locking state
Status: CLOSED FIXED
Product: UCS
Classification: Unclassified
Component: S4 Connector
UCS 4.0
Other Linux
: P5 normal (vote)
: UCS 4.3
Assigned To: Arvid Requate
Stefan Gohmann
: interim-2
: 32010 38558 (view as bug list)
Depends on:
Blocks: 46353 35014 35072 39817 46175 46200 46354
  Show dependency treegraph
 
Reported: 2013-07-18 16:16 CEST by Arvid Requate
Modified: 2021-03-11 13:08 CET (History)
6 users (show)

See Also:
What kind of report is it?: Bug Report
What type of bug is this?: 5: Major Usability: Impairs usability in key scenarios
Who will be affected by this bug?: 2: Will only affect a few installed domains
How will those affected feel about the bug?: 2: A Pain – users won’t like this once they notice it
User Pain: 0.114
Enterprise Customer affected?: Yes
School Customer affected?:
ISV affected?:
Waiting Support:
Flags outvoted (downgraded) after PO Review:
Ticket number: 2014121921000011, 2010012910000175
Bug group (optional):
Max CVSS v3 score:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Arvid Requate univentionstaff 2013-07-18 16:16:46 CEST
The S4 Connector currently does not sync the account locking state. Due to the differing locking semantics in Samba3/OpenLDAP and Samba4/AD it might not be trivial to do this:

* The lockoutTime in Samba4/AD attribute specifies when the account was locked (100ns format, local daylightsaving time). The account is then locked for a period specified by the attribute lockoutDuration. After that period the user may log in again. The flag is then reset only after successfull login.

* This attribute currently has no clear counterpart in the Samba3/OpenLDAP schema (badPasswordTime might be somewhat close in meaning).

* The connector can only detect and synchronize a Samba4/AD account unlock to UDM once the user logged in successfully in Samba4/AD, since only this causes a write operation to the lockoutTime attribute in Samba4/AD.

* AFAIK the lockoutDuration in Samba4/AD can be specified not only via the domain object but also via GPOs.


Some additional details:

** A short test showed that Samba4 allows to set lockoutTime to any value (research for Ticket#2012051121003316 showed that native AD only allowed reset to "0").

** Unlock is also possible via userAccountControl: https://git.samba.org/?p=samba.git;a=commitdiff;h=7f760ed84b4b34937b3a65577f971cc95f452e0f

** In Samba3/OpenLDAP the lockout is connected to the attribute sambaAcctFlags. This flag is a bit similar to the calculated Samba4/AD attribute msDS-User-Account-Control-Computed, but it can also be written to.



Summarizing:

* UCS->S4 sync of UDM Samba account lock is hard: could work if the UDM writes the lockoutTime to some OpenLDAP attribute and the S4 Connector synchronizes it. But then, this requires lockoutDuration to be consistent for all objects in UDM an Samba4.

* UCS->S4 sync of UDM Samba account unlock is easy: the S4 Connector synchronizes an UDM locking change to to Samba4, preferably via userAccountControl.

* S4->UCS sync of Samba4 account lock is possible: if lockoutTime != 0 the S4 Connector would need to check msDS-User-Account-Control-Computed. If that is true it should lock the UDM Samba account. It should probably sync the lockoutTime too for the next point.

* S4->UCS sync of Samba4 account unlock: maybe easy: If the lockTimeout is synchroinized, the S4 Connector can discover that the lockTimeout was reset to zero in Samba4. If it is not, then it can discover that lockTimeout==0 while the UDM Samba account is currently locked.



+++ This bug was initially created as a clone of Bug #31587 +++
Comment 1 Arvid Requate univentionstaff 2013-07-18 16:18:47 CEST
Based also on research for Ticket#2012051121003316 and Ticket#: 2010012910000175
Comment 2 Janek Walkenhorst univentionstaff 2013-07-18 16:18:49 CEST
*** Bug 32010 has been marked as a duplicate of this bug. ***
Comment 3 Arvid Requate univentionstaff 2014-10-30 18:07:56 CET
Another way of unlocking a Samba/AD account is by setting lockoutTime to 0.
Comment 4 Tim Petersen univentionstaff 2014-12-23 09:00:39 CET
Reported at 2014121921000011 - seems like a part of the problem.
Comment 5 Tim Petersen univentionstaff 2014-12-23 09:03:19 CET
(In reply to Tim Petersen from comment #4)
> Reported at 2014121921000011 - seems like a part of the problem.

Clarification: It seems that accounts are locked forever if using an ad password policy that locks the account after x wrong login attempts for y minutes.
Comment 6 Arvid Requate univentionstaff 2014-12-23 16:10:42 CET
(In reply to Tim Petersen from comment #4)
> Reported at 2014121921000011 - seems like a part of the problem.

I don't think that this is part of the problem. This bug here is about synchronization of the locking state between OpenLDAP/UDM and Samba ADDC.


I checked that the lockout / timed unlock in Samba ADDC works generally in UCS 4.0 (it has been implemented via Bug 32974).


But the unlock behaviour indeed shows a bit unexpected behaviour in one particular case, I opened Bug 37416 for that.
Comment 7 Arvid Requate univentionstaff 2017-01-18 14:15:52 CET
Note: Windows/AD specifies at least two ways of resetting the lockoutTime:

A) by setting lockoutTime to 0
   https://msdn.microsoft.com/en-us/library/cc245684.aspx

B) by setting userAccountControl bit UF_LOCKOUT (this is counterintuitive!):
   https://msdn.microsoft.com/en-us/library/cc245673.aspx

The latter option additionally resets UF_PASSWORD_EXPIRED if set on the account.
Comment 8 Arvid Requate univentionstaff 2017-01-18 14:29:19 CET
There is actually a solution for the UCS->S4 sync of UDM Samba account lock:

AD accounts can be disabled by setting the UF_ACCOUNTDISABLE bit in userAccountControl.



Note: AD has three concepts here:

1. Temporary account lockout on repeated failed logon attempts:
   https://technet.microsoft.com/en-us/library/cc775412(v=ws.10).aspx

2. Manually disabling accounts
   by setting the UF_ACCOUNTDISABLE bit in userAccountControl

3. Password expiry
Comment 9 Arvid Requate univentionstaff 2017-01-18 14:46:11 CET
Note: Felix just discovered that there are two distinct definitions of the userAccountControl bits: https://msdn.microsoft.com/en-us/library/cc245737.aspx

From his tests, it seems to be USER_ACCOUNT_DISABLED and not UF_ACCOUNTDISABLE.
Comment 10 Felix Botner univentionstaff 2017-01-18 16:57:20 CET
import samba.dcerpc.samr
from samba.credentials import Credentials, DONT_USE_KERBEROS
from samba.param import LoadParm
from samba.dcerpc import drsuapi, lsa, security


lp = LoadParm()
lp.load('/dev/null')

creds = Credentials()
creds.guess(lp)
creds.set_kerberos_state(DONT_USE_KERBEROS)

bind_username = 'Administrator'
bind_password = 'Univention.88'
ad_ldap_host = '10.200.7.132'
ad_netbios_domainname = 'w2k12.test'
rid = 1106

creds.set_username(bind_username)
creds.set_password(bind_password)

binding_options = "\pipe\samr"
binding = "ncacn_np:%s[%s]" % (ad_ldap_host, binding_options)

samr = samba.dcerpc.samr.samr(binding, lp, creds)
handle = samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)

sam_domain = lsa.String()
sam_domain.string = ad_netbios_domainname
sid = samr.LookupDomain(handle, sam_domain)
dom_handle = samr.OpenDomain(handle, security.SEC_FLAG_MAXIMUM_ALLOWED, sid)
user_handle = samr.OpenUser(dom_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, rid)

USER_ACCOUNT_FLAGS = dict(
        USER_ACCOUNT_DISABLED                       = 0x00000001,
        USER_HOME_DIRECTORY_REQUIRED                = 0x00000002,
        USER_PASSWORD_NOT_REQUIRED                  = 0x00000004,
        USER_TEMP_DUPLICATE_ACCOUNT                 = 0x00000008,
        USER_NORMAL_ACCOUNT                         = 0x00000010,
        USER_MNS_LOGON_ACCOUNT                      = 0x00000020,
        USER_INTERDOMAIN_TRUST_ACCOUNT              = 0x00000040,
        USER_WORKSTATION_TRUST_ACCOUNT              = 0x00000080,
        USER_SERVER_TRUST_ACCOUNT                   = 0x00000100,
        USER_DONT_EXPIRE_PASSWORD                   = 0x00000200,
        USER_ACCOUNT_AUTO_LOCKED                    = 0x00000400,
        USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED        = 0x00000800,
        USER_SMARTCARD_REQUIRED                     = 0x00001000,
        USER_TRUSTED_FOR_DELEGATION                 = 0x00002000,
        USER_NOT_DELEGATED                          = 0x00004000,
        USER_USE_DES_KEY_ONLY                       = 0x00008000,
        USER_DONT_REQUIRE_PREAUTH                   = 0x00010000,
        USER_PASSWORD_EXPIRED                       = 0x00020000,
        USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x00040000,
        USER_NO_AUTH_DATA_REQUIRED                  = 0x00080000,
        USER_PARTIAL_SECRETS_ACCOUNT                = 0x00100000,
        USER_USE_AES_KEYS                           = 0x00200000,
)

info = samr.QueryUserInfo(user_handle, 16)

for flag in USER_ACCOUNT_FLAGS:
        if info.acct_flags & USER_ACCOUNT_FLAGS[flag]:
                print flag, 'enabled'

# remove flag, enable account
info.acct_flags &= ~USER_ACCOUNT_FLAGS['USER_ACCOUNT_DISABLED']

# add flag, disable account
info.acct_flags |= USER_ACCOUNT_FLAGS['USER_ACCOUNT_DISABLED']


userinfo16 = samba.dcerpc.samr.UserInfo16()
userinfo16.acct_flags = info.acct_flags
print userinfo16.acct_flags
samr.SetUserInfo(user_handle, 16, userinfo16)
Comment 11 Felix Botner univentionstaff 2017-01-18 18:00:37 CET
Ah, but 'USER_ACCOUNT_DISABLED' is not "locking" the account. There is a difference between lock and disable.

and here i found ;-)

http://microsoft.public.active.directory.interfaces.narkive.com/gD2S1AdN/lock-an-account-in-active-directory-using-ldap-api

   "As you have discovered, you can't set lockoutTime to a value either.
    That is managed by the system.

    The only way to lock out an account programmatically via LDAP is to 
    actually bind incorrectly enough times in succession to trip the lockout 
    policy."
Comment 12 Arvid Requate univentionstaff 2017-01-18 19:06:53 CET
* Re: Comment 10: This should also be possible via ldapmodify.


* Re: Comment 11:

> Ah, but 'USER_ACCOUNT_DISABLED' is not "locking" the account. There is a
> difference between lock and disable.

Yes, see Comment 8.


* Re: Comment 11:

>    "As you have discovered, you can't set lockoutTime to a value either.
>    That is managed by the system.

True for AD but not for Samba, see Comment 0:

> ** A short test showed that Samba4 allows to set lockoutTime to any value 

 

* Re: Comment 11:

>    The only way to lock out an account programmatically via LDAP is to 
>    actually bind incorrectly enough times in succession to trip the lockout 
>    policy."

Yes, see Comment 0:

> Summarizing:
> 
> * UCS->S4 sync of UDM Samba account lock is hard: could work if the UDM writes
> the lockoutTime to some OpenLDAP attribute and the S4 Connector synchronizes
> it. But then, this requires lockoutDuration to be consistent for all objects
> in UDM an Samba4.
Comment 13 Arvid Requate univentionstaff 2017-01-31 16:52:58 CET
We have several different concepts and techniques here and need to clearly define what we want, can and need to do (see Bug 39817 Comment 1):


A) Automatic temporary account lockout on repeated failed logon attempts
A.1) For Samba/AD: (Bug 32974)
A.2) For PAM login: auth/faillog (Bug 18750)
A.3) For LDAP login: ldap/ppolicy/.* (Bug 31907)

B) Locked login methods (see Bug 39817)
B.1) UCS specific concept (Bug 18825)

C) Account deactivation
C.1) Samba/AD: Manually setting userAccountControl "D" flag via ADUC
C.2) UDM (Bug 18825)

Bug 39817 discusses B vs C. This bug is about A.
Comment 14 Arvid Requate univentionstaff 2017-04-26 12:44:34 CEST
TODO:

* sync Samba/AD badPasswordTime        <->  OpenLDAP sambaBadPasswordTime
* sync Samba/AD (lockoutTime != 0)      ->  OpenLDAP sambaAcctFlags ("L")
* sync OpenLDAP (sambaAcctFlags != "L") ->  Samba/AD lockoutTime = 0


After this the following point can be done at Bug 39817:

In UMC/UDM we show an Account as locked if sambaAcctFlags = "L".
Optionally we can show the time until it is locked. That value can be calculated by adding the value of sambaBadPasswordTime to sambaLockoutDuration (as configured on the objectclass=sambadomain object).
Comment 15 Arvid Requate univentionstaff 2018-01-23 23:15:06 CET
branch: arequate/bug32014

df25693cf3: Sync account locking state and unlock

closing for initial qa, changelog-4.3-0 still TBD.
Comment 16 Florian Best univentionstaff 2018-01-23 23:28:41 CET
Code-Review: Looks good except two things, which were meantioned as comments:
'L' in some_dict.get('foo', [None]) causes a TypeError if 'foo' is not set.
Comment 17 Florian Best univentionstaff 2018-01-30 20:56:01 CET
Thank you, Arvid. I merged your current changes.
Comment 18 Arvid Requate univentionstaff 2018-02-07 19:18:29 CET
Ok, the S4-Connector now does this:

==========================================================
1. Sync account lockout *state* from Samba/AD to OpenLDAP:
* sync Samba/AD (lockoutTime != 0)
       ->  OpenLDAP sambaAcctFlags ("L")
  and  Samba/AD badPasswordTime
       ->  OpenLDAP sambaBadPasswordTime

2. Sync lockout *reset* from OpenLDAP to Samba/AD:
* sync OpenLDAP ("L" not in sambaAcctFlags)
       ->  Samba/AD lockoutTime = 0

3. Sync lockout *activation* from OpenLDAP to Samba/AD:
* sync OpenLDAP ("L" in sambaAcctFlags)
       ->  Samba/AD lockoutTime = sambaBadPasswordTime
  and  OpenLDAP sambaBadPasswordTime
       ->  Samba/AD badPasswordTime
==========================================================

The third part is not possible in native Microsoft AD as stated above, but it's possible in Samba and it makes lockout behavior more consistent.

Changelog adjusted.
Comment 19 Stefan Gohmann univentionstaff 2018-02-21 10:59:24 CET
(In reply to Arvid Requate from comment #18)
> Ok, the S4-Connector now does this:
> 
> ==========================================================
> 1. Sync account lockout *state* from Samba/AD to OpenLDAP:
> * sync Samba/AD (lockoutTime != 0)
>        ->  OpenLDAP sambaAcctFlags ("L")
>   and  Samba/AD badPasswordTime
>        ->  OpenLDAP sambaBadPasswordTime
> 
> 2. Sync lockout *reset* from OpenLDAP to Samba/AD:
> * sync OpenLDAP ("L" not in sambaAcctFlags)
>        ->  Samba/AD lockoutTime = 0
> 
> 3. Sync lockout *activation* from OpenLDAP to Samba/AD:
> * sync OpenLDAP ("L" in sambaAcctFlags)
>        ->  Samba/AD lockoutTime = sambaBadPasswordTime
>   and  OpenLDAP sambaBadPasswordTime
>        ->  Samba/AD badPasswordTime
> ==========================================================
> 
> The third part is not possible in native Microsoft AD as stated above, but
> it's possible in Samba and it makes lockout behavior more consistent.

Thanks for the overview. Works as expected.

> Changelog adjusted.

OK
Comment 20 Stefan Gohmann univentionstaff 2018-03-14 14:37:44 CET
UCS 4.3 has been released:
 https://docs.software-univention.de/release-notes-4.3-0-en.html
 https://docs.software-univention.de/release-notes-4.3-0-de.html

If this error occurs again, please use "Clone This Bug".
Comment 21 Arvid Requate univentionstaff 2021-03-11 13:08:04 CET
*** Bug 38558 has been marked as a duplicate of this bug. ***