def _paginate_scan_and_process(self, dn, filter, attributes, process_item, external_process, context): """ Retrieve every LDAP user and apply the 'process' on each entry Search is paginated to support more than 1000 entries :param process (function): the function to apply to each LDAP entry returned by the search :return: the list of the user names that have been processed """ cnx = self.get_ldap_connection() # Create the page control to work from page_control = SimplePagedResultsControl(True, size=1000, cookie='') result = [] pages = 0 processed_items=[] # Do searches until we run out of "pages" to get from # the LDAP server. while True: pages += 1 # Send search request try: response = cnx.search_ext(dn, ldap.SCOPE_ONELEVEL, filter, attrlist=attributes, serverctrls=[page_control]) except ldap.LDAPError as e: log.error('LDAP search failed: %s' % e) # Pull the results from the search request try: rtype, rdata, rmsgid, serverctrls = cnx.result3(response) except ldap.LDAPError as e: log.error('Could not pull LDAP results: %s' % e) # Each "rdata" is a tuple of the form (dn, attrs), where dn is # a string containing the DN (distinguished name) of the entry, # and attrs is a dictionary containing the attributes associated # with the entry. The keys of attrs are strings, and the associated # values are lists of strings. for item in rdata: processed_id = process_item(item, external_process, context) processed_items.append(processed_id) # Get cookie for next request result.extend(rdata) controls = [control for control in serverctrls if control.controlType == SimplePagedResultsControl.controlType] if not controls: print('The server ignores RFC 2696 control') break # Ok, we did find the page control, yank the cookie from it and # insert it into the control for our next search. If however there # is no cookie, we are done! page_control.cookie = controls[0].cookie if not controls[0].cookie: break return processed_items
def paged_search(self, base=None, scope=ldap.SCOPE_SUBTREE, page_size=1000, criticality=True, serverctrls=None, **search_args): cookie = '' criticality = criticality initial = True if serverctrls is None: serverctrls = [] else: serverctrls = list(serverctrls) if base is None: base = self._config(self.CFG_BASEDN) if base: page_control = SimplePagedResultsControl(criticality, page_size, cookie) while initial or page_control.cookie: initial = False try: msgid = self.search_ext( base, scope, serverctrls=(serverctrls + list([page_control])), **search_args) except ldap.LDAPError as error: raise error # (rtype, results, msgid, sent_serverctrls) (_, results, _, controls) = self.result3(msgid) for control in controls: if control.controlType == page_control.controlType: page_control.cookie = control.cookie yield results
def paged_search(self, base_dn, scope, search_filter, attr_list): if not self.conn: return None total_result = [] ctrl = SimplePagedResultsControl(True, size=LdapConn.PAGE_SIZE, cookie='') while True: try: result = self.conn.search_ext(base_dn, scope, search_filter, attr_list, serverctrls=[ctrl]) rtype, rdata, rmsgid, ctrls = self.conn.result3(result) except ldap.LDAPError as e: if type(e.message ) == dict and e.message['desc'] == 'No such object': pass else: logging.warning( 'Search failed for base dn(%s), filter(%s) ' 'on server %s error: %s' % (base_dn, search_filter, self.host, e.message)) return None total_result.extend(rdata) page_ctrls = [ c for c in ctrls if c.controlType == SimplePagedResultsControl.controlType ] if not page_ctrls or not page_ctrls[0].cookie: break ctrl.cookie = page_ctrls[0].cookie return total_result
def get_page(self, page_size, full_record): """ Method used to retrieve all the objects in the "page" using Simple Paged Results Manipulation and Server Side Sorting extensions https://tools.ietf.org/html/rfc2696 https://tools.ietf.org/html/rfc2891 :param full_record: flag identifying that we hav to extract the full set of fields :param page_size: size of page :return: generator """ fields = self.ldap_query_fields if full_record: fields = None # set ldap control extensions if not self.pg_ctrl: self.pg_ctrl = SimplePagedResultsControl(True, page_size, '') serverctrls = [self.pg_ctrl] if fields: # if we have defined set of fields, use the last one for the sorting serverctrls.append(SSSRequestControl(ordering_rules=[fields[-1]])) msgid = self.ldap_connection.search_ext(self.settings['base_dn'], ldap.SCOPE_SUBTREE, self.settings['filter'], fields, serverctrls=serverctrls) _, records, msgid, serverctrls = self.ldap_connection.result3(msgid) self.pg_ctrl.cookie = [ _ for _ in serverctrls if _.controlType == SimplePagedResultsControl.controlType ][0].cookie if not self.pg_ctrl.cookie: # disconnect, the page is the last one self.ldap_connection.unbind_s() return (self.clean_record(record[1]) for record in records if (record[0] and record[1]))
def main(**kwargs): ldapuri = kwargs["<ldapuri>"] basedn = kwargs["<basedn>"] debug = kwargs["--debug"] verbose = kwargs["--verbose"] output_file = kwargs["--output"] schema = kwargs["--schema"] binddn = kwargs["--binddn"] password = kwargs["--password"] askpass = kwargs["--askpass"] starttls = kwargs["--starttls"] cafile = kwargs["--cafile"] passfile = kwargs["--passfile"] trace_level = int(kwargs["--trace-level"]) timeout = int(kwargs["--timeout"]) if debug: print(f"askpass: {askpass}") if askpass: password = getpass("Bind password: "******"displayName": (None, "=", "*"), "title": (None, "=", "*"), } attrlist, filterstr = get_attrlist_filterstr(schema, filters) ldap_conn = ldap.initialize(ldapuri, trace_level=trace_level) set_options(ldap_conn, ldap_opts) if starttls: ldap_conn.start_tls_s() if binddn is not None and password is not None: try: ldap_conn.simple_bind_s(binddn, password) except ldap.LDAPError as e: sys.exit(ldap_errmsg(e)) serverctrls = [SimplePagedResultsControl(size=2147483647, cookie='')] try: result = ldap_conn.search_ext_s( basedn, ldap.SCOPE_SUBTREE, filterstr=filterstr, serverctrls=serverctrls, attrlist=attrlist, ) except ldap.LDAPError as e: sys.exit(ldap_errmsg(e)) if result is not None: with smart_open(output_file) as f: gen_orgchart(f, result_to_org(result), ORGCHART_TEMPLATE_STR)