Index: conffiles/etc/univention/s4connector/s4/mapping.py =================================================================== --- conffiles/etc/univention/s4connector/s4/mapping.py (Revision 57373) +++ conffiles/etc/univention/s4connector/s4/mapping.py (Arbeitskopie) @@ -59,6 +59,7 @@ 'CN=DomainUpdates,CN=System,@%@connector/s4/ldap/base@%@', 'CN=Password Settings Container,CN=System,@%@connector/s4/ldap/base@%@', 'DC=RootDNSServers,CN=MicrosoftDNS,CN=System,@%@connector/s4/ldap/base@%@', + 'DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones,@%@connector/s4/ldap/base@%@', 'CN=File Replication Service,CN=System,@%@connector/s4/ldap/base@%@', 'CN=RpcServices,CN=System,@%@connector/s4/ldap/base@%@', 'CN=Meetings,CN=System,@%@connector/s4/ldap/base@%@', @@ -599,42 +600,56 @@ }, ), +@!@ + +sync_mode_dns = configRegistry.get('connector/s4/mapping/dns/syncmode') +if not sync_mode_dns: + sync_mode_dns = configRegistry.get('connector/s4/mapping/syncmode') + +if configRegistry.get('connector/s4/mapping/dns/position') == 'legacy': + s4_dns_ldap_base = "CN=System,%s" % (configRegistry['connector/s4/ldap/base'],) +else: + s4_dns_ldap_base = "DC=DomainDnsZones,%s" % (configRegistry['connector/s4/ldap/base'],) + +dns_section = ''' 'dns': univention.s4connector.property ( - ucs_default_dn='cn=dns,@%@ldap/base@%@', - con_default_dn='CN=MicrosoftDNS,CN=System,@%@connector/s4/ldap/base@%@', + ucs_default_dn='cn=dns,%(ldap_base)s', + con_default_dn='CN=MicrosoftDNS,%(s4_dns_ldap_base)s', ucs_module='dns/dns', identify=univention.s4connector.s4.dns.identify, + sync_mode='%(sync_mode_dns)s', - @!@ -if configRegistry.get('connector/s4/mapping/dns/syncmode'): - print "sync_mode='%s'," % configRegistry.get('connector/s4/mapping/dns/syncmode') -else: - print "sync_mode='%s'," % configRegistry.get('connector/s4/mapping/syncmode') -@!@ - scope='sub', con_search_filter='(|(objectClass=dnsNode)(objectClass=dnsZone))', - position_mapping = [( ',cn=dns,@%@ldap/base@%@', ',CN=MicrosoftDNS,CN=System,@%@connector/s4/ldap/base@%@' )], + position_mapping = [( ',cn=dns,%(ldap_base)s', ',CN=MicrosoftDNS,%(s4_dns_ldap_base)s' )], +''' % { + 'ldap_base': configRegistry['ldap/base'], + 'sync_mode_dns': sync_mode_dns, + 's4_dns_ldap_base': s4_dns_ldap_base, + } -@!@ ignore_filter = '' for dns in configRegistry.get('connector/s4/mapping/dns/ignorelist', '').split(','): if dns: ignore_filter += '(%s)' % (dns) if ignore_filter: - print " ignore_filter='(|%s)'," % ignore_filter -@!@ + dns_section = dns_section + ''' + ignore_filter='(|%s)',''' % ignore_filter + dns_section = dns_section + ''' ignore_subtree = global_ignore_subtree, con_sync_function = univention.s4connector.s4.dns.ucs2con, ucs_sync_function = univention.s4connector.s4.dns.con2ucs, - ), -@!@ + ),''' + +print dns_section + + if configRegistry.is_true('connector/s4/mapping/gpo', True): ignore_filter = '' for gpo in configRegistry.get('connector/s4/mapping/gpo/ignorelist', '').split(','): Index: debian/univention-s4-connector.postinst =================================================================== --- debian/univention-s4-connector.postinst (Revision 57373) +++ debian/univention-s4-connector.postinst (Arbeitskopie) @@ -109,6 +109,10 @@ --filter "(objectClass=groupPolicyContainer)" fi + if [ "$1" = "configure" -a -n "$2" ] && dpkg --compare-versions "$2" lt 9.0.16-11; then + univention-config-registry set connector/s4/mapping/dns/position?'legacy' + fi + if [ "$skip_final_restart" != "true" ]; then /etc/init.d/univention-s4-connector restart fi Index: debian/univention-s4-connector.univention-config-registry-variables =================================================================== --- debian/univention-s4-connector.univention-config-registry-variables (Revision 57373) +++ debian/univention-s4-connector.univention-config-registry-variables (Arbeitskopie) @@ -267,3 +267,9 @@ Description[en]=Group policies are stored in Group Policy Objects (GPOs) in the directory /var/lib/samba/sysvol/ on all Samba 4 domain controllers. The GPOs and the corresponding access rights are referenced in Samba 4 LDAP. If this option is activated, the access rights of the GPO references are synchronised to the UCS LDAP along with the references. If the variable is unset, the references are not synchronised. Type=bool Categories=service-s4con + +[connector/s4/mapping/dns/position] +Description[de]=Diese Variable bestimmt die Basis-DN der DNS Objekte im Samba Verzeichnisdienst. Falls sie auf dem Wert 'legacy' steht, dann sucht der S4-Connector die DNS-Objekte unter CN=System statt unter DC=DomainDNSZones. Diese Variable sollte nur einmalig nach manueller Migration der DNS-Objekte angepasst werden, falls sie noch auf 'legacy' steht. +Description[en]=This variable determins the base DN of DNS objects in the Samba directory service. When set to 'legacy', the S4 Connector searches DNS objects below CN=System instead of below DC=DomainDNSZones. This variable should only be modified once after manual migration of the DNS objects, if it still has the value 'legacy'. +Type=str +Categories=service-s4con Index: modules/univention/s4connector/s4/__init__.py =================================================================== --- modules/univention/s4connector/s4/__init__.py (Revision 57373) +++ modules/univention/s4connector/s4/__init__.py (Arbeitskopie) @@ -38,7 +38,7 @@ import univention.s4connector import univention.debug2 as ud from ldap.controls import LDAPControl -from ldap.controls import SimplePagedResultsControl +from ldap.controls import SimplePagedResultsControl, LDAPControl from samba.dcerpc import security from samba.ndr import ndr_pack, ndr_unpack from samba.dcerpc import misc @@ -45,6 +45,11 @@ DECODE_IGNORELIST=['objectSid', 'objectGUID', 'repsFrom', 'replUpToDateVector', 'ipsecData', 'logonHours', 'userCertificate', 'dNSProperty', 'dnsRecord'] +LDAP_SERVER_SHOW_DELETED_OID = "1.2.840.113556.1.4.417" +LDB_CONTROL_DOMAIN_SCOPE_OID = "1.2.840.113556.1.4.1339" +LDB_CONTROL_RELAX_OID = "1.3.6.1.4.1.4203.666.5.12" +LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16' + # page results PAGE_SIZE = 1000 @@ -110,7 +115,6 @@ ud.debug(ud.LDAP, ud.INFO, 'add_primary_group_to_addlist: Set primary group to %s (rid) for %s' % (primary_group_rid, object.get('dn'))) addlist.append(('primaryGroupID', [primary_group_rid])) - LDB_CONTROL_RELAX_OID = '1.3.6.1.4.1.4203.666.5.12' serverctrls.append(LDAPControl(LDB_CONTROL_RELAX_OID,criticality=0)) def __is_groupType_local(groupType): @@ -126,7 +130,6 @@ ud.debug(ud.LDAP, ud.INFO, "groupType: %s" % groupType) if __is_groupType_local(groupType): - LDB_CONTROL_RELAX_OID = '1.3.6.1.4.1.4203.666.5.12' serverctrls.append(LDAPControl(LDB_CONTROL_RELAX_OID,criticality=0)) sambaSID = object.get('attributes', {}).get('sambaSID', [])[0] @@ -384,8 +387,7 @@ def old_user_dn_mapping(s4connector, given_object): object = copy.deepcopy(given_object) - # LDAP_SERVER_SHOW_DELETED_OID -> 1.2.840.113556.1.4.417 - ctrls = [LDAPControl('1.2.840.113556.1.4.417',criticality=1)] + ctrls = [LDAPControl(LDAP_SERVER_SHOW_DELETED_OID, criticality=1)] samaccountname = '' if object.has_key('sAMAccountName'): @@ -753,8 +755,7 @@ ud.debug(ud.LDAP, ud.INFO,"__init__: init add config section 'S4 GUID'") self.config.add_section('S4 GUID') try: - # LDAP_SERVER_SHOW_DELETED_OID -> 1.2.840.113556.1.4.417 - self.ctrl_show_deleted = LDAPControl('1.2.840.113556.1.4.417',criticality=1) + self.ctrl_show_deleted = LDAPControl(LDAP_SERVER_SHOW_DELETED_OID, criticality=1) res = self.lo_s4.lo.search_ext_s('',ldap.SCOPE_BASE, 'objectclass=*',[], serverctrls=[ self.ctrl_show_deleted ], timeout=-1, sizelimit=0) @@ -773,7 +774,6 @@ # objectSid modification for an Samba4 object is only possible with the "provision" control: if self.configRegistry.is_true('connector/s4/mapping/sid_to_s4', False): - LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16' self.serverctrls_for_add_and_modify.append(LDAPControl(LDB_CONTROL_PROVISION_OID,criticality=0) ) # Save a list of objects just created, this is needed to @@ -865,6 +865,12 @@ self.lo_s4.lo.set_option(ldap.OPT_REFERRALS,0) + if not self.configRegistry.get('connector/s4/mapping/dns/position') == 'legacy': + self.s4_ldap_partitions = (self.s4_ldap_base, "DC=DomainDNSZones,%s" % self.s4_ldap_base) + else: + self.s4_ldap_partitions = (self.s4_ldap_base,) + + # encode string to unicode def encode(self, string): try: @@ -1003,6 +1009,17 @@ return max(usnchanged,usncreated) + def __search_s4_partitions(self, scope=ldap.SCOPE_SUBTREE, filter='', attrlist= [], show_deleted=False): + ''' + search s4 across all partitions listed in self.s4_ldap_partitions + ''' + _d=ud.function('ldap.__search_s4_partitions') + res = [] + for base in self.s4_ldap_partitions: + res += self.__search_s4(base, scope, filter, attrlist, show_deleted) + + return res + def __search_s4(self, base=None, scope=ldap.SCOPE_SUBTREE, filter='', attrlist= [], show_deleted=False): ''' search s4 @@ -1012,12 +1029,13 @@ if not base: base=self.lo_s4.base - ctrls=[] - ctrls.append(SimplePagedResultsControl(True, PAGE_SIZE, '')) + ctrls=[ + LDAPControl(LDB_CONTROL_DOMAIN_SCOPE_OID, criticality=0), ## Don't show referrals + SimplePagedResultsControl(True, PAGE_SIZE, '')), + ] if show_deleted: - # LDAP_SERVER_SHOW_DELETED_OID -> 1.2.840.113556.1.4.417 - ctrls.append(LDAPControl('1.2.840.113556.1.4.417',criticality=1)) + ctrls.append(LDAPControl(LDAP_SERVER_SHOW_DELETED_OID, criticality=1)) ud.debug(ud.LDAP, ud.INFO, "Search S4 with filter: %s" % filter) msgid = self.lo_s4.lo.search_ext(base, scope, filter, attrlist, serverctrls=ctrls, timeout=-1, sizelimit=0) @@ -1046,7 +1064,6 @@ else: ud.debug(ud.LDAP, ud.WARN, "S4 ignores PAGE_RESULTS") break - return encode_s4_resultlist(res) @@ -1078,7 +1095,8 @@ if filter !='': usnFilter = '(&(%s)(%s))' % ( filter, usnFilter ) - return self.__search_s4( filter=usnFilter, show_deleted=show_deleted) + res = self.__search_s4_partitions(filter=usnFilter, show_deleted=show_deleted) + return sorted(res, key=lambda element: element[1][attribute][0]) # search fpr objects with uSNCreated and uSNChanged in the known range @@ -1132,9 +1150,10 @@ filter = '(&(%s)(|(uSNChanged=%s)(uSNCreated=%s)))' % (filter,changeUSN,changeUSN) else: filter = '(|(uSNChanged=%s)(uSNCreated=%s))' % (changeUSN,changeUSN) - return self.__search_s4(filter=filter, show_deleted=show_deleted) + return self.__search_s4_partitions(filter=usnFilter, show_deleted=show_deleted) + def __dn_from_deleted_object(self, object, GUID): ''' gets dn for deleted object (original dn before the object was moved into the deleted objects container)