Find local groups that a domain user belongs to? - c#

I'm using the System.DirectoryServices.AccountManagement namespace to find domain users and their corresponding AD security groups. This works well.
I'm also using that namespace to query the local security groups on a remote server. I am able to find a security group and then list the users of that group no problem.
What I'm having issues with is displaying which LOCAL groups a DOMAIN user belongs to:
PrincipalContext localmachine = new PrincipalContext(ContextType.Machine, "ServerName");
PrincipalContext domain = new PrincipalContext(ContextType.Domain);
// find the user using the domain context (Works fine)
UserPrincipal user = UserPrincipal.FindByIdentity(domain, userName);
// if found - grab its groups
if (user != null)
{
// The get groups method is the only method that would accept a new context
PrincipalSearchResult<Principal> groups = user.GetGroups(localMachine);
// no groups are returned .... removed rest of code
}
I'm attempting to use the GetGroups method passing in the localMachine PrincipalContext but no groups are returned.
The users exists only in the Domain AD. There is not an entry for this user in the local users on the localMachine. The domain users are added to local security groups.
Any ideas? I'd like to be able to pull a list of all local groups this domain user belongs to and then see if a certain groups exists in that list. The only option that is working now is for me to search certain groups on the system and see if the domain user belongs to that group.

The following code will return the local groups that a domain user is member of:
PrincipalContext domain = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(domain, userName);
foreach (GroupPrincipal group in user.GetAuthorizationGroups())
{
if (group.Context.ConnectedServer == serverName)
Console.Out.WriteLine("{0}\\{1}", group.Context.Name, group.SamAccountName);
}

I know my answer is late, but this worked for me (after I tried all sorts of permutations):
private static IList<string> GetUserLocalGroups(string userAccountName, string computerName, string domainName)
{
List<string> groups = new List<string>();
// We have to deal with a local computer
DirectoryEntry root = new DirectoryEntry(String.Format("WinNT://{0},Computer", computerName), null, null, AuthenticationTypes.Secure);
foreach (DirectoryEntry groupDirectoryEntry in root.Children)
{
if (groupDirectoryEntry.SchemaClassName != "Group")
continue;
string groupName = groupDirectoryEntry.Name;
Console.WriteLine("Checking: {0}", groupName);
if (IsUserMemberOfGroup(groupDirectoryEntry, String.Format("WinNT://{0}/{1}", domainName, userAccountName)))
{
groups.Add(groupName);
}
}
return groups;
}
private static bool IsUserMemberOfGroup(DirectoryEntry group, string userPath)
{
return (bool)group.Invoke(
"IsMember",
new object[] { userPath }
);
}
The call is something like this:
GetUserLocalGroups("samaccountname", "computerName.yourdomain", "yourdomain");

Related

How to add a user from another domain to a local domain group?

Using C# I would like to add a user from one domain to a local domain. The domains have a two way trust. Currently I get the error
'No principal matching the specified parameters was found.' on the .Save() line.
I have the DN of the user (e.g 'CN=Adams, Sam,OU=Beer, DC=Drinkers,DC=local').
The groups is something like CN=Drunks, OU=Groups,DC=Bars,DC=local.
This works when it is the same domain, but when it is cross domains is when I get the error. The user account that I am using has admin rights locally and read rights in the other domain.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, m_AD_connection.Domain, m_AD_connection.Path, ContextOptions.Negotiate, m_AD_connection.UserName, m_AD_connection.Password))
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, GroupName);
if (group != null)
{
group.Members.Add(pc, IdentityType.DistinguishedName, DN);
group.Save();
return true;
}
else
return false;
}
Any suggestions on what I need to do?
Your issue is in this line:
group.Members.Add(pc, IdentityType.DistinguishedName, DN);
The context parameter should be the context required to look up the user, not the group. So you need to create a new PrincipalContext for the second domain and pass that to Add(). For example:
var drinkersPc = new PrincipalContext(ContextType.Domain, "drinkers.local");
group.Members.Add(drinkersPc, IdentityType.DistinguishedName, DN);

How do I create a custom Active Directory permission and group so that I can verify users against this?

