C# Distribution list attributes (active directory) - c#

Hi I'm trying to update my distribution lists menagers using LDAP
And I need to know what is the attribute of the "manager can update membership list" checkbox
I want only use c# NOT vbs or powershell
I can update the menageby but I prefer that you write it for the exmple..

The simple answer is there is no attribute for the "Manager can update membership list" checkbox, the check box is a security setting. When you check it the security of the group is modified to include the manager with the required permissions, unticking removes the managers rights under the security tab to modify the group.
You can use the ObjectSecurity to see if a SID has a unique ACL entry, in a standard environment this should be enough. This code should give you an idea of how to do it.
NTAccount acc = new NTAccount(managersam);
SecurityIdentifier sid = (SecurityIdentifier)acc.Translate(typeof(SecurityIdentifier));
ActiveDirectorySecurity sdc = YourGroupObject.ObjectSecurity;
AuthorizationRuleCollection arc= sdc.GetAccessRules(true, false, Type.GetType("System.Security.Principal.SecurityIdentifier"));
foreach (AuthorizationRule ar in arc) {
if (ar.IdentityReference== sid
{
managercanedit= true;
}
}

Related

Check active directory attribute permission (UnlockAccount, PasswordNeverExpires, ExpirePasswordNow, ....)

In my small tool, I give the service desk user the ability to reset user passwords from "Active Directory Users and Computer Console".
The user can also change some AD attributes.
Now I have a problem
Admin-User1 = can do everything
Admin-User2 = is not allowed to write the attribute "UserCannotChangePassword".
Here is an example how I do it:
PrincipalContext AdPrincipalContextUsers = new PrincipalContext(ContextType.Domain, "DC01", #"MyDom.local\Admin-User2", "PWD123");
string strDistinguishedName = "CN=Test-User1,OU=Users,OU=MYC,DC=MyDom,DC=local";
UserPrincipal objAdUser = UserPrincipal.FindByIdentity(AdPrincipalContextUsers, strDistinguishedName);
objAdUser.UserCannotChangePassword = (bool)ChkUserCannotChangePassword.IsChecked;
objAdUser.Save();
About "try, catch" I can intercept, but this is not a nice solution.
I would love to solve it like this: When the program starts I check if the Admin-UserX has permission on the attribute. The checkbox is then "checkbox.enable=true" else "checkbox.enable=false".
I found this one: How can I check if a user has write rights in Active Directory using C#?
The objAdUser Attribute:
UserCannotChangePassword
UnlockAccount
Enabled
PasswordNeverExpires
ExpirePasswordNow
are unfortunately not found under "allowedAttributesEffective".
Now my question:
How can I check the permission on the Active Directoy attribute.
Thanks for your help.
Greeting Brauschi

LDAP Path And Permissions To Query Local User Directory?

I am working on a web application, ASP.NET, C#. Users are required to log in using an account local to the machine the app is running on, which I'll call "cyclops" for this example. I want the app to be able to query the local directory of users and groups to determine what groups the user is in. The code looks something like this:
DirectoryEntry entry = new DirectoryEntry("WinNT://cyclops/Users", "SomeServiceAccount",
"SvcAcctP#$$word", AuthenticationTypes.Secure);
entry.RefreshCache();
// Etc.
My two problems are:
That's pretty clearly not the correct path to use, but my research
and experimentation hasn't found the right answer. This MSDN
article talks about local paths, but doesn't fill in the blanks.
Do I use "LDAP://cyclops/Users", "WinNT://localhost/Users",
"WinNT://cyclops/cn=Users"?
As you can see, I'm providing the
credentials of a local service account. That account needs
permission to access the local directory, but I have no idea where
to set those permissions. Is it a specific file somewhere? Does
the account need to be a member of a particular group?
My experimentation has produced many errors: "The group name could not be found.", "The provider does not support searching...", "The server is not operational.", "Unknown error (0x80005004)", etc.
Thank you for your time...
-JW
WinNT requires the following format
WinNT://<domain/server>/<object name>,<object class>
To get groups of a given user, use
using (DirectoryEntry user = new DirectoryEntry("WinNT://./UserAccount,user"))
{
foreach(object group in (IEnumerable)user.Invoke("Groups",null))
{
using(DirectoryEntry g = new DirectoryEntry(group))
{
Response.Write(g.Name);
}
}
}
where
UserAccount is a name of required user.
dot stands for current machine (you can replace it with cyclops or use Environment.MachineName)
user credentials ("SomeServiceAccount", "SvcAcctP#$$word") might be required, depends on setup
To get users in a particular group, use
using (DirectoryEntry entry = new DirectoryEntry("WinNT://./Users,group"))
{
foreach (object member in (IEnumerable)entry.Invoke("Members"))
{
using(DirectoryEntry m = new DirectoryEntry(member))
{
Response.Write(m.Name);
}
}
}
where
Users is a name of group

Active Directory Group Membership Checking in .Net 4.5

I have an ASP.Net MVC application using Windows Authentication, and I am checking group membership for security on controller actions.
Simple as it sounds, I've found no other Question that can resolve the problem I am experiencing.
First Attempt: [Authorize]
The classic method is to simply slap an Authorize data annotation attribute on the controller action and go to town:
[Authorize(Roles = #"domain\groupName1")]
No dice. I am prompted for credentials. Usually this means something is wrong with the Windows Authentication configuration but it's setup fine: (1) HttpContext.User is a WindowsPrincipal object, and (2) I confirmed another known group name works.
Second Attempt: IsInRole()
The next step taken was to go a more old fashioned route and use IPrincipal.IsInRole(), and again, one returns false, the other true.
var wp = (WindowsPrincipal)User;
// false
var inGroup1 = wp.IsInRole(#"domain\groupName1");
// true
var inGroup2 = wp.IsInRole(#"domain\groupName2");
Stumped... so I hit up my systems nerds and we double check everything. User is a group member? Yes. Group name is spelled correctly? Yes. The next step was to snag the SID.
Third Attempt: Search Identity's Group Collection
In my controller I check the WindowsIdentity and look through the group collection for the SID of the troublesome group:
var wi = (WindowsIdentity)wp.Identity;
var group = wi.Groups.SingleOrDefault(g => g.Value == "group1-sidValue");
The group variable is the SecurityIdentifier object. Because it is not null, we can be certain that this current user is a member of the group that both the [Authorize()] or IsInRole() attempts fail to confirm.
Fourth Attempt: DirectoryServices.AccountManagement
At this point, I'm going nuts and add reference to the AccountManagement APIs. I search the domain context for the GroupPrincipal by both name and SID:
var pc = new PrincipalContext(ContextType.Domain, "domain");
var gp1byName = GroupPrincipal.FindByIdentity(pc, "groupName1")
var gp1bySid = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, "group1-sidValue");
Both group principal variables are ripe with the same object, and I verified through a watch variable that the principal's Members collection contains a UserPrincipal object with the same SID as the current WindowsPrincipal on HttpContext.
Question:
What in the hell have I missed here? Why would both role checking methodologies fail when it is plain and clear through object exploration that the user is a valid member of this given group?
The fact that one group checks fine and the other does not seems the most strange part at this point.
Answer:
Essentially it's translation issues between WindowsIdentity and NTAccount (both of these System.Security.Principal) and lastly, the actual Active Directory entry.
When validating a WindowsIdentity against AD, if you want to use anything other than the Sam or the Sid, you will need to use System.DirectoryServices.AccountManagement.
Caveat: In .Net 4.5 the security principals include Claims but that's out of context.
Long Explanation:
In a Windows Authenticated web application, HttpContext.User is a WindowsPrincipal object wrapping an underlying WindowsIdentity.
WindowsIdentity has for most intents and purposes only two properties with which the authenticated user can be identified: Name and User.
These properties translate to two properties on the identity's corresponding AD account entry:
WindowsIdentity.Name = SamAccountName
WindowsIdentity.User = SID
The [Authorize] filter attribute ultimately calls IsInRole(string role) on the underlying principal... and the IsInRole() string overload instantiates an NTAccount with the role (the "SamAccountName" in an AD entry).
This explains the failure in #1 and #2 above.
To authorize the HttpContext.User against anything but his/her Sid or SamAccountName, you'll need DirectoryServices.AccountManagement or classic LDAP.
I have an ASP.Net MVC application using Windows Authentication, and I am checking group membership for security on controller actions. Simple as it sounds, I've found no other Question that can resolve the problem I am experiencing.
Took me a lot of time to find something
http://www.c-sharpcorner.com/uploadfile/scottlysle/test-for-user-group-membership-in-Asp-Net-C-Sharp/
My code to check if user belongs to an AD group :
foreach (System.Security.Principal.IdentityReference group in System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)
{
if (String.Equals(group.Translate(typeof(System.Security.Principal.NTAccount)).ToString(), #"your_domain_name\your_group_name", StringComparison.InvariantCultureIgnoreCase))
{
// the user belongs to a group
}
}
That is all I needed beside <authentication mode="Windows"/> in Web.config file

How to edit the registry keys of a specific user programatically?

I want to change a few settings of a Windows user that I created in my application. If I understand correctly, his "HKEY_CURRENT_USER" values will be under HKEY_USERS/<sid>/.... Is this correct? How can I get the sid of the user, if I know the user name and the domain?
Edit: How can I correctly edit the HKCU keys of that user, if I have the sid already?
I have a program that does exactly that. Here is the relevant part of the code:
NTAccount ntuser = new NTAccount(strUser);
SecurityIdentifier sID = (SecurityIdentifier) ntuser.Translate(typeof(SecurityIdentifier));
strSID = sID.ToString();
You will need to import two namespaces:
using System.DirectoryServices;
using System.Security.Principal;
Hope this helps.
Then use Registry.Users.SetValue with SID string\path to set the registry value.
This might not work as intended if you are editing a logged-off profile, especially a roaming profile.
There are two steps to this. First you must get the users sid. Second you must load the users registry hive. Other users hives are not loaded by default so you must load it explicitly.
The answer in Daniel White's comment is the best way to get the sid.
To load the user's registry hive, use the LoadUserProfile windows API via pinvoke. There is a complementary UnloadUserProfile to unload the hive when you are done with it.
You can use Query by example and search using PrincipalSearcher for appropriate UserPrincipal
// Since you know the domain and user
PrincipalContext context = new PrincipalContext(ContextType.Domain);
// Create the principal user object from the context
UserPrincipal usr = new UserPrincipal(context);
usr .GivenName = "Jim";
usr .Surname = "Daly";
// Create a PrincipalSearcher object.
PrincipalSearcher ps = new PrincipalSearcher(usr);
PrincipalSearchResult<Principal> results = ps.FindAll();
foreach (UserPrincipal user in results) {
if(user.DisplayName == userName) {
var usersSid = user.Sid.ToString();
}
}

ASP.NET Active Directory C# field specification

We've got an active directory here. provided the unique user id of the user, I need to access the organization->manager->name attribute related to that userid. Basically this will be used to send an approval form to the manager of the person submitting request.
Any idea how this could be done?
You can use the following code :
/* Retreiving object from SID
*/
string SidLDAPURLForm = "LDAP://WM2008R2ENT:389/<SID={0}>";
System.Security.Principal.SecurityIdentifier sidToFind = new System.Security.Principal.SecurityIdentifier("S-1-5-21-3115856885-816991240-3296679909-1106");
/*
System.Security.Principal.NTAccount user = new System.Security.Principal.NTAccount("SomeUsername");
System.Security.Principal.SecurityIdentifier sidToFind = user.Translate(System.Security.Principal.SecurityIdentifier)
*/
DirectoryEntry userEntry = new DirectoryEntry(string.Format(SidLDAPURLForm, sidToFind.Value));
string managerDn = userEntry.Properties["manager"].Value.ToString();
But you can also find in this post other ways to seach bind to Active-directory.
Since you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. 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:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// do something here....
}
// find the group in question
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "YourGroupNameHere");
// if found....
if (group != null)
{
// iterate over members
foreach (Principal p in group.GetMembers())
{
Console.WriteLine("{0}: {1}", p.StructuralObjectClass, p.DisplayName);
// do whatever you need to do to those members
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
I'm not 100% sure what you want to do in your concrete case... the UserPrincipal has an EmployeeId property - is that what you want to search for?
Use the System.DirectoryServices.DirectoryEntry class to read out the appropriate property of the user object. The constructor of DirectoryEntry requires that you have an LDAP path to the user. Getting the LDAP path can often be tricky though as IIS prefers handing over the SAM account name only. If you provide more details of what the user id you have looks like it is easier to point you in the right direction.
To do this the account which runs the ASP.NET application needs read access to the AD, which probably doesn't have by default. Changing the application pool to run under "NetworkService" is the easiest way if the web server belongs to the AD. The ASP.NET app will then use the MACHINE$ account of the server to access the AD.

Categories