async def set_objectacl_by_dn( self, object_dn, data, flags=SDFlagsRequest.DACL_SECURITY_INFORMATION | SDFlagsRequest.GROUP_SECURITY_INFORMATION | SDFlagsRequest.OWNER_SECURITY_INFORMATION): """ Updates the security descriptor of the LDAP object :param object_dn: The object's DN :type object_dn: str :param data: The actual data as bytearray to be updated in the Security Descriptor of the specified object :type data: bytes :param flags: Flags indicate the data type to be updated. :type flags: :class:`SDFlagsRequest` :return: A tuple of (True, None) on success or (False, Exception) on error. :rtype: tuple """ req_flags = SDFlagsRequestValue({'Flags': flags}) controls = [ Control({ 'controlType': b'1.2.840.113556.1.4.801', 'controlValue': req_flags.dump(), 'criticality': True, }) ] changes = {'nTSecurityDescriptor': [('replace', [data])]} return await self._con.modify(object_dn, changes, controls=controls)
async def pagedsearch(self, ldap_filter, attributes, controls=None): """ Performs a paged search on the AD, using the filter and attributes as a normal query does. Needs to connect to the server first! Parameters: ldap_filter (str): LDAP query filter attributes (list): Attributes list to recieve in the result controls (obj): Additional control dict Returns: generator """ logger.debug('Paged search, filter: %s attributes: %s' % (ldap_filter, ','.join(attributes))) if self._con.status != MSLDAPClientStatus.RUNNING: if self._con.status == MSLDAPClientStatus.ERROR: print('There was an error in the connection!') return elif self._con.status == MSLDAPClientStatus.ERROR: print('Theconnection is in stopped state!') return if self._tree is None: raise Exception('BIND first!') t = [] for x in attributes: t.append(x.encode()) attributes = t ldap_filter = query_syntax_converter(ldap_filter) t = [] if controls is not None: for control in controls: t.append( Control({ 'controlType': control[0].encode(), 'criticality': control[1], 'controlValue': control[2] })) controls = t async for entry, err in self._con.pagedsearch( self._tree.encode(), ldap_filter, attributes=attributes, paged_size=self.ldap_query_page_size, controls=controls): if err is not None: raise err if entry['objectName'] == '' and entry['attributes'] == '': #searchresref... continue #print('et %s ' % entry) yield entry
async def modify(self, dn, changes, controls=None): """ Performs the modify operation. :param dn: The DN of the object whose attributes are to be modified :type dn: str :param changes: Describes the changes to be made on the object. Must be a dictionary of the following format: {'attribute': [('change_type', [value])]} :type changes: dict :param controls: additional controls to be passed in the query :type controls: dict :return: A tuple of (True, None) on success or (False, Exception) on error. :rtype: (:class:`bool`, :class:`Exception`) """ if controls is None: controls = [] controls_conv = [] for control in controls: controls_conv.append(Control(control)) return await self._con.modify(dn, changes, controls=controls_conv)
async def pagedsearch(self, base, query, attributes, search_scope=2, size_limit=1000, typesOnly=False, derefAliases=0, timeLimit=None, controls=None): """ Paged search is the same as the search operation and uses it under the hood. Adds automatic control to read all results in a paged manner. :param base: base tree on which the search should be performed :type base: str :param query: filter query that defines what should be searched for :type query: str :param attributes: a list of attributes to be included in the response :type attributes: List[str] :param search_scope: Specifies the search operation's scope. Default: 2 (Subtree) :type search_scope: int :param types_only: indicates whether the entries returned should include attribute types only or both types and values. Default: False (both) :type types_only: bool :param size_limit: Size limit of result elements per query. Default: 1000 :type size_limit: int :param derefAliases: Specifies the behavior on how aliases are dereferenced. Default: 0 (never) :type derefAliases: int :param timeLimit: Maximum time the search should take. If time limit reached the server SHOULD return an error :type timeLimit: int :param controls: additional controls to be passed in the query :type controls: dict :return: Async generator which yields (`dict`, None) tuple on success or (None, `Exception`) on error :rtype: Iterator[(:class:`dict`, :class:`Exception`)] """ if self.status != MSLDAPClientStatus.RUNNING: yield None, Exception( 'Connection not running! Probably encountered an error') return try: cookie = b'' while True: ctrl_list_temp = [ Control({ 'controlType': b'1.2.840.113556.1.4.319', 'controlValue': SearchControlValue({ 'size': size_limit, 'cookie': cookie }).dump() }) ] if controls is not None: ctrl_list_temp.extend(controls) ctrs = Controls(ctrl_list_temp) async for res, err in self.search(base, query, attributes, search_scope=search_scope, size_limit=size_limit, types_only=typesOnly, derefAliases=derefAliases, timeLimit=timeLimit, controls=ctrs, return_done=True): if err is not None: yield (None, err) return if 'resultCode' in res['protocolOp']: for control in res['controls']: if control[ 'controlType'] == b'1.2.840.113556.1.4.319': try: cookie = SearchControlValue.load( control['controlValue'] ).native['cookie'] except Exception as e: raise e break else: raise Exception( 'SearchControl missing from server response!') else: yield (convert_result(res['protocolOp']), None) if cookie == b'': break except Exception as e: yield (None, e)
async def pagedsearch(self, query, attributes, controls=None): """ Performs a paged search on the AD, using the filter and attributes as a normal query does. !The LDAP connection MUST be active before invoking this function! :param query: LDAP query filter :type query: str :param attributes: List of requested attributes :type attributes: List[str] :param controls: additional controls to be passed in the query :type controls: dict :param level: Recursion level :type level: int :return: Async generator which yields (`dict`, None) tuple on success or (None, `Exception`) on error :rtype: Iterator[(:class:`dict`, :class:`Exception`)] """ logger.debug('Paged search, filter: %s attributes: %s' % (query, ','.join(attributes))) if self._con.status != MSLDAPClientStatus.RUNNING: if self._con.status == MSLDAPClientStatus.ERROR: print('There was an error in the connection!') return elif self._con.status == MSLDAPClientStatus.ERROR: print('Theconnection is in stopped state!') return if self._tree is None: raise Exception('BIND first!') t = [] for x in attributes: t.append(x.encode()) attributes = t t = [] if controls is not None: for control in controls: t.append( Control({ 'controlType': control[0].encode(), 'criticality': control[1], 'controlValue': control[2] })) controls = t async for entry, err in self._con.pagedsearch( self._tree, query, attributes=attributes, size_limit=self.ldap_query_page_size, controls=controls): if err is not None: yield None, err return if entry['objectName'] == '' and entry['attributes'] == '': #searchresref... continue #print('et %s ' % entry) yield entry, None
async def pagedsearch(self, base, filter, attributes, search_scope=2, paged_size=1000, typesOnly=False, derefAliases=0, timeLimit=None, controls=None): if self.status != MSLDAPClientStatus.RUNNING: yield None, Exception( 'Connection not running! Probably encountered an error') return try: cookie = b'' while True: ctrl_list_temp = [ Control({ 'controlType': b'1.2.840.113556.1.4.319', 'controlValue': SearchControlValue({ 'size': paged_size, 'cookie': cookie }).dump() }) ] if controls is not None: ctrl_list_temp.extend(controls) ctrs = Controls(ctrl_list_temp) async for res, err in self.search(base, filter, attributes, search_scope=search_scope, paged_size=paged_size, typesOnly=typesOnly, derefAliases=derefAliases, timeLimit=timeLimit, controls=ctrs, return_done=True): if err is not None: yield (None, err) return if 'resultCode' in res['protocolOp']: for control in res['controls']: if control[ 'controlType'] == b'1.2.840.113556.1.4.319': try: cookie = SearchControlValue.load( control['controlValue'] ).native['cookie'] except Exception as e: raise e break else: raise Exception( 'SearchControl missing from server response!') else: yield (convert_result(res['protocolOp']), None) if cookie == b'': break except Exception as e: yield (None, e)