mirror of https://github.com/winsw/winsw
86 lines
2.5 KiB
C#
86 lines
2.5 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Runtime.InteropServices;
|
|
using static winsw.Native.SecurityApis;
|
|
|
|
namespace winsw.Native
|
|
{
|
|
internal static class Security
|
|
{
|
|
internal static void AddServiceLogonRight(string domain, string user)
|
|
{
|
|
IntPtr sid = GetAccountSid(domain, user);
|
|
|
|
try
|
|
{
|
|
AddAccountRight(sid, AccountRights.SE_SERVICE_LOGON_NAME);
|
|
}
|
|
finally
|
|
{
|
|
_ = FreeSid(sid);
|
|
Marshal.FreeHGlobal(sid);
|
|
}
|
|
}
|
|
|
|
private static IntPtr GetAccountSid(string domain, string user)
|
|
{
|
|
int sidSize = 0;
|
|
int domainNameLength = 0;
|
|
|
|
if (domain == ".")
|
|
{
|
|
domain = Environment.MachineName;
|
|
}
|
|
|
|
string accountName = domain + "\\" + user;
|
|
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, IntPtr.Zero, ref domainNameLength, out _);
|
|
|
|
IntPtr sid = Marshal.AllocHGlobal(sidSize);
|
|
IntPtr domainName = Marshal.AllocHGlobal(domainNameLength * sizeof(char));
|
|
|
|
try
|
|
{
|
|
if (!LookupAccountName(null, accountName, sid, ref sidSize, domainName, ref domainNameLength, out _))
|
|
{
|
|
Throw.Win32Exception("Failed to find the account.");
|
|
}
|
|
|
|
return sid;
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(domainName);
|
|
}
|
|
}
|
|
|
|
private static void AddAccountRight(IntPtr sid, string rightName)
|
|
{
|
|
uint status = LsaOpenPolicy(IntPtr.Zero, default, PolicyAccess.ALL_ACCESS, out IntPtr policyHandle);
|
|
if (status != 0)
|
|
{
|
|
throw new Win32Exception(LsaNtStatusToWinError(status));
|
|
}
|
|
|
|
try
|
|
{
|
|
LSA_UNICODE_STRING userRight = new LSA_UNICODE_STRING
|
|
{
|
|
Buffer = rightName,
|
|
Length = (ushort)(rightName.Length * sizeof(char)),
|
|
MaximumLength = (ushort)((rightName.Length + 1) * sizeof(char)),
|
|
};
|
|
|
|
status = LsaAddAccountRights(policyHandle, sid, userRight, 1);
|
|
if (status != 0)
|
|
{
|
|
throw new Win32Exception(LsaNtStatusToWinError(status));
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
_ = LsaClose(policyHandle);
|
|
}
|
|
}
|
|
}
|
|
}
|