From 42e01a9b27bc1e67e54ddebaae0718bfcf3a2038 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 9 Dec 2017 17:00:09 -0800 Subject: [PATCH 1/6] src: launcher: RunAs, LogonCreateProcess --- build/VStudio/tools/launcher.vcxproj | 8 +- src/launcher/launcher.c | 128 +++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 9 deletions(-) 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); } From ea873ece22083fcbf6f237a1230fa40d081e902d Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 9 Dec 2017 17:45:10 -0800 Subject: [PATCH 2/6] src: launcher: LogonCreateProcess: ImpersonateLoggedOnUser --- src/launcher/launcher.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index 7e2a319a..150f5dcb 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -207,6 +207,10 @@ static BOOL LogonCreateProcess( Environment = EnvironmentBlock; } + Success = ImpersonateLoggedOnUser(LogonToken); + if (!Success) + goto exit; + Success = CreateProcessAsUserW( LogonToken, ApplicationName, @@ -220,6 +224,10 @@ static BOOL LogonCreateProcess( StartupInfo, ProcessInformation); + if (!RevertToSelf()) + /* should not happen! */ + ExitProcess(GetLastError()); + exit: if (!Success) LastError = GetLastError(); From fd3e5bad433756bc89e204013ed7251f5bc37080 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sun, 10 Dec 2017 14:49:18 -0800 Subject: [PATCH 3/6] src: launcher: SvcInstanceAddUserRights: - users who start a file system can always stop it and get info about it --- src/launcher/launcher.c | 72 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index 150f5dcb..c217eb4d 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -16,6 +16,7 @@ */ #include +#include #include #include @@ -454,6 +455,67 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg return STATUS_SUCCESS; } +static NTSTATUS SvcInstanceAddUserRights(HANDLE Token, + PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR *PNewSecurityDescriptor) +{ + PSECURITY_DESCRIPTOR NewSecurityDescriptor; + TOKEN_USER *User = 0; + EXPLICIT_ACCESSW AccessEntry; + DWORD Size, LastError; + NTSTATUS Result; + + *PNewSecurityDescriptor = 0; + + if (GetTokenInformation(Token, TokenUser, 0, 0, &Size)) + { + Result = STATUS_INVALID_PARAMETER; + goto exit; + } + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + User = MemAlloc(Size); + if (0 == User) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!GetTokenInformation(Token, TokenUser, User, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_STOP; + AccessEntry.grfAccessMode = GRANT_ACCESS; + AccessEntry.grfInheritance = NO_INHERITANCE; + AccessEntry.Trustee.pMultipleTrustee = 0; + AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID; + AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + AccessEntry.Trustee.ptstrName = User->User.Sid; + + LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor, + &Size, &NewSecurityDescriptor); + if (0 != LastError) + { + Result = FspNtStatusFromWin32(LastError); + goto exit; + } + + *PNewSecurityDescriptor = NewSecurityDescriptor; + Result = STATUS_SUCCESS; + +exit: + MemFree(User); + + return Result; +} + static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess, PSECURITY_DESCRIPTOR SecurityDescriptor) { @@ -620,7 +682,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken, WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512], RunAsBuf[256]; PWSTR CommandLine, Security; DWORD JobControl, Credentials; - PSECURITY_DESCRIPTOR SecurityDescriptor = 0; + PSECURITY_DESCRIPTOR SecurityDescriptor = 0, NewSecurityDescriptor; PWSTR Argv[10]; PROCESS_INFORMATION ProcessInfo; NTSTATUS Result; @@ -745,6 +807,14 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken, if (!NT_SUCCESS(Result)) goto exit; + Result = SvcInstanceAddUserRights(ClientToken, SecurityDescriptor, &NewSecurityDescriptor); + if (!NT_SUCCESS(Result)) + goto exit; + LocalFree(SecurityDescriptor); + SecurityDescriptor = NewSecurityDescriptor; + + //FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor); + ClassNameSize = (lstrlenW(ClassName) + 1) * sizeof(WCHAR); InstanceNameSize = (lstrlenW(InstanceName) + 1) * sizeof(WCHAR); From 4fe85222b12af8f57ea5fa9dbff2ac97d4148c4f Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 11 Dec 2017 15:03:32 -0800 Subject: [PATCH 4/6] dll: wksid: well known SID's --- build/VStudio/winfsp_dll.vcxproj | 1 + build/VStudio/winfsp_dll.vcxproj.filters | 3 + inc/winfsp/winfsp.h | 1 + src/dll/debug.c | 15 +++ src/dll/fsctl.c | 11 +-- src/dll/library.c | 1 + src/dll/library.h | 7 ++ src/dll/posix.c | 30 +++--- src/dll/util.c | 14 +-- src/dll/wksid.c | 114 +++++++++++++++++++++++ 10 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 src/dll/wksid.c diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index 7bee8cb9..784bfe71 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -51,6 +51,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index 4b1f7e2b..b93ce5e2 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -112,6 +112,9 @@ Source\fuse + + Source + diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 9fd5b97f..5b25d8cb 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -1700,6 +1700,7 @@ FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap); FSP_API VOID FspDebugLogSetHandle(HANDLE Handle); FSP_API VOID FspDebugLog(const char *Format, ...); FSP_API VOID FspDebugLogSD(const char *Format, PSECURITY_DESCRIPTOR SecurityDescriptor); +FSP_API VOID FspDebugLogSid(const char *format, PSID Sid); FSP_API VOID FspDebugLogFT(const char *Format, PFILETIME FileTime); FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request); FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response); diff --git a/src/dll/debug.c b/src/dll/debug.c index ff8c98f5..5960a5b3 100644 --- a/src/dll/debug.c +++ b/src/dll/debug.c @@ -63,6 +63,21 @@ FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDesc FspDebugLog(format, "invalid security descriptor"); } +FSP_API VOID FspDebugLogSid(const char *format, PSID Sid) +{ + char *S; + + if (0 == Sid) + FspDebugLog(format, "null SID"); + else if (ConvertSidToStringSidA(Sid, &S)) + { + FspDebugLog(format, S); + LocalFree(S); + } + else + FspDebugLog(format, "invalid SID"); +} + FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime) { SYSTEMTIME SystemTime; diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 56668cc9..26ff3acc 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -284,7 +284,7 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle) * This function adds an ACE that allows Everyone to start a service. */ - PSID WorldSid = 0; + PSID WorldSid; PSECURITY_DESCRIPTOR SecurityDescriptor = 0; PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0; EXPLICIT_ACCESSW AccessEntry; @@ -296,18 +296,12 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle) NTSTATUS Result; /* get the Everyone (World) SID */ - Size = SECURITY_MAX_SID_SIZE; - WorldSid = MemAlloc(Size); + WorldSid = FspWksidGet(WinWorldSid); if (0 == WorldSid) { Result = STATUS_INSUFFICIENT_RESOURCES; goto exit; } - if (!CreateWellKnownSid(WinWorldSid, 0, WorldSid, &Size)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } /* get the service security descriptor DACL */ Size = 0; @@ -394,7 +388,6 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle) exit: LocalFree(NewSecurityDescriptor); MemFree(SecurityDescriptor); - MemFree(WorldSid); return Result; } diff --git a/src/dll/library.c b/src/dll/library.c index 5e5c113e..ea56c177 100644 --- a/src/dll/library.c +++ b/src/dll/library.c @@ -44,6 +44,7 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved) FspServiceFinalize(Dynamic); FspEventLogFinalize(Dynamic); FspPosixFinalize(Dynamic); + FspWksidFinalize(Dynamic); break; case DLL_THREAD_DETACH: diff --git a/src/dll/library.h b/src/dll/library.h index b3c1376c..e82901d1 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -31,11 +31,15 @@ FspDebugLog("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", __VA_ARGS__) #define DEBUGLOGSD(fmt, SD) \ FspDebugLogSD("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", SD) +#define DEBUGLOGSID(fmt, Sid) \ + FspDebugLogSid("[U] " LIBRARY_NAME "!" __FUNCTION__ ": " fmt "\n", Sid) #else #define DEBUGLOG(fmt, ...) ((void)0) #define DEBUGLOGSD(fmt, SD) ((void)0) +#define DEBUGLOGSID(fmt, Sid) ((void)0) #endif +VOID FspWksidFinalize(BOOLEAN Dynamic); VOID FspPosixFinalize(BOOLEAN Dynamic); VOID FspEventLogFinalize(BOOLEAN Dynamic); VOID FspServiceFinalize(BOOLEAN Dynamic); @@ -49,6 +53,9 @@ NTSTATUS FspNpUnregister(VOID); NTSTATUS FspEventLogRegister(VOID); NTSTATUS FspEventLogUnregister(VOID); +PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult); +PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType); + PWSTR FspDiagIdent(VOID); VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer, diff --git a/src/dll/posix.c b/src/dll/posix.c index 5640115c..ef566e18 100644 --- a/src/dll/posix.c +++ b/src/dll/posix.c @@ -453,9 +453,12 @@ FSP_API NTSTATUS FspPosixMapPermissionsToSecurityDescriptor( if (!NT_SUCCESS(Result)) goto exit; - Result = FspPosixMapUidToSid(0x10100, &WorldSid); - if (!NT_SUCCESS(Result)) + WorldSid = FspWksidGet(WinWorldSid); + if (0 == WorldSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; goto exit; + } OwnerPerm = (Mode & 0700) >> 6; GroupPerm = (Mode & 0070) >> 3; @@ -579,9 +582,6 @@ exit: MemFree(Acl); - if (0 != WorldSid) - FspDeleteSid(WorldSid, FspPosixMapUidToSid); - if (0 != GroupSid) FspDeleteSid(GroupSid, FspPosixMapUidToSid); @@ -649,13 +649,19 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions( if (0 != Acl) { - Result = FspPosixMapUidToSid(0x10100, &WorldSid); - if (!NT_SUCCESS(Result)) + WorldSid = FspWksidGet(WinWorldSid); + if (0 == WorldSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; goto exit; + } - Result = FspPosixMapUidToSid(11, &AuthUsersSid); - if (!NT_SUCCESS(Result)) + AuthUsersSid = FspWksidGet(WinAuthenticatedUserSid); + if (0 == AuthUsersSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; goto exit; + } OwnerAllow = OwnerDeny = GroupAllow = GroupDeny = WorldAllow = WorldDeny = 0; @@ -771,12 +777,6 @@ FSP_API NTSTATUS FspPosixMapSecurityDescriptorToPermissions( Result = STATUS_SUCCESS; exit: - if (0 != AuthUsersSid) - FspDeleteSid(AuthUsersSid, FspPosixMapUidToSid); - - if (0 != WorldSid) - FspDeleteSid(WorldSid, FspPosixMapUidToSid); - return Result; lasterror: diff --git a/src/dll/util.c b/src/dll/util.c index cd36df5c..27746351 100644 --- a/src/dll/util.c +++ b/src/dll/util.c @@ -97,24 +97,14 @@ FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName, { PSECURITY_DESCRIPTOR SecurityDescriptor = 0; PSID OwnerSid, WellKnownSid = 0; - DWORD SidSize, LastError; + DWORD LastError; /* if it is a small number treat it like a well known SID */ if (1024 > (INT_PTR)Sid) { - SidSize = SECURITY_MAX_SID_SIZE; - WellKnownSid = MemAlloc(SidSize); + WellKnownSid = FspWksidNew((INT_PTR)Sid, &Result); if (0 == WellKnownSid) - { - Result = STATUS_INSUFFICIENT_RESOURCES; goto sid_exit; - } - - if (!CreateWellKnownSid((INT_PTR)Sid, 0, WellKnownSid, &SidSize)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto sid_exit; - } } LastError = GetSecurityInfo(Pipe, SE_FILE_OBJECT, diff --git a/src/dll/wksid.c b/src/dll/wksid.c new file mode 100644 index 00000000..4617fcde --- /dev/null +++ b/src/dll/wksid.c @@ -0,0 +1,114 @@ +/** + * @file dll/wksid.c + * + * @copyright 2015-2017 Bill Zissimopoulos + */ +/* + * This file is part of WinFsp. + * + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License version 3 as published by the Free Software + * Foundation. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#include + +static INIT_ONCE FspWksidInitOnce = INIT_ONCE_STATIC_INIT; +static PSID FspWksidWorld; +static PSID FspWksidAuthenticatedUser; +static PSID FspWksidLocalSystem; +static PSID FspWksidLocalService; +static PSID FspWksidNetworkService; + +static BOOL WINAPI FspWksidInitialize( + PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) +{ + FspWksidWorld = FspWksidNew(WinWorldSid, 0); + FspWksidAuthenticatedUser = FspWksidNew(WinAuthenticatedUserSid, 0); + FspWksidLocalSystem = FspWksidNew(WinLocalSystemSid, 0); + FspWksidLocalService = FspWksidNew(WinLocalServiceSid, 0); + FspWksidNetworkService = FspWksidNew(WinNetworkServiceSid, 0); + + //DEBUGLOGSID("FspWksidWorld=%s", FspWksidWorld); + //DEBUGLOGSID("FspWksidAuthenticatedUser=%s", FspWksidAuthenticatedUser); + //DEBUGLOGSID("FspWksidLocalSystem=%s", FspWksidLocalSystem); + //DEBUGLOGSID("FspWksidLocalService=%s", FspWksidLocalService); + //DEBUGLOGSID("FspWksidNetworkService=%s", FspWksidNetworkService); + + return TRUE; +} + +VOID FspWksidFinalize(BOOLEAN Dynamic) +{ + /* + * This function is called during DLL_PROCESS_DETACH. We must therefore keep + * finalization tasks to a minimum. + * + * We must deregister our event source (if any). We only do so if the library + * is being explicitly unloaded (rather than the process exiting). + */ + + if (Dynamic) + { + MemFree(FspWksidWorld); FspWksidWorld = 0; + MemFree(FspWksidAuthenticatedUser); FspWksidAuthenticatedUser = 0; + MemFree(FspWksidLocalSystem); FspWksidLocalSystem = 0; + MemFree(FspWksidLocalService); FspWksidLocalService = 0; + MemFree(FspWksidNetworkService); FspWksidNetworkService = 0; + } +} + +PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult) +{ + NTSTATUS Result; + PSID Sid; + DWORD Size; + + Size = SECURITY_MAX_SID_SIZE; + Sid = MemAlloc(Size); + if (0 == Sid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!CreateWellKnownSid(WellKnownSidType, 0, Sid, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + MemFree(Sid); Sid = 0; + goto exit; + } + + Result = STATUS_SUCCESS; + +exit: + if (0 != PResult) + *PResult = Result; + + return Sid; +} + +PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType) +{ + InitOnceExecuteOnce(&FspWksidInitOnce, FspWksidInitialize, 0, 0); + + switch (WellKnownSidType) + { + case WinWorldSid: + return FspWksidWorld; + case WinAuthenticatedUserSid: + return FspWksidAuthenticatedUser; + case WinLocalSystemSid: + return FspWksidLocalSystem; + case WinLocalServiceSid: + return FspWksidLocalService; + case WinNetworkServiceSid: + return FspWksidNetworkService; + default: + return 0; + } +} From 5d3b37122c1f8aa4b1527448b7670d0388fff6fd Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 12 Dec 2017 14:39:56 -0800 Subject: [PATCH 5/6] launcher: LogonCreateProcess --- src/launcher/launcher.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index 6c4abe52..d7cae7d5 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -646,7 +646,8 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR UserName, * Not ideal, but... */ StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo; - if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE, + if (!LogonCreateProcess(UserName, + Executable, CommandLine, 0, 0, TRUE, CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfoEx.StartupInfo, ProcessInfo)) { From ff155694ce2ac8d3d4c235a5fb96438671710e00 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 19 Dec 2017 14:49:22 -0800 Subject: [PATCH 6/6] launcher: can now perform DefineDosDevice in LocalSystem context dll: uses launcher to DefineDosDevice for LocalService, etc. --- inc/winfsp/winfsp.h | 13 ++++ src/dll/fs.c | 112 ++++++++++++++++++++++++-- src/dll/service.c | 100 ++++++++++++++++++++++++ src/dll/wksid.c | 18 ++--- src/launcher/launcher.c | 169 ++++++++++++++++++++++++++++++++++++++++ src/launcher/launcher.h | 3 +- 6 files changed, 397 insertions(+), 18 deletions(-) diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 5b25d8cb..8da15a75 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -1675,6 +1675,19 @@ FSP_API VOID FspServiceStop(FSP_SERVICE *Service); * TRUE if the process is running in running user interactive mode. */ FSP_API BOOLEAN FspServiceIsInteractive(VOID); +/** + * Check if the supplied token is from the service context. + * + * @param Token + * Token to check. Pass NULL to check the current process token. + * @param PIsLocalSystem + * Pointer to a boolean that will receive a TRUE value if the token belongs to LocalSystem + * and FALSE otherwise. May be NULL. + * @return + * STATUS_SUCCESS if the token is from the service context. STATUS_ACCESS_DENIED if it is not. + * Other error codes are possible. + */ +FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem); /** * Log a service message. * diff --git a/src/dll/fs.c b/src/dll/fs.c index 66d7e634..e222d16f 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -16,6 +16,7 @@ */ #include +#include enum { @@ -187,17 +188,101 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem) MemFree(FileSystem); } +static NTSTATUS FspFileSystemLauncherDefineDosDevice( + WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName) +{ + NTSTATUS Result; + ULONG MountPointLen, VolumeNameLen; + PWSTR PipeBuf = 0, P; + DWORD BytesTransferred; + + MountPointLen = lstrlenW(MountPoint); + VolumeNameLen = lstrlenW(VolumeName); + + if (2 != MountPointLen || + FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= VolumeNameLen) + return STATUS_INVALID_PARAMETER; + + PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE); + if (0 == PipeBuf) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + P = PipeBuf; + *P++ = LauncherDefineDosDevice; + *P++ = Sign; + memcpy(P, MountPoint, MountPointLen * sizeof(WCHAR)); P += MountPointLen; *P++ = L'\0'; + memcpy(P, VolumeName, VolumeNameLen * sizeof(WCHAR)); P += VolumeNameLen; *P++ = L'\0'; + + Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, + PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, + &BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER); + if (!NT_SUCCESS(Result)) + goto exit; + + if (sizeof(WCHAR) > BytesTransferred) + Result = RPC_NT_PROTOCOL_ERROR; + else if (LauncherSuccess == PipeBuf[0]) + Result = STATUS_SUCCESS; + else if (LauncherFailure == PipeBuf[0]) + { + DWORD ErrorCode = 0; + + for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++) + { + if (L'0' > *P || *P > L'9') + break; + + ErrorCode = 10 * ErrorCode + (*P - L'0'); + } + + Result = FspNtStatusFromWin32(ErrorCode); + if (0 == Result) + Result = RPC_NT_PROTOCOL_ERROR; + } + else + Result = RPC_NT_PROTOCOL_ERROR; + +exit: + MemFree(PipeBuf); + + return Result; +} + static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, PHANDLE PMountHandle) { + NTSTATUS Result; + BOOLEAN IsLocalSystem, IsServiceContext; + *PMountHandle = 0; - if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName)) - return FspNtStatusFromWin32(GetLastError()); + Result = FspServiceContextCheck(0, &IsLocalSystem); + IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem; + if (IsServiceContext) + { + /* + * If the current process is in the service context but not LocalSystem, + * ask the launcher to DefineDosDevice for us. This is because the launcher + * runs in the LocalSystem context and can create global drives. + * + * In this case the launcher will also add DELETE access to the drive symlink + * for us, so that we can make it temporary below. + */ + Result = FspFileSystemLauncherDefineDosDevice(L'+', MountPoint, VolumeName); + if (!NT_SUCCESS(Result)) + return Result; + } + else + { + if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName)) + return FspNtStatusFromWin32(GetLastError()); + } if (0 != FspNtOpenSymbolicLinkObject) { - NTSTATUS Result; WCHAR SymlinkBuf[6]; UNICODE_STRING Symlink; OBJECT_ATTRIBUTES Obja; @@ -224,6 +309,13 @@ static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeN } } + /* HACK: + * + * Handles do not use the low 2 bits (unless they are console handles). + * Abuse this fact to remember that we are running in the service context. + */ + *PMountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)*PMountHandle | IsServiceContext); + return STATUS_SUCCESS; } @@ -411,8 +503,18 @@ exit: static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle) { - DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, - MountPoint, VolumeName); + BOOLEAN IsServiceContext = 0 != ((DWORD)(UINT_PTR)MountHandle & 1); + MountHandle = (HANDLE)(UINT_PTR)((DWORD)(UINT_PTR)MountHandle & ~1); + if (IsServiceContext) + /* + * If the current process is in the service context but not LocalSystem, + * ask the launcher to DefineDosDevice for us. This is because the launcher + * runs in the LocalSystem context and can remove global drives. + */ + FspFileSystemLauncherDefineDosDevice(L'-', MountPoint, VolumeName); + else + DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, + MountPoint, VolumeName); if (0 != MountHandle) FspNtClose(MountHandle); diff --git a/src/dll/service.c b/src/dll/service.c index 3bc318cb..c0ce5326 100644 --- a/src/dll/service.c +++ b/src/dll/service.c @@ -566,6 +566,106 @@ FSP_API BOOLEAN FspServiceIsInteractive(VOID) return IsInteractive; } +FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem) +{ + NTSTATUS Result; + PSID LocalSystemSid, ServiceSid; + BOOLEAN IsLocalSystem = FALSE; + BOOL HasServiceSid = FALSE; + HANDLE ProcessToken = 0, ImpersonationToken = 0; + DWORD SessionId, Size; + union + { + TOKEN_USER V; + UINT8 B[128]; + } UserInfoBuf; + PTOKEN_USER UserInfo = &UserInfoBuf.V; + + LocalSystemSid = FspWksidGet(WinLocalSystemSid); + ServiceSid = FspWksidGet(WinServiceSid); + if (0 == LocalSystemSid || 0 == ServiceSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (0 == Token) + { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &ProcessToken) || + !DuplicateToken(ProcessToken, SecurityImpersonation, &ImpersonationToken)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + Token = ImpersonationToken; + } + + if (!GetTokenInformation(Token, TokenSessionId, &SessionId, sizeof SessionId, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + if (0 != SessionId) + { + Result = STATUS_ACCESS_DENIED; + goto exit; + } + + if (!GetTokenInformation(Token, TokenUser, UserInfo, sizeof UserInfoBuf, &Size)) + { + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + UserInfo = MemAlloc(Size); + if (0 == UserInfo) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!GetTokenInformation(Token, TokenUser, UserInfo, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + } + + IsLocalSystem = EqualSid(LocalSystemSid, UserInfo->User.Sid); + if (IsLocalSystem) + { + Result = STATUS_SUCCESS; + goto exit; + } + + if (!CheckTokenMembership(Token, ServiceSid, &HasServiceSid)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + Result = HasServiceSid ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; + +exit: + if (0 != PIsLocalSystem) + *PIsLocalSystem = NT_SUCCESS(Result) ? IsLocalSystem : FALSE; + + if (UserInfo != &UserInfoBuf.V) + MemFree(UserInfo); + + if (0 != ImpersonationToken) + CloseHandle(ImpersonationToken); + + if (0 != ProcessToken) + CloseHandle(ProcessToken); + + return Result; +} + FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...) { va_list ap; diff --git a/src/dll/wksid.c b/src/dll/wksid.c index 4617fcde..a89b50e3 100644 --- a/src/dll/wksid.c +++ b/src/dll/wksid.c @@ -21,8 +21,7 @@ static INIT_ONCE FspWksidInitOnce = INIT_ONCE_STATIC_INIT; static PSID FspWksidWorld; static PSID FspWksidAuthenticatedUser; static PSID FspWksidLocalSystem; -static PSID FspWksidLocalService; -static PSID FspWksidNetworkService; +static PSID FspWksidService; static BOOL WINAPI FspWksidInitialize( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) @@ -30,14 +29,12 @@ static BOOL WINAPI FspWksidInitialize( FspWksidWorld = FspWksidNew(WinWorldSid, 0); FspWksidAuthenticatedUser = FspWksidNew(WinAuthenticatedUserSid, 0); FspWksidLocalSystem = FspWksidNew(WinLocalSystemSid, 0); - FspWksidLocalService = FspWksidNew(WinLocalServiceSid, 0); - FspWksidNetworkService = FspWksidNew(WinNetworkServiceSid, 0); + FspWksidService = FspWksidNew(WinServiceSid, 0); //DEBUGLOGSID("FspWksidWorld=%s", FspWksidWorld); //DEBUGLOGSID("FspWksidAuthenticatedUser=%s", FspWksidAuthenticatedUser); //DEBUGLOGSID("FspWksidLocalSystem=%s", FspWksidLocalSystem); - //DEBUGLOGSID("FspWksidLocalService=%s", FspWksidLocalService); - //DEBUGLOGSID("FspWksidNetworkService=%s", FspWksidNetworkService); + //DEBUGLOGSID("FspWksidService=%s", FspWksidService); return TRUE; } @@ -57,8 +54,7 @@ VOID FspWksidFinalize(BOOLEAN Dynamic) MemFree(FspWksidWorld); FspWksidWorld = 0; MemFree(FspWksidAuthenticatedUser); FspWksidAuthenticatedUser = 0; MemFree(FspWksidLocalSystem); FspWksidLocalSystem = 0; - MemFree(FspWksidLocalService); FspWksidLocalService = 0; - MemFree(FspWksidNetworkService); FspWksidNetworkService = 0; + MemFree(FspWksidService); FspWksidService = 0; } } @@ -104,10 +100,8 @@ PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType) return FspWksidAuthenticatedUser; case WinLocalSystemSid: return FspWksidLocalSystem; - case WinLocalServiceSid: - return FspWksidLocalService; - case WinNetworkServiceSid: - return FspWksidNetworkService; + case WinServiceSid: + return FspWksidService; default: return 0; } diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index d7cae7d5..52f94f65 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -22,6 +22,13 @@ #define PROGNAME "WinFsp.Launcher" +static NTSTATUS (NTAPI *SvcNtOpenSymbolicLinkObject)( + PHANDLE LinkHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes); +static NTSTATUS (NTAPI *SvcNtClose)( + HANDLE Handle); + BOOL CreateOverlappedPipe( PHANDLE PReadPipe, PHANDLE PWritePipe, DWORD Size, @@ -143,6 +150,96 @@ exit: return Result; } +static NTSTATUS AddAccessForTokenUser(HANDLE Handle, DWORD Access, HANDLE Token) +{ + TOKEN_USER *User = 0; + PSECURITY_DESCRIPTOR SecurityDescriptor = 0; + PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0; + EXPLICIT_ACCESSW AccessEntry; + DWORD Size, LastError; + NTSTATUS Result; + + if (GetTokenInformation(Token, TokenUser, 0, 0, &Size)) + { + Result = STATUS_INVALID_PARAMETER; + goto exit; + } + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + User = MemAlloc(Size); + if (0 == User) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!GetTokenInformation(Token, TokenUser, User, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + if (GetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, 0, 0, &Size)) + { + Result = STATUS_INVALID_PARAMETER; + goto exit; + } + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + SecurityDescriptor = MemAlloc(Size); + if (0 == SecurityDescriptor) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!GetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + AccessEntry.grfAccessPermissions = Access; + AccessEntry.grfAccessMode = GRANT_ACCESS; + AccessEntry.grfInheritance = NO_INHERITANCE; + AccessEntry.Trustee.pMultipleTrustee = 0; + AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID; + AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + AccessEntry.Trustee.ptstrName = User->User.Sid; + + LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor, + &Size, &NewSecurityDescriptor); + if (0 != LastError) + { + Result = FspNtStatusFromWin32(LastError); + goto exit; + } + + if (!SetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + Result = STATUS_SUCCESS; + +exit: + LocalFree(NewSecurityDescriptor); + MemFree(SecurityDescriptor); + MemFree(User); + + return Result; +} + static BOOL LogonCreateProcess( PWSTR UserName, LPCWSTR ApplicationName, @@ -1206,6 +1303,53 @@ NTSTATUS SvcInstanceStopAndWaitAll(VOID) return STATUS_SUCCESS; } +NTSTATUS SvcDefineDosDevice(HANDLE ClientToken, + PWSTR DeviceName, PWSTR TargetPath) +{ + NTSTATUS Result; + + if (L'+' != DeviceName[0] && L'-' != DeviceName[0]) + return STATUS_INVALID_PARAMETER; + + Result = FspServiceContextCheck(ClientToken, 0); + if (!NT_SUCCESS(Result)) + return Result; + + if (!DefineDosDeviceW( + DDD_RAW_TARGET_PATH | + (L'+' == DeviceName[0] ? 0 : DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE), + DeviceName + 1, TargetPath)) + return FspNtStatusFromWin32(GetLastError()); + + if (L'+' == DeviceName[0] && 0 != SvcNtOpenSymbolicLinkObject) + { + /* The drive symlink now exists; add DELETE access to it for the ClientToken. */ + WCHAR SymlinkBuf[6]; + UNICODE_STRING Symlink; + OBJECT_ATTRIBUTES Obja; + HANDLE MountHandle; + + memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf); + SymlinkBuf[4] = DeviceName[1]; + Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf; + Symlink.Buffer = SymlinkBuf; + + memset(&Obja, 0, sizeof Obja); + Obja.Length = sizeof Obja; + Obja.ObjectName = &Symlink; + Obja.Attributes = OBJ_CASE_INSENSITIVE; + + Result = SvcNtOpenSymbolicLinkObject(&MountHandle, READ_CONTROL | WRITE_DAC, &Obja); + if (NT_SUCCESS(Result)) + { + AddAccessForTokenUser(MountHandle, DELETE, ClientToken); + SvcNtClose(MountHandle); + } + } + + return STATUS_SUCCESS; +} + static HANDLE SvcJob, SvcThread, SvcEvent; static DWORD SvcThreadId; static HANDLE SvcPipe = INVALID_HANDLE_VALUE; @@ -1526,6 +1670,7 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize) PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR); PWSTR ClassName, InstanceName, UserName; + PWSTR DeviceName, TargetPath; ULONG Argc; PWSTR Argv[9]; BOOLEAN HasSecret = FALSE; NTSTATUS Result; @@ -1587,6 +1732,17 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize) SvcPipeTransactResult(Result, PipeBuf, PSize); break; + case LauncherDefineDosDevice: + DeviceName = SvcPipeTransactGetPart(&P, PipeBufEnd); + TargetPath = SvcPipeTransactGetPart(&P, PipeBufEnd); + + Result = STATUS_INVALID_PARAMETER; + if (0 != DeviceName && 0 != TargetPath) + Result = SvcDefineDosDevice(ClientToken, DeviceName, TargetPath); + + SvcPipeTransactResult(Result, PipeBuf, PSize); + break; + #if !defined(NDEBUG) case LauncherQuit: SetEvent(SvcEvent); @@ -1605,6 +1761,19 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize) int wmain(int argc, wchar_t **argv) { + HANDLE Handle = GetModuleHandleW(L"ntdll.dll"); + if (0 != Handle) + { + SvcNtOpenSymbolicLinkObject = (PVOID)GetProcAddress(Handle, "NtOpenSymbolicLinkObject"); + SvcNtClose = (PVOID)GetProcAddress(Handle, "NtClose"); + + if (0 == SvcNtOpenSymbolicLinkObject || 0 == SvcNtClose) + { + SvcNtOpenSymbolicLinkObject = 0; + SvcNtClose = 0; + } + } + return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0); } diff --git a/src/launcher/launcher.h b/src/launcher/launcher.h index 06e1e869..2ac642bb 100644 --- a/src/launcher/launcher.h +++ b/src/launcher/launcher.h @@ -29,7 +29,7 @@ #define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}" #define LAUNCHER_PIPE_BUFFER_SIZE 4096 -#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000 +#define LAUNCHER_PIPE_DEFAULT_TIMEOUT (2 * 15000 + 1000) #define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000 @@ -62,6 +62,7 @@ enum LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */ LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */ LauncherSvcInstanceList = 'L', /* requires: none*/ + LauncherDefineDosDevice = 'D', LauncherQuit = 'Q', /* DEBUG version only */ LauncherSuccess = '$',