private static SafeNativeHandle GetPrimaryTokenForUser(SecurityIdentifier sid, List <string> requiredPrivileges = null) { NativeHelpers.ProcessAccessFlags accessFlags = NativeHelpers.ProcessAccessFlags.PROCESS_QUERY_INFORMATION; // According to CreateProcessWithTokenW we require a token with // TOKEN_QUERY, TOKEN_DUPLICATE and TOKEN_ASSIGN_PRIMARY // Also add in TOKEN_IMPERSONATE so we can get an impersonated token TokenAccessLevels dwAccess = TokenAccessLevels.Query | TokenAccessLevels.Duplicate | TokenAccessLevels.AssignPrimary | TokenAccessLevels.Impersonate; foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses()) { using (process) { using (SafeNativeHandle hProcess = NativeMethods.OpenProcess(accessFlags, false, (UInt32)process.Id)) { if (hProcess.IsInvalid) { continue; } SafeNativeHandle hToken; NativeMethods.OpenProcessToken(hProcess, dwAccess, out hToken); if (hToken.IsInvalid) { continue; } using (hToken) { if (!sid.Equals(GetTokenUserSID(hToken))) { continue; } // Filter out any Network logon tokens, using become with that is useless when S4U // can give us a Batch logon NativeHelpers.SECURITY_LOGON_TYPE tokenLogonType = GetTokenLogonType(hToken); if (tokenLogonType == NativeHelpers.SECURITY_LOGON_TYPE.Network) { continue; } // Check that the required privileges are on the token if (requiredPrivileges != null) { List <string> actualPrivileges = GetTokenPrivileges(hToken); int missing = requiredPrivileges.Where(x => !actualPrivileges.Contains(x)).Count(); if (missing > 0) { continue; } } SafeNativeHandle dupToken; if (!NativeMethods.DuplicateTokenEx(hToken, TokenAccessLevels.MaximumAllowed, IntPtr.Zero, NativeHelpers.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, NativeHelpers.TOKEN_TYPE.TokenPrimary, out dupToken)) { continue; } return(dupToken); } } } } return(null); }
public static extern SafeNativeHandle OpenProcess( NativeHelpers.ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId);