comparing multiple IEnumerables for distinct and different records - c#

I am comparing the active directory groups of 3 or more users, and I will never know the number of users to compare before the program is run. What I am ultimately trying to do is to get a list of similar active directory groups between the users I am comparing and a list of the non-similar groups for the users. I also want to be able to tell what user is assigned to the non-similar groups which adds another issue in the comparison. Here is the code I have so far. Basically I foreach though this for every user but then I am stuck on not only how to compare them all, but how to store all of the IEnumerable objects before I have to compare them.
using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "Domain"))
{
using (PrincipalSearchResult<Principal> user = UserPrincipal.FindByIdentity(principalContext, userName))
{
return user.GetGroups();
}
}
Since I don't know the number of users, I don't how many Ienumerables I need to create to store the groups, much less compare them all.
Any help would be much appreciated. I have tried using a hashset, but I couldn't figure out how to retain the users properties along with the group assignments when I did this.

Related

C# - GroupPrincipal.Getmembers(true) not returning domain users, what is the alternative for this?

GroupPrincipal.Getmembers(true) returns all users from nested groups but not the domain users (which is the primary group). Is there anyway to fix this, so we can get all users including domain users.
I tried GroupPrincipal.Getmembers(false) but it did not bring in all the users, would be helpful to see the code for this.
I don't want to add domain users as a separate group as it will be hard coding and also the performance takes a hit.
Please give some suggestions on this, been searching for long
Thanks
here is the sample code
using (var context1 = new PrincipalContext(ContextType.Domain, ""))
{
using (var group = GroupPrincipal.FindByIdentity(context1,"groupname"))
{
if (group == null)
{
}
else
{
var users = group.GetMembers(true);
foreach (UserPrincipal user in users)
{
users.ToList().ForEach(sr => result.Add(sr.SamAccountName));
//user variable has the details about the user
}
}
}
}​
This is working as intended. Domain Users is not populated the same way as normal groups due to some legacy quirks of AD in the Windows 2000 days. Nesting Domain Users in a group really isn't a great idea considering the broad access it implicitly grants. But, if you want to find these members, you'll need to search for users by the primaryGroupID attribute. It should be set to 513 for Domain Users.

GetAuthorizationGroups() wrongly assumes I´m an domain administrator

