View | Details | Raw Unified | Return to bug 43628 | Differences between
and this patch

Collapse All | Expand All

(-)base/univention-python/debian/changelog (+7 lines)
 Lines 1-3    Link Here 
1
univention-python (10.0.4-1) UNRELEASED; urgency=medium
2
3
  * Bug 43628: Support lookup of specific attributes via PostReadControl
4
    (RFC 4527)
5
6
 -- Arvid Requate <requate@univention.de>  Mon, 10 Jul 2017 19:28:18 +0200
7
1
univention-python (10.0.3-4) unstable; urgency=medium
8
univention-python (10.0.3-4) unstable; urgency=medium
2
9
3
  * Bug #41234: Revert changes made with Bug #36169 due to fix of Bug #36343
10
  * Bug #41234: Revert changes made with Bug #36169 due to fix of Bug #36343
(-)base/univention-python/debian/control (+1 lines)
 Lines 12-17    Link Here 
12
Architecture: all
12
Architecture: all
13
Depends: ${misc:Depends}, ${python:Depends},
13
Depends: ${misc:Depends}, ${python:Depends},
14
 python-ldap,
14
 python-ldap,
15
 python-pyasn1-modules,
15
 python-dns,
16
 python-dns,
16
 python-univention-debug,
17
 python-univention-debug,
17
 python-cracklib
18
 python-cracklib
(-)base/univention-python/modules/uldap.py (-22 / +106 lines)
 Lines 34-39    Link Here 
34
import ldap
34
import ldap
35
import ldap.schema
35
import ldap.schema
36
import ldap.sasl
36
import ldap.sasl
37
from ldap.controls.readentry import PostReadControl
37
import univention.debug
38
import univention.debug
38
from univention.config_registry import ConfigRegistry
39
from univention.config_registry import ConfigRegistry
39
from ldapurl import LDAPUrl
40
from ldapurl import LDAPUrl
 Lines 401-407    Link Here 
401
			self.__schema = ldap.schema.SubSchema(self.lo.read_subschemasubentry_s(self.lo.search_subschemasubentry_s()), 0)
402
			self.__schema = ldap.schema.SubSchema(self.lo.read_subschemasubentry_s(self.lo.search_subschemasubentry_s()), 0)
402
		return self.__schema
403
		return self.__schema
403
404
404
	def add(self, dn, al):
405
	def add(self, dn, al, postread_attrs=None):
405
		"""Add LDAP entry with dn and attributes in add_list=(attribute-name, old-values. new-values) or (attribute-name, new-values)."""
406
		"""Add LDAP entry with dn and attributes in add_list=(attribute-name, old-values. new-values) or (attribute-name, new-values)."""
406
407
407
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.add dn=%s' % dn)
408
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.add dn=%s' % dn)
 Lines 416-430    Link Here 
416
			nal[key] |= set(val)
417
			nal[key] |= set(val)
417
418
418
		nal = self.__encode_entry([(k, list(v)) for k, v in nal.items()])
419
		nal = self.__encode_entry([(k, list(v)) for k, v in nal.items()])
420
421
		if postread_attrs:
422
			serverctrls = [PostReadControl(True, postread_attrs),]
423
			return self.add_ext_s(dn, nal, serverctrls=serverctrls)
424
		else:
425
			return self.add_s(dn, nal)
426
427
	def add_s(self, dn, al):
428
		"""Redirect add_s directly to lo"""
419
		try:
429
		try:
420
			self.lo.add_ext_s(dn, nal)
430
			self.lo.add_ext_s(dn, al)
421
		except ldap.REFERRAL as exc:
431
		except ldap.REFERRAL as exc:
422
			if not self.follow_referral:
432
			if not self.follow_referral:
423
				raise
433
				raise
424
			lo_ref = self._handle_referral(exc)
434
			lo_ref = self._handle_referral(exc)
425
			lo_ref.add_ext_s(dn, nal)
435
			lo_ref.add_ext_s(dn, al)
426
436
427
	def modify(self, dn, changes):
437
	def add_ext_s(self, dn, al, serverctrls=None):
438
		"""Redirect add_ext_s directly to lo"""
439
		try:
440
			msgid = self.lo.add_ext(dn, al, serverctrls=serverctrls)
441
			rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid)
442
		except ldap.REFERRAL as exc:
443
			if not self.follow_referral:
444
				raise
445
			lo_ref = self._handle_referral(exc)
446
			msgid = lo_ref.add_ext(dn, al, serverctrls=serverctrls)
