I'm using .Net account management libraries to access Active Directory to search the details of current http request user.
My app pool runs with custom account and it also from the same domain. Server and users also belong to same domain.
public string GetEmployeeId(string SAMAccountName)
{
using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal userprincipal = new UserPrincipal(domainContext))
{
userprincipal.SamAccountName = SAMAccountName;
using (PrincipalSearcher ps = new PrincipalSearcher())
{
ps.QueryFilter = userprincipal;
UserPrincipal user = ps.FindOne() as UserPrincipal;
return user.EmployeeId;
}
}
}
}
Setup works perfectly but intermittently i get below error from AD.after sometime it works for the same user without any error.
Is there any way to check logs / events from the AD side to find the reason for this error.
System.Runtime.InteropServices.COMException (0x80005000): Unknown error >(0x80005000)
I worked with a Microsoft Engineer for a long time to fix this so hopefully my solution can help others fix their problems.
First off the error code 0x80005000 referrers to an invalid ADSI pathname was passed, which wasn’t particularly helpfully.
We did a lot of tracing which was also not very helpful. Last thing we did was use Process Monitor to trace the Registry.
When the error occurred, I noticed a HIVE UNLOADED result happened (see screenshot)
Based on this we also found this error appearing in the event log.
Log Name: Application
Source: Microsoft-Windows-User Profiles Service
Date: 10/26/2009 8:22:13 AM
Event ID: 1530
Task Category: None
Level: Warning
Keywords: Classic
User: SYSTEM
Computer: SERVERNAME
Description:
Windows detected your registry file is still in use by other applications or services. The file will be unloaded now. The applications or services that hold your registry file may not function properly afterwards.
DETAIL -
1 user registry handles leaked from \Registry\User\S-1-5-21-1049297961-3057247634-349289542-1004_Classes:
Process 2428 (\Device\HarddiskVolume1\Windows\System32\dllhost.exe) has opened key \REGISTRY\USER\S-1-5-21-1123456789-3057247634-349289542-1004_CLASSES
The engineer suggested this article https://support.microsoft.com/en-us/help/2287297/a-com-application-may-stop-working-on-windows-server-2008-when-a-user
Which seem to fix my problem.
Try to identify what domain server you will use:
Something like:
= new PrincipalContext(ContextType.Domain, "YOURADDOMAIN");
Related
I am trying to get information about the currently logged in user via a Windows service, specifically is the user is an admin level role or not. The service is properly collecting the currently logged in user, and I have code that works when the computer the service is running on is connected to the network, but I can't always guarantee the computer will be on the network when the service does this user level check.
Long story short, does WindowsIdentity require the computer be connected to the network to create an identity? I can't find anything online that clearly states if this is the case.
I only need to get whether or not the current user is an admin level role or not for the local system. I don't care if it's an admin at the domain level, although I understand this is probably going to be the case if the system is on a network.
If there is a better way to do this for my needs, I am happy to see other recommendations.
I have done some major googling and looked at a number of other SO answers, but none of them seem to work when the computer is not on the network. They did help me get a version that works when the computer is on the network though.
I also looked at the MS documentation for this and don't see anything clear about network needs. I may have missed something thought.
The below method works while on network.
private bool IsUserAdministrator(string accountName)
{
var result = false;
try
{
using (var identity = new WindowsIdentity(accountName))
{
var principal = new WindowsPrincipal(identity);
var adminSid = new SecurityIdentifier("BA");
result = principal.UserClaims.Any(c => c.Value.Equals(adminSid.ToString()));
}
}
catch (Exception)
{
// Exception handled by returning false
}
return result;
}
This method also works, when on network. The failure point while debugging is the new WindowsIdentity().
private bool IsUserAdministrator(string accountName)
{
using (WindowsIdentity identity = new WindowsIdentity(accountName))
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
Once again, when connected to the network, both of these either return 'true' when the user is an admin role, or 'false' when the user is not admin role.
When not connected to the network this fails and throws the exception {"There are currently no logon servers available to service the logon request.\r\n"}.
Is this an issue with WindowsIdentity or is something else causing this? Is this an LDAP issue?
Sorry, I realize there are multiple questions spread throughout this, but the number one issue is, does WindowsIdentity need network connection, and if yes, is there another way to achieve my goals?
We are making use of ADLDS for our user management and authentication. We can successfully query the instance without problems. However, trying to perform an operation such as SetPassword will fail or even trying to create a new user if a password is not set, it fails. I can successfully update a user as long as its not password I'm trying to update. I've been reading a lot of different articles relating to this but not finding a resolution. Posting to see if I can get some fresh perspective on this issue, thanks for any input.
EXAMPLE
ContextType ctxType = ContextType.ApplicationDirectory;
string server = "myadldsserver.com";
string usersCN = "CN=Users,..."; // container where users reside
ContextOptions ctxOpts = ContextOptions.SimpleBind;
string uname = "myuser";
string pswrd = "mypass";
using(var ctx = new PrincipalContext(ctxType, server, usersCN, ctxOpts, uname, pswrd)
using(var newUser = new UserPrincipal(ctx)) {
newUser.Name = "newusername";
newUser.Enabled = true;
newUser.UserPrincipalName = "newusername";
newUser.Save();
newUser.SetPassword("newuserpassword");
}
ERROR 1
The first problem I encounter if I try to create a new UserPrincipal and call Save without having set the password like in Example above I get the exception A constraint violation occurred. with an InnerException extend message of 0000052D: AtrErr: DSID-033807D7, #1:0: 0000052D: DSID-033807D7, problem 1005 (CONSTRAINT_ATT_TYPE), data 2246, Att 9005a (unicodePwd)
Because of this error I tried moving the SetPassword before calling Save along with other approaches I found online such as getting the DirectoryEntry from the UserPrincipal and trying to call SetPassword but got a different error.
ERROR 2
Calling SetPassword before calling UserPrincipal.Save, when save is called, results in the error The directory property cannot be found in the cache.
Note that the same error will occur if I trying calling ResetPassword or getting a DirectoryEntry and calling Invoke("SetPassword"... as well
ERROR 3
From my research most seem to indicate this could have to do with needing to access AD LDS using a Secure connection. So, I changed my server to include the port of 636 string server = "myadldsserver.com:636" and I changed the ContextOptions to be ContextOptions.SimpleBind | ContextOptions.SecureSocketLayer.
Making these changes when the PrincipalContext is being constructed I get the following exception The server could not be contacted. with an inner exception of The LDAP server is unavailable., HResult is -2146233087
JAVA and LDP
To add some background to this, we do have similar code written in an older Java application. We are trying to port some of this logic over to .NET side in C#. The code in Java makes use of a Java keystore that contains the certificate that was generated on the AD LDS server. The Java application of course has no issues using the SSL port. We know the server seems to be configured correctly, it's just an issue of how to access it from .NET side.
Is there an equivalent on the .NET side such as the keystore in Java? We know that an SSL connection can be made to server. We have verified this using LDP as well.
GOALS
Be able to create a new user and set their password during creation
Be able to ResetPassword or ChangePassword for a user
Connect to our AD LDS instance from .NET securely
Have you tried using Microsoft Management Console to import the certificate?
Two ways to install the certificate
Either
Open a cmd.exe console and type "MMC"
File > Add/Remove Snap-In...
Select Certificates, click Add
Choose Computer Account and Local Computer when prompted, then OK...
Certificates should now be showing under Console Root
Certificates > Trusted Root Certification Authorities > Certificates > (right-click) > All Tasks > Import Certificate...
Find the certificate you want to import, click Next and choose defaults (Trusted Root Certification Authorities should already be
selected)
Click Next, Finish
(or)
Simply double-click on the .cer file for the certificate in Windows
Explorer, click Install Certificate... > Next > select the option to
"Place all certificates in following store" > Browse... > Select
Trusted Root Certification Authorities. Continue with next until done.
At this point your certificate is installed, and you should be able to communicate securely with your ADLDS server.
I've looked at a couple of StackOverflow threads now. This comes closest.
I'm stuck using VS2005, and .NET 2.0. The server is Win2008. Not R2.
I'm building a C# ASP.NET web application that reads information from a database that's modified by a VB6 application. The database configuration settings are stored in the registry.
I'm using the Registry.GetValue() function and it's returning a null value.
If I make the Application Pool run as Administrator, the code returns the expected value. With any other user, the ToString throws a System.NullReferenceException. I have tried the following:
Making the AppPool use and assigning Full Control to the following users does not work:
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM
NT AUTHORITY\LOCAL SERVICE
A custom user in the Administrators group.
I cannot apply permissions to IIS APPPOOL\DefaultAppPool because the user doesn't seem to exist. This is a documented fault of Server 2008.
If I make the AppPool use the Administrator account, the system works.
Attached is the relevant code:
string root = "HKEY_CURRENT_USER";
string keyName = #"Software\Some\Key\Somewhere\";
string valueName = "someValue";
string fullKey = root + #"\" + keyName;
object keyValue;
try
{
keyValue = Registry.GetValue(fullKey, valueName, "Value not found.");
string val = keyValue.ToString();
return val;
}
catch (Exception ex)
{
return ex.GetType().ToString();
}
Unless it's running as Administrator, the above code always returns a System.NullReferenceException when running keyValue.ToString(). It never throws the System.Security.SecurityException.
I'm not eager to make my web app require Admin access.
You are searching under the key for the current user. Clearly the data exists under the key for the Administrator but not for the other users.
For the service accounts that don't have a profile, HKEY_CURRENT_USER resolves to HKEY_USERS.Default.
So to make it work with service accounts, you need to add the value to
HKEY_USERS\.Default\Software\Some\Key\Somewhere\
To make it work for the custom user in the Administrators group, you need to add it to
HKEY_USERS\<sid>\Software\Some\Key\Somewhere\
where is the SID of the custom user.
This isn't related to needing Admin access, you're just looking in the wrong place!
If the data isn't user-specific, try putting it in:
HKEY_LOCAL_MACHINE\Software\Some\Key\Somewhere\
then all the users will normally be able to read the same value.
I'm attempting to determine whether a user is a member of a given group using System.DirectoryServices.AccountManagment.
I'm doing this inside a SharePoint WebPart in SharePoint 2007 on a 64-bit system.
Project targets .NET 3.5
Impersonation is enabled in the web.config.
The IIS Site in question is using an IIS App Pool with a domain user configured as the identity.
I am able to instantiate a PrincipalContext as such:
PrincipalContext pc = new PrincipalContext(ContextType.Domain)
Next, I try to grab a principal:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, "MYDOMAIN\somegroup");
// snip: exception thrown by line above.
}
Both the above and UserPrincipal.FindByIdentity with a user SAM throw a DirectoryServicesCOMException: "Logon failure: Unknown user name or bad password"
I've tried passing in a complete SAMAccountName to either FindByIdentity (in the form of MYDOMAIN\username) or just the username with no change in behavior. I've tried executing the code with other credentials using both the HostingEnvironment.Impersonate and SPSecurity.RunWithElevatedPrivileges approaches and also experience the same result.
I've also tried instantiating my context with the domain name in place:
Principal Context pc = new PrincipalContext(ContextType.Domain, "MYDOMAIN");
This throws a PrincipalServerDownException: "The server could not be contacted."
I'm working on a reasonably hardened server. I did not lock the system down so I am unsure exactly what has been done to it. If there are credentials I need to allocate to my pool identity's user or in the domain security policy in order for these to work, I can configure the domain accordingly. Are there any settings that would be preventing my code from running? Am I missing something in the code itself? Is this just not possible in a SharePoint web?
EDIT:
Given further testing, my code functions correctly when tested in a Console application targeting .NET 4.0. I targeted a different framework because I didn't have AccountManagement available to me in the console app when targeting .NET 3.5 for some reason.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
using (UserPrincipal adUser = UserPrincipal.FindByIdentity(pc, "MYDOMAIN\joe.user"))
using (GroupPrincipal adGroup = GroupPrincipal.FindByIdentity(pc, "MYDOMAIN\user group"))
{
if (adUser.IsMemberOf(adGroup))
{
Console.WriteLine("User is a member!");
}
else
{
Console.WriteLine("User is NOT a member.");
}
}
What varies in my SharePoint environment that might prohibit this function from executing?
I added the account used by the IIS Application Pool to the Administrators group and this issue was resolved.
I need to validate the LDAP user by checking if there exists such a user name in the specified domain. For this I am using this code -
DirectoryEntry entry = new DirectoryEntry("LDAP://" + strDomainController);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "SAMAccountName=" + strUserName;
SearchResult result = searcher.FindOne();
return (result != null) ? true : false;
This is a method in a class library which I intened to reference and use whereever I need this functionality in my project.
To test this, I created a simple test application. The test occurs like this -
Console.WriteLine(MyClassLib.MyValidateUserMethod("UserName", "Domain",ref strError).ToString());
The problem I am facing is that this works fine when I test it with my testapp but in my project, when I try to use the same method with the same credentials - The DirectoryEntry object throws an "System.DirectoryServices.DirectoryServicesCOMException" exception and the search.Filter fails and throws ex = {"Logon failure: unknown user name or bad password.\r\n"} exception.
I have tried impersonation but that doesn't help. Somehow the same method works fine in mytestapp and doesn't work in my project. Both these applications are in my local dev machine. What am I missing? Any ideas?
I tried almost every possible solution I could find on every such thread but I still could not resolve it.
I tried to redo the entire thing and then it worked. I think, the reason that was responsible for it to work with my test app and not with my project is that my project was stored in a network location and my test app was stored in my PC's hard drive.
It started working fine with my project when I copied my project on to my PC's hard drive. My best guess is that since the project was located on the network, perhaps there were not enough permissions granted for a LDAP validation.
Are you sure your test application and your real application are running as the same user, so they have the same permissions in AD? Though exceptions thrown by DirectoryEntry objects are tough to troubleshoot, that's the first thing I'd check. What kind of a project is it - web app or desktop app? If it's a web app, then the user running the app pool may not have the necessary permissions.