< Summary

Class:Impersonate.Impersonator
Assembly:SharpHoundCommonLib
File(s):D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Impersonate.cs
Covered lines:0
Uncovered lines:46
Coverable lines:46
Total lines:178
Line coverage:0% (0 of 46)
Covered branches:0
Total branches:10
Branch coverage:0% (0 of 10)

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%100%
.ctor(...)100%100%
.ctor()100%100%
Dispose()100%100%
Impersonate(...)0%800%
UndoImpersonation()0%200%

File(s)

D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Impersonate.cs

#LineLine coverage
 1//credit to Phillip Allan-Harding (Twitter @phillipharding) for this library.
 2
 3using System;
 4using System.ComponentModel;
 5using System.Runtime.InteropServices;
 6using System.Security.Principal;
 7using System.Xml.Linq;
 8
 9namespace Impersonate {
 10    public enum LogonType {
 11        LOGON32_LOGON_INTERACTIVE = 2,
 12        LOGON32_LOGON_NETWORK = 3,
 13        LOGON32_LOGON_BATCH = 4,
 14        LOGON32_LOGON_SERVICE = 5,
 15        LOGON32_LOGON_UNLOCK = 7,
 16        LOGON32_LOGON_NETWORK_CLEARTEXT = 8, // Win2K or higher
 17        LOGON32_LOGON_NEW_CREDENTIALS = 9 // Win2K or higher
 18    };
 19
 20    public enum LogonProvider {
 21        LOGON32_PROVIDER_DEFAULT = 0,
 22        LOGON32_PROVIDER_WINNT35 = 1,
 23        LOGON32_PROVIDER_WINNT40 = 2,
 24        LOGON32_PROVIDER_WINNT50 = 3
 25    };
 26
 27    public enum ImpersonationLevel {
 28        SecurityAnonymous = 0,
 29        SecurityIdentification = 1,
 30        SecurityImpersonation = 2,
 31        SecurityDelegation = 3
 32    }
 33
 34    class Win32NativeMethods {
 35        [DllImport("advapi32.dll", SetLastError = true)]
 36        public static extern int LogonUser(string lpszUserName,
 37            string lpszDomain,
 38            string lpszPassword,
 39            int dwLogonType,
 40            int dwLogonProvider,
 41            ref IntPtr phToken);
 42
 43        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 44        public static extern int DuplicateToken(IntPtr hToken,
 45            int impersonationLevel,
 46            ref IntPtr hNewToken);
 47
 48        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 49        public static extern bool RevertToSelf();
 50
 51        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 52        public static extern bool CloseHandle(IntPtr handle);
 53    }
 54
 55    /// <summary>
 56    /// Allows code to be executed under the security context of a specified user account.
 57    /// </summary>
 58    /// <remarks>
 59    ///
 60    /// Implements IDispose, so can be used via a using-directive or method calls;
 61    ///  ...
 62    ///
 63    ///  var imp = new Impersonator( "myUsername", "myDomainname", "myPassword" );
 64    ///  imp.UndoImpersonation();
 65    ///
 66    ///  ...
 67    ///
 68    ///   var imp = new Impersonator();
 69    ///  imp.Impersonate("myUsername", "myDomainname", "myPassword");
 70    ///  imp.UndoImpersonation();
 71    ///
 72    ///  ...
 73    ///
 74    ///  using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
 75    ///  {
 76    ///   ...
 77    ///   1
 78    ///   ...
 79    ///  }
 80    ///
 81    ///  ...
 82    /// </remarks>
 83    public class Impersonator : IDisposable {
 84        private WindowsImpersonationContext _wic;
 85
 86        /// <summary>
 87        /// Begins impersonation with the given credentials, Logon type and Logon provider.
 88        /// </summary>
 89        ///<param name = "userName" > Name of the user.</param>
 90        ///<param name = "domainName" > Name of the domain.</param>
 91        ///<param name = "password" > The password. <see cref = "System.String" /></ param >
 92        ///< param name="logonType">Type of the logon.</param>
 93        ///<param name = "logonProvider" > The logon provider. <see cref = "Mit.Sharepoint.WebParts.EventLogQuery.Networ
 094        public Impersonator(string userName, string domainName, string password, LogonType logonType,
 095            LogonProvider logonProvider) {
 096            Impersonate(userName, domainName, password, logonType, logonProvider);
 097        }
 98
 99        /// <summary>
 100        /// Begins impersonation with the given credentials.
 101        /// </summary>
 102        ///<param name = "userName" > Name of the user.</param>
 103        ///<param name = "domainName" > Name of the domain.</param>
 104        ///<param name = "password" > The password. <see cref = "System.String" /></ param >
 0105        public Impersonator(string userName, string domainName, string password) {
 0106            Impersonate(userName, domainName, password, LogonType.LOGON32_LOGON_INTERACTIVE,
 0107                LogonProvider.LOGON32_PROVIDER_DEFAULT);
 0108        }
 109
 110        /// <summary>
 111        /// Initializes a new instance of the <see cref="Impersonator"/> class.
 112        /// </summary>
 0113        public Impersonator() {
 0114        }
 115
 116        /// <summary>
 117        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 118        /// </summary>
 0119        public void Dispose() {
 0120            UndoImpersonation();
 0121        }
 122
 123        /// <summary>
 124        /// Impersonates the specified user account.
 125        /// </summary>
 126        ///<param name = "userName" > Name of the user.</param>
 127        ///<param name = "domainName" > Name of the domain.</param>
 128        ///<param name = "password" > The password. <see cref = "System.String" /></ param >
 129        ///< param name="logonType">Type of the logon.</param>
 130        ///<param name = "logonProvider" > The logon provider. <see cref = "Mit.Sharepoint.WebParts.EventLogQuery.Networ
 131        public void Impersonate(string userName, string domainName, string password, LogonType logonType = LogonType.LOG
 0132            LogonProvider logonProvider = LogonProvider.LOGON32_PROVIDER_DEFAULT) {
 0133            UndoImpersonation();
 134
 0135            IntPtr logonToken = IntPtr.Zero;
 0136            IntPtr logonTokenDuplicate = IntPtr.Zero;
 0137            try {
 138                // revert to the application pool identity, saving the identity of the current requestor
 0139                _wic = WindowsIdentity.Impersonate(IntPtr.Zero);
 140
 141                // do logon & impersonate
 0142                if (Win32NativeMethods.LogonUser(userName,
 0143                        domainName,
 0144                        password,
 0145                        (int)logonType,
 0146                        (int)logonProvider,
 0147                        ref logonToken) != 0) {
 0148                    if (Win32NativeMethods.DuplicateToken(logonToken, (int)ImpersonationLevel.SecurityImpersonation,
 0149                            ref logonTokenDuplicate) != 0) {
 0150                        var wi = new WindowsIdentity(logonTokenDuplicate);
 0151                        wi.Impersonate(); // discard the returned identity context (which is the context of the applicat
 0152                    }
 153                    else
 0154                        throw new Win32Exception(Marshal.GetLastWin32Error());
 0155                }
 156                else
 0157                    throw new Win32Exception(Marshal.GetLastWin32Error());
 0158            }
 0159            finally {
 0160                if (logonToken != IntPtr.Zero)
 0161                    Win32NativeMethods.CloseHandle(logonToken);
 162
 0163                if (logonTokenDuplicate != IntPtr.Zero)
 0164                    Win32NativeMethods.CloseHandle(logonTokenDuplicate);
 0165            }
 0166        }
 167
 168        /// <summary>
 169        /// Stops impersonation.
 170        /// </summary>
 0171        private void UndoImpersonation() {
 172            // restore saved requestor identity
 0173            if (_wic != null)
 0174                _wic.Undo();
 0175            _wic = null;
 0176        }
 177    }
 178}