447
			rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid)
448
		for c in resp_ctrls:
449
			if c.controlType == PostReadControl.controlType:
450
				return c.entry
451
452
	def modify(self, dn, changes, postread_attrs=None):
428
		"""Modify LDAP entry dn with attributes in changes=(attribute-name, old-values, new-values)."""
453
		"""Modify LDAP entry dn with attributes in changes=(attribute-name, old-values, new-values)."""
429
454
430
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.modify %s' % dn)
455
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.modify %s' % dn)
 Lines 454-469    Link Here 
454
			ml.append((op, key, val))
479
			ml.append((op, key, val))
455
		ml = self.__encode_entry(ml)
480
		ml = self.__encode_entry(ml)
456
481
482
		if postread_attrs:
483
			serverctrls = [PostReadControl(True, postread_attrs),]
484
		else:
485
			serverctrls = []
486
487
		resp_entry = {}
457
		# check if we need to rename the object
488
		# check if we need to rename the object
458
		new_dn, new_rdn = self.__get_new_dn(dn, ml)
489
		new_dn, new_rdn = self.__get_new_dn(dn, ml)
459
		if not self.compare_dn(dn, new_dn):
490
		if not self.compare_dn(dn, new_dn):
460
			univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, 'rename %s' % (new_rdn,))
491
			univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, 'rename %s' % (new_rdn,))
461
			self.lo.rename_s(dn, new_rdn, None, delold=1)
492
			if postread_attrs:
493
				resp_entry = self.rename_ext_s(dn, new_rdn, None, delold=1, serverctrls=serverctrls)
494
			else:
495
				self.lo.rename_s(dn, new_rdn, None, delold=1)
462
			dn = new_dn
496
			dn = new_dn
463
		if ml:
497
		if ml:
464
			self.modify_s(dn, ml)
498
			if postread_attrs:
465
		return dn
499
				resp_entry = self.modify_ext_s(dn, ml, serverctrls=serverctrls)
500
			else:
501
				self.modify_s(dn, ml)
466
502
503
		if postread_attrs:
504
			return (dn, resp_entry)
505
		else:
506
			return dn
507
467
	@classmethod
508
	@classmethod
468
	def __get_new_dn(self, dn, ml):
509
	def __get_new_dn(self, dn, ml):
469
		"""
510
		"""
 Lines 494-524    Link Here 
494
			lo_ref = self._handle_referral(exc)
535
			lo_ref = self._handle_referral(exc)
495
			lo_ref.modify_ext_s(dn, ml)
536
			lo_ref.modify_ext_s(dn, ml)
496
537
497
	def rename(self, dn, newdn):
538
	def modify_ext_s(self, dn, ml, serverctrls=None):
539
		"""Redirect modify_ext_s directly to lo"""
540
		try:
541
			msgid = self.lo.modify_ext(dn, ml, serverctrls=serverctrls)
542
			rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid)
543
		except ldap.REFERRAL as exc:
544
			if not self.follow_referral:
545
				raise
546
			lo_ref = self._handle_referral(exc)
547
			msgid = lo_ref.modify_ext(dn, ml, serverctrls=serverctrls)
548
			rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid)
549
		for c in resp_ctrls:
550
			if c.controlType == PostReadControl.controlType:
551
				return c.entry
552
553
	def rename(self, dn, newdn, postread_attrs=None):
498
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename %s -> %s' % (dn, newdn))
554
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename %s -> %s' % (dn, newdn))
499
		oldsdn = self.parentDn(dn)
555
		oldsdn = self.parentDn(dn)
500
		newrdn = ldap.dn.dn2str([ldap.dn.str2dn(newdn)[0]])
556
		newrdn = ldap.dn.dn2str([ldap.dn.str2dn(newdn)[0]])
501
		newsdn = ldap.dn.dn2str(ldap.dn.str2dn(newdn)[1:])
557
		newsdn = ldap.dn.dn2str(ldap.dn.str2dn(newdn)[1:])
502
558
559
		if postread_attrs:
560
			serverctrls = [PostReadControl(True, postread_attrs),]
561
		else:
562
			serverctrls = []
563
564
		resp_entry = {}
503
		if not newsdn.lower() == oldsdn.lower():
565
		if not newsdn.lower() == oldsdn.lower():
504
			univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: move %s to %s in %s' % (dn, newrdn, newsdn))
566
			univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: move %s to %s in %s' % (dn, newrdn, newsdn))
505
			try:
567
			if postread_attrs:
