Reputation: 2107
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();
}
Upvotes: 1
Views: 19048
Reputation: 1570
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
Upvotes: 7