Esempio n. 1
0
    def _get_replication(self, replica_flags,
                          drs_error=drsuapi.DRSUAPI_EXOP_ERR_NONE, drs=None, drs_handle=None,
                          highwatermark=None, uptodateness_vector=None,
                          more_flags=0, max_objects=133, exop=0,
                          dest_dsa=drsuapi.DRSUAPI_DS_BIND_GUID_W2K3,
                          source_dsa=None, invocation_id=None, nc_dn_str=None):
        """
        Builds a DsGetNCChanges request based on the information provided
        and returns the response received from the DC.
        """
        if source_dsa is None:
            source_dsa = self.test_ldb_dc.get_ntds_GUID()
        if invocation_id is None:
            invocation_id = self.test_ldb_dc.get_invocation_id()
        if nc_dn_str is None:
            nc_dn_str = self.test_ldb_dc.domain_dn()

        if highwatermark is None:
            if self.default_hwm is None:
                (highwatermark, _) = self._get_highest_hwm_utdv(self.test_ldb_dc)
            else:
                highwatermark = self.default_hwm

        if drs is None:
            drs = self.drs
        if drs_handle is None:
            drs_handle = self.drs_handle

        req10 = self._getnc_req10(dest_dsa=dest_dsa,
                                  invocation_id=invocation_id,
                                  nc_dn_str=nc_dn_str,
                                  exop=exop,
                                  max_objects=max_objects,
                                  replica_flags=replica_flags,
                                  more_flags=more_flags)
        req10.highwatermark = highwatermark
        if uptodateness_vector is not None:
            uptodateness_vector_v1 = drsuapi.DsReplicaCursorCtrEx()
            cursors = []
            for i in xrange(0, uptodateness_vector.count):
                c = uptodateness_vector.cursors[i]
                c1 = drsuapi.DsReplicaCursor()
                c1.source_dsa_invocation_id = c.source_dsa_invocation_id
                c1.highest_usn = c.highest_usn
                cursors.append(c1)
            uptodateness_vector_v1.count = len(cursors)
            uptodateness_vector_v1.cursors = cursors
            req10.uptodateness_vector = uptodateness_vector_v1
        (level, ctr) = drs.DsGetNCChanges(drs_handle, 10, req10)
        self._ctr6_debug(ctr)

        self.assertEqual(level, 6, "expected level 6 response!")
        self.assertEqual(ctr.source_dsa_guid, misc.GUID(source_dsa))
        self.assertEqual(ctr.source_dsa_invocation_id, misc.GUID(invocation_id))
        self.assertEqual(ctr.extended_ret, drs_error)

        return ctr
Esempio n. 2
0
    def _get_highest_hwm_utdv(self, ldb_conn):
        res = ldb_conn.search("", scope=ldb.SCOPE_BASE, attrs=["highestCommittedUSN"])
        hwm = drsuapi.DsReplicaHighWaterMark()
        hwm.tmp_highest_usn = long(res[0]["highestCommittedUSN"][0])
        hwm.reserved_usn = 0
        hwm.highest_usn = hwm.tmp_highest_usn

        utdv = drsuapi.DsReplicaCursorCtrEx()
        cursors = []
        c1 = drsuapi.DsReplicaCursor()
        c1.source_dsa_invocation_id = misc.GUID(ldb_conn.get_invocation_id())
        c1.highest_usn = hwm.highest_usn
        cursors.append(c1)
        utdv.count = len(cursors)
        utdv.cursors = cursors
        return (hwm, utdv)
