credential cache - c#

Does anyone know how to use the credential cache or network credential to get the user's personal info from the Active Directory using C# or VB? I need to get personal info such as name, telephone ID and so on.

See the System.DirectoryServices class documentation.

DirectorySearcher ds = new DirectorySearcher("LDAP://DC=test,dc=com");
ds.Filter = String.Format("&(samaccountname={0})(objectcategory=user)",Environment.Username);
ds.PropertiesToLoad.Add("telephoneNumber");
ds.PropertiesToLoad.Add("Name");
// add all properties here
DirectoryEntry de = ds.FindOne();
By default a user will have sufficent rights to read their own personal details.
If they do not you may need to use Delegation on your directory to allow SELF read access to extra attributes

Related

Read and write "uid" property in Active Directory from a desktop application in .NET

I'm trying to manipulate the uid property of AD to store some extra info but I'm getting an UnauthorizedAccessException when using this code:
DirectoryEntry de = new DirectoryEntry("LDAP://somedomain.net");
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectClass=user)(|(cn=" + username + ")(sAMAccountName=" + username + ")))";
ds.PropertiesToLoad.Add("uid");
SearchResult? rs = ds.FindOne();
if (rs != null)
{
DirectoryEntry de = rs.GetDirectoryEntry();
if (rs.Properties.Contains("uid"))
de.Properties["uid"].Value = "123456";
else
de.Properties["uid"].Add("123456");
de.CommitChanges();
}
I have no trouble when I manipulate the postalCode property instead of uid using the same code, so I'm really lost. Don't I have enough privileges on the domain to write to the uid property? Or do I have to access it in a different way?
EDIT: it seems I can't access postalCode property of another user other than mine. I suppose that I have to login with a domain administrator account or impersonate it in some way, but I have no idea how to do that ...
It seems I can't access "postalCode" property of another user other than mine. I supose that I have to login with a domain administrator account or impersonate it in some way, but I have no idea of how...
The DirectoryEntry class constructor takes explicit credentials for exactly this kind of scenario:
DirectoryEntry de = new DirectoryEntry("LDAP://somedomain.net/", "SOMEDOMAIN\Administrator", "sup3rs3cr3t");
Rather than using a Domain Admin account, I'd strongly suggest delegating the minimum required access permissions on the target accounts to a service account the credentials of which you can then use in your program - this way you limit the potential impact from someone stealing the credentials.

Is the GUID Property of a UserPrinciple Object in Active Directory Unique and Non-spoofable?

We are using Windows active directory to log users in without a password. The way we are currently doing it like this:
using System.DirectoryServices.AccountManagement;
var context = new PrincipalContext(ContextType.Domain, System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName);
var result = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, Environment.UserName);
Then we have a stored SamAccountName in our database which we match against the returned result.SamAccountName
This is definitely not secure as users could have the same SamAccountName and log in using that.
We are exploring the use of the GUID which exists on the UserPrinciple (result.GUID). My question is, is this variable non-spoofable on the windows side? Can we match the GUID that exists on the UserPrincple object with a variable we store on our database? Is this secure? Does this property always exist on an AD UserPrinciple? If not, how would we securely authenticate a user through this Windows Active Directory Login?
"sAMAccountName" is unique in a domain.
But you can also use both "objectSID" and "objectGIUD" for this purpose,this fields remain unchanged.
Note That If an object is moved to another domain, the objectSID changes, but not the objectGUID.
Overall, the best choice is "objectGIUD"
according to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a5c0a863-cad1-4df8-a194-cb58f24ab1e6/is-objectguid-unique-in-the-domainforest?forum=winserverDS

Problems with LDAP

I am having trouble with LDAP. Now I use this code:
DirectoryEntry ldapConnection = new DirectoryEntry("LDAPS://*******.com:636", "User#bloom.local", "Password");
ldapConnection.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;
DirectorySearcher search = new DirectorySearcher(ldapConnection);
var result = search.Filter = "(objectClass=*)";
search.FindAll();
I spent a large number of experiments, but never received:
Unknown error (0x80005000)
or
The server is not operational.
My property in the softerra LDAP Administrator:
The problem is that the simple authentication mechanism requires an LDAP distinguished name (DN) and you provided just a user name. At least, this is what your screenshot shows.
The DN of the administrator is likely something like cn=Administrator,cn=Users,dc=bloom,dc=local.
Also, I would probably steer away from using the administrator credentials in production. It is much more preferable to create an account with the right privileges.

DirectoryEntry results in The server is unwilling to process the request

I am writing a small app that integrates with AD and will be listing users and allowing members of the site to edit certain fields of the users. These fields will be, first name, last name, display name and email.
When I run the following code I get an exception that says
The server is unwilling to process the request.
Please note that result is not null and contains the correct active directory user that I want to edit. Also note that result is of type SearchResult. Also note that the user I am using to connect to AD is the Administrative user.
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
entryToUpdate.Properties["cn"].Value = user.Name;
entryToUpdate.Properties["mail"].Value = user.Email;
entryToUpdate.Properties["sn"].Value = user.Surname;
entryToUpdate.Properties["displayName"].Value = user.DisplayName;
string username = user.Email.Substring(0, user.Email.IndexOf("#"));
entryToUpdate.Properties["sAMAccountName"].Value = username;
entryToUpdate.CommitChanges();
Any Ideas?
I believe
entryToUpdate.Properties["cn"].Value = user.Name;
is your Problem. Use givenName as first Name. "cn" is managed by the System.
Also:
If using Exchange, the Mail attribute is managed by it.
Consider the ramifications of modifing samAccountName. Users may not know how to log in, seperate Systems with pseudo SSO may not recognize them, the Login Name does not match the local Profile Name, etc.

LDAP Directory Entry in .Net - not working with OU=Users

I have the following code (C#):
(Tweaked from: http://www.eggheadcafe.com/conversation.aspx?messageid=31766061&threadid=31766050)
DirectorySearcher dseSearcher = new DirectorySearcher();
string rootDSE = dseSearcher.SearchRoot.Path;
DirectoryEntry rootDE = new DirectoryEntry(rootDSE);
string userDSE = rootDSE.Insert(7, "OU=Users,");
DirectoryEntry userDE = new DirectoryEntry(userDSE);
The rootDSE is created correctly, however, the user userDSE is unusable and throws "There is no such object on the server" exception if I attempt to use it.
The LDAP strings are as follows:
Root: LDAP://DC=company,DC=local
User: LDAP://OU=Users,DC=company,DC=local
I'm running on Vista as Admin, but need this to work on XP (Admin) as well.
I'm new to LDAP and Directory Management, so I'm stumbling around in the dark here. Any thoughts? Also - any articles to link too that could give me some insight into how it all works would be appreciated.
The first thing I would try as a test is to hardcode your desired path when you create a directory entry like so:
DirectoryEntry de = new DirectoryEntry("LDAP://OU=Users,DC=company,DC=local");
This will tell you pretty quick if this is an actual path in your Active Directory. I don't know what your AD looks like so I can't tell you if this is a valid path or not. Under your Active Directory Users and Computers MMC plugin, if this path is correct, then you should have your root domain, and a OU folder under the root called Users.
Paths are generated backwards in AD, so if your Users folder is under another OU off the root than it would be
DirectoryEntry de = new DirectoryEntry("LDAP://OU=Users,OU=<first OU folder>,DC=company,DC=local");
So your AD schema would look like:
Root
|
--><first OU folder>
|
-->Users
A great article on how to manage Active Directory in .NET:
HowTo: Do (Almost) Everything in Active Directory via C#
You might also want to research the System.DirectoryServices, System.DirectoryServices.ActiveDirectory, and the System.DirectoryServices.AccountManagement namespaces provided in the .Net 3.5 Framework. I believe System.DirectoryServices, and ActiveDirctory namespaces were available staring in .Net 1.1, and AccountManagement was introduced in .Net 3.5.
Microsoft Documentation - A lot of good links on how to use the namespace
Addendum:
To actually find a user in AD you will want to do the following:
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://DC=company,DC=local";
de.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=user) (cn=" + username + "))";
SearchResult result = deSearch.FindOne();
if (result != null)
{
DirectoryEntry deUser = new DirectoryEntry(result.Path);
... do what ever you need to the deUser
deUser.Close();
}
This may seem silly and stupid, but the default tree setup in Active Directory is not OU=Users,dc=domain,dc=com but rather cn=Users,dc=domain,dc=com (Note the CN= not the OU= for Users.
It seems stupid since a container object (objectClass of cn) in AD cannot be a recipient of group policy, but for reasons I do not understand, that is the default. (actually I do understand, it is because containment for a CN is more similar to an NT domain than OU)
Gets almost everybody I meet, first time they try to LDAP bind/auth to AD.
As geoffc mentioned correctly, in Active Directory the "Users" under the domain is a container object rather than organizational unit object.
This results in a totally different LDAP path which is why you get the error message.
Try the following code and post if it fixes your issue:
// Replace the "company" and "com" with actual domain values...
DirectoryEntry de = new DirectoryEntry("LDAP://CN=Users,DC=company,DC=com");
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
// Set your other search params here

Categories