Note that there are some explanatory texts on larger screens.

plurals
  1. POC# Nested impersonation - impersonate a user whilst already impersonating another
    text
    copied!<p>I have a fairly odd requirement to be able to impersonate a user, when I'm already impersonating another, using C#.</p> <p>I'm writing an app to allow the management of Active Directory users. This app will provide the ability for anyone in the company to view and maintain certain details about themselves (some of which will not actually be saved to Active Directory, but some of which will), for managers to be able to view and maintain details about their team, and for HR to be able to view and maintain details about anyone. </p> <p>For obvious reasons I don't want to develop or test this against the live domain. We have recently ported all users over to this domain from another domain, which means I can actually test against the old domain without affecting anything. However, to enable me to do this I have to impersonate my old account on the old domain, which I do on loading the application.</p> <p>Although for me everything will work fine as I'm setup as a domain admin, going forward obviously not all users will be domain admins, and won't be able to write to AD under their own account, and therefore we have another domain admin user setup specifically for this application, whenever data needs to be saved to AD that user is impersonated. This was working great before when I was testing against an Active Directory I'd setup on a virtual machine because I was logging onto the local domain, however that didn't allow me to step through the code in Visual Studio so debugging was slow, and hence I've stopped using that virtual machine and am using this old domain. Now I'm already impersonating another user (i.e. my old domain account), when it then tries to impersonate the domain admin user it fails with an "System.Security.SecurityException: Access is denied." exception. The line this fails on is just writing out some debugging information using "WindowsIdentity.GetCurrent().Name". </p> <p>If I change my code so I'm actually logging in using the new domain admin rather than my old account, the first time it goes through it logs in successfully (so the credentials are correct), however when it then goes through and tries to do the same again to write to AD it fails with the above exception. Therefore I think it must be a problem with trying to do a nested impersonate. </p> <p>Is it possible to do a nested impersonate? </p> <p>Below is the code I'm using:</p> <pre><code>private static WindowsImpersonationContext ImpersonateUser(out string result, string sUsername, string sDomain, string sPassword) { // initialize tokens var pExistingTokenHandle = new IntPtr(0); var pDuplicateTokenHandle = new IntPtr(0); // if domain name was blank, assume local machine if (sDomain == "") { sDomain = Environment.MachineName; } try { result = null; const int logon32ProviderDefault = 0; // create token const int logon32LogonInteractive = 2; // get handle to token var bImpersonated = LogonUser(sUsername, sDomain, sPassword, logon32LogonInteractive, logon32ProviderDefault, ref pExistingTokenHandle); // did impersonation fail? if (!bImpersonated) { var nErrorCode = Marshal.GetLastWin32Error(); result = "LogonUser() failed with error code: " + nErrorCode + "\r\n"; } // Get identity before impersonation result += string.Format("Before impersonation: {0}\r\n", WindowsIdentity.GetCurrent().Name); var bRetVal = DuplicateToken(pExistingTokenHandle, (int)SecurityImpersonationLevel.SecurityImpersonation, ref pDuplicateTokenHandle); // did DuplicateToken fail? if (bRetVal) { // create new identity using new primary token var newId = new WindowsIdentity(pDuplicateTokenHandle); var impersonatedUser = newId.Impersonate(); // check the identity after impersonation result += "After impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n"; return impersonatedUser; } else { var nErrorCode = Marshal.GetLastWin32Error(); CloseHandle(pExistingTokenHandle); // close existing handle result += "DuplicateToken() failed with error code: " + nErrorCode + "\r\n"; return null; } } finally { // close handle(s) if (pExistingTokenHandle != IntPtr.Zero) { CloseHandle(pExistingTokenHandle); } if (pDuplicateTokenHandle != IntPtr.Zero) { CloseHandle(pDuplicateTokenHandle); } } } </code></pre> <p>When this is called for the nested impersonation which fails, "bImpersonated" is actually "true", as is bRetVal, which suggests its worked, however when it gets to "WindowsIdentity.GetCurrent().Name" it fails with the exception above. </p> <p>I hope this makes sense, and would appreciate any assistance.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload