Univention Bugzilla – Bug 56309
udm users/user create doesn't update univentionLastUsedValue of cn=uidNumber if allocated SID is taken
Last modified: 2023-07-19 17:15:34 CEST
In a UCS@school domain with a UCS 5.0-4 errata726 primary a customer experienced that the S4-Connector repeatedly generated rejects due to SID values already occupied in Samba/AD. connector-s4.log had: === ldap.CONSTRAINT_VIOLATION: {'desc': 'Constraint violation', 'info': '0000202F: ../../lib/ldb/ldb_key_value/ldb_kv_index.c:3065: Failed to re-index objectSid in CN=someuser,CN=schueler,CN=users,OU=foo,DC=school,DC=domain - ../../lib/ldb/ldb_key_value/ldb_kv_index.c:2910: unique index violation on objectSid in CN=someuser,CN=schueler,CN=users,OU=foo,DC=school,DC=domain'} === Support found that the SIDs where blocked by deleted objects under "CN=Deleted Objects" and the "tombstone reanimation" procedure was not initiated by the S4-Connector because the new user didn't match the name of the deleted object. In UCS@school, the udm allocator is responsible to allocate SIDs and the allocation starts the search for a free RID at the value of (1000 + uidNumber*2). This in turn depends on the allocated uidNumber and that starts at the value that is stored in univentionLastUsedValue and the object cn=uidNumber,cn=temporary,cn=univention,$ldap_base. We checked the customer environment and found that that value univentionLastUsedValue had not changed since 20221212074241Z and creating a new user with udm also didn't update the value. So udm always started at some lower value of uidNumber and in turn allocated some arbitrary sambaSID that it found to be free, in this case that of a deleted object. Debugging showed that the request_lock('sid+user', uidNum) call from __generate_user_sid() calls self._release_locks() in case the initial guess for the sambaSID cannot be locked. This can happen, if the naive (1000+uidNumber*2) formula suggests a sambaSID that happens to be already taken. The __generate_user_sid() call then catches the noLock exception and suggests a new sambaSID until it succeeds. So far so good, and the user is created successfully. But: Since _release_locks() flushed all memory about the allocated uidNumber, it will never again be updated in the univentionLastUsedValue.
See URL field above for a naive untested patch proposal.
Stacktrace from the _release_locks() call: https://pastebin.knut.univention.de/vKFzEyYp
Workaround: manually update the univentionLastUsedValue of cn=uidNumber to the currently highest uidNumber in the domain (via ldapmodify) and check that the (1000+2*(uidNumber+1)) is still free.
(In reply to Arvid Requate from comment #2) > Stacktrace from the _release_locks() call: > https://pastebin.knut.univention.de/vKFzEyYp _release_locks called File "/usr/share/univention-directory-manager-tools/univention-cli-server", line 302, in <module> main() File "/usr/share/univention-directory-manager-tools/univention-cli-server", line 293, in main server_main(args) File "/usr/share/univention-directory-manager-tools/univention-cli-server", line 167, in server_main handler.handle_request() File "/usr/lib/python3.7/socketserver.py", line 296, in handle_request return self._handle_request_noblock() File "/usr/lib/python3.7/socketserver.py", line 316, in _handle_request_noblock self.process_request(request, client_address) File "/usr/lib/python3.7/socketserver.py", line 616, in process_request self.finish_request(request, client_address) File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/lib/python3.7/socketserver.py", line 720, in __init__ self.handle() File "/usr/share/univention-directory-manager-tools/univention-cli-server", line 93, in handle doit(sarglist, self.request, stdout, stderr) File "/usr/share/univention-directory-manager-tools/univention-cli-server", line 238, in doit univention.admincli.admin.main(arglist, stdout, stderr) File "/usr/lib/python3/dist-packages/univention/admincli/admin.py", line 351, in main _doit(arglist, stdout=stdout, stderr=stderr) File "/usr/lib/python3/dist-packages/univention/admincli/admin.py", line 600, in _doit cli.create(input, append, ignore_exists, parsed_options, parsed_append_options, parsed_remove_options, policy_reference) File "/usr/lib/python3/dist-packages/univention/admincli/admin.py", line 628, in create return self._create(self.module_name, self.module, self.dn, self.lo, self.position, self.superordinate, *args, **kwargs) File "/usr/lib/python3/dist-packages/univention/admincli/admin.py", line 679, in _create dn = object.create() File "/usr/lib/python3/dist-packages/univention/admin/handlers/__init__.py", line 557, in create dn = self._create(response=response, serverctrls=serverctrls) File "/usr/lib/python3/dist-packages/univention/admin/handlers/__init__.py", line 1268, in _create al.extend(self._ldap_modlist()) File "/usr/lib/python3/dist-packages/univention/admin/handlers/users/user.py", line 1583, in _ldap_modlist ml = self._modlist_samba_sid(ml) File "/usr/lib/python3/dist-packages/univention/admin/handlers/users/user.py", line 1942, in _modlist_samba_sid sid = self.__generate_user_sid(self['uidNumber']) File "/usr/lib/python3/dist-packages/univention/admin/handlers/users/user.py", line 2062, in __generate_user_sid return self.request_lock('sid+user', uidNum) File "/usr/lib/python3/dist-packages/univention/admin/handlers/__init__.py", line 1711, in request_lock self._release_locks() File "/usr/lib/python3/dist-packages/univention/admin/handlers/__init__.py", line 1680, in _release_locks f.write("%s\n" % ''.join(traceback.format_stack()))
25b40c47b2 | release only specific locks when locking fails Built in errata5.0-4 as version 15.0.24-13.
OK: functional test OK: Code review FYI: as the values aren't added to self.alloc yet the release_lock(name) is a NO-OP (I don't think a lock is requested twice). but ok for me, as the new function signature might be usefull in the future and the code line represents the idea. OK: Code review that if this case happens afterwards at the very end on operations like create/modify/etc the requested locks during that operation are cleaned up/released. OK: Jenkins tests ok OK: YAML
<https://errata.software-univention.de/#/?erratum=5.0x745>