Programatically adding users to IIS_Usrs in C# - c#

I want know how can i add service account users under IIS_USRS user group via some web interface. I need to provide it as some a part of my app.
Environment - IIS 6.0 +
Thanks
Amit Ranjan

You can use ADSI (Active Directory Service Interfaces) by adding a reference to "system.directoryservices.dll"
Then you can use a DirectoryEntry like this :
public static void AddUserToGroup(string userDistinguishedname, string groupDistinguishedName) {
DirectoryEntry group = new DirectoryEntry("LDAP://ldap.mydomain.com/" + groupDistinguishedName);
DirectoryEntry user = new DirectoryEntry("LDAP://ldap.mydomain.com/" + userDistinguishedname);
group.Username = "Administrator";
group.Password = "myAdminPassword";
using (group) //group is your DirectoryEntry for group
{
//member if your user DirectoryEntry
group.Invoke("Add", new string[] { user.Path });
}
}
Hope this help

Related

Windows Authentication issue in IIS using ASP.NET app in a multi-domain forest

I am trying to implement a web-based intranet project that uses Windows Authentication. The web server (Windows 2012 Server) is in Domain A, but I need to be able to access the site from computers in any domain within the forest. I am just testing this using computers in domains A and B.
In IIS 7.0, I have enabled Windows Authentication and disabled all others, including Anonymous Authentication. In web.config I have:
<authentication mode="Windows"></authentication>
<identity impersonate="true" />
<authorization>
<deny users="?" />
</authorization>
Authenticated users need to be in AD group "TestGroup"; I removed the <allow groups="TestGroup" /> in web.config for testing purposes; I also added a few labels on home page to display my user's ID, groups I belongs to, all members of "TestGroup" and whether I am a member of "TestGroup" or not, jut for debugging purposes.
I believe I have done everything correct so far. With web.config as is:
When I access from a PC in domain A, I am not prompted to log in (whihc is correct since I am already logged in to domain A), and all lebles show correct data.
When I access from a PC in domain B, I am asked to log in (correctly), user ID label shows my ID correctly but shows no groups for my user ID and no group members in "TestGroup".
If I remove the identity section in web.config:
When access from a PC in either domain A or domain B, User ID label shows "NT AUTHORITY/NETWORK SERVICE", nothing listed as groups I belong to (since I am now apparently "NT Authority"), but group members for "TestGroup" are listed correctly. Accessing from PC in domain B pops up login dialog box, correctly.
If I remove the authorization section and leave identity section in web.config:
I am not asked to login from PCs in either domain;
Accessing from PC in domain A shows everything correctly
Accessing from PC in domain B, shows user ID corrctly but no group membership and no users listed for "TestGroup" group.
It seems that in order to be able to show correct user ID, I need to have impersonate set to true; in order to require users to log in form a PC outside domain A I need to have authorization part, but both together don't seem to work from PCs outside domain A.
This is what I am using to get user ID, user group membership and group members:
WindowsIdentity wiUser = WindowsIdentity.GetCurrent();
string sID = wiUser.Name.ToUpper().Repl("DomainA\\", string.Empty);
string sGroupName = #"TestGroup";
List<string> lsGroups = Utils.GetUserADGroups(sID);
bool bTC = lsGroups.Contains(sGroupName);
StringCollection scGroupMembers = Utils.GetGroupMembers(Utils.DomainType., sGroupName);
static string adDomain = "USA.ABC.DEF.COM";
static string adContainer = "DC=USA,DC=abc,DC=def,DC=com";
static string adADPath = "LDAP://USA.abc.def.com";
public static List<string> GetUserADGroups(string UserName)
{
List<string> lsGroups = new List<string>();
try
{
PrincipalContext pc = new PrincipalContext(ContextType.Domain, adDomain, adContainer);
UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, UserName);
PrincipalSearchResult<Principal> psr = up.GetGroups(pc);
foreach (Principal p in psr)
{
lsGroups.Add(p.Name);
}
}
catch (Exception)
{
}
return lsGroups;
}
public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
DirectoryEntry de = new DirectoryEntry(adDSADPath);
System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();
try
{
//DirectoryEntry DirectoryRoot = new DirectoryEntry(sADPath);
DirectorySearcher DirectorySearch = new DirectorySearcher(de, ("(CN=" + (strGroup + ")")));
SearchResultCollection DirectorySearchCollection = DirectorySearch.FindAll();
foreach (SearchResult DirectorySearchResult in DirectorySearchCollection)
{
ResultPropertyCollection ResultPropertyCollection = DirectorySearchResult.Properties;
foreach (string GroupMemberDN in ResultPropertyCollection["member"])
{
DirectoryEntry DirectoryMember = new DirectoryEntry(("LDAP://" + GroupMemberDN));
System.DirectoryServices.PropertyCollection DirectoryMemberProperties = DirectoryMember.Properties;
object DirectoryItem = DirectoryMemberProperties["sAMAccountName"].Value;
if (null != DirectoryItem)
{
GroupMembers.Add(DirectoryItem.ToString());
}
}
}
}
catch (Exception ex)
{
}
return GroupMembers;
}
I also tried to use this to see if user is a member of the group but it throws error if I access the site from PC in domain B:
public static bool IsMember(string UserName, string GroupName)
{
try
{
PrincipalContext pc = new PrincipalContext(ContextType.Domain, adDomain, adContainer);
UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, UserName);
PrincipalSearchResult<Principal> psr = up.GetGroups(pc);
foreach (Principal result in psr)
{
if (string.Compare(result.Name, GroupName, true) == 0)
return true;
}
return false;
}
catch (Exception e)
{
throw e;
}
}
What ended up solving my problem was wrapping the functionality in the methods in:
using (System.Web.Hosting.HostingEnvironment.Impersonate())
{
}
For example, I change the method in my original post from:
public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
DirectoryEntry de = new DirectoryEntry(adDSADPath);
System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();
...
}
to:
public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
using (System.Web.Hosting.HostingEnvironment.Impersonate())
{
DirectoryEntry de = new DirectoryEntry(adDSADPath);
System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();
...
}
}
Hope this saves someone else some grief as it caused me a lot!

