Publish Article
Go Freelance

Impersonate User Account To Access Network Resources

In this age and time of development there is hardly any application that does not access resources across network machines. A very simple example could be that an application needs to read a file that exists on another machine. When doing file I/O operations, all the operations have to go through operating system security checks. Meaning unless the user has proper authorization to read or write a file, the operating system will deny the access to it and you will get very familiar error code 5. Microsoft .Net Framework runs on top of Windows Operating System and for that matter any operating system that can host Microsoft .Net Frameowrk. Therefore when an application wants to access a resource, the call goes through Win32 layer.

What will happen if the application is running under the security context of a user who does not have authorization to access the resource on network machine? The answer is very simple. When network machine checks the authorization for that user and finds that he does not have rights for the I/O operation and will deny access to it. So how do we solve this problem so that user can access the resource on network machine. There are two options. Either we add that user's account in the DACL of that object or that user impersonates as someone who is authorized to access that resource.

In this article we will show how you can impersonate a user account to create a folder on a network machine. System.Seurity.Principal namespace provides a class WindowsIdentity that does precisely what we intend to do. It has a method Impersonate that you can call to impersonate as any authenticated user. The only catch with this method if that it requires access token of the user who you want to impersonate as. Framework does not provide any means of getting security access token of a user other than the one who is already authenticated. This is where Interop/PInvoke comes to our rescue.

You can call LogonUser Win32 API to authenticate user credentials. If the user's credentials (login, password and domain tupple) are verified, this call returns the access token for the user. If the user could not be verified, this call fails and you can call GetLastError to find the reason for failure. For invalid crdentials, the error code would be 1326. For more information on Win32 error codes you can look at list of Win32 error codes.

WindowsIdentity newId = new WindowsIdentity(accessTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();						

After you have authenticated the user, the returned access token can be used to call Impersonate method of WindowsIdentity class. After this call, the execution thread will run under the context of impersonated user. After you are done with the process, you should always call Undo method on WindowsImpersonationContext object. This method will revert the thread execution to the security context that it was running under before Impersonate method was called.

There is a very detailed sample in WindowsIdentity class in Microsoft .Net Framework Documentation that shows how you can use PInvoke to use LogonUser API and other Win32 APIs. Therefore we would not spend time showing you that same example here. We have wrapped that implementation in NetworkSecurity class in the sample for this article. But there are some very important points that we would like to discuss about these Win32 APIs and network resource access.

  • LogonUser API requires SE_TCB_NAME previlege enabled for the process. What this previlege means is that the process should be part of the Trusted Computing Block. In simple words what this means is that the process should have unrestricted access on the system. Operating system does not give this previlege to any process other than processes running as drivers and services. You can enable this previlege for any process from Local System Policy console of your system. We do not recommend this approach because this opens up a huge security hole in your application by opening up access to any malicious code that may get executed under your application's context. For Windows XP and higher operating systems, LogonUser API does not require this previlege enabled any more. The API takes care of it for you.
  • If you are unsure if Impersonate method actually did its job or not, enable auditing of Logon/Logoff events from security policy. Now when you call Impersonate method, there will be an entry for Logon/Logoff event in the Security Log in event viewer whiich will show the impersonated user's login name. And if you have enabled auditing for file I/O on remote machine, every file access by your application will have an entry under the impersonated user's account. If you don't see the impersonated user's login in event log that would mean that impersonation did not succeed.
  • LogonUser API returns impersonation token when LOGON32_LOGON_NETWORK option is specified in the call. What this means is that this token can only be used for threads and can not be attached to processes. To get primary token from impersonation token you should call DuplicateToken API. When you call DuplicateToken API, you can modiy the type of impersonation level for the token. Meaning if you don't want the network machine to use the credentails to make any other network call for that user, you shoud always set the impersonation level to SecurityImpersonation.
  • To access a folder on a remote machine it is important that a share for that folder exists on the remote machine. If there is no user share then atleast an Admin Share (with $ sign at the end) should exists for that folder. Otherwise all your network operations on that folder will end up with "Folder XXXX does not exist or not found" error.

We have created a small ASP.Net application using Visual Studio .Net 2003. This application creates a new folder on a network machine after impersonating a user account who has the right kind of access rights on that folder. This sample has been tested on Windows XP and Windows 2003 Web Server.

Go Freelance
Home     About us     Contact us    Copyright    Privacy Policy    Return Policy    Advertisers
Copyright © Netomatix