506
				self.lo.rename_s(dn, newrdn, newsdn)
568
				resp_entry = self.rename_ext_s(dn, newrdn, newsdn, serverctrls=serverctrls)
507
			except ldap.REFERRAL as exc:
569
			else:
508
				if not self.follow_referral:
570
				self.rename_s(dn, newrdn, newsdn)
509
					raise
510
				lo_ref = self._handle_referral(exc)
511
				lo_ref.rename_s(dn, newrdn, newsdn)
512
		else:
571
		else:
513
			univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: modrdn %s to %s' % (dn, newrdn))
572
			univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: modrdn %s to %s' % (dn, newrdn))
514
			try:
573
			if postread_attrs:
515
				self.lo.rename_s(dn, newrdn)
574
				resp_entry = self.rename_ext_s(dn, newrdn, serverctrls=serverctrls)
516
			except ldap.REFERRAL as exc:
575
			else:
517
				if not self.follow_referral:
576
				self.rename_s(dn, newrdn)
518
					raise
519
				lo_ref = self._handle_referral(exc)
520
				lo_ref.rename_s(dn, newrdn)
521
577
578
		if postread_attrs:
579
			return resp_entry
580
581
	def rename_s(self, dn, newrdn, newsuperior=None):
582
		"""Redirect rename_s directly to lo"""
583
		try:
584
			self.lo.rename_s(dn, newrdn, newsuperior)
585
		except ldap.REFERRAL as exc:
586
			if not self.follow_referral:
587
				raise
588
			lo_ref = self._handle_referral(exc)
589
			lo_ref.rename_s(dn, newrdn, newsuperior)
590
591
	def rename_ext_s(self, dn, newrdn, newsuperior=None, serverctrls=None):
592
		"""Redirect rename_ext_s directly to lo"""
593
		try:
594
			msgid = self.lo.rename(dn, newrdn, newsuperior, serverctrls=serverctrls)
595
			rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid)
596
		except ldap.REFERRAL as exc:
597
			if not self.follow_referral:
598
				raise
599
			lo_ref = self._handle_referral(exc)
600
			lo_ref.rename(dn, newrdn, newsuperior, serverctrls=serverctrls)
601
			rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid)
602
		for c in resp_ctrls:
603
			if c.controlType == PostReadControl.controlType:
604
				return c.entry
605
522
	def delete(self, dn):
606
	def delete(self, dn):
523
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.delete %s' % dn)
607
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.delete %s' % dn)
524
		if dn:
608
		if dn:
(-)management/univention-directory-manager-modules/debian/changelog (+7 lines)
 Lines 1-3    Link Here 
1
univention-directory-manager-modules (12.0.18-1) UNRELEASED; urgency=medium
2
3
  * Bug 43628: Support lookup of specific attributes via PostReadControl
4
    (RFC 4527)
5
6
 -- Arvid Requate <requate@univention.de>  Mon, 10 Jul 2017 19:32:17 +0200
7
1
univention-directory-manager-modules (12.0.17-74) unstable; urgency=medium
8
univention-directory-manager-modules (12.0.17-74) unstable; urgency=medium
2
9
3
  * Bug #42015: Applied patch from Florian Best - Fix LDAP error when
10
  * Bug #42015: Applied patch from Florian Best - Fix LDAP error when
(-)management/univention-directory-manager-modules/debian/control (-1 / +1 lines)
 Lines 14-20    Link Here 
14
Architecture: all
14
Architecture: all
15
Depends: ${misc:Depends}, ${python:Depends},
15
Depends: ${misc:Depends}, ${python:Depends},
16
 python (>= 2.7),
16
 python (>= 2.7),
17
 python-univention (>> 6.0.21),
17
 python-univention (>= 10.0.4-1),
18
 python-univention-heimdal (>= 4.0.1-1),
18
 python-univention-heimdal (>= 4.0.1-1),
19
 makepasswd,
19
 makepasswd,
20
 python-m2crypto,
20
 python-m2crypto,
(-)management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py (-3 / +30 lines)
 Lines 108-113    Link Here 
108
		self.options = []
108
		self.options = []
109
		self.old_options = []
109
		self.old_options = []
110
		self.alloc = []
110
		self.alloc = []
111
		self.postread_attrs = None
112
		self.resp_entry = {}
111
113
112
		if not isinstance(self.lo, univention.admin.uldap.access):
114
		if not isinstance(self.lo, univention.admin.uldap.access):
113
			if not isinstance(self.lo, univention.uldap.access):
