I don't know if "nested" is the word for what I need, but here's the explanation:
I have a user, "John". "John" is member of the group "A". Group "B" has group "A" as a member.
So, transitively, "John" should also be member of the group "B".
When I retrieve the John's group, I only get "A", and not "B", doing it like this:
DirectorySearcher searcher = new DirectorySearcher();
DirectoryEntry rootEntry = new DirectoryEntry(_ldap, _loginName, _password, AuthenticationTypes.ReadonlyServer);
searcher.SearchRoot = rootEntry;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = "(&(sAMAccountName=" + filter.Split('\\')[1] + ")(objectClass=user))";
searcher.PropertiesToLoad.Add("memberOf");
searcher.PropertiesToLoad.Add("displayname");
SearchResult sr = searcher.FindOne();
How can I achieve this?
Thank you!
I ended up using the "tokenGroups" property of the user, which seems to return all the groups the user is in, even the ones in which he is member transitively.
here's my code:
DirectorySearcher searcher = new DirectorySearcher();
DirectoryEntry rootEntry = new DirectoryEntry(_ldap, _loginName, _password, AuthenticationTypes.ReadonlyServer);
searcher.SearchRoot = rootEntry;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = "(&(sAMAccountName=" + filter.Split('\\')[1] + ")(objectClass=user))";
searcher.PropertiesToLoad.Add("memberOf");
searcher.PropertiesToLoad.Add("displayname");
SearchResult sr = searcher.FindOne();
DirectoryEntry userDirectoryEntry = result.GetDirectoryEntry();
userDirectoryEntry.RefreshCache(new string[] { "tokenGroups" });
foreach (byte[] byteEntry in userDirectoryEntry.Properties["tokenGroups"])
{
if (CompareByteArrays(byteEntry, objectSid))
{
isMember = true;
break;
}
}
It's a mix of this and this link, where objectSid is the objectSID of the group which I find by name.
Thanks a lot for your help!
Related
I want to get all email addresses from Active Directory. Below, I tried this case but it didn't get all emails. I need all emails such as ObjectClass=group, ObjectClass=user etc...
I tried these,
deSearch.Filter = "(|(ObjectClass=user)(ObjectClass=group))";
deSearch.Filter = "(mail=*#abc.com)";
Full code:
DirectoryEntry de = new DirectoryEntry();
de.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(mail=*)";
SearchResultCollection results = deSearch.FindAll();
foreach (SearchResult sResultSet in results)
{
if (sResultSet.Properties["Mail"].Count > 0)
{
if (sResultSet.Properties.Contains("Mail")
{
mailPackage.Mail = sResultSet.Properties["Mail"][0].ToString();
}
mailList.Add(mailPackage);
}
}
return mailList;
I have a procedure that retrieves the user node out of AD:
public static void ConnectActiveDirectory()
{
List<string> lstGroups = new List<string>();
DirectoryEntry entry;
string user = "username";
string server = ConfigurationManager.AppSettings["ActiveDirectory.Server"];
entry = new DirectoryEntry(#"LDAP://" + server);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "sAMAccountName=" + user;
searcher.PropertiesToLoad.Add("MemberOf");
SearchResult result = searcher.FindOne();
}
The idea is to save all the groups in the list of strings without doing something like:
foreach (ResultPropertyValueCollection s in result.Properties.Values)
{
string groupname = null;
for (int i = 0; i < s.Count; i++)
{
dn = s[i].ToString();
equalsIndex = dn.IndexOf("=", 1);
commaIndex = dn.IndexOf(",", 1);
groupname = dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1);
lstGroups.Add(groupname);
}
}
Is there any method that I can use in 'DirectorySearcher' Class?
Also, is there any way to delete the first Hashtable? the adspath one from the SearchResult object.
Instead of parsing the distinguished name by yourself, you can use the DirectoryEntry object to ask AD for the display name. For example:
var directoryEntry = new DirectoryEntry(#"LDAP://address");
var directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = "samaccountname=user";
directorySearcher.PropertiesToLoad.Add("memberOf");
var result = directorySearcher.FindOne();
foreach (var i in result.Properties["memberOf"])
{
var group = new DirectoryEntry(#"LDAP://" + i);
Console.WriteLine(group.Properties["DisplayName"]);
}
We use the secretary property of Active Directory, which is a multivalued DN property. I want to efficiently find all the groups for which a given user is a listed secretary. What is the best way to perform this query in C#/.NET?
This code will return a list of sAMAccountNames of groups in context's OU that include distinguishedName as one of the secretaries listed:
var filter = "(&(objectClass=group)(secretary=" + distinguishedName + "))";
PrincipalContext context = new PrincipalContext(...); // place to search from
var up = new GroupPrincipal(context);
var list = new List<string>();
using (var searcher = new PrincipalSearcher(up))
{
var ds = searcher.GetUnderlyingSearcher() as DirectorySearcher;
// if you only want to search in a single OU (as defined by 'context')
ds.SearchScope = SearchScope.OneLevel;
ds.Filter = filter;
ds.PropertiesToLoad.Add("sAMAccountName");
var results = ds.FindAll();
foreach (SearchResult r in results)
{
var name = r.GetDirectoryEntry().Properties["sAMAccountName"].Value as string;
list.Add(name);
}
}
I need to get sAMAccountName by passing EmployeeId to the active directory.
Please help me.
I don't know what is the EmployeeId for you but here is how to access all the users and display some fields :
Domain domain = Domain.GetCurrentDomain();
var searchRoot = domain.GetDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("sAMAccountName");
search.PropertiesToLoad.Add("userPrincipalName");
search.PropertiesToLoad.Add("displayName");
SearchResultCollection results = search.FindAll();
if (results != null)
{
foreach(SearchResult result in results)
{
Console.WriteLine("{0} ({1}) sAMAccountName={2}",
result.Properties["displayName"].OfType<object>().FirstOrDefault(),
result.Properties["userPrincipalName"].OfType<object>().FirstOrDefault(),
result.Properties["sAMAccountName"].OfType<object>().FirstOrDefault());
}
}
To discover all the fields present on your schema you can use AdExplorer.
Try this (with many thanks to VirtualBlackFox)
string employeeId ="someEmployeeId";
Domain domain = Domain.GetCurrentDomain();
var searchRoot = domain.GetDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.PropertiesToLoad.Add("EmployeeID");
search.PropertiesToLoad.Add("sAMAccountName");
search.Filter = String.Format("(&(objectCategory=person)(EmployeeID={0}))", employeeId );
SearchResult searchResult =search.FindOne();
if (searchResult != null)
{
object o = searchResult.Properties["sAMAccountName"].OfType<object>().FirstOrDefault();
if (o != null)
{
string sAMAccountName= o.ToString();
}
}
I need all email address of a particular group. Please help me
string filter1 = string.Format("(&(objectClass=group)(cn={0}))", "groupname");
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = filter1;
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("member");
SearchResult res = searcher.FindOne();
ArrayList userNames = new ArrayList();
if (res != null)
{
for (int counter = 0; counter <res.Properties["member"].Count; counter++)
{
string user = (string)res.Properties["member"][counter];
userNames.Add(user);
}
}
I am getting uesr name and other details but not get email. Please tell me the way to find email address of each user directly.
You can try with this code - based on PrincipalContext class
var username = "username";
var domain = "domain";
var emailAddresses = new List<string>();
var principalContext = new PrincipalContext(ContextType.Domain, domain);
var userPrincipal = UserPrincipal.FindByIdentity(principalContext, username);
// Add the "mail" entry
emailAddresses.Add(userPrincipal.EmailAddress);
Link : http://msdn.microsoft.com/fr-fr/library/bb344891(v=vs.90).aspx