I have a domain group name and have to check if a domain user is part of it recursively. After getting my users domain prinical I try to get through all authorization groups
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
UserPrincipal userPrin = UserPrincipal.FindByIdentity(ctx, userToCheck);
if (userPrin != null)
{
foreach (GroupPrincipal group in userPrin.GetAuthorizationGroups())
{
if (group.Name.Equals(groupName, System.StringComparison.OrdinalIgnoreCase))
{
if (group.Context.Name.StartsWith(domain, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
}
[I know, the startsWith might not be the best way but everything work like a a charm]
Only problem: I have two accounts that are both NOT part of the builtin administrators group of the domain. Both user principals are found and the groups are enumerated but:
For one user the result is FALSE when checking builtin administrators group
For one user the result is TRUE when checking builtin administrators group
I know that the group checked is indeed the correct domain object for both tries.
Why does it say the one account is in that group?
UPDATE
When searching via cmd (net user /domain) the group does NOT show up.
When running the code from another machine (same user is queries) the group does also not show up.
But if you query the current user that is logged in as an administrator this user is considered to be in the group
CN=Administratoren,CN=Builtin,DC=domain,DC=de
which is just wrong. He might be in the local group but definetly NOT in the domain administrators group.
The SID of the group is S-1-5-32-544 btw.
UPDATE2
Since PrincipalContext internally uses the DirectorySearcher I tried to have a solution with the directory searcher. It returns only the correct groups. (although I´m not sure right now if it has a function für recursive group search like Principle context has)
So either this is a bug or has something to do with the additional groups like dlatikay pointed out
This method searches all groups recursively and returns the groups in which the user is a member. The returned set may also include additional groups that system would consider the user a member of for authorization purposes.
The groups that are returned by this method may include groups from a different scope and store than the principal. For example, if the principal is an AD DS object that has a DN of "CN=SpecialGroups,DC=Fabrikam,DC=com, the returned set can contain groups that belong to the "CN=NormalGroups,DC=Fabrikam,DC=com.
But why does it return additional groups, I have to make sure the user really is privileged in the groups returned.

c# LDAP membership enumeration

here is my problem: I need to enumerate the members of certain groups in our Active Directory. The complication is that the DN of the objects that are in the 'membersOf' property of the groups do not contain the identifier I need. Specifically, the CN of the user object is useless to me, only a property of the user object (the userID) is useful.
So three approaches comes to mind:
I can first enumerate the group to get a list of DN's in the group, and then do a lookup on each user DN to find out their userID
I can enumerate every user in the AD, grabbing their userID & their membersOf collection, and then check afterwards if they have the right memberships.
I could grab a list of all users with their CN's and userID's, and then enumerate the groups to get the member CN's. Then I could join the lists on the original list to get my list of member userID's.
Some problems immediately appear - option 1) will generate an extremely large number of subqueries and congest network traffic (undesirable), and option 2) pulls a HUGE amount of data from AD (something like 30mb). Option 3) is middle of the road - but it still pulls quite a bit of data and has multiple queries. Is there another option for how to do this which does not have these problems?
I am doing this in c# using the System.DirectoryServices tools.
Thank you in advance for your time and consideration.
Maybe there's an option #4, too:
you could set up a DirectorySearcher which enumerates users
you could define memberOf=....... as one of your search criteria
you can define what attributes you need from the directory searcher very easily
If this works (and I'm under the impression I got this to work before - but it's been quite a while!) then you could do one, single fairly focused search and automatically get your information that you need.
Try something like this:
// define the "root" of your search (where to begin)
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=users,dc=yourcompany,dc=com");
DirectorySearcher searcher = new DirectorySearcher(searchRoot);
// set properties
searcher.SearchScope = SearchScope.Subtree;
// define search filter
searcher.Filter = "(&(objectCategory=Person)(memberof=CN=YourGroup,OU=Users,DC=YourDomain,DC=com))";
// define attributes to load
searcher.PropertiesToLoad.Add("userid");
... add more if needed .....
foreach(SearchResult entry in searcher.FindAll())
{
string userid = entry.Properties["userid"][0].ToString();
}

Using System.DirectoryServices.xxx is it possible to determine what AD Groups a user can manage?

I'm attempting to load a list of groups for a user and wanting to show if they have authority to edit group membership or not.
What in the Active Directory indicates that a user can edit the members of a group and how can i look this up using System.DirectoryServices in 3.5+
Im using the following to obtain the groups for a user
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, userName);
if ( user != null)
{
PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
foreach(Principal p in groups)
{
if ( p is GroupPrincipal)
...
}
}
Any help appreciated
This is very time consuming, due to the way that permissions are managed on objects. A similar question might be, "How do I list every folder on the domain that an account can write data to". The reason this is time consuming is because each object holds it's own Access Control List (ACL).
I'm fairly sure the only way to find out every group you can manage would be to check every group and see what the permissions are on that group, then compare your group membership to the permissions on the group.
In Active Directory, how do I determine type of ActiveDirectoryAccessRule? has some code which may prove helpful if this is the route you end up going.
A saner approach might be to use the "Delegate" field to delegate permissions to certain groups, this field could be easily queried using LDAP, or let the person pick any group and then check the group's permissions after it's been selected.

ActiveDirectory DirectorySearcher: Check if user is member of a group

I want to know if a given user is member of a group or not. Now, I don't know much about ActiveDirecory or Exchange servers, but in Outlook I can see that a user can be "memberOf" a group (and i can query those groups with DirectorySearcher.PropertiesToLoad.Add("memberof");), but there are also other groups that users are not actively members of, but that contain users. If you mail to those groups (or aliases) you reach all the users contained in it.
Basically, given a username (like DOMAIN\JDoe), how to check if it is contained in the group FUNNY_USERS in C#?
Use the System.DirectoryServices.AccountManagement namespace added in .Net 3.5 if it's available. Here's an example for group checking:
using(var pc = new PrincipalContext(ContextType.Domain))
using(var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "DOMAIN\JDoe"))
using(var group = GroupPrincipal.FindByIdentity(pc, "FUNNY_USERS"))
{
return user.IsMemberOf(group);
}
Get all members in a group:
http://snipplr.com/view/4646/get-members-of-an-active-directory-distribution-group/
Once you have the list just loop through the usernames once.
Or:
Function to return all the groups the user is a member of
The users you see in Outlook is probably distribution groups. There are distribution groups and security groups in Active Directory. It seems like you want to check for either/or.
See my post at this similar question for an example in C# using only ldap calls

Categories

Resources