Posted By

dmilligan on 09/06/09


Tagged

security Impersonate WindowsIdentity Impersonator


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

umang_nine


Impersonator


 / Published in: C#
 

Impersonation of a user to allow code to execute code under another user context.

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Security.Principal;
  5. using System.Runtime.InteropServices;
  6. using System.ComponentModel;
  7.  
  8. namespace MyNamespace.Security
  9. {
  10. /// <summary>
  11. /// Impersonation of a user. Allows to execute code under another
  12. /// user context.
  13. /// Please note that the account that instantiates the Impersonator class
  14. /// needs to have the 'Act as part of operating system' privilege set.
  15. /// </summary>
  16. /// <remarks>
  17. /// This class is based on the information in the Microsoft knowledge base
  18. /// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
  19. ///
  20. /// Encapsulate an instance into a using-directive like e.g.:
  21. ///
  22. /// ...
  23. /// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
  24. /// {
  25. /// ...
  26. /// [code that executes under the new context]
  27. /// ...
  28. /// }
  29. /// ...
  30. ///
  31. /// </remarks>
  32. public class Impersonator : IDisposable
  33. {
  34. #region Public methods
  35.  
  36. /// <summary>
  37. /// Constructor. Starts the impersonation with the given credentials.
  38. /// Please note that the account that instantiates the Impersonator class
  39. /// needs to have the 'Act as part of operating system' privilege set.
  40. /// </summary>
  41. /// <param name="userName">The name of the user to act as.</param>
  42. /// <param name="domainName">The domain name of the user to act as.</param>
  43. /// <param name="password">The password of the user to act as.</param>
  44. public Impersonator(string userName, string domainName, string password)
  45. {
  46. ImpersonateValidUser(userName, domainName, password);
  47. }
  48.  
  49. /// <summary>
  50. /// Constructor. Starts the impersonation with the given credentials.
  51. /// Please note that the account that instantiates the Impersonator class
  52. /// needs to have the 'Act as part of operating system' privilege set.
  53. /// </summary>
  54. /// <param name="userName">The name of the user to act as.</param>
  55. /// <param name="domainName">The domain name of the user to act as. also can be the name of the server the account resides on</param>
  56. /// <param name="password">The password of the user to act as.</param>
  57. /// <param name="newCredentials">Set to </param>
  58. public Impersonator(string userName, string domainName, string password, bool newCredentials)
  59. {
  60. ImpersonateValidUser(userName, domainName, password, LOGON32_LOGON_NEW_CREDENTIALS);
  61. }
  62.  
  63. #endregion
  64.  
  65. #region IDisposable
  66.  
  67. public void Dispose()
  68. {
  69. UndoImpersonation();
  70. }
  71.  
  72.  
  73. #endregion
  74.  
  75. #region P/Invoke
  76.  
  77. [DllImport("advapi32.dll", SetLastError = true)]
  78. private static extern int LogonUser(
  79. string lpszUserName,
  80. string lpszDomain,
  81. string lpszPassword,
  82. int dwLogonType,
  83. int dwLogonProvider,
  84. ref IntPtr phToken);
  85.  
  86. [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  87. private static extern int DuplicateToken(
  88. IntPtr hToken,
  89. int impersonationLevel,
  90. ref IntPtr hNewToken);
  91.  
  92. [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  93. private static extern bool RevertToSelf();
  94.  
  95. [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  96. private static extern bool CloseHandle(
  97. IntPtr handle);
  98.  
  99. private const int LOGON32_PROVIDER_DEFAULT = 0;
  100.  
  101. private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
  102. private const int LOGON32_LOGON_INTERACTIVE = 2;
  103. #endregion
  104.  
  105. #region Private member.
  106.  
  107. /// <summary>
  108. /// Does the actual impersonation.
  109. /// </summary>
  110. /// <param name="userName">The name of the user to act as.</param>
  111. /// <param name="domainName">The domain name of the user to act as.</param>
  112. /// <param name="password">The password of the user to act as.</param>
  113. private void ImpersonateValidUser(string userName, string domain, string password, int provider)
  114. {
  115. WindowsIdentity tempWindowsIdentity = null;
  116. IntPtr token = IntPtr.Zero;
  117. IntPtr tokenDuplicate = IntPtr.Zero;
  118.  
  119. try
  120. {
  121. if (RevertToSelf())
  122. {
  123. if (LogonUser(
  124. userName,
  125. domain,
  126. password,
  127. provider,
  128. LOGON32_PROVIDER_DEFAULT,
  129. ref token) != 0)
  130. {
  131. if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
  132. {
  133. tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
  134. impersonationContext = tempWindowsIdentity.Impersonate();
  135. }
  136. else
  137. {
  138. throw new Win32Exception(Marshal.GetLastWin32Error());
  139. }
  140. }
  141. else
  142. {
  143. throw new Win32Exception(Marshal.GetLastWin32Error());
  144. }
  145. }
  146. else
  147. {
  148. throw new Win32Exception(Marshal.GetLastWin32Error());
  149. }
  150. }
  151. finally
  152. {
  153. if (token != IntPtr.Zero)
  154. {
  155. CloseHandle(token);
  156. }
  157. if (tokenDuplicate != IntPtr.Zero)
  158. {
  159. CloseHandle(tokenDuplicate);
  160. }
  161. }
  162. }
  163. /// <summary>
  164. /// Does the actual impersonation.
  165. /// </summary>
  166. /// <param name="userName">The name of the user to act as.</param>
  167. /// <param name="domainName">The domain name of the user to act as.</param>
  168. /// <param name="password">The password of the user to act as.</param>
  169. private void ImpersonateValidUser(string userName, string domain, string password)
  170. {
  171. ImpersonateValidUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE);
  172. }
  173.  
  174. /// <summary>
  175. /// Reverts the impersonation.
  176. /// </summary>
  177. private void UndoImpersonation()
  178. {
  179. if (impersonationContext != null)
  180. {
  181. impersonationContext.Undo();
  182. }
  183. }
  184.  
  185. private WindowsImpersonationContext impersonationContext = null;
  186.  
  187. #endregion
  188. }
  189. }

Report this snippet  

You need to login to post a comment.