1

I am using C# Core 2 using Active Directory as the authentication method with Novell - I have got the verify user based on password section working, authenticating them if the username and password are correct in AD.

I want to get the user group of the logged in user, to add further security, in the same way [Authorize(roles="*")]would.

The below code is what I have so far, I know the connection is correct, but I cannot get any results in the SearchResults, it always returns as a count of 0.

Where am I going wrong? Not had any previous Active Directory exposure.

Search function :

    int searchScope = LdapConnection.SCOPE_BASE;
    string searchFilter = "(CN = " + username + ")";
    string searchBase = "OU=Users,OU=TOD,OU=Departments,DC=domain,DC=com";
    // folder structure Users/TOD/Departments/List of people

    // reading members of dynamic group could take long so set timeout to 10 seconds
    LdapSearchConstraints constraints = new LdapSearchConstraints();
    constraints.TimeLimit = 10000;

    #region connection
    string host = "mydomain.com";
    string un = "mydomain\\" + username;
    int port = 389;
    int version = LdapConnection.Ldap_V3;

    var conn = new LdapConnection();

    conn.SecureSocketLayer = false;
    conn.Connect(host, port);
    conn.Bind(version, un, pass); //parsed in through function params
    #endregion

    LdapSearchResults searchResults = conn.Search(
        searchBase,
        searchScope,
        searchFilter,
        null, // no specified attributes
        false, // return attr and value
        constraints);
      // always returns a search with 0 count

UPDATED:

I am getting LDAP connection errors intermittently, and on other occasions the search is brought back as empty - I don't know if this is to do with waiting but it will immediately hit the break point I set at conn.Disconnect() rather than any break points in the while loop.

