diff --git a/build/VStudio/tools/launcher.vcxproj b/build/VStudio/tools/launcher.vcxproj index 8edcb1e1..e22a61c8 100644 --- a/build/VStudio/tools/launcher.vcxproj +++ b/build/VStudio/tools/launcher.vcxproj @@ -112,7 +112,7 @@ Console true true - %(AdditionalDependencies);rpcrt4.lib + %(AdditionalDependencies);rpcrt4.lib;userenv.lib $(OutDir)$(TargetName).public.pdb @@ -134,7 +134,7 @@ Console true true - %(AdditionalDependencies);rpcrt4.lib + %(AdditionalDependencies);rpcrt4.lib;userenv.lib $(OutDir)$(TargetName).public.pdb @@ -159,7 +159,7 @@ true true true - %(AdditionalDependencies);rpcrt4.lib + %(AdditionalDependencies);rpcrt4.lib;userenv.lib $(OutDir)$(TargetName).public.pdb @@ -184,7 +184,7 @@ true true true - %(AdditionalDependencies);rpcrt4.lib + %(AdditionalDependencies);rpcrt4.lib;userenv.lib $(OutDir)$(TargetName).public.pdb diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index 76b19d93..7e2a319a 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -17,6 +17,7 @@ #include #include +#include #define PROGNAME "WinFsp.Launcher" @@ -137,6 +138,103 @@ exit: return Result; } +static BOOL LogonCreateProcess( + PWSTR UserName, + LPCWSTR ApplicationName, + LPWSTR CommandLine, + LPSECURITY_ATTRIBUTES ProcessAttributes, + LPSECURITY_ATTRIBUTES ThreadAttributes, + BOOL InheritHandles, + DWORD CreationFlags, + LPVOID Environment, + LPCWSTR CurrentDirectory, + LPSTARTUPINFOW StartupInfo, + LPPROCESS_INFORMATION ProcessInformation) +{ + PWSTR DomainName = 0; + + if (0 != UserName) + { + if (0 == invariant_wcsicmp(UserName, L"LocalSystem")) + UserName = 0; + else + if (0 == invariant_wcsicmp(UserName, L"LocalService") || + 0 == invariant_wcsicmp(UserName, L"NetworkService")) + DomainName = L"NT AUTHORITY"; + else + { + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + } + + if (0 == UserName) + /* without a user name go ahead and call CreateProcessW */ + return CreateProcessW( + ApplicationName, + CommandLine, + ProcessAttributes, + ThreadAttributes, + InheritHandles, + CreationFlags, + Environment, + CurrentDirectory, + StartupInfo, + ProcessInformation); + + HANDLE LogonToken = 0; + PVOID EnvironmentBlock = 0; + DWORD LastError; + BOOL Success; + + Success = LogonUserW( + UserName, + DomainName, + 0, + LOGON32_LOGON_SERVICE, + LOGON32_PROVIDER_DEFAULT, + &LogonToken); + if (!Success) + goto exit; + + if (0 == Environment) + { + Success = CreateEnvironmentBlock(&EnvironmentBlock, LogonToken, FALSE); + if (!Success) + goto exit; + + CreationFlags |= CREATE_UNICODE_ENVIRONMENT; + Environment = EnvironmentBlock; + } + + Success = CreateProcessAsUserW( + LogonToken, + ApplicationName, + CommandLine, + ProcessAttributes, + ThreadAttributes, + InheritHandles, + CreationFlags, + Environment, + CurrentDirectory, + StartupInfo, + ProcessInformation); + +exit: + if (!Success) + LastError = GetLastError(); + + if (0 != EnvironmentBlock) + DestroyEnvironmentBlock(EnvironmentBlock); + if (0 != LogonToken) + CloseHandle(LogonToken); + + if (!Success) + SetLastError(LastError); + + return Success; +} + typedef struct { HANDLE Process; @@ -376,7 +474,8 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess, return Result; } -NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine, +NTSTATUS SvcInstanceCreateProcess(PWSTR UserName, + PWSTR Executable, PWSTR CommandLine, HANDLE StdioHandles[2], PPROCESS_INFORMATION ProcessInfo) { @@ -454,7 +553,8 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine, StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1]; StartupInfoEx.StartupInfo.hStdError = ChildHandles[2]; - if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE, + if (!LogonCreateProcess(UserName, + Executable, CommandLine, 0, 0, TRUE, CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0, &StartupInfoEx.StartupInfo, ProcessInfo)) { @@ -464,7 +564,8 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine, } else { - if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE, + if (!LogonCreateProcess(UserName, + Executable, CommandLine, 0, 0, FALSE, CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfoEx.StartupInfo, ProcessInfo)) { @@ -508,7 +609,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken, HKEY RegKey = 0; DWORD RegResult, RegSize; DWORD ClassNameSize, InstanceNameSize; - WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512]; + WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512], RunAsBuf[256]; PWSTR CommandLine, Security; DWORD JobControl, Credentials; PSECURITY_DESCRIPTOR SecurityDescriptor = 0; @@ -595,6 +696,16 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken, goto exit; } + RegSize = sizeof RunAsBuf; + RunAsBuf[0] = L'\0'; + RegResult = RegGetValueW(RegKey, ClassName, L"RunAs", RRF_RT_REG_SZ, 0, + RunAsBuf, &RegSize); + if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult) + { + Result = FspNtStatusFromWin32(RegResult); + goto exit; + } + RegSize = sizeof JobControl; JobControl = 1; /* default is YES! */ RegResult = RegGetValueW(RegKey, ClassName, L"JobControl", RRF_RT_REG_DWORD, 0, @@ -650,7 +761,8 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken, if (!NT_SUCCESS(Result)) goto exit; - Result = SvcInstanceCreateProcess(Executable, SvcInstance->CommandLine, + Result = SvcInstanceCreateProcess(L'\0' != RunAsBuf[0] ? RunAsBuf : 0, + Executable, SvcInstance->CommandLine, RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo); if (!NT_SUCCESS(Result)) goto exit; @@ -721,6 +833,9 @@ exit: LeaveCriticalSection(&SvcInstanceLock); + FspServiceLog(EVENTLOG_INFORMATION_TYPE, + L"create %s\\%s = %lx", ClassName, InstanceName, Result); + return Result; } @@ -754,6 +869,9 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout) { SVC_INSTANCE *SvcInstance = Context; + FspServiceLog(EVENTLOG_INFORMATION_TYPE, + L"terminated %s\\%s", SvcInstance->ClassName, SvcInstance->InstanceName); + SvcInstanceRelease(SvcInstance); }