From fcbc087b4be31b768e78167448412f4e6c214b52 Mon Sep 17 00:00:00 2001
From: NextTurn <45985406+NextTurn@users.noreply.github.com>
Date: Sat, 1 Aug 2020 00:00:00 +0800
Subject: [PATCH] Handle special accounts
---
src/WinSW.Core/Native/Security.cs | 28 +++++++++++++--------------
src/WinSW.Core/Native/SecurityApis.cs | 5 +----
src/WinSW/Program.cs | 18 +++++++++++++----
3 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/src/WinSW.Core/Native/Security.cs b/src/WinSW.Core/Native/Security.cs
index d91e466..9720ff1 100644
--- a/src/WinSW.Core/Native/Security.cs
+++ b/src/WinSW.Core/Native/Security.cs
@@ -9,9 +9,9 @@ namespace WinSW.Native
{
///
///
- internal static void AddServiceLogonRight(string userName)
+ internal static void AddServiceLogonRight(ref string userName)
{
- IntPtr sid = GetAccountSid(userName);
+ IntPtr sid = GetAccountSid(ref userName);
try
{
@@ -19,13 +19,12 @@ namespace WinSW.Native
}
finally
{
- _ = FreeSid(sid);
Marshal.FreeHGlobal(sid);
}
}
///
- private static IntPtr GetAccountSid(string accountName)
+ private static IntPtr GetAccountSid(ref string accountName)
{
int sidSize = 0;
int domainNameLength = 0;
@@ -35,24 +34,23 @@ namespace WinSW.Native
accountName = Environment.MachineName + accountName.Substring(1);
}
- _ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, IntPtr.Zero, ref domainNameLength, out _);
+ _ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, null, ref domainNameLength, out _);
IntPtr sid = Marshal.AllocHGlobal(sidSize);
- IntPtr domainName = Marshal.AllocHGlobal(domainNameLength * sizeof(char));
+ string? domainName = domainNameLength == 0 ? null : new string('\0', domainNameLength - 1);
- try
+ if (!LookupAccountName(null, accountName, sid, ref sidSize, domainName, ref domainNameLength, out _))
{
- if (!LookupAccountName(null, accountName, sid, ref sidSize, domainName, ref domainNameLength, out _))
- {
- Throw.Command.Win32Exception("Failed to find the account.");
- }
+ Throw.Command.Win32Exception("Failed to find the account.");
+ }
- return sid;
- }
- finally
+ // intentionally undocumented
+ if (!accountName.Contains("\\") && !accountName.Contains("@"))
{
- Marshal.FreeHGlobal(domainName);
+ accountName = domainName + '\\' + accountName;
}
+
+ return sid;
}
///
diff --git a/src/WinSW.Core/Native/SecurityApis.cs b/src/WinSW.Core/Native/SecurityApis.cs
index 5b1c88b..14c0929 100644
--- a/src/WinSW.Core/Native/SecurityApis.cs
+++ b/src/WinSW.Core/Native/SecurityApis.cs
@@ -7,9 +7,6 @@ namespace WinSW.Native
{
internal static class SecurityApis
{
- [DllImport(Libraries.Advapi32, SetLastError = false)]
- internal static extern IntPtr FreeSid(IntPtr sid);
-
[DllImport(Libraries.Advapi32, SetLastError = true)]
internal static extern bool GetTokenInformation(
IntPtr tokenHandle,
@@ -24,7 +21,7 @@ namespace WinSW.Native
string accountName,
IntPtr sid,
ref int sidSize,
- IntPtr referencedDomainName,
+ string? referencedDomainName,
ref int referencedDomainNameLength,
out int use);
diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs
index d988e13..93e188d 100644
--- a/src/WinSW/Program.cs
+++ b/src/WinSW/Program.cs
@@ -345,7 +345,7 @@ namespace WinSW
username = config.ServiceAccountUserName ?? username;
password = config.ServiceAccountPassword ?? password;
- if (username is null || password is null)
+ if (username is null || password is null && !IsSpecialAccount(username))
{
switch (config.ServiceAccountPrompt)
{
@@ -364,9 +364,9 @@ namespace WinSW
}
}
- if (username != null)
+ if (username != null && !IsSpecialAccount(username))
{
- Security.AddServiceLogonRight(username);
+ Security.AddServiceLogonRight(ref username);
}
using Service sc = scm.CreateService(
@@ -422,7 +422,7 @@ namespace WinSW
username = Console.ReadLine();
}
- if (password is null)
+ if (password is null && !IsSpecialAccount(username))
{
Console.Write("Password: ");
password = ReadPassword();
@@ -430,6 +430,16 @@ namespace WinSW
Console.WriteLine();
}
+
+ static bool IsSpecialAccount(string accountName) => accountName switch
+ {
+ @"LocalSystem" => true,
+ @".\LocalSystem" => true,
+ @"NT AUTHORITY\LocalService" => true,
+ @"NT AUTHORITY\NetworkService" => true,
+ string name when name == $@"{Environment.MachineName}\LocalSystem" => true,
+ _ => false
+ };
}
void Uninstall(string? pathToConfig, bool noElevate)