mirror of https://github.com/winsw/winsw
Allow prompting for credentials
parent
5efcc8aca5
commit
afe25d1d82
|
@ -207,13 +207,24 @@ namespace winsw
|
|||
allowServiceLogonRight = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (descriptor.HasServiceAccount())
|
||||
else if (descriptor.HasServiceAccount())
|
||||
{
|
||||
username = descriptor.ServiceAccountUserName;
|
||||
password = descriptor.ServiceAccountPassword;
|
||||
allowServiceLogonRight = descriptor.AllowServiceAcountLogonRight;
|
||||
|
||||
if (username is null || password is null)
|
||||
{
|
||||
switch (descriptor.ServiceAccountPrompt)
|
||||
{
|
||||
case "dialog":
|
||||
PropmtForCredentialsDialog();
|
||||
break;
|
||||
|
||||
case "console":
|
||||
PromptForCredentialsConsole();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,6 +268,116 @@ namespace winsw
|
|||
{
|
||||
EventLog.CreateEventSource(eventLogSource, "Application");
|
||||
}
|
||||
|
||||
void PropmtForCredentialsDialog()
|
||||
{
|
||||
username ??= string.Empty;
|
||||
password ??= string.Empty;
|
||||
|
||||
int inBufferSize = 0;
|
||||
_ = CredentialApis.CredPackAuthenticationBuffer(
|
||||
0,
|
||||
username,
|
||||
password,
|
||||
IntPtr.Zero,
|
||||
ref inBufferSize);
|
||||
|
||||
IntPtr inBuffer = Marshal.AllocCoTaskMem(inBufferSize);
|
||||
try
|
||||
{
|
||||
if (!CredentialApis.CredPackAuthenticationBuffer(
|
||||
0,
|
||||
username,
|
||||
password,
|
||||
inBuffer,
|
||||
ref inBufferSize))
|
||||
{
|
||||
Throw.Win32Exception("Failed to pack auth buffer.");
|
||||
}
|
||||
|
||||
CredentialApis.CREDUI_INFO info = new CredentialApis.CREDUI_INFO
|
||||
{
|
||||
Size = Marshal.SizeOf(typeof(CredentialApis.CREDUI_INFO)),
|
||||
CaptionText = "Windows Service Wrapper", // TODO
|
||||
MessageText = "service account credentials", // TODO
|
||||
};
|
||||
uint authPackage = 0;
|
||||
bool save = false;
|
||||
int error = CredentialApis.CredUIPromptForWindowsCredentials(
|
||||
info,
|
||||
0,
|
||||
ref authPackage,
|
||||
inBuffer,
|
||||
inBufferSize,
|
||||
out IntPtr outBuffer,
|
||||
out uint outBufferSize,
|
||||
ref save,
|
||||
CredentialApis.CREDUIWIN_GENERIC);
|
||||
|
||||
if (error != Errors.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int userNameLength = 0;
|
||||
int passwordLength = 0;
|
||||
_ = CredentialApis.CredUnPackAuthenticationBuffer(
|
||||
0,
|
||||
outBuffer,
|
||||
outBufferSize,
|
||||
null,
|
||||
ref userNameLength,
|
||||
default,
|
||||
default,
|
||||
null,
|
||||
ref passwordLength);
|
||||
|
||||
username = userNameLength == 0 ? null : new string('\0', userNameLength - 1);
|
||||
password = passwordLength == 0 ? null : new string('\0', passwordLength - 1);
|
||||
|
||||
if (!CredentialApis.CredUnPackAuthenticationBuffer(
|
||||
0,
|
||||
outBuffer,
|
||||
outBufferSize,
|
||||
username,
|
||||
ref userNameLength,
|
||||
default,
|
||||
default,
|
||||
password,
|
||||
ref passwordLength))
|
||||
{
|
||||
Throw.Win32Exception("Failed to unpack auth buffer.");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(outBuffer);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(inBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void PromptForCredentialsConsole()
|
||||
{
|
||||
if (username is null)
|
||||
{
|
||||
Console.Write("Username: ");
|
||||
username = Console.ReadLine();
|
||||
}
|
||||
|
||||
if (password is null)
|
||||
{
|
||||
Console.Write("Password: ");
|
||||
password = ReadPassword();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
void Uninstall()
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace winsw.Native
|
||||
{
|
||||
internal static class CredentialApis
|
||||
{
|
||||
internal const uint CREDUIWIN_GENERIC = 0x00000001;
|
||||
|
||||
[DllImport(Libraries.CredUI, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CredPackAuthenticationBufferW")]
|
||||
internal static extern bool CredPackAuthenticationBuffer(
|
||||
uint flags,
|
||||
string userName,
|
||||
string password,
|
||||
IntPtr packedCredentials,
|
||||
ref int packedCredentialsSize);
|
||||
|
||||
[DllImport(Libraries.CredUI, SetLastError = false, CharSet = CharSet.Unicode, EntryPoint = "CredUIPromptForWindowsCredentialsW")]
|
||||
internal static extern int CredUIPromptForWindowsCredentials(
|
||||
in CREDUI_INFO uiInfo,
|
||||
uint authError,
|
||||
ref uint authPackage,
|
||||
IntPtr inAuthBuffer,
|
||||
int inAuthBufferSize,
|
||||
out IntPtr outAuthBuffer,
|
||||
out uint outAuthBufferSize,
|
||||
ref bool save,
|
||||
uint flags);
|
||||
|
||||
[DllImport(Libraries.CredUI, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CredUnPackAuthenticationBufferW")]
|
||||
internal static extern bool CredUnPackAuthenticationBuffer(
|
||||
uint flags,
|
||||
IntPtr authBuffer,
|
||||
uint authBufferSize,
|
||||
string? userName,
|
||||
ref int maxUserName,
|
||||
string? domainName,
|
||||
IntPtr maxDomainName,
|
||||
string? password,
|
||||
ref int maxPassword);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct CREDUI_INFO
|
||||
{
|
||||
internal int Size;
|
||||
internal IntPtr ParentWindow;
|
||||
internal string MessageText;
|
||||
internal string CaptionText;
|
||||
internal IntPtr BannerBitmap;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
internal static class Errors
|
||||
{
|
||||
internal const int ERROR_SUCCESS = 0;
|
||||
internal const int ERROR_ACCESS_DENIED = 5;
|
||||
internal const int ERROR_INVALID_HANDLE = 6;
|
||||
internal const int ERROR_INVALID_PARAMETER = 7;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
internal static class Libraries
|
||||
{
|
||||
internal const string Advapi32 = "advapi32.dll";
|
||||
internal const string CredUI = "credui.dll";
|
||||
internal const string Kernel32 = "kernel32.dll";
|
||||
internal const string NtDll = "ntdll.dll";
|
||||
}
|
||||
|
|
|
@ -643,6 +643,8 @@ namespace winsw
|
|||
return null;
|
||||
}
|
||||
|
||||
public string? ServiceAccountPrompt => GetServiceAccountPart("prompt")?.ToLowerInvariant();
|
||||
|
||||
protected string? AllowServiceLogon => GetServiceAccountPart("allowservicelogon");
|
||||
|
||||
public string? ServiceAccountPassword => GetServiceAccountPart("password");
|
||||
|
@ -651,7 +653,7 @@ namespace winsw
|
|||
|
||||
public bool HasServiceAccount()
|
||||
{
|
||||
return !string.IsNullOrEmpty(ServiceAccountUserName);
|
||||
return this.dom.SelectSingleNode("//serviceaccount") != null;
|
||||
}
|
||||
|
||||
public bool AllowServiceAcountLogonRight
|
||||
|
|
Loading…
Reference in New Issue