def check_dn(self, obj, attrname, syntax_oid):
        error_count = 0
        for val in obj[attrname]:
            dsdb_dn = dsdb_Dn(self.samdb, val, syntax_oid)

            # all DNs should have a GUID component
            guid = dsdb_dn.dn.get_extended_component("GUID")
            if guid is None:
                error_count += 1
                self.err_incorrect_dn_GUID(obj.dn, attrname, val, dsdb_dn,
                    "missing GUID")
                continue

            guidstr = str(misc.GUID(guid))

            attrs = ['isDeleted']
            linkID = self.samdb_schema.get_linkId_from_lDAPDisplayName(attrname)
            reverse_link_name = self.samdb_schema.get_backlink_from_lDAPDisplayName(attrname)
            if reverse_link_name is not None:
                attrs.append(reverse_link_name)

            # check its the right GUID
            try:
                res = self.samdb.search(base="<GUID=%s>" % guidstr, scope=ldb.SCOPE_BASE,
                                        attrs=attrs, controls=["extended_dn:1:1", "show_recycled:1"])
            except ldb.LdbError, (enum, estr):
                error_count += 1
                self.err_incorrect_dn_GUID(obj.dn, attrname, val, dsdb_dn, "incorrect GUID")
                continue

            # now we have two cases - the source object might or might not be deleted
            is_deleted = 'isDeleted' in obj and obj['isDeleted'][0].upper() == 'TRUE'
            target_is_deleted = 'isDeleted' in res[0] and res[0]['isDeleted'][0].upper() == 'TRUE'

            # the target DN is not allowed to be deleted, unless the target DN is the
            # special Deleted Objects container
            if target_is_deleted and not is_deleted and not self.is_deleted_objects_dn(dsdb_dn):
                error_count += 1
                self.err_deleted_dn(obj.dn, attrname, val, dsdb_dn, res[0].dn)
                continue

            # check the DN matches in string form
            if res[0].dn.extended_str() != dsdb_dn.dn.extended_str():
                error_count += 1
                self.err_dn_target_mismatch(obj.dn, attrname, val, dsdb_dn,
                                            res[0].dn, "incorrect string version of DN")
                continue

            if is_deleted and not target_is_deleted and reverse_link_name is not None:
                revealed_dn = self.find_revealed_link(obj.dn, attrname, guid)
                rmd_flags = revealed_dn.dn.get_extended_component("RMD_FLAGS")
                if rmd_flags is not None and (int(rmd_flags) & 1) == 0:
                    # the RMD_FLAGS for this link should be 1, as the target is deleted
                    self.err_incorrect_rmd_flags(obj, attrname, revealed_dn)
                    continue

            # check the reverse_link is correct if there should be one
            if reverse_link_name is not None:
                match_count = 0
                if reverse_link_name in res[0]:
                    for v in res[0][reverse_link_name]:
                        if v == obj.dn.extended_str():
                            match_count += 1
                if match_count != 1:
                    error_count += 1
                    if linkID & 1:
                        self.err_orphaned_backlink(obj, attrname, val, reverse_link_name, dsdb_dn.dn)
                    else:
                        self.err_missing_backlink(obj, attrname, val, reverse_link_name, dsdb_dn.dn)
                    continue

        return error_count
check a DN attribute for correctness
dataset/ETHPy150Open byt3bl33d3r/pth-toolkit/lib/python2.7/site-packages/samba/dbchecker.py/dbcheck.check_dn