|
|
Duplicated Group Names
Last post 04-22-2008, 6:14 PM by dunnry. 9 replies.
-
-
04-17-2008, 1:18 AM |
-
IgorMax
-
-
-
Joined on 08-30-2007
-
-
Posts 38
-
-
|
Re: Duplicated Group Names
I noticed that in BOTH cases (#1 and #3) de.RefreshCache(new string[] { "tokenGroups" }) already has duplicated group names, but since we are filtering them with sAMAccountName in #1 case we do not see them, but if you simply iterate through the user.Properties["tokenGroups"] (#3) you can see duplicated group names.
Anybody noticed something like that ? Any help ? Thank You.
|
|
-
04-17-2008, 1:19 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 2,720
-
-
|
Re: Duplicated Group Names
tokenGroups has SIDs in it and should not contain duplicates. Which technique are you using to convert the groups into friendly names?
|
|
-
04-17-2008, 5:15 PM |
-
IgorMax
-
-
-
Joined on 08-30-2007
-
-
Posts 38
-
-
|
Re: Duplicated Group Names
I use the code from the book. What I noticed, that irc already has more SIDs than it is supposed to be, but SIDs itself are different. When I convert those SIDs to the group names it doubles group names except USERS group and DOMAIN USERS. So, If I have 12 groups I am gonna have USERS, DOMAIN USERS and 5 duplicates:
public static IdentityReferenceCollection ExpandTokenGroups(DirectoryEntry de) { de.RefreshCache(new string[] { "tokenGroups" }); IdentityReferenceCollection irc = new IdentityReferenceCollection(); foreach (byte[] sidBytes in de.Properties["tokenGroups"]) { irc.Add(new SecurityIdentifier(sidBytes, 0)); } return irc; }
IdentityReferenceCollection irc = ExpandTokenGroups(de).Translate(typeof(NTAccount)); int groups = 0; // Number of Records (Groups) foreach (NTAccount account in irc) { String strGroupName = account.ToString(); item = lstUserGroups.Items.Add(strGroupName); }
|
|
-
04-17-2008, 7:19 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 2,720
-
-
|
Re: Duplicated Group Names
Can you show some sample output of the SIDs and the matching names for each of the SIDs so we can see the duplicated names? This should not be possible, so an example would be very helpful.
|
|
-
04-18-2008, 11:34 AM |
-
IgorMax
-
-
-
Joined on 08-30-2007
-
-
Posts 38
-
-
|
Re: Duplicated Group Names
Sorry for the long post, if it would be possible to send images I could send screenshots of results. I tried 3 different methods:
1.--- Method #1 ---
public static PropertyValueCollection GetUserGroupsValueCollection(DirectoryEntry de) { PropertyValueCollection valcol = null; if (de.Properties.Contains("memberOf") == true) valcol = de.Properties["memberOf"]; return valcol; } private int GetUserGroups1(DirectoryEntry de) { ListViewItem item; PropertyValueCollection valcol = GetUserGroupsValueCollection(de); int groups = 0; // Number of Records (Groups) if (valcol != null) { for (int i = 0; i <= valcol.Count - 1; i++) { item = lstUserGroups.Items.Add(CreateGroupPath(valcol[i].ToString())); item.SubItems.Add(valcol[i].ToString()); groups++; } } return groups; }
Output: Value {Dimensions:[5]} object {object[]} [0] "CN=AC Building 12 Users,OU=Distribution Groups,OU=Groups,OU=AD Objects OUs,DC=acr,DC=ocgoventerprise,DC=com" [1] "CN=AC,OU=Security Groups,OU=Groups,OU=AD Objects OUs,DC=acr,DC=ocgoventerprise,DC=com" [2] "CN=Optical Image,OU=Security Groups,OU=Groups,OU=AD Objects OUs,DC=acr,DC=ocgoventerprise,DC=com" [3] "CN=JVProcessing,OU=Security Groups,OU=Groups,OU=AD Objects OUs,DC=acr,DC=ocgoventerprise,DC=com" [4] "CN=GenLedger,OU=Security Groups,OU=Groups,OU=AD Objects OUs,DC=acr,DC=ocgoventerprise,DC=com"
2. --- Method #2 ---
public static SearchResultCollection GetUserGorupsSearchResultCollection(DirectoryEntry de, string path) { SearchResultCollection src = null; de.RefreshCache(new string[] { "tokenGroups" }); int count = de.Properties["tokenGroups"].Count; if (count > 0) { StringBuilder sb = new StringBuilder(); sb.Append("(|"); foreach (byte[] sid in de.Properties["tokenGroups"]) { sb.AppendFormat("(objectSid={0})", BuildFilterOctetString(sid)); } sb.Append(")");
DirectoryEntry searchRoot = GetDirectoryEntry(path); using (searchRoot) { DirectorySearcher ds = new DirectorySearcher(searchRoot, sb.ToString()); ds.Sort = new SortOption("samAccountName", SortDirection.Ascending); src = ds.FindAll(); } } return src; } private int GetUserGroups2(DirectoryEntry de) { ListViewItem item; int groups = 0; using (SearchResultCollection src = GetUserGorupsSearchResultCollection(de, RootPath)) { if (src != null) { foreach (SearchResult sr in src) { if (sr.Properties.Contains("samAccountName")) { groups++;
item = lstUserGroups.Items.Add(sr.Properties["samAccountName"][0].ToString()); } } } } return groups; }
Output: from de.Properties["tokenGroups"]: Value {Dimensions:[10]} object {object[]} [0] {Dimensions:[28]} object {byte[]} [1] {Dimensions:[28]} object {byte[]} [2] {Dimensions:[28]} object {byte[]} [3] {Dimensions:[28]} object {byte[]} [4] {Dimensions:[16]} object {byte[]} [5] {Dimensions:[28]} object {byte[]} [6] {Dimensions:[28]} object {byte[]} [7] {Dimensions:[28]} object {byte[]} [8] {Dimensions:[28]} object {byte[]} [9] {Dimensions:[28]} object {byte[]}
After FindAll": AC Domain Users GenLedger JVProcessing Optical Image Users
3. --- Method #3 --- public static IdentityReferenceCollection ExpandTokenGroups(DirectoryEntry de) { de.RefreshCache(new string[] { "tokenGroups" }); IdentityReferenceCollection irc = new IdentityReferenceCollection(); foreach (byte[] sidBytes in de.Properties["tokenGroups"]) { irc.Add(new SecurityIdentifier(sidBytes, 0)); } return irc; } private int GetUserGroups3(DirectoryEntry de) { ListViewItem item; IdentityReferenceCollection irc = ExpandTokenGroups(de).Translate(typeof(NTAccount)); int groups = 0; // Number of Records (Groups) foreach (NTAccount account in irc) { String strGroupName = account.ToString(); item = lstUserGroups.Items.Add(strGroupName); groups++; } return groups; }
Output: after RefreshCache from de.Properties["tokenGroups"]:
Value {Dimensions:[10]} object {object[]}
[0] {Dimensions:[28]} object {byte[]}
[1] {Dimensions:[28]} object {byte[]}
[2] {Dimensions:[28]} object {byte[]}
[3] {Dimensions:[28]} object {byte[]}
[4] {Dimensions:[16]} object {byte[]}
[5] {Dimensions:[28]} object {byte[]}
[6] {Dimensions:[28]} object {byte[]}
[7] {Dimensions:[28]} object {byte[]}
[8] {Dimensions:[28]} object {byte[]}
[9] {Dimensions:[28]} object {byte[]}
irc: [0] {S-1-5-21-1060284298-117609710-682003330-1527} [1] {S-1-5-21-1060284298-117609710-682003330-1502} [2] {S-1-5-21-1060284298-117609710-682003330-1913} [3] {S-1-5-21-1060284298-117609710-682003330-1293} [4] {S-1-5-32-545} object [5] {S-1-5-21-19096952-383467857-3795854435-2625} [6] {S-1-5-21-19096952-383467857-3795854435-513} [7] {S-1-5-21-19096952-383467857-3795854435-2647} [8] {S-1-5-21-19096952-383467857-3795854435-2643} [9] {S-1-5-21-19096952-383467857-3795854435-2639}
After Translating NTAccount: ACR\GenLedger ACR\AC ACR\JVProcessing ACR\Optical Image BUILTIN\Users ACR\AC ACR\Domain Users ACR\Optical Image ACR\JVProcessing ACR\GenLedger
As You can see in Method #3 I see double names. May be I'm just missing something or do not understand something. And using method #1 I can see group 'AC Building 12 Users' which is not displayed using methods#2 and #3. Weired but that's what is happening.
Thank You.
|
|
-
04-18-2008, 1:05 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 2,720
-
-
|
Re: Duplicated Group Names
In the third example, it appears that you have different groups with the same friendly name. Note how the SID is different for the two different ACR\GenLedger groups? It would be useful to discover how that is possible. Normally it is not possible to have the same NetBIOS prefix (ACR in this case) used more than once in a forest or between trusted forests.
Perhaps your AD admins can explain this to you. It is also possible to look up the domain information for those SIDs based on the SID prefix.
I believe that the second and third outputs are correct though. The missing group is likely NOT a security group, so is not included in the token. You can check to see if the "Security enabled" bit is set on the group type.
|
|
-
04-18-2008, 1:52 PM |
-
IgorMax
-
-
-
Joined on 08-30-2007
-
-
Posts 38
-
-
|
Re: Duplicated Group Names
I tested this logic in 16 different domains and noticed that it does NOT return duplicates for every domain or every user or every group, just for some of them, I cannot find any consistency so far :(. And sometimes during translating group name into NTAccount I get exception "Unable to cast object of type 'System.Security.Principal.SecurityIdentifier' to type 'System.Security.Principal.NTAccount'."
Regarding missing group, you are right it is a Distribution, not a Security group.
I think I am going to use method #2 since this one returns all security groups without any problems so far :).
2 more questions: 1. How can I read domain information based on the SID prefix? 2. Is it possible to get Security and Distribution groups together, or I have to combine 2 methods to be able to do that ?
Thank You very much.
|
|
-
04-18-2008, 3:43 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 2,720
-
-
|
Re: Duplicated Group Names
If you want to use distribution groups for security purposes, then an approach that uses tokenGroups or a Windows token of any sort won't do what you want. Most of the time, people do NOT want to use distribution groups for security purposes, so this is not a problem.
To consider both security and distro groups equally, you are probably better off building an approach that uses memberOf and recursion to expand the user's group membership. That won't get you the primary group though, so if you want that, you'll need to get that through a different mechanism. It all depends on what you mean by a "group" for your purposes.
I'm not sure why you would be getting errors on the translation between SIDs and NTAccounts. Usually that indicates some sort of trust relationship problem or an RPC problem of some sort. It can be hard to diagnose.
To use the SID prefix to find info about the domain, you can create a new SID based on the prefix (just remove the last RID value at the end) and either use that in an LDAP query to find the domainDNS object with that SID or perhaps try the Translate method on that.
I can't remember for sure if you can use the GC to find the object via the <SID=xxxx> DN syntax, but that would be the easiest way if it does.
|
|
-
04-22-2008, 6:14 PM |
-
dunnry
-
-
-
Joined on 04-05-2006
-
Seattle, WA
-
Posts 661
-
-
|
Re: Duplicated Group Names
The error you see is oftentimes when the group membership is from another domain or the local context cannot resolve the SID using LsaLookupSid (IIRC). You can at least protect against that with simple modification: private int GetUserGroups3(DirectoryEntry de) { ListViewItem item; IdentityReferenceCollection irc = ExpandTokenGroups(de).Translate(typeof(NTAccount)); int groups = 0; // Number of Records (Groups) foreach (IdentityReference account in irc) { if (account is NTAccount) //protect here { String strGroupName = account.ToString(); item = lstUserGroups.Items.Add(strGroupName); groups++; } } return groups; }
Ryan Dunn Extemporaneous MumblingsThe .NET Developer's Guide to Directory Services Programming
|
|
|
|