115
			if not isinstance(self.lo, univention.uldap.access):
 Lines 672-677    Link Here 
672
		self.call_udm_property_hook('hook_open', self)
674
		self.call_udm_property_hook('hook_open', self)
673
		self.save()
675
		self.save()
674
676
677
	def create(self, postread_attrs=None):
678
		if postread_attrs:
679
			self.postread_attrs = postread_attrs
680
		res = base.create(self)
681
		if self.postread_attrs:
682
			self.oldattr.update(self.resp_entry)
683
		return res
684
685
	def modify(self, modify_childs=1, ignore_license=0, postread_attrs=None):
686
		if postread_attrs:
687
			self.postread_attrs = postread_attrs
688
		res = base.modify(self, modify_childs=1, ignore_license=0)
689
		if self.postread_attrs:
690
			self.oldattr.update(self.resp_entry)
691
		return res
692
675
	def _remove_option(self, name):
693
	def _remove_option(self, name):
676
		if name in self.options:
694
		if name in self.options:
677
			self.options.remove(name)
695
			self.options.remove(name)
 Lines 781-787    Link Here 
781
799
782
		# if anything goes wrong we need to remove the already created object, otherwise we run into 'already exists' errors
800
		# if anything goes wrong we need to remove the already created object, otherwise we run into 'already exists' errors
783
		try:
801
		try:
784
			self.lo.add(self.dn, al)
802
			if self.postread_attrs:
803
				self.resp_entry = self.lo.add(self.dn, al, postread_attrs=self.postread_attrs)
804
			else:
805
				self.lo.add(self.dn, al)
785
			self._exists = True
806
			self._exists = True
786
			self._ldap_post_create()
807
			self._ldap_post_create()
787
		except:
808
		except:
 Lines 826-838    Link Here 
826
847
827
		# FIXME: timeout without exception if objectClass of Object is not exsistant !!
848
		# FIXME: timeout without exception if objectClass of Object is not exsistant !!
828
		univention.debug.debug(univention.debug.ADMIN, 99, 'Modify dn=%r;\nmodlist=%r;\noldattr=%r;' % (self.dn, ml, self.oldattr))
849
		univention.debug.debug(univention.debug.ADMIN, 99, 'Modify dn=%r;\nmodlist=%r;\noldattr=%r;' % (self.dn, ml, self.oldattr))
829
		self.lo.modify(self.dn, ml, ignore_license=ignore_license)
850
		if self.postread_attrs:
851
			dn, self.resp_entry = self.lo.modify(self.dn, ml, ignore_license=ignore_license, postread_attrs=self.postread_attrs)
852
		else:
853
			self.lo.modify(self.dn, ml, ignore_license=ignore_license)
830
854
831
		self._ldap_post_modify()
855
		self._ldap_post_modify()
832
		self.call_udm_property_hook('hook_ldap_post_modify', self)
856
		self.call_udm_property_hook('hook_ldap_post_modify', self)
833
857
834
		self.save()
858
		self.save()
835
		return self.dn
859
		if self.postread_attrs:
860
			return (dn, self.resp_entry)
861
		else:
862
			return self.dn
836
863
837
	def set_default_values(self):
864
	def set_default_values(self):
838
		# Make sure all default values are set...
865
		# Make sure all default values are set...
(-)management/univention-directory-manager-modules/modules/univention/admin/uldap.py (-8 / +8 lines)
 Lines 458-464    Link Here 
458
		univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'getPolicies modules dn %s result' % dn)
458
		univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'getPolicies modules dn %s result' % dn)
459
		return self.lo.getPolicies(dn, policies, attrs, result, fixedattrs)
459
		return self.lo.getPolicies(dn, policies, attrs, result, fixedattrs)
460
460
461
	def add(self, dn, al, exceptions=False):
461
	def add(self, dn, al, exceptions=False, postread_attrs=None):
462
		self._validateLicense()
462
		self._validateLicense()
463
		if not self.allow_modify:
463
		if not self.allow_modify:
464
			univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'add dn: %s' % dn)
464
			univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'add dn: %s' % dn)
 Lines 466-474    Link Here 
466
			return []
466
			return []
467
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s al=%s' % (dn, al))
467
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s al=%s' % (dn, al))
468
		if exceptions:
468
		if exceptions:
469
			return self.lo.add(dn, al)
469
			return self.lo.add(dn, al, postread_attrs=postread_attrs)
470
		try:
470
		try:
471
			return self.lo.add(dn, al)