Esempio n. 3
0
    def replicate(self,
                  dn,
                  source_dsa_invocation_id,
                  destination_dsa_guid,
                  schema=False,
                  exop=drsuapi.DRSUAPI_EXOP_NONE,
                  rodc=False,
                  replica_flags=None,
                  full_sync=True,
                  sync_forced=False):
        '''replicate a single DN'''

        # setup for a GetNCChanges call
        req8 = drsuapi.DsGetNCChangesRequest8()

        req8.destination_dsa_guid = destination_dsa_guid
        req8.source_dsa_invocation_id = source_dsa_invocation_id
        req8.naming_context = drsuapi.DsReplicaObjectIdentifier()
        req8.naming_context.dn = dn

        # Default to a full replication if we don't find an upToDatenessVector
        udv = None
        hwm = drsuapi.DsReplicaHighWaterMark()
        hwm.tmp_highest_usn = 0
        hwm.reserved_usn = 0
        hwm.highest_usn = 0

        if not full_sync:
            res = self.samdb.search(base=dn,
                                    scope=ldb.SCOPE_BASE,
                                    attrs=["repsFrom"])
            if "repsFrom" in res[0]:
                for reps_from_packed in res[0]["repsFrom"]:
                    reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob,
                                               reps_from_packed)
                    if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id:
                        hwm = reps_from_obj.ctr.highwatermark

            udv = drsuapi.DsReplicaCursorCtrEx()
            udv.version = 1
            udv.reserved1 = 0
            udv.reserved2 = 0

            cursors_v1 = []
            cursors_v2 = dsdb._dsdb_load_udv_v2(
                self.samdb, self.samdb.get_default_basedn())
            for cursor_v2 in cursors_v2:
                cursor_v1 = drsuapi.DsReplicaCursor()
                cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id
                cursor_v1.highest_usn = cursor_v2.highest_usn
                cursors_v1.append(cursor_v1)

            udv.cursors = cursors_v1
            udv.count = len(cursors_v1)

        req8.highwatermark = hwm
        req8.uptodateness_vector = udv

        if replica_flags is not None:
            req8.replica_flags = replica_flags
        elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
            req8.replica_flags = 0
        else:
            req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC
                                  | drsuapi.DRSUAPI_DRS_PER_SYNC
                                  | drsuapi.DRSUAPI_DRS_GET_ANC
                                  | drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
                                  drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP)
            if rodc:
                req8.replica_flags |= (
                    drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
            else:
                req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP

        if sync_forced:
            req8.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED

        req8.max_object_count = 402
        req8.max_ndr_size = 402116
        req8.extended_op = exop
        req8.fsmo_info = 0
        req8.partial_attribute_set = None
        req8.partial_attribute_set_ex = None
        req8.mapping_ctr.num_mappings = 0
        req8.mapping_ctr.mappings = None

        if not schema and rodc:
            req8.partial_attribute_set = drs_get_rodc_partial_attribute_set(
                self.samdb)

        if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8:
            req_level = 8
            req = req8
        else:
            req_level = 5
            req5 = drsuapi.DsGetNCChangesRequest5()
            for a in dir(req5):
                if a[0] != '_':
                    setattr(req5, a, getattr(req8, a))
            req = req5

        num_objects = 0
        num_links = 0
        while True:
            (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level,
                                                   req)
            if ctr.first_object is None and ctr.object_count != 0:
                raise RuntimeError(
                    "DsGetNCChanges: NULL first_object with object_count=%u" %
                    (ctr.object_count))
            self.net.replicate_chunk(self.replication_state,
                                     level,
                                     ctr,
                                     schema=schema,
                                     req_level=req_level,
                                     req=req)

            num_objects += ctr.object_count

            # Cope with servers that do not return level 6, so do not return any links
            try:
                num_links += ctr.linked_attributes_count
            except AttributeError:
                pass

            if ctr.more_data == 0:
                break
            req.highwatermark = ctr.new_highwatermark

        return (num_objects, num_links)
Esempio n. 4
0
                                   bind_info)

    null_guid = misc.GUID()

    naming_context = drsuapi.DsReplicaObjectIdentifier()
    naming_context.dn = dn
    highwatermark = store_hwm
    uptodateness_vector = None
    if store_utdv is not None:
        uptodateness_vector = drsuapi.DsReplicaCursorCtrEx()
        if store_utdv.version == 1:
            uptodateness_vector.cursors = store_utdv.cursors
        elif store_utdv.version == 2:
            cursors = []
            for i in range(0, store_utdv.ctr.count):
                cursor = drsuapi.DsReplicaCursor()
                cursor.source_dsa_invocation_id = store_utdv.ctr.cursors[
                    i].source_dsa_invocation_id
                cursor.highest_usn = store_utdv.ctr.cursors[i].highest_usn
                cursors.append(cursor)
            uptodateness_vector.cursors = cursors

    req8 = drsuapi.DsGetNCChangesRequest8()

    req8.destination_dsa_guid = null_guid
    req8.source_dsa_invocation_id = null_guid
    req8.naming_context = naming_context
    req8.highwatermark = highwatermark
    req8.uptodateness_vector = uptodateness_vector
    req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC
                          | drsuapi.DRSUAPI_DRS_PER_SYNC
