Force PrincipalContext to connect to a specific server - c#

Is there a way to force PrincipalContext to connect to a specific Domain Controller? I'm enumerating the list of locked accounts for my application, and I would like to be able to query multiple servers and return the list from all DCs.
Currently I get whichever DC my PrincipalContext happens to connect to, and my list is not always completely correct of accounts that are locked out.
I've done some digging, but don't see any way to make reference to which Domain Controller the call for PrincipalContext connects to.

Yes, you can connect to a specific domain controller.
new PrincipalContext(ContextType.Domain, name, container, username, password);
The name part of this principal context can be set to an IP address of a domain controller. I assume that you speak about different active directories otherwise you may have a problem how the domain controllers are distributing the information.
Also, make sure the container is the correct with OC=... and DC=....
Hope it helps!

Related

Retrieving the local group name by which a particular user belongs to

I want to retrieve the local group name by which a particular user belongs to. IE, suppose if we know the user and don't know his/her group name in such case i want to retrieve the group name.
The same classes/libraries that can be used to retrieve such information for within an Active Directory domain can be used to retrieve this information from the local machine.
You can use the PrincipalContext class, and related classes to retrieve information about users, groups and much more. The constructor of the PrincipalContext class allows you to specify a context to search in.
By initializing the PrincipalContext class like this:
PrincipalContext ctx = new PrincipalContext(ContextType.Machine,Environment.MachineName);
You will operate within your local machine's context. Using the related classes and functions that the PrincipalContext class exposes, you can accomplish what you want.
Here is a reference on how to get a list of groups a user is a member of:
How to get the groups of a user in Active Directory? (c#, asp.net)
Even though the link above explains how to do this for an active directory. It still uses the PrincipalContext class. It's just a way of modifying how you initialize the instance.

Accessing user info from a one way trust

I have two domains, MINE and THEIRS. MINE is my local domain and has a one way trust with THEIRS (using LDAPS port 636), so that MINE trusts THEIRS but THEIRS does not trust MINE. I can add users from THEIRS to groups in MINE, and have users from THEIR log into machines and applications on the MINE network. The trust appears to be working properly.
I am writing a little .Net application (not ASP.Net) to test connectivity over the WAN. We have one app that isn't seeing users from THEIRS in groups in MINE. Other apps, like SharePoint, work fine.
I tried using ASP.Net 4 option with System.DirectoryServices.AccountManagement objects, like PrincipalContext, UserPrincipal, GroupPrincipal, etc. Quick code snippet
PrincipalContext domainContext = GetDomainContext(DomainName, ConnectionPort,
UseSpecifiedCredentials, Credentials);
GroupPrincipal theGroup = GroupPrincipal.FindByIdentity(domainContext,
IdentityType.SamAccountName, GroupName);
PrincipalCollection theUsers = theGroup.Members;
var users = from u in theUsers
select u.Name;
return users.ToArray();
It all works GREAT when I connect directly to MINE. The issue comes in with connecting to THEIRS. Either the 1 way trust of the LDAPS traffic is returning the error:
System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
So I switch to .Net 2 variations using DirectoryEntry, DirectorySearcher, etc. This actually works against THEIRS domain.
List<string> userNames = new List<string>();
string searchString = string.Format("(sAMAccountName={0})", GroupName);
SearchResult result = SearchAD(DomainName, ConnectionPort, searchString);
I can connect directly to the THEIRS domain, using some impersonation in the code.
When I query the groups in MINE, I get back the SID for the users from THEIRS, not a user account.
The following users are a member of testGroup:
CN=S-1-5-21-....,CN=ForeignSecurityPrincipals,DC=MINE,DC=local
CN=S-1-5-21-....,CN=ForeignSecurityPrincipals,DC=MINE,DC=local
I tried the impersonation on this as well, running it as a user from THEIRS but no luck.
How can I get user info from THEIRS when the user is in MINE? Do I have to take the above CN/SID and query THEIRS domain? What am I missing in the .Net 4 stuff?
I assume you have your ASP.NET machine running in MINE.
Your System.DirectoryServices.AccountManagement approach should just work if you make sure you use a domain user account from THEIR domain to run the application. In normal one-way trust configuration (unless you are doing selective authentication trust), the domain user account from THEIR should have permissions to read from both MINE and THEIR.
To make sure you use a domain user from THEIR domain, you can simply set the AppPool identity. Of course, you can use impersonation to do it too.

How to search AD Global Caalogue rather than Domain Controller?

I have some c# code that successfully searches a domain however our customer is saying that it needs to search the global catalogue. How easy is this? Does it make any sense?
AD Global Catalog (GC) can be on any Domain Controller (usually it is on all of them) and changes done to Active Directory replicate to all domain controllers every few minutes. There are however some settings in AD that are not replicated and can be only found on this particular domain controller that's why it's often necessary to search the value on all domain controllers then just ask one.
So to answer your question you most likely are doing good job (can't say for sure without source code) querying one domain controller and this is exactly what your customer is requiring you to do. But you may need to add option to scan other domain controllers for additional information (this could be Last Logon Times for users if i remember good that is stored per domain controller and is not replicated).
Unless there's more to it then you are telling us in the question :-)
Firs of all Global Catalog is a Directory. Programaticaly, it can be queried exactly in the same way as Active-Directory.
You just have to find the GCs adresses and ports. It can be easily done, querying the DNS of you client domain for service (SRV) entries _gc._tcp.DNSDomain. The entries will give you the DNS adress and the port (generally 3268) of the global catalogs present.
Here is the Nslookup example :
> set type=srv
> _gc._tcp.societe.fr
Serveur : srventr2.societe.fr
Address: 192.168.183.138
_gc._tcp.societe.fr SRV service location:
priority = 0
weight = 100
port = 3268
svr hostname = srventr2.societe.fr
srventr2.societe.fr internet address = 192.168.183.138
After that, you can search the Global Catalog exactly in the same way as a normal directory. As you can read in comments it's only interresting if you've got multiple domains in your forest. This is because all the objects of all domains of the forest can be found in the GC, but be carefull for each object all the attributes are not present (as specified in the SCHEMA).
The answer to this was pretty simple all I did was change the url from...
GC://<url> to LDAP://<ur>

MVC Active Directory Membership

I am trying to make use of the active directory membership rather than SQL but there is very limited documentation available online. I have managed to connect my application to the domain controller without any problems but when you use "Context.User.Identity.Name" it comes up with DOMAIN\User. I want to basically drill down and get information such as full name, e-mail address, etc.
I just need a useful link and the searching I have done doesn't appear to have got me anywhere!
Many thanks
This should give you a bit of a clue: http://msdn.microsoft.com/en-us/library/ms973834.aspx
and here is a list of LDAP properties that you might want to play around with in the search result: http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm
Have you tried with this doc?
http://msdn.microsoft.com/en-US/library/system.web.security.activedirectorymembershipprovider%28v=vs.90%29.aspx
Can help?
If you are making use of Active Directory then you are likely using Windows Authentication. If so, all you need to do is:
Reference System.DirectoryServices.AccountManagement
In code (perhaps a controller action or model constructor)
// establishes your domain as the context for your user lookup
var principalContext = new PrincipalContext(ContextType.Domain, "domainName");
// gets the current user's UserPrincipal object
var userPrincipal.FindByIdentity(principalContext, #User.Identity.Name)
// example
var email = userPrincipal.EmailAddress;
Note:
This works because Windows Authentication means User.Identity on the current HttpContext is a WindowsIdentity and thus its Name property can be used to search AD.
You aren't limited to looking up the current user. You can use FindByIdentity() to search any value passed, and this method exists on other principals (ex. GroupPrincipal). You can also designate you wish to search by another type such as SID instead of Name.
Enjoy!

How to tie into a domain server's login for program access rights

I need to write a program used internally where different users will have different abilities within the program.
Rather than making users have a new username and password, how do I tie into an existing domain server's login system?
Assume .NET (C#, VB, ASP, etc)
-Adam
For WinForms, use System.Threading.Thread.CurrentPrincipal with the IsInRole() method to check which groups they are a member of. You do need to set the principal policy of the AppDomain to WindowsPrincipal first.
Use this to get the current user name:
private string getWindowsUsername()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
return Thread.CurrentPrincipal.Identity.Name;
}
And then something like this to check a role:
if (Thread.CurrentPrincipal.IsInRole("Domain Users") == true)
{}
In ASP.NET, the thread will belong to IIS, so instead you should
Set the virtual folder or website to require authentication
Get the user name supplied by the browser with Request.ServerVariables("LOGON_USER")
Use the DirectorySearcher class to find the users groups
I would use LDAP
and the DirectorySearcher Class:
http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx
Assuming this is served through IIS, I would tell IIS to authenticate via the domain, but I would keep authorization (what roles a user is associated with, accessible functionality, etc) within the application itself.
You can retreive the username used to authenticate via
Trim(Request.ServerVariables("LOGON_USER")).Replace("/", "\").Replace("'", "''")
OR
CStr(Session("User")).Substring(CStr(Session("User")).LastIndexOf("\") + 1)

Categories