def _drs_fetch_pfm(server, samdb, creds, lp): """Fetch prefixMap using DRS interface""" binding_str = "ncacn_ip_tcp:%s[print,seal]" % server drs = drsuapi.drsuapi(binding_str, lp, creds) (drs_handle, supported_extensions) = drs_DsBind(drs) print "DRS Handle: %s" % drs_handle req8 = drsuapi.DsGetNCChangesRequest8() dest_dsa = misc.GUID("9c637462-5b8c-4467-aef2-bdb1f57bc4ef") replica_flags = 0 req8.destination_dsa_guid = dest_dsa req8.source_dsa_invocation_id = misc.GUID(samdb.get_invocation_id()) req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = unicode(samdb.get_schema_basedn()) req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = None req8.replica_flags = replica_flags req8.max_object_count = 0 req8.max_ndr_size = 402116 req8.extended_op = 0 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 (level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8) pfm = ctr.mapping_ctr # check for schemaInfo element pfm_it = pfm.mappings[-1] assert pfm_it.id_prefix == 0 assert pfm_it.oid.length == 21 s = '' for x in pfm_it.oid.binary_oid: s += chr(x) pfm_schi = ndr_unpack(drsblobs.schemaInfoBlob, s) assert pfm_schi.marker == 0xFF # remove schemaInfo element pfm.num_mappings -= 1 return (pfm, pfm_schi)
def DsAddEntry(ctx, rec): '''add a record via the DRSUAPI DsAddEntry call''' if ctx.drsuapi is None: ctx.drsuapi_connect() if ctx.tmp_samdb is None: ctx.create_tmp_samdb() id = drsuapi.DsReplicaObjectIdentifier() id.dn = rec['dn'] attrs = [] for a in rec: if a == 'dn': continue if not isinstance(rec[a], list): v = [rec[a]] else: v = rec[a] rattr = ctx.tmp_samdb.dsdb_DsReplicaAttribute(ctx.tmp_samdb, a, v) attrs.append(rattr) attribute_ctr = drsuapi.DsReplicaAttributeCtr() attribute_ctr.num_attributes = len(attrs) attribute_ctr.attributes = attrs object = drsuapi.DsReplicaObject() object.identifier = id object.attribute_ctr = attribute_ctr first_object = drsuapi.DsReplicaObjectListItem() first_object.object = object req2 = drsuapi.DsAddEntryRequest2() req2.first_object = first_object (level, ctr) = ctx.drsuapi.DsAddEntry(ctx.drsuapi_handle, 2, req2) if ctr.err_ver != 1: raise RuntimeError("expected err_ver 1, got %u" % ctr.err_ver) if ctr.err_data.status != (0, 'WERR_OK'): print("DsAddEntry failed with status %s info %s" % (ctr.err_data.status, ctr.err_data.info.extended_err)) raise RuntimeError("DsAddEntry failed")
def _getnc_req10(self, dest_dsa, invocation_id, nc_dn_str, exop, replica_flags=0, max_objects=0, partial_attribute_set=None, partial_attribute_set_ex=None, mapping_ctr=None, more_flags=0): req10 = drsuapi.DsGetNCChangesRequest10() req10.destination_dsa_guid = misc.GUID( dest_dsa) if dest_dsa else misc.GUID() req10.source_dsa_invocation_id = misc.GUID(invocation_id) req10.naming_context = drsuapi.DsReplicaObjectIdentifier() req10.naming_context.dn = str(nc_dn_str) req10.highwatermark = drsuapi.DsReplicaHighWaterMark() req10.highwatermark.tmp_highest_usn = 0 req10.highwatermark.reserved_usn = 0 req10.highwatermark.highest_usn = 0 req10.uptodateness_vector = None req10.replica_flags = replica_flags req10.max_object_count = max_objects req10.max_ndr_size = 402116 req10.extended_op = exop req10.fsmo_info = 0 req10.partial_attribute_set = partial_attribute_set req10.partial_attribute_set_ex = partial_attribute_set_ex if mapping_ctr: req10.mapping_ctr = mapping_ctr else: req10.mapping_ctr.num_mappings = 0 req10.mapping_ctr.mappings = None req10.more_flags = more_flags return req10
def _exop_req8(self, dest_dsa, invocation_id, nc_dn_str, exop): req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = misc.GUID(dest_dsa) req8.source_dsa_invocation_id = misc.GUID(invocation_id) req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = unicode(nc_dn_str) req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = None req8.replica_flags = 0 req8.max_object_count = 0 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 return req8
def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None): '''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 req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = None 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 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 = self.drs_get_rodc_partial_attribute_set( ) 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 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) if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark
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)
bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7 bind_info.info.supported_extensions |= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT (info, drs_handle) = drs_conn.DsBind(misc.GUID(drsuapi.DRSUAPI_DS_BIND_GUID), 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)
def get_password_from_ad(connector, user_dn, reconnect=False): _d = ud.function('ldap.ad.get_password_from_ad') # noqa: F841 ud.debug(ud.LDAP, ud.INFO, "get_password_from_ad: Read password from AD: %s" % user_dn) nt_hash = None if not connector.drs or reconnect: connector.open_drs_connection() req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = misc.GUID(connector.computer_guid) req8.source_dsa_invocation_id = misc.GUID(connector.computer_guid) req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = user_dn req8.replica_flags = 0 req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = drsuapi.DRSUAPI_EXOP_REPL_SECRET req8.fsmo_info = 0 while True: (level, ctr) = connector.drs.DsGetNCChanges(connector.drsuapi_handle, 8, req8) rid = None unicode_blob = None keys = [] if ctr.first_object is None: break for i in ctr.first_object.object.attribute_ctr.attributes: if str(i.attid) == "589970": # DRSUAPI_ATTID_objectSid if i.value_ctr.values: for j in i.value_ctr.values: sid = ndr_unpack(security.dom_sid, j.blob) _tmp, rid = sid.split() if str(i.attid) == "589914": # DRSUAPI_ATTID_unicodePwd if i.value_ctr.values: for j in i.value_ctr.values: unicode_blob = j.blob ud.debug( ud.LDAP, ud.INFO, "get_password_from_ad: Found unicodePwd blob") if i.attid == drsuapi.DRSUAPI_ATTID_supplementalCredentials and connector.baseConfig.is_true( '%s/ad/mapping/user/password/kerberos/enabled' % connector.CONFIGBASENAME, False): if i.value_ctr.values: for j in i.value_ctr.values: ud.debug( ud.LDAP, ud.INFO, "get_password_from_ad: Found supplementalCredentials blob" ) spl = decrypt_supplementalCredentials( connector, j.blob) keys = calculate_krb5keys(spl) if rid and unicode_blob: nt_hash = decrypt(connector.drs.user_session_key, unicode_blob, rid).upper() if ctr.more_data == 0: break ud.debug(ud.LDAP, ud.INFO, "get_password_from_ad: AD Hash: %s" % nt_hash) return nt_hash, keys
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)