Esempio n. 5
0
    def _check_replication(self,
                           expected_dns,
                           replica_flags,
                           expected_links=[],
                           drs_error=drsuapi.DRSUAPI_EXOP_ERR_NONE,
                           drs=None,
                           drs_handle=None,
                           highwatermark=None,
                           uptodateness_vector=None,
                           more_flags=0,
                           more_data=False,
                           dn_ordered=True,
                           links_ordered=True,
                           max_objects=133,
                           exop=0,
                           dest_dsa=drsuapi.DRSUAPI_DS_BIND_GUID_W2K3,
                           source_dsa=None,
                           invocation_id=None,
                           nc_dn_str=None,
                           nc_object_count=0,
                           nc_linked_attributes_count=0):
        """
        Makes sure that replication returns the specific error given.
        """
        if source_dsa is None:
            source_dsa = self.ldb_dc1.get_ntds_GUID()
        if invocation_id is None:
            invocation_id = self.ldb_dc1.get_invocation_id()
        if nc_dn_str is None:
            nc_dn_str = self.ldb_dc1.domain_dn()

        if highwatermark is None:
            if self.default_hwm is None:
                (highwatermark, _) = self._get_highest_hwm_utdv(self.ldb_dc1)
            else:
                highwatermark = self.default_hwm

        if drs is None:
            drs = self.drs
        if drs_handle is None:
            drs_handle = self.drs_handle

        req10 = self._getnc_req10(dest_dsa=dest_dsa,
                                  invocation_id=invocation_id,
                                  nc_dn_str=nc_dn_str,
                                  exop=exop,
                                  max_objects=max_objects,
                                  replica_flags=replica_flags)
        req10.highwatermark = highwatermark
        if uptodateness_vector is not None:
            uptodateness_vector_v1 = drsuapi.DsReplicaCursorCtrEx()
            cursors = []
            for i in xrange(0, uptodateness_vector.count):
                c = uptodateness_vector.cursors[i]
                c1 = drsuapi.DsReplicaCursor()
                c1.source_dsa_invocation_id = c.source_dsa_invocation_id
                c1.highest_usn = c.highest_usn
                cursors.append(c1)
            uptodateness_vector_v1.count = len(cursors)
            uptodateness_vector_v1.cursors = cursors
            req10.uptodateness_vector = uptodateness_vector_v1
        (level, ctr) = drs.DsGetNCChanges(drs_handle, 10, req10)

        self.assertEqual(level, 6, "expected level 6 response!")
        self.assertEqual(ctr.source_dsa_guid, misc.GUID(source_dsa))
        self.assertEqual(ctr.source_dsa_invocation_id,
                         misc.GUID(invocation_id))
        ctr6 = ctr
        self.assertEqual(ctr6.extended_ret, drs_error)
        self._check_ctr6(ctr6,
                         expected_dns,
                         expected_links,
                         nc_object_count=nc_object_count)
        return (ctr6.new_highwatermark, ctr6.uptodateness_vector)
