Wednesday, June 21, 2006

Sometimes it is necessary to change the user under whose account asp.net runs to execute a special method. This could be the case e.g. if you want to access an ADS with a local asp.net user and you get an error message "invalid username or password" (there is the possibility to pass a username and passwort, but that didn't work for me).

The usage of the class below is very simple:

...
Impersonation
imp = new Impersonation();
imp.ImpersonateValidUser(
"username", "domain", "password");
//execute your work here
imp.UndoImpersonation();
....




using
System;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace
Security
{

   public class Impersonation
   
{

      
public const int LOGON32_LOGON_INTERACTIVE = 2;
      
public const int LOGON32_PROVIDER_DEFAULT = 0;
      
WindowsImpersonationContext impersonationContext;

      [DllImport("advapi32.dll")]
      
public static extern int LogonUserA(String lpszUserName, 
         
String lpszDomain,
         
String lpszPassword,
         
int dwLogonType, 
         
int dwLogonProvider,
         
ref IntPtr phToken);
      
      [
DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
      
public static extern int DuplicateToken(IntPtr hToken, 
         
int impersonationLevel, 
         
ref IntPtr hNewToken);

      [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
      
public static extern bool RevertToSelf();

      [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
      
public static extern bool CloseHandle(IntPtr handle);

      public bool ImpersonateValidUser(String userName, String domain, String password)
      {
         
WindowsIdentity tempWindowsIdentity;
         
IntPtr token = IntPtr.Zero;
         
IntPtr tokenDuplicate = IntPtr.Zero;
         
         
if(RevertToSelf())
         {
            
if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
               LOGON32_PROVIDER_DEFAULT,
ref token) != 0)
            {
               
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
               {
                  tempWindowsIdentity =
new WindowsIdentity(tokenDuplicate);
                  impersonationContext = tempWindowsIdentity.Impersonate();
                  
if (impersonationContext != null)
                  {
                     CloseHandle(token);
                     CloseHandle(tokenDuplicate);
                     
return true;
                  }
               }
            } 
         }

         if(token!= IntPtr.Zero) CloseHandle(token);
         
if(tokenDuplicate!=IntPtr.Zero) CloseHandle(tokenDuplicate);
         
return false;
      
}

      public void UndoImpersonation()
      {
         impersonationContext.Undo();
      }

   }
}

6/21/2006 8:07:46 AM (Mitteleuropäische Sommerzeit , UTC+02:00)  #    Disclaimer  |  Comments [1]  |