I have looked at many search results but I am struggling to find a way to programmatically (using C#) create a custom permission and a custom group in Active Directory.
I have an application that will need to have about 50 individual permissions, such as: can encrypt data, can decrypt data, can export private key, can delete keypair, etc. These permissions will be assigned to a custom group. For instance, the group may be called: standard user, security manager, etc.
Users will be assigned one or more of these groups. I need all of this to be managed through Active Directory. The software that is being written is in C#. The users will be in Active Directory.
The software will check that the user has a particular permission when a function on the application is to be executed. If the user does not have permission then they will be required to enter an override. This override is simply a prompt for the credentials of another user who DOES have the relevant permissions.
I want to emphasise that this needs to be managed through Active Directory because the software is running on a domain and the permissions will be managed by the Domain Administrator.
As such, I believe the ASP.Net Roles functionality is not sufficient? In addition, I am not sure if Azure AD is the same as Windows AD.
I would very much appreciate any guidance as to which .NET assembly/namespace will provide the following capability:
Create permission
Create group
Assign permission to group
Assign user to group
Remove user from group
Remove permission from group
I need to to do this programatically because the software will have an installer and will be responsible for adding the application-specific custom permissions and groups during installation if they do not already exist.
It may be possible that I am approaching this wrong so I am open to suggestions otherwise. As long as I am able to perform the above then great!
Thank you!
As I understood,
Here you can try below code
Try once
1) Create Group
PrincipalContext principalContext =
new PrincipalContext(ContextType.Domain, LDAPDomain, LDAPContainer,
LDAPAdmin, LDAPPassword);
GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");
if (group == null)
{
GroupPrincipal groupPrincipal = new GroupPrincipal(principalContext);
groupPrincipal.Name = "groupName";
groupPrincipal.SamAccountName = "samAccountName";
groupPrincipal.UserPrincipalName = "userPrincipleName";
groupPrincipal.GroupScope = GroupScope.Global;
groupPrincipal.Description = "groupNameDescription";
groupPrincipal.DisplayName = "groupNameDisplayName";
groupPrincipal.Save();
}
2) Add User To Group
GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");
UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, "userName");
bool isUserAdded = false;
if (user != null & group != null)
{
if (user.IsMemberOf(group))
{
//Do Code
}
else
{
group.Members.Add(user);
group.Save();
isUserAdded = user.IsMemberOf(group);
}
}
if (isUserAdded)
{
//Do Code
}
3) Remove User From Group
GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");
UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, "userName");
bool isUserRemoved = false;
if (user != null & group != null)
{
if (user.IsMemberOf(group))
{
group.Members.Remove(user);
group.Save();
isUserRemoved = user.IsMemberOf(group);
}
else
{
//Do Code
}
}
if (!isUserRemoved)
{
//Do Code
}
4) Add or Remove AccessRule(Permission) to Group
From my side, I have no clear idea about what actually your logic or implementation,
But Here I tried to give a solution for adding or remving access rule to group
//DirectoryEntry for OU Level
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://OU=MYOU,DC=MYDC,DC=COM");
NTAccount account = new NTAccount("MYDC", "groupName");
ActiveDirectoryAccessRule ruleRead = new ActiveDirectoryAccessRule(
account,
ActiveDirectoryRights.ReadProperty,
AccessControlType.Allow,
ActiveDirectorySecurityInheritance.None);
ActiveDirectoryAccessRule ruleWrite = new ActiveDirectoryAccessRule(
account,
ActiveDirectoryRights.WriteProperty,
AccessControlType.Deny,
ActiveDirectorySecurityInheritance.None);
if (Permission == "User shall be able to export private key from an RSA keypair")
{
directoryEntry.ObjectSecurity.AddAccessRule(ruleRead);
directoryEntry.ObjectSecurity.AddAccessRule(ruleWrite);
directoryEntry.Options.SecurityMasks = SecurityMasks.Dacl;
directoryEntry.CommitChanges();
Console.WriteLine("Added Deny Access to Read & Write.");
}
if (Permission == "User is able to decrypt imported data")
{
directoryEntry.ObjectSecurity.RemoveAccessRule(ruleRead);
directoryEntry.ObjectSecurity.RemoveAccessRule(ruleWrite);
directoryEntry.Options.SecurityMasks = SecurityMasks.Dacl;
directoryEntry.CommitChanges();
Console.WriteLine("Removed Deny Access to Read & Write.");
}
directoryEntry.Close();
directoryEntry.Dispose();
Note: Please test all above code in your test environment first.
You're trying to use AD as both your AuthZ store and your AuthZ engine if I follow the question correctly. The former (using it as a data store) makes perfect sense, but, I don't think it's the right tool to evaluate access for your app.
What I would do is layer your groups in two levels:
Level 1 - permission groups (e.g. can encrypt, can decrypt, etc.)
Level 2 - roles - these are members of various permission groups, and in turn users are added to these groups to grant them the roles. They will inherit the permissions the roles have when their logon token is built by Windows.
Assuming your app uses Windows Authentication, the WindowsTokenRoleProvider (https://msdn.microsoft.com/en-us/library/system.web.security.windowstokenroleprovider(v=vs.110).aspx) will surface all of the group memberships up into your app and you can then check if someone is in a permission group and let them do something (or not)...

C# Console Application - Get Current User AD Groups

I'm writing a script to get a list of the current user's AD Groups and creates a .txt file to a Path.
I've had a look around and it seems like I should be using these references:
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
I'm also using this:
UserPrincipal user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain, "<Domain>"), IdentityType.SamAccountName, "<UserName>");
foreach (GroupPrincipal group in user.GetGroups())
{
Console.Out.WriteLine(group);
}
But this doesn't quite list all the groups that the user should be in.
Is there something I'm missing?
I use this block of code to get the user groups:
String domainName = #"<your domain>";
String username = domainName + #"\<your username>";
PrincipalContext thisDomain = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(thisDomain, username);
PrincipalSearchResult<Principal> userGroups = userPrincipal.GetAuthorizationGroups();
foreach (Principal principal in userGroups.OfType<GroupPrincipal>())
{
Debug.WriteLine(principal.Name);
}
As far as I can tell, it lists all the groups the user is a member of by comparison to what is held in Active Directory and looking at the user object in the MMC snap in

Active Directory - Get Manager account (from Distinguished Name)

I am trying to get the manager's account for a user account in active directory.
Here's the code I have..
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
DirectoryContext directoryContext = new DirectoryContext(DirectoryContextType.Domain, "MyDomain");
Domain domain = Domain.GetDomain(directoryContext);
// Find MY directory Entry
DirectorySearcher search = new DirectorySearcher(domain.GetDirectoryEntry())
{
Filter = String.Format("(SAMAccountName={0})", "<my user id>")
};
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("manager");
DirectoryEntry userAccount = search.FindOne()?.GetDirectoryEntry();
As you can see, there's a property called manager that is requested and comes back as
CN=Manager Name,OU=Employee,OU=United Kingdom, OU=CompantUsers, DC=MyDomain, DC=xxx,DC=zzzzz
The CN=Manager Name is the full name, not the LoginID/SAMAccountName (as used when I searched for MY AD entry ... so how can I now find the AD entry for my manager
Ahhh ... When you know the right question to ask then Google knows the answer ... I did not know that the CN..... string was known as a distinguishedName
if (userAccount.Properties["manager"].Value != null)
{
DirectorySearcher search2 = new DirectorySearcher(domain.GetDirectoryEntry())
{
Filter = string.Format("(distinguishedName={0})", userAccount.Properties["manager"].Value)
};
search2.PropertiesToLoad.Add("displayName");
search2.PropertiesToLoad.Add("mail");
search2.PropertiesToLoad.Add("manager");
DirectoryEntry mgrAcc = search2.FindOne()?.GetDirectoryEntry();
}

Can not retrieve Active Directory user in C#

I built a test Active Directory server in Window 2008 and I also run the DNS server on it. On my client machine which runs the C# application, I can authenticate the user against the Active directory server using the function below:
public static UserPrincipal GetUserPrincipal(string usrName,string pswd,string domainName)
{
UserPrincipal usr;
PrincipalContext ad;
// Enter Active Directory settings
ad = new PrincipalContext(ContextType.Domain, domainName,usrName,pswd);
//search user
usr = new UserPrincipal(ad);
usr.SamAccountName = usrName;
PrincipalSearcher search = new PrincipalSearcher(usr);
usr = (UserPrincipal)search.FindOne();
search.Dispose();
return usr;
}
In a separate logic I tried to retrieve a user back from the server using a user name. I used the functions below:
public static DirectoryEntry CreateDirectoryEntry()
{
// create AD connection
DirectoryEntry de = new DirectoryEntry("LDAP://CN=Users,DC=rootforest,DC=com","LDAP","password");
de.AuthenticationType = AuthenticationTypes.Secure;
return de;
}
public static ResultPropertyCollection GetUserProperty(string domainName, string usrName)
{
DirectoryEntry de = CreateDirectoryEntry();
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(SamAccountName=" + usrName + ")";
SearchResult results = deSearch.FindOne();
return null;
}
However, I got no response back from the LDAP server at all, not even an exception. Am I missing certain settings on LDAP server, any of you able to see a flaw in my code (pls don't mind the hard code values, I was testing with this code).
As part of my troubleshooting, I confirmed that I can ping to the rootforest.com from the client machine. I confirmed the user with property samaccountname "LDAP" exists. My path seems to be right because when I go onto the LDAP server and type :
dsquery user -name LDAP*
I got the following:
CN=LDAP L. LDAP,CN=Users,DC=rootforest,DC=com
Any help would be greatly appreciated, I've spent most of my day troubleshooting and researching this little bugger and I think it could be something small which I overlooked.
I don't understand why you're using the new PrincipalContext / UserPrincipal stuff in your first example, but fall back to the hard to use DirectoryEntry stuff in your second example.... doesn't really make sense... also: your second function GetUserProperty seems to return null always - typo or not??
Since you're on already using the System.DirectoryServices.AccountManagement (S.DS.AM) namespace - use it for your second task, too! Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
public static ????? GetUserProperty(string domainName, string usrName)
{
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, usrName);
if(user != null)
{
// return what you need to return from your user principal here
}
else
{
return null;
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD:
I think your code have a few problems:
Why do you return null in your GetUserProperty() function? You should return results instead.
The attribute you are using in your search filter is misspelled. Use sSAMAccountName instead. Furthermore extend your query to search only for user accounts. Here is an example: (&(objectCategory=person)(objectClass=user)(sAMAccountName=usrName))
You could also use the UserPrincipal class to search for an identity in Active Directory. The UserPrincipal class provides a static method called FindByIdentity() to search for a user identity.
Hope, this helps.

Categories