I'm using the .net directory searcher to query data from OpenLDAP. It connects OK and I can query the user data, but operational attributes don't seem to be returned. This is a problem, as I need the entryUUID. I've tried adding "entryUUID" to the propertiesToLoad parameter when constructing the DirectorySearcher, and have also tried "+" (which according to the OpenLDAP documentation should return all operational attributes), but no joy.
Does anyone have any suggestions please?
I couldn't find a way of doing this, so in the end I used the LDAPConnection class in the DirectoryServices.Protocols namespace instead. The DirectorySearcher class seems to be primarily designed for querying Active Directory - while it can query other LDAP Directories its functionality is limited.
Related
I am developing a webapp in ASP.NET MVC C# where you can create automated emails that are sent out in the company yearly.
I am looking for a way to verify that the To-addresses specified by the user are valid and exist in the company.
I thought this could be accomplished by looking up Outlook's address book, since it contains all email addresses in the company.
I have searched around and found https://msdn.microsoft.com/en-us/library/ff184631.aspx which suggests using the Microsoft.Office.Interop.Outlook package. However, as far as I can see, using this package requires that the Outlook application is installed. I suppose this can be problematic for a solution that runs on a server.
Can I use the Microsoft.Office.Interop.Outlook package to accomplish my goal, or do I need to use another method that better supports a server?
Following the tip of Filburt in the comments, I found this code piece that accomplishes my goal
https://code.msdn.microsoft.com/windowsdesktop/A-very-simple-example-to-8bbe95f0
It looks up in Active Directory.
I have simplified the code from the link to the following. In this example we check if the email address addyToCheck#domain.com exists in the AD:
using System.DirectoryServices;
// check if address exists
var searcher = new DirectorySearcher();
searcher.Filter = "(&(mail=" + "addyToCheck#domain.com" + "))";
if (searcher.FindOne() != null) {
// the email exists in AD - all good!
}
This works for me locally and I suppose it will on the server as well. Let me know if you see anything wrong. Thank you.
I want to search for users in an Active Directory environment with GC://DC=xxx,DC=yyy,DC=zzz format. But how can I programmatically find the global catalogs in an arbitary Active Directory environment? Does each domain name correspond to a global catalog always? Any alternative means I can try?
Note: The Forest.FindAllGlobalCatalogs() returns a list of server names but I'm actually not able to search using them.
Edit1: Here's what I want to do : Suppose my activedirectory has a domain called domain1.root.com, then I will use GC://DC=domain1,DC=root,DC=com to search for a user. But is this always a Global catalog? Must every domain have a global catalog?
Edit2: I am now able to search for users using the following code:
var currentForest = Forest.GetCurrentForest();
var globalCatalog = currentForest.FindGlobalCatalog();
Console.WriteLine(globalCatalog.Name);
//DirectorySearcher searcher = new DirectorySearcher("GC://"+y.Name);
DirectorySearcher searcher = globalCatalog.GetDirectorySearcher();
searcher.Filter = #"samaccountname=skaranth";
Console.WriteLine(searcher.SearchRoot.Path);
var result = searcher.FindOne();
if(result!=null)
Console.WriteLine(result.Properties["distinguishedname"][0]);
searcher.Dispose();
globalCatalog.Dispose();
currentForest.Dispose();
What exactly do you want to achieve with this??
The Global Catalog is a special subset of attributes that are stored on certain domain controllers. While each domain controller has a full set of attributes and object for that one domain, the Global Catalog contains data from all of the domains in the AD forest.
So the GC really only comes into play when you need to find things across multiple domains. If you have just a single domain, the GC won't really help you at all.
Forest.FindAllGlobalCatalogs() will indeed give you the list of all domain controller servers that contain a global catalog data set. So why can't you use those to search?? Can you show us what you've tried so far??
The Global Catalog is just that - global - e.g. you shouldn't have any reason at all to want to specify a specific server..... the servers should all have the same set of data anyway.
So again: why do you feel the need to find a server with a global catalog, and what do you want to do with that information once you have it? Why do you feel the need to specify a server when doing a global catalog search??
Usingng that search string format Active Directory will handle finding a GC server for you when you submit your query. It'll do lookups based on that AD site structure, find the closest GC server and use that server to query against.
Edit:
In answer to your edit, using the GC:// prefix indicates that you are interested in doing a Global Catalog search so it will always use a global catalog server, so yes to your question about it always being a Global Catalog. It's when you prefix your search string with LDAP:// that you'll hit a domain controller and will have to deal with non-global attributes. No need to figure out a specific server, AD will do that for you.
Here's a search string that will get you a user by their user principal name, return the userPrincipalName, cn, and distinguisedName attribute values (if any), and do a subtree search starting at the root of the domain:
GC://domain1.root.com;(&(objectClass=user)(objectCategory=Person)(userPrincipalName=myuser));userPrincipalName,cn,distinguishedName;subtree
Keep in mind that you'll then have to do an LDAP:// search to get the attributes that are not stored in the Global Catalog, binding to the path value of the distinguishedName returned by the GC search.
I have been requested to expose a web service for managing Active Directory Users via an intranet. I have been advised that LDAP is viewed as a security vulnerability and is not to be used.
Given this constraint, I have managed to connect via ADSI with a DirectoryEntry object like this:
DirectoryEntry de = new DirectoryEntry();
de.Path = "WinNT://TheDomain.local";
de.Username = "NTUser1";
de.Password = "pwdpwdpwd2";
I can loop through the children of this DirectoryEntry get the ones that are users. On the Users, I can see these basic properties: UserFlags, MaxStorage, PasswordAge, PasswordExpired, LoginHours, FullName, Description, BadPasswordAttempts, LastLogin, HomeDirectory, LoginScript, Profile, HomeDirDrive, Parameters, PrimaryGroupID, Name, MinPasswordLength, MaxPasswordAge, MinPasswordAge, PasswordHistoryLength, AutoUnlockInterval, LockoutObservationInterval, MaxBadPasswordsAllowed, objectSid.
There are a number of User properties that are visible in the Active Directory MMC that are not accessible from the DirectoryEntry object including: LastName, NameSuffix, Department, etc...
These other properties are all documented in msdn as being exposed by IADsUser (http://msdn.microsoft.com/en-us/library/aa746340%28VS.85%29.aspx).
1) Is LDAP actually a vulnerable protocol? More so than the ADSI (WinNT) connection shown above? LDAP seems to be pretty common for this purpose.
2) How can I retrieve/set these other properties of the User?
TIA
1- LDAP packet transmission is performed as plaintext, so somebody can capture your data.
If you use LDAPS protocol or TLS-enable your LDAP connection, it is safe. ADSI is just an implementation of LDAP client by Microsoft, and it supports both LDAP and LDAPS connections.
When you use ADSI against your corporate Active Directory, it primarily tries to start a LDAPS connection.
So you are safe of you use ADSI; or you can use any other client or programming library as well if you use secure connection. the default port for LDAPS is 636.
2- To get more information about directory objects, you can use the GetInfoEx method, it loads exactly the attributes you want. Below you can see an example:
http://msdn.microsoft.com/en-us/library/aa746411%28v=vs.85%29.aspx
But some of the properties that you look for, are stored in the Active Directory by attribute names different from the MMC console. e.g. First name is stored as 'givenName' and Last name is stored as 'sn'. Look here to find names of attributes you need;
You can find more information here.
http://www.techgalaxy.net/Docs/Dev/Using_ADSI_and_LDAP_with_AD.htm explains the difference between LDAP and ADSI: http://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx includes illustrations.
In short, ADSI is a simplified wrapper around LDAP. If there's any insecurity to it, it's in the binding, which here appears to be SIMPLE (unencrypted plaintext username and password). If you bind the LDAP connection using any other method (or over an SSL connection), it should be secure.
Apologies for not knowing the right way to phrase this question.
Given a domain name and an alias, for example CONTOSO\steveh how can I get the friendly display name for that alias? For example, in Outlook email sent to CONTOSO\steveh appears as 'Steve Holt'?
If you are using .net 3.5, add references to System.DirectoryServices and System.DirectoryServices.AccountManagement and try this:
PrincipalContext c = new PrincipalContext(ContextType.Domain,"CONTOSO");
UserPrincipal principal = UserPrincipal.FindByIdentity(c,"steveh");
Console.WriteLine(principal.DisplayName);
I can't verify if it works for a domain since I'm running on a standalone machine but it should help you get started.
You can query ActiveDirectory through LDAP I recommend taking a look at this question which has some basic information. You should be able to get a general direction from there.
Provided I have admin access, I need a way to manage (Create, modify, remove) local accounts in a remote machine from an ASP.NET client.
I'm clueless in how to approach this. Is WMI a possibility (System.Management namespace)?
Any pointers?
Give this a try:
DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://ComputerName" & ",computer", "AdminUN", "AdminPW");
DirectoryEntry user = directoryEntry.Children.Add("username", "user");
user.Invoke("SetPassword", new object[] { "password"});
ser.CommitChanges();
If you do need to go the Active Directory route, you can change the directoryEntry path string to something like this: LDAP://CN=ComputerName,DC=MySample,DC=com
I used System.DirectoryServices to get data from users in a n ActiveDirectory (LDAP).
I don't know if that's the kind of thing you're looking for.
Hope it helps.
You should be able to do this via DirectoryEntry.