title: Impersonation and DirectoryEntry
body: <p>I am impersonating a user account successfully, but I am not able to use the impersonated account to bind to AD and pull down a <code>DirectoryEntry</code>. </p>
  
  <p>The below code outputs:</p>
  
  <ul>
  <li>Before impersonation I am: DOMAIN\user</li>
  <li>After impersonation I am: DOMAIN\admin</li>
  <li>Error: C:\Users\user\ADSI_Impersonation\bin\Debug\ADSI_Impersonation.exe
  samaccountname:</li>
  </ul>
  
  <p>My issue seems similar to:</p>
  
  <p><a href="http://support.microsoft.com/kb/329986" rel="noreferrer">How to use the System.DirectoryServices namespace in ASP.NET</a></p>
  
  <p>I am obtaining a primary token. I understand that I need to use delegation to use the impersonated token on a remote computer. I confirmed that the account doesn't have the flag checked "Account is sensitive and cannot be delegated". I also confirmed that the Local Group Policy and Domain Group Policies are not preventing delegation: </p>
  
  <p>Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\</p>
  
  <p>What am I missing?</p>
  
  <p>Thanks!</p>
  
  <pre><code>using System;
  using System.DirectoryServices;
  using System.Security;
  using System.Security.Principal;
  using System.Runtime.InteropServices;
  using Microsoft.Win32.SafeHandles;
  using System.Runtime.ConstrainedExecution;
  
  namespace ADSI_Impersonation
  {
      class Program
      {
          [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
          public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
              int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
  
          [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
          public static extern bool CloseHandle(IntPtr handle);
  
          static void Main(string[] args)
          {
              const int LOGON32_PROVIDER_DEFAULT = 0;
              const int LOGON32_LOGON_INTERACTIVE = 2;
  
              string userName = "admin@domain.com";
              string password = "password";
  
              Console.WriteLine("Before impersonation I am: " + WindowsIdentity.GetCurrent().Name);
  
              SafeTokenHandle safeTokenHandle;
  
              try
              {
                  bool returnValue = LogonUser(userName, null, password,
                      LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                      out safeTokenHandle);
  
                  if (returnValue)
                  {
                      WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                      WindowsImpersonationContext impersonatedUser = newId.Impersonate();
                  }
                  else
                  {
                      Console.WriteLine("Unable to create impersonatedUser.");
                      return;
                  }
              }
              catch (Exception e)
              {
                  Console.WriteLine("Authentication error.\r\n" + e.Message);
              }
  
              Console.WriteLine("After impersonation I am: " + WindowsIdentity.GetCurrent().Name);
  
              string OU = "LDAP://dc=domain,dc=com";
              DirectoryEntry entry = new DirectoryEntry(OU);
              entry.AuthenticationType = AuthenticationTypes.Secure;
  
              DirectorySearcher mySearcher = new DirectorySearcher();
              mySearcher.SearchRoot = entry;
              mySearcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
              mySearcher.PropertiesToLoad.Add("cn");
              mySearcher.PropertiesToLoad.Add("samaccountname");
  
              string cn = "fistname mi. lastname";
              string samaccountname = "";
  
              try
              {
                  // Create the LDAP query and send the request
                  mySearcher.Filter = "(cn=" + cn + ")";
  
                  SearchResultCollection searchresultcollection = mySearcher.FindAll();
  
                  DirectoryEntry ADentry = searchresultcollection[0].GetDirectoryEntry();
  
                  Console.WriteLine("samaccountname: " + ADentry.Properties["samaccountname"].Value.ToString());
              }
              catch (Exception e)
              {
                  Console.WriteLine("Error: " + e.Message);
              }
  
              Console.WriteLine("samaccountname: " + samaccountname);
              Console.ReadLine();
          }
      }
  
      public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
      {
          private SafeTokenHandle()
              : base(true)
          {
          }
  
          [DllImport("kernel32.dll")]
          [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
          [SuppressUnmanagedCodeSecurity]
          [return: MarshalAs(UnmanagedType.Bool)]
          private static extern bool CloseHandle(IntPtr handle);
  
          protected override bool ReleaseHandle()
          {
              return CloseHandle(handle);
          }
      }
  }
  </code></pre>