471
			return self.lo.add(dn, al, postread_attrs=postread_attrs)
472
		except ldap.ALREADY_EXISTS as msg:
472
		except ldap.ALREADY_EXISTS as msg:
473
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg))
473
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg))
474
			raise univention.admin.uexceptions.objectExists(dn)
474
			raise univention.admin.uexceptions.objectExists(dn)
 Lines 481-487    Link Here 
481
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg))
481
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg))
482
			raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg)
482
			raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg)
483
483
484
	def modify(self, dn, changes, exceptions=False, ignore_license=0):
484
	def modify(self, dn, changes, exceptions=False, ignore_license=0, postread_attrs=None):
485
		self._validateLicense()
485
		self._validateLicense()
486
		if not self.allow_modify and not ignore_license:
486
		if not self.allow_modify and not ignore_license:
487
			univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'modify dn: %s' % dn)
487
			univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'modify dn: %s' % dn)
 Lines 489-497    Link Here 
489
			return []
489
			return []
490
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s ml=%s' % (dn, changes))
490
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s ml=%s' % (dn, changes))
491
		if exceptions:
491
		if exceptions:
492
			return self.lo.modify(dn, changes)
492
			return self.lo.modify(dn, changes, postread_attrs=postread_attrs)
493
		try:
493
		try:
494
			return self.lo.modify(dn, changes)
494
			return self.lo.modify(dn, changes, postread_attrs=postread_attrs)
495
		except ldap.NO_SUCH_OBJECT as msg:
495
		except ldap.NO_SUCH_OBJECT as msg:
496
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg))
496
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg))
497
			raise univention.admin.uexceptions.noObject(dn)
497
			raise univention.admin.uexceptions.noObject(dn)
 Lines 504-510    Link Here 
504
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg))
504
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg))
505
			raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg)
505
			raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg)
506
506
507
	def rename(self, dn, newdn, move_childs=0, ignore_license=False):
507
	def rename(self, dn, newdn, move_childs=0, ignore_license=False, postread_attrs=None):
508
		if not move_childs == 0:
508
		if not move_childs == 0:
509
			raise univention.admin.uexceptions.noObject(_("Moving children is not supported."))
509
			raise univention.admin.uexceptions.noObject(_("Moving children is not supported."))
510
		self._validateLicense()
510
		self._validateLicense()
 Lines 514-520    Link Here 
514
			return []
514
			return []
515
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s newdn=%s' % (dn, newdn))
515
		univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s newdn=%s' % (dn, newdn))
516
		try:
516
		try:
517
			return self.lo.rename(dn, newdn)
517
			return self.lo.rename(dn, newdn, postread_attrs=postread_attrs)
518
		except ldap.NO_SUCH_OBJECT as msg:
518
		except ldap.NO_SUCH_OBJECT as msg:
519
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s err=%s' % (dn, msg))
519
			univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s err=%s' % (dn, msg))
520
			raise univention.admin.uexceptions.noObject(dn)
520
			raise univention.admin.uexceptions.noObject(dn)
(-)services/univention-s4-connector/debian/changelog (+7 lines)
 Lines 1-3    Link Here 
1
univention-s4-connector (11.0.8-1) UNRELEASED; urgency=medium
2
3
  * Bug 43628: during sync_to_ucs remember entryCSN of msGPO changes
4
    to be able to identify and skip them later in sync_from_ucs.
5
6
 -- Arvid Requate <requate@univention.de>  Mon, 10 Jul 2017 19:33:24 +0200
7
1
univention-s4-connector (11.0.7-12) unstable; urgency=medium
8
univention-s4-connector (11.0.7-12) unstable; urgency=medium
2
9
3
  * Bug #43072: s4connector/dns: fix ptr_record deletion.
10
  * Bug #43072: s4connector/dns: fix ptr_record deletion.
(-)services/univention-s4-connector/debian/control (-1 / +1 lines)
 Lines 16-22    Link Here 
16
 python-univention (>=8.0.3-1),
16
 python-univention (>=8.0.3-1),
17
 python-univention-license,
17
 python-univention-license,
18
 python-univention-heimdal (>= 4.0.2-2),
18
 python-univention-heimdal (>= 4.0.2-2),
19
 python-univention-directory-manager (>= 7.0.232-2),
19
 python-univention-directory-manager (>= 12.0.18-1),
20
 python-pysqlite2
20
 python-pysqlite2
21
Provides: ${python:Provides}
21
Provides: ${python:Provides}
22
Description: UCS - Modules for connector sychronisation
22
Description: UCS - Modules for connector sychronisation
(-)services/univention-s4-connector/modules/univention/s4connector/__init__.py (-5 / +79 lines)
 Lines 482-488    Link Here 
482
482
483
		self.open_ucs()
483
		self.open_ucs()
484
484
485
		for section in ['DN Mapping UCS', 'DN Mapping CON', 'UCS rejected', 'UCS deleted']:
485
		for section in ['DN Mapping UCS', 'DN Mapping CON', 'UCS rejected', 'UCS deleted', 'UCS entryCSN']:
486
			if not self.config.has_section(section):
486
			if not self.config.has_section(section):
487
				self.config.add_section(section)
487
				self.config.add_section(section)
488
488
 Lines 623-628    Link Here 
623
			if ucs:
623
			if ucs:
624
				self._remove_config_option('DN Mapping UCS', self._encode_dn_as_config_option(ucs.lower()))
624
				self._remove_config_option('DN Mapping UCS', self._encode_dn_as_config_option(ucs.lower()))
625
625
626
	def _remember_entryCSN_commited_by_connector(self, entryUUID, entryCSN):
627
		"""Remember the entryCSN of a change committed by the S4-Connector itself"""
628
		_d = ud.function('ldap._remember_entryCSN_commited_by_connector')
629
		value = self._get_config_option('UCS entryCSN', entryUUID)
630
		if value:
631
			entryCSN_set = set(value.split(','))
632
			entryCSN_set.add(entryCSN)
633
			value = ','.join(entryCSN_set)
634
		else:
635
			value = entryCSN
636
		self._set_config_option('UCS entryCSN', entryUUID, value)
637
638
	def _get_last_entryCSN_commited_by_connector(self, entryUUID):
639
		"""Remember the entryCSN of a change committed by the S4-Connector itself"""
640
		_d = ud.function('ldap._get_last_entryCSN_commited_by_connector')
641
		return self._get_config_option('UCS entryCSN', entryUUID)
642
643
	def _forget_entryCSN(self, entryUUID, entryCSN):
644
		_d = ud.function('ldap._forget_entryCSN')
645
		value = self._get_config_option('UCS entryCSN', entryUUID)
646
		if value:
647
			entryCSN_set = set(value.split(','))
648
			if entryCSN in entryCSN_set:
649
				entryCSN_set.remove(entryCSN)
650
				if entryCSN_set:
651
					value = ','.join(entryCSN_set)
652
					self._set_config_option('UCS entryCSN', entryUUID, value)
653
				else:
654
					self._remove_config_option('UCS entryCSN', entryUUID)
655
				return True
656
			else:
657
				return False
658
		else:
659
			return False
660
626
	def _get_dn_by_ucs(self, dn_ucs):
661
	def _get_dn_by_ucs(self, dn_ucs):
627
		_d = ud.function('ldap._get_dn_by_ucs')
662
		_d = ud.function('ldap._get_dn_by_ucs')
628
		return self._decode_dn_from_config_option(self._get_config_option('DN Mapping UCS', self._encode_dn_as_config_option(dn_ucs.lower())))
663
		return self._decode_dn_from_config_option(self._get_config_option('DN Mapping UCS', self._encode_dn_as_config_option(dn_ucs.lower())))
 Lines 766-771    Link Here 
766
					break
801
					break
767
802
768
			entryUUID = new.get('entryUUID', [None])[0]
803
			entryUUID = new.get('entryUUID', [None])[0]
804
			if key == 'msGPO':
805
				entryCSN = new.get('entryCSN', [None])[0]
806
				if self._forget_entryCSN(entryUUID, entryCSN):
807
					ud.debug(ud.LDAP, ud.PROCESS, "__sync_file_from_ucs: Object with entryUUID %s: Ignoring own change %s" % (entryUUID, entryCSN))
808
					return True
809
769
			if entryUUID:
810
			if entryUUID:
770
				if self.was_entryUUID_deleted(entryUUID):
811
				if self.was_entryUUID_deleted(entryUUID):
771
					if self._get_entryUUID(dn) == entryUUID:
812
					if self._get_entryUUID(dn) == entryUUID:
 Lines 1222-1228    Link Here 
1222
					else:
1263
					else:
1223
						ud.debug(ud.LDAP, ud.INFO, '__set_values: Skip: %s' % con_attribute)
1264
						ud.debug(ud.LDAP, ud.INFO, '__set_values: Skip: %s' % con_attribute)
1224
1265
1225
	def __modify_custom_attributes(self, property_type, object, ucs_object, module, position, modtype="modify"):
1266
	def __modify_custom_attributes(self, property_type, object, ucs_object, module, position, modtype="modify", postread_attrs=None):
1226
		if 'custom_attributes' in object:
1267
		if 'custom_attributes' in object:
1227
			ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: custom attributes found: %s' % object['custom_attributes'])
1268
			ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: custom attributes found: %s' % object['custom_attributes'])
1228
			modlist = object['custom_attributes']['modlist']
1269
			modlist = object['custom_attributes']['modlist']
 Lines 1245-1251    Link Here 
1245
					modlist.append(('objectClass', oc[0][1]['objectClass'], noc))
1286
					modlist.append(('objectClass', oc[0][1]['objectClass'], noc))
1246
1287
1247
			ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: modlist: %s' % modlist)
1288
			ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: modlist: %s' % modlist)
1248
			self.lo.modify(ucs_object.dn, modlist)
1289
			if postread_attrs:
1290
				resp = self.lo.modify(ucs_object.dn, modlist, postread_attrs=postread_attrs)
1291
				try:
1292
					resp_entry = resp[1]
1293
					entryUUID = resp_entry['entryUUID'][0]
1294
					entryCSN = resp_entry['entryCSN'][0]
1295
					self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN)
1296
				except (IndexError, KeyError):
1297
					pass
1298
			else:
1299
				self.lo.modify(ucs_object.dn, modlist)
1249
1300
1250
			return True
1301
			return True
1251
		else:
1302
		else:
 Lines 1264-1270    Link Here 
1264
		self.__set_values(property_type, object, ucs_object, modtype='add')
1315
		self.__set_values(property_type, object, ucs_object, modtype='add')
1265
		for function in self.property[property_type].ucs_create_functions:
1316
		for function in self.property[property_type].ucs_create_functions:
1266
			function(self, property_type, ucs_object)
1317
			function(self, property_type, ucs_object)
1267
		return ucs_object.create() and self.__modify_custom_attributes(property_type, object, ucs_object, module, position)
1318
		if property_type == 'msGPO':
1319
			res = ucs_object.create(postread_attrs=['entryCSN', 'entryUUID'])
1320
			if res:
1321
				entryUUID = ucs_object.oldattr['entryUUID'][0]
1322
				entryCSN = ucs_object.oldattr['entryCSN'][0]
1323
				self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN)
1324
				res = self.__modify_custom_attributes(property_type, object, ucs_object, module, position, postread_attrs=['entryCSN', 'entryUUID'])
1325
		else:
1326
			res = ucs_object.create()
1327
		return res
1268
1328
1269
	def modify_in_ucs(self, property_type, object, module, position):
1329
	def modify_in_ucs(self, property_type, object, module, position):
1270
		_d = ud.function('ldap.modify_in_ucs')
1330
		_d = ud.function('ldap.modify_in_ucs')
 Lines 1278-1284    Link Here 
1278
		ucs_object_dn = object[dntype]
1338
		ucs_object_dn = object[dntype]
1279
		ucs_object = univention.admin.objects.get(module, None, self.lo, dn=ucs_object_dn, position='')
1339
		ucs_object = univention.admin.objects.get(module, None, self.lo, dn=ucs_object_dn, position='')
1280
		self.__set_values(property_type, object, ucs_object)
1340
		self.__set_values(property_type, object, ucs_object)
1281
		return ucs_object.modify() and self.__modify_custom_attributes(property_type, object, ucs_object, module, position)
1341
		if property_type == 'msGPO':
1342
			res = ucs_object.modify(postread_attrs=['entryCSN', 'entryUUID'])
1343
			if res:
1344
				try:
1345
					entryUUID = ucs_object.oldattr['entryUUID'][0]
1346
					entryCSN = ucs_object.oldattr['entryCSN'][0]
1347
					self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN)
1348
				except (IndexError, KeyError):
1349
					pass
1350
				res = self.__modify_custom_attributes(property_type, object, ucs_object, module, position, postread_attrs=['entryCSN', 'entryUUID'])
1351
		else:
1352
			res = ucs_object.modify()
1353
		return res
1282
1354
1283
	def move_in_ucs(self, property_type, object, module, position):
1355
	def move_in_ucs(self, property_type, object, module, position):
1284
		_d = ud.function('ldap.move_in_ucs')
1356
		_d = ud.function('ldap.move_in_ucs')
 Lines 1363-1368    Link Here 
1363
			ucs_object.open()
1435
			ucs_object.open()
1364
			ucs_object.remove()
1436
			ucs_object.remove()
1365
			self.update_deleted_cache_after_removal(entryUUID, objectGUID)
1437
			self.update_deleted_cache_after_removal(entryUUID, objectGUID)
1438
			if property_type == 'msGPO':
1439
				self._forget_entryCSN(entryUUID)
1366
			return True
1440
			return True
1367
		except Exception, e:
1441
		except Exception, e:
1368
			ud.debug(ud.LDAP, ud.INFO, "delete object exception: %s" % e)
1442
			ud.debug(ud.LDAP, ud.INFO, "delete object exception: %s" % e)
(-)services/univention-s4-connector/modules/univention/s4connector/s4/ntsecurity_descriptor.py (-11 / +9 lines)
 Lines 36-42    Link Here 
36
import univention.debug2 as ud
36
import univention.debug2 as ud
37
from samba.dcerpc import security
37
from samba.dcerpc import security
38
from samba.ndr import ndr_pack, ndr_unpack
38
from samba.ndr import ndr_pack, ndr_unpack
39
from samba.dcerpc import misc
40
39
41
40
42
def encode_sddl_to_sd_in_ndr(domain_sid, ntsd_sddl):
41
def encode_sddl_to_sd_in_ndr(domain_sid, ntsd_sddl):
 Lines 88-94    Link Here 
88
		return
87
		return
89
88
90
	ucs_ntsd_sddl = object['attributes']['msNTSecurityDescriptor'][0]
89
	ucs_ntsd_sddl = object['attributes']['msNTSecurityDescriptor'][0]
91
	s4_attributes = s4connector.lo_s4.get(s4_dn, attr=['nTSecurityDescriptor', 'uSNChanged', 'objectGUID'])
90
	s4_attributes = s4connector.lo_s4.get(s4_dn, attr=['nTSecurityDescriptor'])
92
	ntsd_ndr = s4_attributes.get('nTSecurityDescriptor')
91
	ntsd_ndr = s4_attributes.get('nTSecurityDescriptor')
93
92
94
	if ntsd_ndr:
93
	if ntsd_ndr:
 Lines 98-111    Link Here 
98
			ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: nTSecurityDescriptors are equal')
97
			ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: nTSecurityDescriptors are equal')
99
			return
98
			return
100
99
101
		guid_blob = s4_attributes.get('objectGUID')[0]
102
		objectGUID = str(ndr_unpack(misc.GUID, guid_blob))
103
		old_s4_object = s4connector.s4cache.get_entry(objectGUID)
104
		if old_s4_object:
105
			if old_s4_object.get('uSNChanged')[0] != s4_attributes.get('uSNChanged')[0]:
106
				ud.debug(ud.LDAP, ud.PROCESS, "ntsd_to_s4: skipping, S4-Object changed: %s" % object['dn'])
107
				return
108
109
		ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: changing nTSecurityDescriptor from %s to %s' % (s4_ntsd_sddl, ucs_ntsd_sddl))
100
		ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: changing nTSecurityDescriptor from %s to %s' % (s4_ntsd_sddl, ucs_ntsd_sddl))
110
101
111
		ucs_ntsd_ndr = encode_sddl_to_sd_in_ndr(domain_sid, ucs_ntsd_sddl)
102
		ucs_ntsd_ndr = encode_sddl_to_sd_in_ndr(domain_sid, ucs_ntsd_sddl)
 Lines 153-156    Link Here 
153
		ml.append(('msNTSecurityDescriptor', ucs_ntsd_sddl, s4_ntsd_sddl))
144
		ml.append(('msNTSecurityDescriptor', ucs_ntsd_sddl, s4_ntsd_sddl))
154
	if ml:
145
	if ml:
155
		ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_ucs: modlist = %s' % ml)
146
		ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_ucs: modlist = %s' % ml)
156
		s4connector.lo.lo.modify(ucs_dn, ml)
147
		resp = s4connector.lo.lo.modify(ucs_dn, ml, postread_attrs=['entryCSN', 'entryUUID'])
148
		try:
149
			resp_entry = resp[1]
150
			entryUUID = resp_entry['entryUUID'][0]
151
			entryCSN = resp_entry['entryCSN'][0]
152
			s4connector._remember_entryCSN_commited_by_connector(entryUUID, entryCSN)
153
		except (IndexError, KeyError):
154
			pass

Return to bug 43628