walruz
walruz

Reputation: 1319

Read all users from AD using Novell.Directory.Ldap.NETStandard

I need to read all users from the AD. Here is code that I am using:

using Novell.Directory.Ldap;
using Novell.Directory.Ldap.Controls;
using System.Linq;

namespace LdapTestApp
{
    class Program
    {
        static void Main()
        {
            LdapConnection ldapConn = new LdapConnection();
            ldapConn.SecureSocketLayer = true;
            ldapConn.Connect(HOST, PORT);

            try
            {
                var cntRead = 0;
                int? cntTotal = null;
                var curPage = 0;

                ldapConn.Bind(USERNAME, PASSWORD);

                do
                {
                    var constraints = new LdapSearchConstraints();
                    constraints.SetControls(new LdapControl[]
                    {
                        new LdapSortControl(new LdapSortKey("sn"), true),
                        new LdapVirtualListControl("sn=*", 0, 10)
                    });

                    ILdapSearchResults searchResults = ldapConn.Search(
                        "OU=All Users,DC=homecredit,DC=ru",
                        LdapConnection.ScopeSub,
                        "(&(objectCategory=person)(objectClass=user))",
                        null,
                        false,
                        constraints
                    );

                    while (searchResults.HasMore() && ((cntTotal == null) || (cntRead < cntTotal)))
                    {
                        ++cntRead;

                        try
                        {
                            LdapEntry entry = searchResults.Next();
                        }
                        catch (LdapReferralException)
                        {
                            continue;
                        }
                    }

                    ++curPage;
                    cntTotal = GetTotalCount(searchResults as LdapSearchResults);
                } while ((cntTotal != null) && (cntRead < cntTotal));
            }
            finally
            {
                ldapConn.Disconnect();
            }
        }

        private static int? GetTotalCount(LdapSearchResults results)
        {
            if (results.ResponseControls != null)
            {
                var r = (from c in results.ResponseControls
                         let d = c as LdapVirtualListResponse
                         where (d != null)
                         select (LdapVirtualListResponse)c).SingleOrDefault();
                if (r != null)
                {
                    return r.ContentCount;
                }
            }

            return null;
        }
    }
}

I used this question Page LDAP query against AD in .NET Core using Novell LDAP as basis. Unfortunatelly I get this exception when I am trying to recieve the very first entry:

"Unavailable Critical Extension"
000020EF: SvcErr: DSID-03140594, problem 5010 (UNAVAIL_EXTENSION), data 0

What am I doing wrong?

Upvotes: 1

Views: 7009

Answers (3)

Dumitru
Dumitru

Reputation: 1

Starting with version 3.5 the library supports Simple Paged Results Control - and the usage is as simple as ldapConnection.SearchUsingSimplePaging(searchOptions, pageSize) or ldapConnection.SearchUsingSimplePaging(ldapEntryConverter, searchOptions, pageSize) - see Github repo for more details - https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard and more specifically use the tests as usage samples.

Upvotes: 0

walruz
walruz

Reputation: 1319

I had to use approach described here: https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard/issues/71#issuecomment-420917269

The solution is far from being perfect but at least I am able to move on.

Upvotes: 0

Max Xapi
Max Xapi

Reputation: 815

VLVs are browsing indexes and are not directly related to the possibility or not to browse large numbers of entries (see generic documentation). So even if this control would be activated on your AD, you wouldn't be able to retrieve more than 1000 elements this way :

So what you can do:

  • use a specific paged results control, but it seems that the Novell C# LDAP library does not have one
  • ask you the question: "is this pertinent to look for all the users in a single request?" (your request looks like a batch request: remember that a LDAP server is not designed for the same purposes than a classic database - that can easily return millions of entries - and that's why most of LDAP directories have default size limits around 1000).

The answer is no: review your design, be more specific in your LDAP search filter, your search base, etc.

The answer is yes:

  • you have a single AD server: ask your administrator to change the MaxPageSize value, but this setting is global and can lead to several side effects (ie. what happens if everybody start to request all the users all the time?)
  • you have several AD servers: you can configure one for specific "batch like" queries like the one you're trying to do (so large MaxPageSize, large timeouts etc.)

Upvotes: 1

Related Questions