Esempio n. 6
0
    def replicate(self,
                  dn,
                  source_dsa_invocation_id,
                  destination_dsa_guid,
                  schema=False,
                  exop=drsuapi.DRSUAPI_EXOP_NONE,
                  rodc=False,
                  replica_flags=None,
                  full_sync=True,
                  sync_forced=False,
                  more_flags=0):
        '''replicate a single DN'''

        # setup for a GetNCChanges call
        if self.supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10:
            req = drsuapi.DsGetNCChangesRequest10()
            req.more_flags = (more_flags | self.more_flags)
            req_level = 10
        else:
            req_level = 8
            req = drsuapi.DsGetNCChangesRequest8()

        req.destination_dsa_guid = destination_dsa_guid
        req.source_dsa_invocation_id = source_dsa_invocation_id
        req.naming_context = drsuapi.DsReplicaObjectIdentifier()
        req.naming_context.dn = dn

        # Default to a full replication if we don't find an upToDatenessVector
        udv = None
        hwm = drsuapi.DsReplicaHighWaterMark()
        hwm.tmp_highest_usn = 0
        hwm.reserved_usn = 0
        hwm.highest_usn = 0

        if not full_sync:
            res = self.samdb.search(base=dn,
                                    scope=ldb.SCOPE_BASE,
                                    attrs=["repsFrom"])
            if "repsFrom" in res[0]:
                for reps_from_packed in res[0]["repsFrom"]:
                    reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob,
                                               reps_from_packed)
                    if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id:
                        hwm = reps_from_obj.ctr.highwatermark

            udv = drsuapi.DsReplicaCursorCtrEx()
            udv.version = 1
            udv.reserved1 = 0
            udv.reserved2 = 0

            cursors_v1 = []
            cursors_v2 = dsdb._dsdb_load_udv_v2(
                self.samdb, self.samdb.get_default_basedn())
            for cursor_v2 in cursors_v2:
                cursor_v1 = drsuapi.DsReplicaCursor()
                cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id
                cursor_v1.highest_usn = cursor_v2.highest_usn
                cursors_v1.append(cursor_v1)

            udv.cursors = cursors_v1
            udv.count = len(cursors_v1)

        req.highwatermark = hwm
        req.uptodateness_vector = udv

        if replica_flags is not None:
            req.replica_flags = replica_flags
        elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
            req.replica_flags = 0
        else:
            req.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC
                                 | drsuapi.DRSUAPI_DRS_PER_SYNC
                                 | drsuapi.DRSUAPI_DRS_GET_ANC
                                 | drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
                                 drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP)
            if rodc:
                req.replica_flags |= (
                    drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
            else:
                req.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP

        if sync_forced:
            req.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED

        req.max_object_count = 402
        req.max_ndr_size = 402116
        req.extended_op = exop
        req.fsmo_info = 0
        req.partial_attribute_set = None
        req.partial_attribute_set_ex = None
        req.mapping_ctr.num_mappings = 0
        req.mapping_ctr.mappings = None

        if not schema and rodc:
            req.partial_attribute_set = drs_get_rodc_partial_attribute_set(
                self.samdb)

        if not self.supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8:
            req_level = 5
            req5 = drsuapi.DsGetNCChangesRequest5()
            for a in dir(req5):
                if a[0] != '_':
                    setattr(req5, a, getattr(req, a))
            req = req5

        num_objects = 0
        num_links = 0
        first_chunk = True

        while True:
            (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level,
                                                   req)
            if ctr.first_object is None and ctr.object_count != 0:
                raise RuntimeError(
                    "DsGetNCChanges: NULL first_object with object_count=%u" %
                    (ctr.object_count))

            try:
                self.process_chunk(level, ctr, schema, req_level, req,
                                   first_chunk)
            except WERRORError as e:
                # Check if retrying with the GET_TGT flag set might resolve this error
                if self._should_retry_with_get_tgt(e.args[0], req):

                    print("Missing target object - retrying with DRS_GET_TGT")
                    req.more_flags |= drsuapi.DRSUAPI_DRS_GET_TGT

                    # try sending the request again (this has the side-effect
                    # of causing the DC to restart the replication from scratch)
                    first_chunk = True
                    continue
                else:
                    raise e

            first_chunk = False
            num_objects += ctr.object_count

            # Cope with servers that do not return level 6, so do not return any links
            try:
                num_links += ctr.linked_attributes_count
            except AttributeError:
                pass

            if ctr.more_data == 0:
                break

            # update the request's HWM so we get the next chunk
            drs_copy_highwater_mark(req.highwatermark, ctr.new_highwatermark)

        return (num_objects, num_links)