Thursday, May 3, 2018

Check group membership in c# recursively

Here is a way to check group membership recursively in c#. I'm sure there is a way to make this more compact and faster and I may do that as I develop it more, but it gets the job done. You need samAccountNames for the group and users and the domains they are in to call the function. It will create a List<string> of each member in each group recursively, most likely there will be duplicates. I do not have it filtering out duplicates upon adding them, but that's possible if someone wanted.

You should be able to paste this code into Visual Studio, add the reference for System.Directory services and fill in the group/user name and appropriate domains and go. Enjoy.




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.DirectoryServices; // add reference to this
using System.Collections;
namespace groupMembershipRecursive
{

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
List<string> groupMemberAccountsToParseThrough = new List<string>();
public bool doesGroupHaveUserInMemberProperties(string groupName, string userName, string groupDomain, string userDomain)
{
bool returnValue = false;
DirectoryEntry de = new DirectoryEntry("LDAP://" + groupDomain);
DirectorySearcher searcher = new DirectorySearcher(de);
searcher.Filter = string.Format("(SAMAccountName={0})", groupName);
SearchResult result = searcher.FindOne();
bool isInGroup = false;
if (result != null)
{
DirectoryEntry groupOrUser = result.GetDirectoryEntry();
PropertyValueCollection groupOrUserProperties = groupOrUser.Properties["member"];

IEnumerable rootMembers = null;
foreach (System.DirectoryServices.PropertyValueCollection prop in groupOrUser.Properties)
{
if (prop.PropertyName == "member")
{
rootMembers = prop.Value as IEnumerable;
}
}
foreach (string rootMember in rootMembers)
{
int index = rootMember.IndexOf(",DC=", StringComparison.OrdinalIgnoreCase);
string domain = rootMember.Remove(0, index);
domain = domain.ReplaceIgnoreCase(",DC=", ".");
string account = rootMember.Remove(index);
if (rootMember.IndexOf(",OU=", StringComparison.OrdinalIgnoreCase) > 0)
{
index = rootMember.IndexOf(",OU=", StringComparison.OrdinalIgnoreCase);
account = rootMember.Remove(index);
}
else
{
while (account.IndexOf(",CN=", StringComparison.OrdinalIgnoreCase) != -1)
{
index = account.IndexOf(",CN=", StringComparison.OrdinalIgnoreCase);
account = account.Remove(index);
}
}
if(account.Contains("CN=", StringComparison.OrdinalIgnoreCase))
{
account = account.ReplaceIgnoreCase("CN=", "");
}
if (account.Contains("\\", StringComparison.OrdinalIgnoreCase))
{
account = account.ReplaceIgnoreCase("\\", "");
}
if (domain.StartsWith("."))
{
domain = domain.Remove(0, 1);
}
doesSubGroupsHaveUserInMemberProperties(rootMember, userName, domain);
Console.Write(rootMember);
}
}
DirectoryEntry deUser = new DirectoryEntry("LDAP://" + userDomain);
DirectorySearcher searcherUser = new DirectorySearcher(deUser);
searcherUser.Filter = string.Format("(SAMAccountName={0})", userName);
SearchResult resultUser = searcherUser.FindOne();
foreach (string groupUser in groupMemberAccountsToParseThrough)
{
ResultPropertyValueCollection distinguishedName = resultUser.Properties["distinguishedname"];
string dn = distinguishedName[0].ToString();
if (groupUser == distinguishedName[0].ToString())
{
returnValue = true;
return returnValue;
}
}
return returnValue;
}
public bool doesSubGroupsHaveUserInMemberProperties(string groupName, string userName, string groupDomain)
{
DirectoryEntry de = new DirectoryEntry("LDAP://" + groupDomain);
DirectorySearcher searcher = new DirectorySearcher(de);
searcher.Filter = "(&(distinguishedName=" + groupName + "))";
SearchResult result = searcher.FindOne();
bool isInGroup = false;
if (result != null)
{
DirectoryEntry groupOrUser = result.GetDirectoryEntry();
IEnumerable members = groupOrUser.Properties["member"];
PropertyValueCollection memberCount = groupOrUser.Properties["member"];
if (memberCount.Count > 0)
{
foreach (string member in members)
{
DirectoryEntry adObjectType = new DirectoryEntry("LDAP://" + member);
var name = adObjectType.Properties["name"];
var objectClass = adObjectType.Properties["objectClass"];
if (adObjectType.Properties["objectClass"].Contains("group"))
{
int index = member.IndexOf(",DC=", StringComparison.OrdinalIgnoreCase);
string domain = member.Remove(0, index);
domain = domain.ReplaceIgnoreCase(",DC=", ".");

if (domain.StartsWith("."))
{
domain = domain.Remove(0, 1);
}
doesSubGroupsHaveUserInMemberProperties(member, userName, domain);
}
else
{
groupMemberAccountsToParseThrough.Add(member);
}
}
}
else
{
groupMemberAccountsToParseThrough.Add(groupName);
}
}
return isInGroup;
}
private void btnCheck_Click(object sender, EventArgs e)
{
// bool result = doesGroupHaveUserInMemberProperties("[groupSamAccountName", "[samAccountName]", "[fqdn]", "[fqdn]");
bool result = doesGroupHaveUserInMemberProperties("Admins", "user1", "sub.domain.com", "domain.com");
tbxResults.Text = result.ToString();
}
}
public static class extensions
{
public static string ReplaceIgnoreCase(this string source, string oldVale, string newVale)
{
if (source.IsNullOrEmpty() || oldVale.IsNullOrEmpty())
return source;
var stringBuilder = new StringBuilder();
string result = source;
int index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);
bool initialRun = true;
while (index >= 0)
{
string substr = result.Substring(0, index);
substr = substr + newVale;
result = result.Remove(0, index);
result = result.Remove(0, oldVale.Length);
stringBuilder.Append(substr);
index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);
}
if (result.Length > 0)
{
stringBuilder.Append(result);
}
return stringBuilder.ToString();
}
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
public static bool IsNot(this bool val)
{
return val == false;
}
public static bool Contains(this string source, string toCheck, StringComparison comp)
{
return source?.IndexOf(toCheck, comp) >= 0;
}
}
}