.NET library for managing local security policy (User Rights Assignment). This library was written to use in PowerShell Module SecurityPolicy providing easy way to manage local security policy.
ConstantName | Group Policy Setting |
---|---|
SeTrustedCredManAccessPrivilege | Access Credential Manager as a trusted caller |
SeNetworkLogonRight | Access this computer from the network |
SeTcbPrivilege | Act as part of the operating system |
SeMachineAccountPrivilege | Add workstations to domain |
SeIncreaseQuotaPrivilege | Adjust memory quotas for a process |
SeInteractiveLogonRight | Allow log on locally |
SeRemoteInteractiveLogonRight | Allow log on through Remote Desktop Services |
SeBackupPrivilege | Back up files and directories |
SeChangeNotifyPrivilege | Bypass traverse checking |
SeSystemtimePrivilege | Change the system time |
SeTimeZonePrivilege | Change the time zone |
SeCreatePagefilePrivilege | Create a pagefile |
SeCreateTokenPrivilege | Create a token object |
SeCreateGlobalPrivilege | Create global objects |
SeCreatePermanentPrivilege | Create permanent shared objects |
SeCreateSymbolicLinkPrivilege | Create symbolic links |
SeDebugPrivilege | Debug programs |
SeDenyNetworkLogonRight | Deny access to this computer from the network |
SeDenyBatchLogonRight | Deny log on as a batch job |
SeDenyServiceLogonRight | Deny log on as a service |
SeDenyInteractiveLogonRight | Deny log on locally |
SeDenyRemoteInteractiveLogonRight | Deny log on through Remote Desktop Services |
SeEnableDelegationPrivilege | Enable computer and user accounts to be trusted for delegation |
SeRemoteShutdownPrivilege | Force shutdown from a remote system |
SeAuditPrivilege | Generate security audits |
SeImpersonatePrivilege | Impersonate a client after authentication |
SeIncreaseWorkingSetPrivilege | Increase a process working set |
SeIncreaseBasePriorityPrivilege | Increase scheduling priority |
SeLoadDriverPrivilege | Load and unload device drivers |
SeLockMemoryPrivilege | Lock pages in memory |
SeBatchLogonRight | Log on as a batch job |
SeServiceLogonRight | Log on as a service |
SeSecurityPrivilege | Manage auditing and security log |
SeRelabelPrivilege | Modify an object label |
SeSystemEnvironmentPrivilege | Modify firmware environment values |
SeDelegateSessionUserImpersonatePrivilege | Obtain an impersonation token for another user in the same session |
SeManageVolumePrivilege | Perform volume maintenance tasks |
SeProfileSingleProcessPrivilege | Profile single process |
SeSystemProfilePrivilege | Profile system performance |
SeUndockPrivilege | Remove computer from docking station |
SeAssignPrimaryTokenPrivilege | Replace a process level token |
SeRestorePrivilege | Restore files and directories |
SeShutdownPrivilege | Shut down the system |
SeSyncAgentPrivilege | Synchronize directory service data |
SeTakeOwnershipPrivilege | Take ownership of files or other objects |
using System;
using LocalSecurityEditor;
namespace TestApp {
internal class Program {
static void Main() {
string[] accounts;
Console.WriteLine("[*] Accessing server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper()) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
Console.WriteLine("[*] Adding Account to the Server");
using (LsaWrapper lsa = new LsaWrapper()) {
lsa.AddPrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
}
Console.WriteLine("[*] Accessing server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper()) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
Console.WriteLine("[*] Accessing server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper()) {
lsa.RemovePrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
}
using (LsaWrapper lsa = new LsaWrapper("")) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
}
}
}
using System;
using LocalSecurityEditor;
namespace TestApp {
internal class Program {
static void Main() {
string[] accounts;
Console.WriteLine("[*] Accessing AD1 server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper("AD1")) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
Console.WriteLine("[*] Adding Account to the Server");
using (LsaWrapper lsa = new LsaWrapper("AD1")) {
lsa.AddPrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
}
Console.WriteLine("[*] Accessing AD1 server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper("AD1")) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
Console.WriteLine("[*] Accessing AD1 server - Displaying Current");
using (LsaWrapper lsa = new LsaWrapper("AD1")) {
lsa.RemovePrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
}
using (LsaWrapper lsa = new LsaWrapper("AD1")) {
accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
}
foreach (var account in accounts) {
Console.WriteLine(account);
}
}
}
}
string serviceName = "ADSync";
string serviceExpectedSid = "S-1-5-80-3245704983-3664226991-764670653-2504430226-901976451";
string serviceSid = NTService.GenerateSID(serviceName);
Console.WriteLine($"The SID for the service '{serviceName}' is: {serviceSid} {serviceExpectedSid} {(serviceSid == serviceExpectedSid)}");
using LocalSecurityEditor;
// Get state for a right (local machine)
var svc = UserRightsAssignment.SeServiceLogonRight.Get();
foreach (var p in svc.Principals) {
Console.WriteLine($"{p.AccountName} -> {p.SidString}");
}
// Manage rights on a remote system (batching via manager)
using (var ur = new UserRights("SERVER01")) {
// Add by account name or SID
ur.Add(UserRightsAssignment.SeBatchLogonRight, new [] { @"DOMAIN\\svc_batch", "S-1-5-32-544" });
// Replace entire set for a right (adds missing, removes extras)
var result = ur.Set(UserRightsAssignment.SeDenyRemoteInteractiveLogonRight,
new [] { @"DOMAIN\\contractor1", @"DOMAIN\\contractor2" });
Console.WriteLine(result); // e.g., SeDenyRemoteInteractiveLogonRight: +1 -0
}
// Performance tip: For many operations, prefer reusing a single UserRights instance
// Less efficient (allocates per call):
// right.Add("user1"); right.Add("user2"); right.Add("user3");
// Better:
// using var ur = new UserRights();
// ur.Add(right, new [] { "user1", "user2", "user3" });
### Async APIs
// Query a single right asynchronously (local)
var state = await new UserRights().GetStateAsync(UserRightsAssignment.SeServiceLogonRight, ct);
// Enumerate all rights asynchronously (remote)
var all = await new UserRights("SERVER01").EnumerateAsync(ct);
// Grant/remove asynchronously
await new UserRights().AddAsync(UserRightsAssignment.SeBatchLogonRight, new[] { @"DOMAIN\\user1" }, ct);
await new UserRights().RemoveAsync(UserRightsAssignment.SeBatchLogonRight, new[] { @"DOMAIN\\user1" }, ct);
// Fluent async extensions
var svc = await UserRightsAssignment.SeServiceLogonRight.GetAsync("SERVER01", ct);
### Thread Safety
- `UserRights`/`LsaWrapper` can be shared safely across tasks.
- Internally uses a reader–writer lock:
- Parallel reads allowed (Get/GetState/Enumerate).
- Writes (Add/Remove/Set) are exclusive.
- Dispose is exclusive and waits for in-flight operations.
- Guidance:
- For many operations, reuse a single `UserRights` instance (reads may run in parallel).
- For heavy fan-out, you can also create per-task instances.
### Aggregate URA Objects (PowerShell-friendly)
```csharp
// One object per user right, each with Principals[]
var all = UserRights.Get(); // static Get() overload — local machine
// stream lazily
foreach (var ura in new UserRights().EnumerateLazy()) { /* ... */ }
// or as dictionary keyed by enum
var byRight = new UserRights().GetByRight(); // instance when batching
// or keyed by ShortName (e.g., "SeServiceLogonRight")
var byShort = new UserRights().GetByShortName();
// Single right as typed object
var single = UserRightsAssignment.SeServiceLogonRight.Get(); // single right via extension
Console.WriteLine($"{single.Name} has {single.Count} principals");
### Credits
This library was created based on help from mutliple sources. Without those, it wouldn't be possible.
- Willy Denoyette [MVP]
- [LSA Functions - Privileges and Impersonation](https://www.codeproject.com/Articles/4863/LSA-Functions-Privileges-and-Impersonation)
- [How to access local security policy of computer using C#](https://social.msdn.microsoft.com/Forums/lync/en-US/3c0e7d5c-a786-45a1-aa65-a4a2a934c0cb/how-to-access-local-security-policy-of-computer-using-c-?forum=csharpgeneral)
- [Programmatically updating local policy in Windows](https://web.archive.org/web/20161006162851/http://www.lshift.net/blog/2013/03/25/programmatically-updating-local-policy-in-windows/)