using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Security.Principal; namespace ZeroLevel.Services.Impersonation { /// /// Класс реализует перевод исполнения программы на права указанного пользователя /// [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public class Impersonation : IDisposable { WindowsImpersonationContext impersonationContext; #region Private methods /// /// Назначение текущему процессу прав от указанного процесса, путем копирования его токена /// /// Указатель на процесс private void ImpersonateByProcess(IntPtr hProcess) { MySafeTokenHandle token; if (!ImpersonationNativeMethods.OpenProcessToken(hProcess, ImpersonationNativeMethods.TokenDesiredAccess.TOKEN_DUPLICATE, out token)) throw new ApplicationException("Не удалось получить токен процесса. Win32 код ошибки: " + Marshal.GetLastWin32Error()); ImpersonateToken(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("Не удалось создать дубликат указанного токена. Win32 код ошибки: " + Marshal.GetLastWin32Error()); } } #endregion #region Public methods /// /// Вход от имени указанного пользователя /// /// Имя пользователя /// Домен /// Пароль /// false - если не удалось выполнить вход по указанным данным 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()); } } /// /// Вход от имени указанного пользователя с указанием способа авторизации /// /// Имя пользователя /// Домен /// Пароль /// Тип авторизации 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()); } } /// /// Копирование прав указанного процесса /// /// Имя процесса 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; } } } /// /// Копирование прав указанного процесса /// /// Идентификатор процесса public void ImpersonateByProcess(int ProcessID) { Process[] myProcesses = Process.GetProcesses(); foreach (Process currentProcess in myProcesses) { if (currentProcess.Id == ProcessID) { ImpersonateByProcess(currentProcess.Handle); break; } } } #endregion /// /// При освобождении рессурсов вернем предыдущего пользователя /// public void Dispose() { impersonationContext?.Undo(); impersonationContext?.Dispose(); GC.SuppressFinalize(this); } } }