get windows users with group name using C# [duplicate]

I have a ASP.NET Website project and I need to list all the users and their groups on my Windows system. I have set the identity impersonation to true and provided the username and password of the admin in the web.config. Where do I start?
Thanks in advance.
Update:
I have the following code at the moment -
var machine = new DirectoryEntry("WinNT://<IP ADDRESS>");
foreach (DirectoryEntry child in machine.Children)
{
// get the child's group(s).
}
When I debug, I can see the list of users in machine.Children. How do I find the group(s) that this user belongs to?
This article covers how to talk to Active Directory and should get you where you want to go:
http://www.codeproject.com/KB/system/everythingInAD.aspx
To get users, you would do something like this:
public List<string> GetUserList()
{
string DomainName="";
string ADUsername="";
string ADPassword="";
List<string> list=new List<string>();
DirectoryEntry entry=new DirectoryEntry(LDAPConnectionString, ADUsername, ADPassword);
DirectorySearcher dSearch=new DirectorySearcher(entry);
dSearch.Filter="(&(objectClass=user))";
foreach(SearchResult sResultSet in dSearch.FindAll())
{
string str=GetProperty(sResultSet, "userPrincipalName");
if(str!="")
list.Add(str);
}
return list;
}
You probably want to start with the DirectoryEntry and Active Directory support in .net.
Here's a good resource: http://www.codeproject.com/KB/system/everythingInAD.aspx
Local access is similar, even if you're not in a domain:
DirectoryEntry localMachine = new DirectoryEntry("WinNT://" +
Environment.MachineName);
DirectoryEntry admGroup = localMachine.Children.Find("administrators",
"group");
object members = admGroup.Invoke("members", null);
foreach (object groupMember in (IEnumerable)members) {
DirectoryEntry member = new DirectoryEntry(groupMember);
//...
}

Connect to Active Directory via LDAP

