using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Security.Principal; namespace ZeroLevel.Services.Impersonation { /// /// The class implements the translation of the program execution to the rights of the specified user. /// [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public class Impersonation : IDisposable { private WindowsImpersonationContext impersonationContext; #region Private methods /// /// Assigning rights to the current process from the specified process, by copying its token /// /// Process pointer private void ImpersonateByProcess(IntPtr hProcess) { MySafeTokenHandle token; if (!ImpersonationNativeMethods.OpenProcessToken(hProcess, ImpersonationNativeMethods.TokenDesiredAccess.TOKEN_DUPLICATE, out token)) throw new ApplicationException("Failed to get the process token. Win32 error code: " + Marshal.GetLastWin32Error()); ImpersonateToken(token); } /// /// The method assigns a duplicate token to the current process. /// /// Token private void ImpersonateToken(MySafeTokenHandle token) { MySafeTokenHandle tokenDuplicate; WindowsIdentity tempWindowsIdentity; using (token) { if (ImpersonationNativeMethods.DuplicateToken(token, (int)ImpersonationNativeMethods.SecurityImpersonationLevel.SecurityImpersonation, out tokenDuplicate) != 0) { using (tokenDuplicate) { if (!tokenDuplicate.IsInvalid) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate.DangerousGetHandle()); impersonationContext = tempWindowsIdentity.Impersonate(); return; } } } else throw new Exception("Failed to create a duplicate of the specified token. Win32 error code: " + Marshal.GetLastWin32Error()); } } #endregion Private methods #region Public methods /// /// Login as a specified user /// /// User name /// User domain /// User password /// false - if failed to log in with the specified data public void ImpersonateByUser(String userName, String domain, String password) { MySafeTokenHandle token; if (ImpersonationNativeMethods.LogonUserA(userName, domain, password, (int)ImpersonationNativeMethods.LogonType.LOGON32_LOGON_INTERACTIVE, (int)ImpersonationNativeMethods.LogonProvider.LOGON32_PROVIDER_DEFAULT, out token) != 0) { ImpersonateToken(token); } else { throw new Exception("LogonUser failed: " + Marshal.GetLastWin32Error().ToString()); } } /// /// Login on behalf of the specified user with the authorization method /// /// Login /// Domain /// Password /// Authorization Type public void ImpersonateByUser(String userName, String domain, String password, ImpersonationNativeMethods.LogonType logonType) { MySafeTokenHandle token; if (ImpersonationNativeMethods.LogonUserA(userName, domain, password, (int)logonType, (int)ImpersonationNativeMethods.LogonProvider.LOGON32_PROVIDER_DEFAULT, out token) != 0) { ImpersonateToken(token); } else { throw new Exception("LogonUser failed: " + Marshal.GetLastWin32Error().ToString()); } } /// /// Copying the rights of the specified process /// /// Process name public void ImpersonateByProcess(string ProcessName) { Process[] myProcesses = Process.GetProcesses(); foreach (Process currentProcess in myProcesses) { if (currentProcess.ProcessName.Equals(ProcessName, StringComparison.OrdinalIgnoreCase)) { ImpersonateByProcess(currentProcess.Handle); break; } } } /// /// Copying the rights of the specified process /// /// Process id public void ImpersonateByProcess(int ProcessID) { Process[] myProcesses = Process.GetProcesses(); foreach (Process currentProcess in myProcesses) { if (currentProcess.Id == ProcessID) { ImpersonateByProcess(currentProcess.Handle); break; } } } #endregion Public methods /// /// When releasing resources, we will return the previous user right /// public void Dispose() { impersonationContext?.Undo(); impersonationContext?.Dispose(); GC.SuppressFinalize(this); } } }