We are developing a C# .NET windows service.
Our service is running under the system account, and we are trying to impersonate the logged in user USER.
The impersonation works ok, i.e. when calling System.Security.Principal.WindowsIdentity.GetCurrent()
after the impersonation we get the correct user 'USER'.
The problem is that when we try to access the user profile we do not get the expected results.
One example is accessing the registry CURRENT_USER. We get an access denied error.
When using a third party function, which we assume uses the registry in part, we get the details for the "real" (prior to impersonation) user.
Also when callingEnvironment.ExpandEnvironmentVariables("%TEMP%")
we get the system profile instead of the logged-in user profile.
Is there a way to completly impersonate a different user?. I know we can use LoadUserProfile to get a specific user profile, but this is not good for us, because we are running a third party dll that uses the current user profile.
Our impersonation code is base on this
To impersonate another user, the impersonator selects the Impersonate icon on the far right of the Tab Bar and selects the user from the Impersonate drop-down list. To stop impersonating a user, the impersonator clicks the Impersonate icon and selects Stop Impersonate from the Impersonate drop-down list.
To impersonate another user you must first retrieve the security information of the user you want to impersonate, cache that information in a security context structure, and then later use the information in the security context structure to send the impersonated messages.
Impersonation is when someone pretends to be another person. If you pretend to be your twin brother all day at school, that's impersonation.
User Impersonation allows Administrators to access and operate as if they were logged in as that User. Administrators can impersonate other authenticated users for testing purposes and view impersonation logs.
As you have discovered, impersonation won't set up HKEY_CURRENT_USER
or the environment.
This is because the impersonation token is per-thread, and HKCU and environment are per-process.
If you need to access the user's usual environment, you will need to use HKEY_USERS\SID
and the impersonated user's SID e.g. HKEY_USERS\S-1-5-21-12345678-12345678-12345678-1234
for example. Call LoadUserProfile
to ensure the key is loaded. (If it is supposed to be the the currently logged-on user it should be loaded already, so you should probably not do that, but check it exists and return an error if not).
You can also work out what their usual environment would be, because this is under the key "Environment" within the HKCU. You merely need to combine that with the system environment.
If the third party DLL actually requires HKCU and the environment to be set up correctly, you will need to create a process within the user's logon session to host the DLL, and send the results of whatever operation back somehow. If only the environment is required, you can create a child process and set the environment manually.
However you haven't said why you want to do this. It sounds like you have settled on this as a portion of the solution to a larger problem. If possible I'd recommend that you see if there is a way to do what you need without getting the user's environment or HKCU at all.
Why can't the DLL just run directly in the user's own session? Why is a service required at all? Can you re-architect your solution so there is a user-mode part which runs in the logon session and hosts the third-party DLL, and it communicates with the service so that the service only does what is absolutely required?
I notice that the code doesn't call LoadUserProfile
, so the users profile isn't loaded.
Note in the remarks of that function, HKEY_CURRENT_USER
still isn't replaced though.
I think you can solve this issue (before calling the third party DLL) by calling RegOverridePredefKey
.
Note that a lot of voodoo might be involved in getting this all working right - I'd try to make sure the override happens as late as possible before the third party call, and is reverted as soon as possible afterwards (hoping that this is all a single call to the library).
As an alternative, I'd seriously try looking around for a different 3rd party offering that doesn't require all of this jumping through hoops.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With