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)