Usually when searching a big LDAP repository, the result set is limited in size by the server to 20000 records (at least for MS Active Directory)
To handle it properly, we should use pagination and in in LDAP world it is done though request / response controls.
The client sends a page request control with the page size and some cookie for session, the on response it sends the next request with the cookie in the response
Here is an example of using pagination with LdapForNet library
byte[]? cookie = null;
while (true)
{
SearchRequest searchRequest = new(ldapSource.BaseDN,
$"(objectClass=user)", LdapSearchScope.LDAP_SCOPE_SUB, attributes);
searchRequest.Controls.Add(new PageResultRequestControl(1000) { Cookie = cookie });
searchRequest.Controls.Add(new SortRequestControl(new SortKey() { AttributeName = "sAMAccountName" }));
SearchResponse searchResponse = (SearchResponse)ldapConnection.SendRequest(searchRequest);
ldapEntries.AddRange(searchResponse.Entries.Select(e => e.ToLdapEntry()));
PageResultResponseControl? pageResultResponseControl =
searchResponse.Controls.OfType<PageResultResponseControl>().FirstOrDefault();
if (pageResultResponseControl != null)
{
cookie = pageResultResponseControl.Cookie;
if (cookie != null && cookie.Length != 0)
{
_logger.LogDebug("Collected entries : {ldapEntries}", ldapEntries.Count);
continue;
}
}
_logger.LogDebug("Collected entries: {ldapEntries}, proceeding...", ldapEntries.Count);
break;
}
The default .NET library does the pagination already for you:
PrincipalContext ctx = new (ContextType.Domain, $"[hostname]:389", username, password);
UserPrincipal userPrincipal = new(ctx);
PrincipalSearcher searcher = new(userPrincipal);
PrincipalSearchResult<Principal> result = searcher.FindAll();
Tags
LDAP