Univention Bugzilla – Bug 32014
S4 Connector does not sync account locking state
Last modified: 2021-03-11 13:08:04 CET
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 +++
Based also on research for Ticket#2012051121003316 and Ticket#: 2010012910000175
*** Bug 32010 has been marked as a duplicate of this bug. ***
Another way of unlocking a Samba/AD account is by setting lockoutTime to 0.
Reported at 2014121921000011 - seems like a part of the problem.
(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.
(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.
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.
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
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.
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)
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."
* 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.
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.
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).
branch: arequate/bug32014 df25693cf3: Sync account locking state and unlock closing for initial qa, changelog-4.3-0 still TBD.
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.
Thank you, Arvid. I merged your current changes.
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.
(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
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".
*** Bug 38558 has been marked as a duplicate of this bug. ***