launcher, launchctl: StartWithSecret

This commit is contained in:
Bill Zissimopoulos 2016-06-28 23:09:10 -07:00
parent c0344f53b0
commit 518cd0e8c0
5 changed files with 287 additions and 18 deletions

View File

@ -110,6 +110,7 @@
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -128,6 +129,7 @@
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -149,6 +151,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -170,6 +173,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@ -18,6 +18,7 @@
#include <dll/library.h> #include <dll/library.h>
#include <launcher/launcher.h> #include <launcher/launcher.h>
#include <npapi.h> #include <npapi.h>
#include <wincred.h>
#define FSP_NP_NAME LIBRARY_NAME ".Np" #define FSP_NP_NAME LIBRARY_NAME ".Np"
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */ #define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
@ -403,7 +404,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags) LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
{ {
DWORD NpResult; DWORD NpResult;
WCHAR UserName[256], Password[256]; WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH], Password[CREDUI_MAX_PASSWORD_LENGTH];
/* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */ /* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */
if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT))) if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT)))

View File

@ -115,7 +115,8 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
} }
int start(PWSTR PipeBuf, ULONG PipeBufSize, int start(PWSTR PipeBuf, ULONG PipeBufSize,
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv) PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv,
BOOLEAN HasSecret)
{ {
PWSTR P; PWSTR P;
DWORD ClassNameSize, InstanceNameSize, ArgvSize; DWORD ClassNameSize, InstanceNameSize, ArgvSize;
@ -130,7 +131,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
P = PipeBuf; P = PipeBuf;
*P++ = LauncherSvcInstanceStart; *P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize; memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize; memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
for (DWORD Argi = 0; Argc > Argi; Argi++) for (DWORD Argi = 0; Argc > Argi; Argi++)
@ -230,7 +231,17 @@ int wmain(int argc, wchar_t **argv)
if (3 > argc || argc > 12) if (3 > argc || argc > 12)
usage(); usage();
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3); return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
FALSE);
}
else
if (0 == lstrcmpW(L"startWithSecret", argv[0]))
{
if (3 > argc || argc > 12)
usage();
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
TRUE);
} }
else else
if (0 == lstrcmpW(L"stop", argv[0])) if (0 == lstrcmpW(L"stop", argv[0]))

View File