I want to connect to our local Active Directory with C#.
I've found this good documentation.
But I really don't get how to connect via LDAP.
Can somebody of you explain how to use the asked parameters?
Sample Code:
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry("rizzo.leeds-art.ac.uk");
ldapConnection.Path = "LDAP://OU=staffusers,DC=leeds-art,DC=ac,DC=uk";
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
I just have the Hostname and the IP Address of our Active Directory Server. What does DC=xxx,DC=xx and so on mean?
DC is your domain. If you want to connect to the domain example.com than your dc's are: DC=example,DC=com
You actually don't need any hostname or ip address of your domain controller (There could be plenty of them).
Just imagine that you're connecting to the domain itself. So for connecting to the domain example.com you can simply write
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
And you're done.
You can also specify a user and a password used to connect:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com", "username", "password");
Also be sure to always write LDAP in upper case. I had some trouble and strange exceptions until I read somewhere that I should try to write it in upper case and that solved my problems.
The directoryEntry.Path Property allows you to dive deeper into your domain. So if you want to search a user in a specific OU (Organizational Unit) you can set it there.
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
directoryEntry.Path = "LDAP://OU=Specific Users,OU=All Users,OU=Users,DC=example,DC=com";
This would match the following AD hierarchy:
com
example
Users
All Users
Specific Users
Simply write the hierarchy from deepest to highest.
Now you can do plenty of things
For example search a user by account name and get the user's surname:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
DirectorySearcher searcher = new DirectorySearcher(directoryEntry) {
PageSize = int.MaxValue,
Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=AnAccountName))"
};
searcher.PropertiesToLoad.Add("sn");
var result = searcher.FindOne();
if (result == null) {
return; // Or whatever you need to do in this case
}
string surname;
if (result.Properties.Contains("sn")) {
surname = result.Properties["sn"][0].ToString();
}
ldapConnection is the server adres: ldap.example.com
Ldap.Connection.Path is the path inside the ADS that you like to use insert in LDAP format.
OU=Your_OU,OU=other_ou,dc=example,dc=com
You start at the deepest OU working back to the root of the AD, then add dc=X for every domain section until you have everything including the top level domain
Now i miss a parameter to authenticate, this works the same as the path for the username
CN=username,OU=users,DC=example,DC=com
Introduction to LDAP
If your email address is 'myname#mydomain.com', try changing the createDirectoryEntry() as below.
XYZ is an optional parameter if it exists in mydomain directory
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry("myname.mydomain.com");
ldapConnection.Path = "LDAP://OU=Users, OU=XYZ,DC=mydomain,DC=com";
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
This will basically check for com -> mydomain -> XYZ -> Users -> abcd
The main function looks as below:
try
{
username = "Firstname LastName"
DirectoryEntry myLdapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.Filter = "(cn=" + username + ")";
....

Query Local Administrator Group

So, I'm kind of stuck here...
I'm writing a program that should be able to list all users in the local administrator group on a MS Windows Server 2008 R2.
The problem here is that I'm only allowed to use .NET 2.0 - so I'm not able to use the GroupPrincipal Class... Which would have made this a really easy task.
Any pointers would be appriciated!
Cheers!
Jeez!
Don't know what I was thinking really - it's so simple!
All creds to Masoud Tabatabaei - found the following codesnippet on:
http://csharptuning.blogspot.se/2007/09/how-to-get-list-of-windows-user-in-c.html
DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + Environment.MachineName);
DirectoryEntry admGroup = localMachine.Children.Find("administrators","group");
object members = admGroup.Invoke("members", null);
foreach (object groupMember in (IEnumerable)members)
{
DirectoryEntry member = new DirectoryEntry(groupMember);
lstUsers.Items.Add(member.Name);
}
Did you try WMI ?
for example
ManagementObjectSearcher search = new ManagementObjectSearcher(#"SELECT * FROM Win32_UserAccount where LocalAccount = true");
ManagementObjectCollection userList = search.Get();
foreach (ManagementObject user in userList)
{
Console.WriteLine("User name: {0}, Full Name: {1}",
user["Name"].ToString(), user["FullName"].ToString());
}
Will give you a list of users in local SAM. You can add other attributes to the query and refine your list.
Do not forget to add a reference to System.Management.dll
If your are still looking for an answer, here:
If you'd like to get the administrator group, you can use this code:
public static DirectoryEntry GetLocalAdminstratorGroup()
{
using (var WindowsActiveDirectory = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer"))
{
return WindowsActiveDirectory.Children.Find(GetLocalizedAdministratorGroupName(), "group");
}
}
//Localized == Language Independent
public static string GetLocalizedAdministratorGroupName()
{
//For English Windows version, this equals "BUILTIN\Administrators".
var adminGroupName = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Translate(typeof(NTAccount)).Value;
//Remove the "BUILTIN\" part, get the local name of the group
return adminGroupName.Split('\\')[1];
}
If you'd also like to enumerate it (like you need a username), you can do this, using the methods before:
object members = AdminGroup.Invoke("members", null);
foreach (object groupMember in (IEnumerable)members)
{
DirectoryEntry member = new DirectoryEntry(groupMember);
Console.WriteLine(member.Name);
}

"The specified domain either does not exist or could not be contacted."

I'm trying to use the DomainServices class to retrieve a list of OU's from my Active Directory.
Here's my code:
public List<OrganizationalUnit> FindOrganizationalUnits(string domainName, string domainExtension, string parentOrganizationUnit)
{
string tmpDirectory = String.Format("LDAP://ou={0},dc={1},dc={2}",
parentOrganizationUnit,
domainName,
domainExtension
);
DirectoryEntry directory = new DirectoryEntry(tmpDirectory);
DirectorySearcher searcher = new DirectorySearcher(directory);
searcher.Filter = "(objectClass=organizationalUnit)";
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("displayName");
var organizationalUnits = new List<OrganizationalUnit>();
foreach (SearchResult result in searcher.FindAll())
{
//I just create and return a new OrganizationalUnit object based on the SearchResult result.
organizationalUnits.Add(new OrganizationalUnit(result));
}
return organizationalUnits;
}
Is there some configuration I have to set on my server end to let me use DirectoryServices to query it's AD objects?
Thanks for the help.
What type of app are you running this code from? AD queries have to be made from an authenticated resource. You can either use the current credentials of the user, or pass in a new name/password.
Services usually don't have any issue, running under LocalSystem, but if this is a web app running under IIS standard permissions, it might cause an issue.
Try adding some credentials where you're instantiating your DirectoryEntry class.

Categories