[TestMethod]
    public void SearchForUserDepartentTest()
    {
        var users = new Dictionary<string,string>();
        var count = 0;

        string searchFilter = "(objectclass=*)";
        string searchBase = "OU=Departments,DC=domain,DC=com"; //ou=users, ou=TOD

        // reading members of dynamic group could take long so set timeout to 10 seconds
        LdapSearchConstraints constraints = new LdapSearchConstraints();
        constraints.TimeLimit = 10000;

        #region connection
        string host = "domain.com";
        string un = "domain\\doatemp2";
        string pass = "****";
        int port = 389;
        int version = LdapConnection.Ldap_V3;

        var conn = new LdapConnection
        {
            SecureSocketLayer = false
        };
        conn.Connect(host, port);
        conn.Bind(version, un, pass);
        #endregion
        try
        {
            LdapSearchResults searchResults = conn.Search(
                searchBase,
                LdapConnection.SCOPE_ONE,
                searchFilter,
                null, // no specified attributes
                false, // return attr and value
                constraints);

            while (searchResults.hasMore())
            {
            // doesn't hit in here intermittently
                count++;
                var nextEntry = searchResults.next();

                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("NAME");

                if (attr == null)
                {
                    users.Add("Distinguished Name", nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else
                {
                    users.Add((nextEntry.getAttribute("SAMACCOUNTNAME") == null)? "NULL ACC Name " + count : nextEntry.getAttribute("SAMACCOUNTNAME").StringValue
                        ,(nextEntry.getAttribute("DISTINGUISHEDNAME") == null)? "NULL DN" + count : nextEntry.getAttribute("distinguishedName").StringValue);
                }                    
            }
        }
        catch (LdapException ldapEx)
        {
            ldapEx.ToString(); // ocassional time outs
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        conn.Disconnect(); // when run hits the break point here, missing out the anything in searchResults.hasMore()
    }

UPDATE 2:

Latest code.

[TestMethod]
public void SearchForUserDepartentTest()
{ 
    var users = new Dictionary<string,string>();
    var count = 0;

    string searchFilter = "(objectclass=*)";
    string searchBase = "OU=Departments,DC=domain,DC=com"; //ou=users, ou=TOD

    // reading members of dynamic group could take long so set timeout to 10 seconds
    LdapSearchConstraints constraints = new LdapSearchConstraints();
    constraints.TimeLimit = 30000;

    #region connection information
    string host = "domain";
    string un = "domain\\doatemp2";
    string pass = "";
    int port = 389;
    int version = LdapConnection.Ldap_V3;
    #endregion

    try
    {
        using (var conn = new LdapConnection { SecureSocketLayer = false })
        {
            conn.Connect(host, port);
            conn.Bind(version, un, pass);

            LdapSearchResults searchResults = conn.Search(
                searchBase,
                LdapConnection.SCOPE_SUB,
                searchFilter,
                null, // no specified attributes
                false, // return attr and value
                constraints);

            while (searchResults.hasMore())
            {
                count++;
                var nextEntry = searchResults.next();

                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("NAME");

                if (attr == null)
                {
                    users.Add("Distinguished Name", nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else
                {
                    users.Add((nextEntry.getAttribute("SAMACCOUNTNAME") == null) ? "NULL ACC Name " + count : nextEntry.getAttribute("SAMACCOUNTNAME").StringValue, 
                        (nextEntry.getAttribute("DISTINGUISHEDNAME") == null) ? "NULL DN" + count : nextEntry.getAttribute("distinguishedName").StringValue);
                }
            }
        }
    }
    catch (LdapException ldapEx)
    {
        ldapEx.ToString(); // ocassional time outs
    }
    catch (Exception ex)
    {
        ex.ToString();
    }

    var check = users;
}

UPDATE 3: Using Core console application in case testing environment was causing adverse effects. With below code getting a readout of LdapConnection timeout 85

public static void SearchForUserDepartent() { var users = new Dictionary(); var count = 0;

string searchFilter = "(objectclass=*)";//string.Empty;
string searchBase = "OU=Users,OU=TOD,OU=Departments,DC=domain,DC=com";

LdapSearchConstraints constraints = new LdapSearchConstraints
{
    TimeLimit = 15000
};

#region connection information
string host = "dm1.domain.com";
string un = "domain\\doatemp2";
string pass = "password";
int port = 389;
#endregion

try
{
    using (var conn = new LdapConnection { SecureSocketLayer = false })
    {
        conn.Connect(host, port);
        conn.Bind(un, pass);

        LdapSearchResults searchResults = conn.Search(
            searchBase,
            LdapConnection.SCOPE_SUB,
            searchFilter,
            null, // no specified attributes
            false, // return attr and value
            constraints);

        while (searchResults.hasMore())
        {
            count++;
            var nextEntry = searchResults.next(); // hits and then goes to timeout

            nextEntry.getAttributeSet();
            Console.WriteLine("Distinguished Name:" + nextEntry.getAttribute("distinguishedName").StringValue);
            Console.ReadKey();
        }
    }
}
catch (LdapException ldapEx)
{
    Console.WriteLine(ldapEx.ToString()); // ocassional time outs
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}
    foreach(var u in users)
    {
        Console.WriteLine("Key:" + u.Key.ToString() + " | Value:" + u.Value.ToString());
    }
Console.ReadKey();
}
3
  • Have you tried the sample code? github.com/dsbenghe/Novell.Directory.Ldap.NETStandard/blob/… Commented Oct 27, 2017 at 9:59
  • @Jaybird that is partly what I've been using but I get nothing back in the searchResults, I think I'm using the searchBase, searchFilter, and/or searchScope incorrectly. Commented Oct 30, 2017 at 11:21
  • @PurpleSmurph, I forgot to say. try to use CN=Users,DC=domain,DC=com or CN=Users,OU=TOD,OU=Departments,DC=domain,DC=com Commented Nov 3, 2017 at 16:42

1 Answer 1

7
+150

LdapSearchResults Count always 0, you should use .hasMore() to get value of your searching

Try somethink like this

                var users = new HashSet<string>();
//My domain have 4 DC's
            LdapSearchResults searchResults = conn.Search(
                "CN=Users,DC=z,DC=x,DC=c,DC=v",//You can use String.Empty for all domain search. This is example about users
                LdapConnection.SCOPE_SUB,//Use SUB
                "(mail=*@somemail.com)",// Example of filtering with *. You can use String.Empty to query without filtering
                null, // no specified attributes
                false // return attr and value
                );

            while (searchResults.hasMore())
            {
                var nextEntry = searchResults.next();
                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("mail");

                if (attr == null)
                {
                    users.Add(nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else {
                    users.Add(nextEntry.getAttribute("mail").StringValue);
                }

            }

for better querying use ActiveDirectory Users and computers. there are has attribute editor witch can provide all information about DC,CN,OU and attrs

Also more info at here and here

UPDATE: as official documentation says:

SCOPE_BASE:Used with search to specify that the scope of entrys to search is to search only the base obect.

SCOPE_ONE:Used with search to specify that the scope of entrys to search is to search only the immediate subordinates of the base obect.

SCOPE_SUB:Used with search to specify that the scope of entrys to search is to search the base object and all entries within its subtree.

SCOPE_SUB that means that you can use searchBase without full entry path or use string.Empty to full domain search

Sign up to request clarification or add additional context in comments.

7 Comments

Not exactly what I'm after but definitely the right path! Thanks. Will update your answer, can see attributes in the attr. I did have the hasMore() but everything always came NULL after, why SCOPE_SUB as that's the main thing I've changed in my function?
I'm also getting occasional LDAP timeout, or just skips past when no results come back - any idea?
Thank you for coming back to me. The update in my question is what I am using, showing the search that I am using, my function has been slightly altered now, as I've wrapped LdapConnection in a using.
@PurpleSmurph, Did you have AD Users and computers?
Yes, we log into all our machines using AD - if that's what you mean? I've updated the question with the function as is, always hits the LdapException
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.