@ -21,6 +21,53 @@
#define PROGNAME "WinFsp.Launcher" #define PROGNAME "WinFsp.Launcher"
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services" #define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
BOOL CreateOverlappedPipe(
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
DWORD ReadMode, DWORD WriteMode)
{
RPC_STATUS RpcStatus;
UUID Uuid;
WCHAR PipeNameBuf[MAX_PATH];
HANDLE ReadPipe, WritePipe;
DWORD LastError;
RpcStatus = UuidCreate(&Uuid);
if (S_OK != RpcStatus && RPC_S_UUID_LOCAL_ONLY != RpcStatus)
{
SetLastError(ERROR_INTERNAL_ERROR);
return FALSE;
}
wsprintfW(PipeNameBuf, L"\\\\.\\pipe\\"
"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
Uuid.Data1, Uuid.Data2, Uuid.Data3,
Uuid.Data4[0], Uuid.Data4[1], Uuid.Data4[2], Uuid.Data4[3],
Uuid.Data4[4], Uuid.Data4[5], Uuid.Data4[6], Uuid.Data4[7]);
ReadPipe = CreateNamedPipeW(PipeNameBuf,
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
1, Size, Size, 120 * 1000, SecurityAttributes);
if (INVALID_HANDLE_VALUE == ReadPipe)
return FALSE;
WritePipe = CreateFileW(PipeNameBuf,
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
if (INVALID_HANDLE_VALUE == WritePipe)
{
LastError = GetLastError();
CloseHandle(ReadPipe);
SetLastError(LastError);
return FALSE;
}
*PReadPipe = ReadPipe;
*PWritePipe = WritePipe;
return TRUE;
}
typedef struct typedef struct
{ {
HANDLE Process; HANDLE Process;
@ -80,6 +127,7 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
typedef struct typedef struct
{ {
LONG RefCount;
PWSTR ClassName; PWSTR ClassName;
PWSTR InstanceName; PWSTR InstanceName;
PWSTR CommandLine; PWSTR CommandLine;
@ -87,6 +135,7 @@ typedef struct
DWORD ProcessId; DWORD ProcessId;
HANDLE Process; HANDLE Process;
HANDLE ProcessWait; HANDLE ProcessWait;
HANDLE StdioHandles[2];
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
WCHAR Buffer[]; WCHAR Buffer[];
} SVC_INSTANCE; } SVC_INSTANCE;
@ -231,8 +280,129 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
return Result; return Result;
} }
NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
HANDLE StdioHandles[2],
PPROCESS_INFORMATION ProcessInfo)
{
STARTUPINFOEXW StartupInfoEx;
HANDLE ChildHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
SIZE_T Size;
NTSTATUS Result;
memset(&StartupInfoEx, 0, sizeof StartupInfoEx);
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
if (0 != StdioHandles)
{
/*
* Create child process and redirect stdin/stdout. Do *not* inherit other handles.
*
* For explanation see:
* https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873/
*/
/* create stdin read/write ends; make them inheritable */
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
0, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
/* create stdout read/write ends; make them inheritable */
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
FILE_FLAG_OVERLAPPED, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
Size = 0;
if (!InitializeProcThreadAttributeList(0, 1, 0, &Size) &&
ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
AttrList = MemAlloc(Size);
if (0 == AttrList)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (!InitializeProcThreadAttributeList(AttrList, 1, 0, &Size))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
/* only the child ends of stdin/stdout are actually inherited */
if (!UpdateProcThreadAttribute(AttrList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
ChildHandles, sizeof ChildHandles, 0, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
StartupInfoEx.lpAttributeList = AttrList;
StartupInfoEx.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
StartupInfoEx.StartupInfo.hStdInput = ChildHandles[0];
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
StartupInfoEx.StartupInfo.hStdError = INVALID_HANDLE_VALUE;
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
(PVOID)&StartupInfoEx, ProcessInfo))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
else
{
if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE,
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
&StartupInfoEx.StartupInfo, ProcessInfo))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
}
Result = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(Result))
{
if (INVALID_HANDLE_VALUE != ParentHandles[0])
CloseHandle(ParentHandles[0]);
if (INVALID_HANDLE_VALUE != ParentHandles[0])
CloseHandle(ParentHandles[0]);
}
else if (0 != StdioHandles)
{
StdioHandles[0] = ParentHandles[0];
StdioHandles[1] = ParentHandles[1];
}
if (INVALID_HANDLE_VALUE != ChildHandles[0])
CloseHandle(ChildHandles[0]);
if (INVALID_HANDLE_VALUE != ChildHandles[1])
CloseHandle(ChildHandles[1]);
MemFree(AttrList);
return Result;
}
NTSTATUS SvcInstanceCreate(HANDLE ClientToken, NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job, PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
BOOLEAN RedirectStdio,
SVC_INSTANCE **PSvcInstance) SVC_INSTANCE **PSvcInstance)
{ {
SVC_INSTANCE *SvcInstance = 0; SVC_INSTANCE *SvcInstance = 0;
@ -244,7 +414,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
DWORD JobControl; DWORD JobControl;
PSECURITY_DESCRIPTOR SecurityDescriptor = 0; PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
PWSTR Argv[10]; PWSTR Argv[10];
STARTUPINFOW StartupInfo;
PROCESS_INFORMATION ProcessInfo; PROCESS_INFORMATION ProcessInfo;
NTSTATUS Result; NTSTATUS Result;
@ -259,7 +428,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
Argv[0] = 0; Argv[0] = 0;
Argc++; Argc++;
memset(&StartupInfo, 0, sizeof StartupInfo);
memset(&ProcessInfo, 0, sizeof ProcessInfo); memset(&ProcessInfo, 0, sizeof ProcessInfo);
EnterCriticalSection(&SvcInstanceLock); EnterCriticalSection(&SvcInstanceLock);
@ -353,23 +521,23 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
} }
memset(SvcInstance, 0, sizeof *SvcInstance); memset(SvcInstance, 0, sizeof *SvcInstance);
SvcInstance->RefCount = 2;
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize); memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize); memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
SvcInstance->ClassName = SvcInstance->Buffer; SvcInstance->ClassName = SvcInstance->Buffer;
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR); SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
SvcInstance->SecurityDescriptor = SecurityDescriptor; SvcInstance->SecurityDescriptor = SecurityDescriptor;
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine); Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
goto exit; goto exit;
StartupInfo.cb = sizeof StartupInfo; Result = SvcInstanceCreateProcess(Executable, CommandLine,
if (!CreateProcessW(Executable, SvcInstance->CommandLine, 0, 0, FALSE, RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfo, &ProcessInfo)) if (!NT_SUCCESS(Result))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit; goto exit;
}
SvcInstance->ProcessId = ProcessInfo.dwProcessId; SvcInstance->ProcessId = ProcessInfo.dwProcessId;
SvcInstance->Process = ProcessInfo.hProcess; SvcInstance->Process = ProcessInfo.hProcess;
@ -413,6 +581,11 @@ exit:
if (0 != SvcInstance) if (0 != SvcInstance)
{ {
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
CloseHandle(SvcInstance->StdioHandles[0]);
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
CloseHandle(SvcInstance->StdioHandles[1]);
if (0 != SvcInstance->ProcessWait) if (0 != SvcInstance->ProcessWait)
UnregisterWaitEx(SvcInstance->ProcessWait, 0); UnregisterWaitEx(SvcInstance->ProcessWait, 0);
@ -435,13 +608,21 @@ exit:
return Result; return Result;
} }
VOID SvcInstanceDelete(SVC_INSTANCE *SvcInstance) static VOID SvcInstanceRelease(SVC_INSTANCE *SvcInstance)
{ {
if (0 != InterlockedDecrement(&SvcInstance->RefCount))
return;
EnterCriticalSection(&SvcInstanceLock); EnterCriticalSection(&SvcInstanceLock);
if (RemoveEntryList(&SvcInstance->ListEntry)) if (RemoveEntryList(&SvcInstance->ListEntry))
SetEvent(SvcInstanceEvent); SetEvent(SvcInstanceEvent);
LeaveCriticalSection(&SvcInstanceLock); LeaveCriticalSection(&SvcInstanceLock);
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
CloseHandle(SvcInstance->StdioHandles[0]);
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
CloseHandle(SvcInstance->StdioHandles[1]);
if (0 != SvcInstance->ProcessWait) if (0 != SvcInstance->ProcessWait)
UnregisterWaitEx(SvcInstance->ProcessWait, 0); UnregisterWaitEx(SvcInstance->ProcessWait, 0);
if (0 != SvcInstance->Process) if (0 != SvcInstance->Process)
@ -457,15 +638,79 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
{ {
SVC_INSTANCE *SvcInstance = Context; SVC_INSTANCE *SvcInstance = Context;
SvcInstanceDelete(SvcInstance); SvcInstanceRelease(SvcInstance);
} }
NTSTATUS SvcInstanceStart(HANDLE ClientToken, NTSTATUS SvcInstanceStart(HANDLE ClientToken,
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job) PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job,
BOOLEAN HasSecret)
{ {
SVC_INSTANCE *SvcInstance; SVC_INSTANCE *SvcInstance;
NTSTATUS Result;
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, Job, &SvcInstance); HasSecret = HasSecret && 0 < Argc && L'\0' != Argv[Argc - 1][0];
Result = SvcInstanceCreate(ClientToken, ClassName, InstanceName,
Argc - HasSecret, Argv, Job, HasSecret,
&SvcInstance);
if (!NT_SUCCESS(Result))
return Result;
if (!HasSecret)
Result = STATUS_SUCCESS;
else
{
PWSTR Secret = Argv[Argc - 1];
UINT8 RspBuf[2];
DWORD BytesTransferred;
OVERLAPPED Overlapped;
if (!WriteFile(SvcInstance->StdioHandles[0], Secret, lstrlenW(Secret), &BytesTransferred, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
memset(&Overlapped, 0, sizeof Overlapped);
if (!ReadFile(SvcInstance->StdioHandles[1], RspBuf, sizeof RspBuf, 0, &Overlapped) &&
ERROR_IO_PENDING != GetLastError())
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
if (!GetOverlappedResultEx(SvcInstance->StdioHandles[1], &Overlapped, &BytesTransferred,
LAUNCHER_START_WITH_SECRET_TIMEOUT, FALSE))
{
if (WAIT_TIMEOUT == GetLastError())
Result = STATUS_TIMEOUT;
else
Result = FspNtStatusFromWin32(GetLastError());
CancelIoEx(SvcInstance->StdioHandles[1], &Overlapped);
goto exit;
}
if (sizeof RspBuf <= BytesTransferred && 'O' == RspBuf[0] && 'K' == RspBuf[1])
Result = STATUS_SUCCESS;
else
Result = STATUS_ACCESS_DENIED;
}
exit:
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
{
CloseHandle(SvcInstance->StdioHandles[0]);
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
{
CloseHandle(SvcInstance->StdioHandles[1]);
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
}
SvcInstanceRelease(SvcInstance);
return Result;
} }
NTSTATUS SvcInstanceStop(HANDLE ClientToken, NTSTATUS SvcInstanceStop(HANDLE ClientToken,
@ -909,12 +1154,16 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR); PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
PWSTR ClassName, InstanceName; PWSTR ClassName, InstanceName;
ULONG Argc; PWSTR Argv[9]; ULONG Argc; PWSTR Argv[9];
BOOLEAN HasSecret = FALSE;
NTSTATUS Result; NTSTATUS Result;
*PSize = 0; *PSize = 0;
switch (*P++) switch (*P++)
{ {
case LauncherSvcInstanceStartWithSecret:
HasSecret = TRUE;
/* fall through! */
case LauncherSvcInstanceStart: case LauncherSvcInstanceStart:
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd); ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd); InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
@ -924,7 +1173,8 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
Result = STATUS_INVALID_PARAMETER; Result = STATUS_INVALID_PARAMETER;
if (0 != ClassName && 0 != InstanceName) if (0 != ClassName && 0 != InstanceName)
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob); Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob,
HasSecret);
SvcPipeTransactResult(Result, PipeBuf, PSize); SvcPipeTransactResult(Result, PipeBuf, PSize);
break; break;

View File

@ -28,6 +28,8 @@
#define LAUNCHER_PIPE_BUFFER_SIZE 2048 #define LAUNCHER_PIPE_BUFFER_SIZE 2048
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000 #define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 30000
/* /*
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and * The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the * GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
@ -53,6 +55,7 @@
enum enum
{ {
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */ LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */ LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */ LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
LauncherSvcInstanceList = 'L', /* requires: none*/ LauncherSvcInstanceList = 'L', /* requires: none*/