using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using Vanara.InteropServices;
using Vanara.PInvoke;
using static Vanara.PInvoke.AdvApi32;
namespace Vanara.Security.AccessControl
{
/// Privilege determining the type of system operations that can be performed.
[TypeConverter(typeof(SystemPrivilegeTypeConverter))]
public enum SystemPrivilege
{
InteractiveLogon = 0x00000001,
/// Required for an account to log on using the network logon type.
NetworkLogon = 0x00000002,
/// Required for an account to log on using the batch logon type.
BatchLogon = 0x00000004,
/// Required for an account to log on using the service logon type.
ServiceLogon = 0x00000010,
/// Explicitly denies an account the right to log on using the interactive logon type.
DenyInteractiveLogon = 0x00000040,
/// Explicitly denies an account the right to log on using the network logon type.
DenyNetworkLogon = 0x00000080,
/// Explicitly denies an account the right to log on using the batch logon type.
DenyBatchLogon = 0x00000100,
/// Explicitly denies an account the right to log on using the service logon type.
DenyServiceLogon = 0x00000200,
/// Remote interactive logon
RemoteInteractiveLogon = 0x00000400,
/// Explicitly denies an account the right to log on remotely using the interactive logon type.
DenyRemoteInteractiveLogon = 0x00000800,
/// Privilege to replace a process-level token.
AssignPrimaryToken = 0x00001000,
/// Privilege to generate security audits.
Audit,
/// Privilege to backup files and directories.
Backup,
/// Privilege to bypass traverse checking.
ChangeNotify,
/// Privilege to create global objects.
CreateGlobal,
/// Privilege to create a pagefile.
CreatePageFile,
/// Privilege to create permanent shared objects.
CreatePermanent,
/// Privilege to create symbolic links.
CreateSymbolicLink,
/// Privilege to create a token object.
CreateToken,
/// Privilege to debug programs.
Debug,
/// Privilege to delegate session using user impersonation.
DelegateSessionUserImpersonate,
/// Privilege to enable computer and user accounts to be trusted for delegation.
EnableDelegation,
/// Privilege to impersonate a client after authentication.
Impersonate,
/// Privilege to increase scheduling priority.
IncreaseBasePriority,
/// Privilege to adjust memory quotas for a process.
IncreaseQuota,
/// Privilege to increase a process working set.
IncreaseWorkingSet,
/// Privilege to load and unload device drivers.
LoadDriver,
/// Privilege to lock pages in memory.
LockMemory,
/// Privilege to add workstations to domain.
MachineAccount,
/// Privilege to manage the files on a volume.
ManageVolume,
/// Privilege to profile single process.
ProfileSingleProcess,
/// Privilege to modify an object label.
Relabel,
/// Privilege to force shutdown from a remote system.
RemoteShutdown,
/// Privilege to restore files and directories.
Restore,
/// Privilege to manage auditing and security log.
Security,
/// Privilege to shut down the system.
Shutdown,
/// Privilege to synchronize directory service data.
SyncAgent,
/// Privilege to modify firmware environment values.
SystemEnvironment,
/// Privilege to profile system performance.
SystemProfile,
/// Privilege to change the system time.
SystemTime,
/// Privilege to take ownership of files or other objects.
TakeOwnership,
/// Privilege to act as part of the operating system.
TrustedComputerBase,
/// Privilege to change the time zone.
TimeZone,
/// Privilege to access Credential Manager as a trusted caller.
TrustedCredentialManagerAccess,
/// Privilege to remove computer from docking station.
Undock,
/// Privilege to read unsolicited input from a terminal device.
UnsolicitedInput
}
/// Extension methods for for working with privileges.
public static class PrivilegeExtension
{
public static SafeCoTaskMemHandle AdjustPrivilege(this SafeTokenHandle hObj, SystemPrivilege priv, PrivilegeAttributes attr)
{
var newState = new PTOKEN_PRIVILEGES(priv.GetLUID(), attr);
var prevState = PTOKEN_PRIVILEGES.GetAllocatedAndEmptyInstance();
var retLen = (uint)prevState.Size;
if (!AdjustTokenPrivileges(hObj, false, newState, newState.SizeInBytes, prevState, ref retLen))
throw new Win32Exception();
prevState.Size = (int)retLen;
return prevState;
}
public static SafeCoTaskMemHandle AdjustPrivileges(this SafeTokenHandle hObj, params PrivilegeAndAttributes[] privileges)
{
if (privileges == null || privileges.Length == 0) return SafeCoTaskMemHandle.Null;
var newState = new PTOKEN_PRIVILEGES(privileges.Select(pa => new LUID_AND_ATTRIBUTES(pa.Privilege.GetLUID(), pa.Attributes)).ToArray());
var prevState = PTOKEN_PRIVILEGES.GetAllocatedAndEmptyInstance();
var retLen = (uint)prevState.Size;
if (!AdjustTokenPrivileges(hObj, false, newState, newState.SizeInBytes, prevState, ref retLen))
throw new Win32Exception();
prevState.Size = (int)retLen;
return prevState;
}
public static void AdjustPrivileges(this SafeTokenHandle hObj, PTOKEN_PRIVILEGES privileges)
{
if (privileges == null) return;
uint retLen = 0;
if (!AdjustTokenPrivileges(hObj, false, privileges, (uint)privileges.SizeInBytes, null, ref retLen))
throw new Win32Exception();
}
public static void AdjustPrivileges(this SafeTokenHandle hObj, SafeCoTaskMemHandle privileges)
{
if (privileges == null || privileges.IsInvalid) return;
uint retLen = 0;
if (!AdjustTokenPrivileges(hObj, false, privileges, (uint)privileges.Size, SafeCoTaskMemHandle.Null, ref retLen))
throw new Win32Exception();
}
public static LUID GetLUID(this SystemPrivilege systemPrivilege, string systemName = null) => SystemPrivilegeTypeConverter.GetLUID(systemPrivilege, systemName);
public static SystemPrivilege GetPrivilege(this LUID luid, string systemName = null) => SystemPrivilegeTypeConverter.GetPrivilege(luid, systemName);
public static bool HasPrivilege(this SafeTokenHandle hObj, SystemPrivilege priv) => HasPrivileges(hObj, true, priv);
public static bool HasPrivileges(this SafeTokenHandle hObj, bool requireAll, params SystemPrivilege[] privs)
{
if (!PrivilegeCheck(hObj, new PRIVILEGE_SET((PrivilegeSetControl)(requireAll ? 1 : 0), privs.Select(p => new LUID_AND_ATTRIBUTES(p.GetLUID(), PrivilegeAttributes.SE_PRIVILEGE_ENABLED)).ToArray()), out bool ret))
Win32Error.ThrowLastError();
return ret;
}
public static IEnumerable GetPrivileges(this SafeTokenHandle hObj) =>
hObj.GetInfo(TOKEN_INFORMATION_CLASS.TokenPrivileges).Privileges;
}
internal class SystemPrivilegeTypeConverter : TypeConverter
{
internal static readonly Dictionary PrivLookup =
new Dictionary(35)
{
{ SystemPrivilege.AssignPrimaryToken, "SeAssignPrimaryTokenPrivilege" },
{ SystemPrivilege.Audit, "SeAuditPrivilege" },
{ SystemPrivilege.Backup, "SeBackupPrivilege" },
{ SystemPrivilege.ChangeNotify, "SeChangeNotifyPrivilege" },
{ SystemPrivilege.CreateGlobal, "SeCreateGlobalPrivilege" },
{ SystemPrivilege.CreatePageFile, "SeCreatePagefilePrivilege" },
{ SystemPrivilege.CreatePermanent, "SeCreatePermanentPrivilege" },
{ SystemPrivilege.CreateSymbolicLink, "SeCreateSymbolicLinkPrivilege" },
{ SystemPrivilege.CreateToken, "SeCreateTokenPrivilege" },
{ SystemPrivilege.Debug, "SeDebugPrivilege" },
{ SystemPrivilege.DelegateSessionUserImpersonate, "SeDelegateSessionUserImpersonatePrivilege" },
{ SystemPrivilege.EnableDelegation, "SeEnableDelegationPrivilege" },
{ SystemPrivilege.Impersonate, "SeImpersonatePrivilege" },
{ SystemPrivilege.IncreaseBasePriority, "SeIncreaseBasePriorityPrivilege" },
{ SystemPrivilege.IncreaseQuota, "SeIncreaseQuotaPrivilege" },
{ SystemPrivilege.IncreaseWorkingSet, "SeIncreaseWorkingSetPrivilege" },
{ SystemPrivilege.LoadDriver, "SeLoadDriverPrivilege" },
{ SystemPrivilege.LockMemory, "SeLockMemoryPrivilege" },
{ SystemPrivilege.MachineAccount, "SeMachineAccountPrivilege" },
{ SystemPrivilege.ManageVolume, "SeManageVolumePrivilege" },
{ SystemPrivilege.ProfileSingleProcess, "SeProfileSingleProcessPrivilege" },
{ SystemPrivilege.Relabel, "SeRelabelPrivilege" },
{ SystemPrivilege.RemoteShutdown, "SeRemoteShutdownPrivilege" },
{ SystemPrivilege.Restore, "SeRestorePrivilege" },
{ SystemPrivilege.Security, "SeSecurityPrivilege" },
{ SystemPrivilege.Shutdown, "SeShutdownPrivilege" },
{ SystemPrivilege.SyncAgent, "SeSyncAgentPrivilege" },
{ SystemPrivilege.SystemEnvironment, "SeSystemEnvironmentPrivilege" },
{ SystemPrivilege.SystemProfile, "SeSystemProfilePrivilege" },
{ SystemPrivilege.SystemTime, "SeSystemTimePrivilege" },
{ SystemPrivilege.TakeOwnership, "SeTakeOwnershipPrivilege" },
{ SystemPrivilege.TrustedComputerBase, "SeTcbPrivilege" },
{ SystemPrivilege.TimeZone, "SeTimeZonePrivilege" },
{ SystemPrivilege.TrustedCredentialManagerAccess, "SeTrustedCredManAccessPrivilege" },
{ SystemPrivilege.Undock, "SeUndockPrivilege" },
{ SystemPrivilege.UnsolicitedInput, "SeUnsolicitedInputPrivilege" },
{ SystemPrivilege.InteractiveLogon, "SeInteractiveLogonRight" },
{ SystemPrivilege.NetworkLogon, "SeNetworkLogonRight" },
{ SystemPrivilege.BatchLogon, "SeBatchLogonRight" },
{ SystemPrivilege.ServiceLogon, "SeServiceLogonRight" },
{ SystemPrivilege.DenyInteractiveLogon, "SeDenyInteractiveLogonRight" },
{ SystemPrivilege.DenyNetworkLogon, "SeDenyNetworkLogonRight" },
{ SystemPrivilege.DenyBatchLogon, "SeDenyBatchLogonRight" },
{ SystemPrivilege.DenyServiceLogon, "SeDenyServiceLogonRight" },
{ SystemPrivilege.RemoteInteractiveLogon, "SeRemoteInteractiveLogonRight" },
{ SystemPrivilege.DenyRemoteInteractiveLogon, "SeDenyRemoteInteractiveLogonRight" },
};
private static readonly Dictionary luidLookup = new Dictionary();
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) =>
sourceType == typeof(string) || sourceType == typeof(LUID) || base.CanConvertFrom(context, sourceType);
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) =>
destinationType == typeof(string) || destinationType == typeof(LUID) || base.CanConvertTo(context, destinationType);
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string s)
{
try { var val = (SystemPrivilege)Enum.Parse(typeof(SystemPrivilege), s, true); return val; } catch { }
try { return ConvertKnownString(s); } catch { }
}
if (value is LUID luid)
return GetPrivilege(luid);
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
return PrivLookup[(SystemPrivilege)value];
if (destinationType == typeof(LUID))
return GetLUID((SystemPrivilege)value);
return base.ConvertTo(context, culture, value, destinationType);
}
internal static SystemPrivilege ConvertKnownString(string s)
{
try { return PrivLookup.First(v => string.Equals(s, v.Value, StringComparison.OrdinalIgnoreCase)).Key; }
catch { throw new ArgumentOutOfRangeException(nameof(s), "Unrecognized privilege string."); }
}
internal static LUID GetLUID(SystemPrivilege systemPrivilege, string systemName = null)
{
LUID val;
lock (luidLookup)
{
if (!luidLookup.TryGetValue(systemPrivilege, out val))
{
val = LUID.FromName(PrivLookup[systemPrivilege], systemName);
luidLookup.Add(systemPrivilege, val);
}
}
return val;
}
internal static SystemPrivilege GetPrivilege(LUID luid, string systemName = null) => ConvertKnownString(luid.GetName(systemName));
}
}