I need to impersonate a user using C#.
I use the LogonUser Win32 API.
This works fine when impersonating users from the same domain as the currently logged-in user.
However I get "false" as response when I try to impersonate users from other domains.
What can cause this?
As Joel says you need trust between the domains.
You also need to be carefull with respect to the security context of the process doing the delegation, and which domain the machine you are running on is in.
Both the machine and the user account of the process must be trusted for delegation, by the domain that you are trying to access.
This means that your code should be running on the domain that you are trying to access.
Hope this helps
Shiraz
You should try calling GetLastError right after LogonUser fail to see if any error information is given.
http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx
There may be some issue with calling GetLastError from c#.
Look here for more information on this : http://blogs.msdn.com/adam_nathan/archive/2003/04/25/56643.aspx
Is there a trust between your two domains? If not, LogonUser will fail.
Related
I've got an IdentityServer setup to connect to an external ADFS server. I'm able to login and obtain an access token via OAuth2 / OpenId Connect. An AspNet.Core WebApi runs within an IIS AppPool with a user that has Kerberos delegation enabled (should have, not sure how to check since I'm not into infrastructure).
What I want to achieve is that the ClaimsIdentity I get from IdentityServer on the WebApi is transformed back to a WindowsIdentity using impersonation, without a password. Just a username should be sufficient. With the actual impersonated WindowsIdentity I should then logon to a database and do some mutations.
I'm not sure if this is even possible, but I've been struggling with this for quite some time now.
I took this as a base for the Impersonation implementation. The only problem I have is that the Context.User.Identity doesn't return a WindowsIdentity, but a ClaimsIdentity.
Another approach I tried is using var user = new WindowsIdentity(username); where username would be the UPN. That creates an Identity, with ImpersonationLevel.Identity instead of ImpersonationLevel.Impersonated. When I run WindowsIdentity.RunImpersonated() with this users access token will give an Access Denied, or IOException when loading the needed assemblies.
So first question: how do I check if the IIS AppPool user has the correct Kerberos delegation rights?
Second question: is it even possible to impersonate a user only with a username?
What you're describing is delegation with "any" authentication method. Protocol-wise this is called Service-for-User-to-Proxy. It requires that the service account is granted that right and you need to check the Active Directory service account is configured for that. You also need to indicate which services can receive impersonated connections.
Once you've configured the service account you should restart the machine running the code (things get negatively cached in memory which takes a while to time out). If your app is running in IIS your service account should already be configured to use the correct Windows local privileges to impersonate.
However, keep in mind that this permission gives your application global permissions for whatever service you're requesting a service ticket to. That means your app can impersonate everyone, which is rightfully a little dangerous.
We have a website running on a different AD domian then we need to authenticate with. For reasons I will not go into, we can not allow a trust between them.
So we have:
Rackspace.Domain
SuperDuperEnterpriseDomain
The website is running at rackspace under their domain and we need to be sure they are authenticated on
Is there a way to in C# to check to see if a user exists on another domain? If so how?
Assuming that you are getting a SuperDuperEnterpriseDomain's username and password, use DsBindWithCred. Note that this function fails with Access Denied even when the credentials are technically valid, such as the account being locked out. Since you are not joined to the target domain, you won't be able to call LogonUser to get finer details on why the credentials are invalid.
For code, see my answer to another question. You can replace the SecureString's with regular strings if you don't mind the security implications.
Currently I have a windows service written in C# (running as LocalSystem) which creates a user account, needed for impersonation, by using the DirectoryEntry to add the user/password and associated UserFlags. Then it simply uses this account to perform some tasks (using impersonation) using the LogonUser() functionality - works perfectly.
However this account should ONLY be used for impersonation by my service, a user should NEVER be able to login (even if he has the credentials) locally or via the network.
To accomplish this I tried setting the Local Policies for “Deny logon locally” and “Deny access to this computer from the network” and added the user my service creates. Now however impersonation fails with the following:
Logon failure: the user has not been granted the requested logon type at this computer (1385)
So, I guess this is NOT the right way to do it … but I need to secure lockdown the account so it can only be used by my service for impersonation purposes and to ensure that no one else can ever logon to the account (even if they have all the credentials).
Is there something in LSA I can use? Or using the DirectoryEntry code similar to when the account was created? Is there a way to allow for an account to exist but not allow users to interactively logon?
Any help would be much appreciated.
Thanks,
You can run the service under the "Network Service" account and grant the server access to the applicable domain resources. Other than that, I am not certain there is a way to solve your problem with a user account.
My application needs to access files on a remote machine that requires a username and password for accessing it.
I'm trying to find out if a directory exists (using Directory.Exists) to verify I can make the 'connection.
Is there a way to supply the username and password when working with remote directories? Currently Exists returns false.
Cheers,
Unfortunately not. You will need to wrap your code using extra code to handle impersonation of a user that does have access.
This article explains how to do it in code further down the page.
Check out this thread on MSDN Forums.
It has code sample for using impersonation, and also explains a bit about using NetUseAdd in order to gain access if the machines are on different domains or non domains.
Use the LogonUser api to login as a specific user and get a token and then use that token with WindowsIdentity.Impersonate.
Link with a sample. (do read the whole post to see it's security problems etc though).
I have a process which is running within the security context of the local system account. From C#, how can I start (using System.Diagnostics.Process.Start) a process that will run within the security context of the currently logged-on user, not the system account?
You will need to get the token of the currently logged on user and call CreateProcessAsUser. Remember with Fast-User-Switching (FUS) that more than one user may be logged in to the machine, so you have to choose which user you want to start your process as.
To enumerate user sessions, you can use the WTSEnumerateSessions API. Use this to find the current session identifiers. Then call WTSQueryUserToken to obtain the token for the currently logged on user. Using this token, you can use CreateProcessAsUser.
Unfortunately, you will need to use P/Invoke for all of these method calls. If you have the username and password, then you can simply use the System.Diagnostics.Process.Start() overload.
I believe you will need to determine/evaluate which session is logged on locally - see WTSEnumerateSessions/WTSQuerySessionInformation/WTSQueryUserToken and I think you are limited to the Win32 API, I don't think theres a managed code wrapper.