// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Runtime.InteropServices; using System.Security.Principal; namespace Spludlow { /// /// Impersonate within a using{} block /// Generally speaking you shouldn't use impersonation, your application should be running as a user with the correct permissions assigned, but sometimes it comes in handy /// Note, impersonation can still not give you the permissions you expect depending on what you are doing. /// It seems to work pretty well for accessing the filesystem and file shares, but other things may still give you access denied. /// public class Impersonation : IDisposable { public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0; [DllImport("advapi32.dll")] public static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); private WindowsImpersonationContext ImpersonationContext = null; public Impersonation(string key) { if (key == null) return; NetworkCredential credential = Spludlow.Credentials.GetCredential(key); if (this.Impersonate(credential) == false) throw new ApplicationException("Impersonation failed:\t" + key); } private bool Impersonate(NetworkCredential credential) { WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if (RevertToSelf()) { if (LogonUserA(credential.UserName, credential.Domain, credential.Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); this.ImpersonationContext = tempWindowsIdentity.Impersonate(); if (this.ImpersonationContext != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if (token != IntPtr.Zero) CloseHandle(token); if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } public void Dispose() { if (this.ImpersonationContext != null) { this.ImpersonationContext.Undo(); this.ImpersonationContext.Dispose(); } } } }