mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
launcher: access check on client token
This commit is contained in:
parent
a81a766bbe
commit
ceef2bf55e
@ -126,14 +126,51 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceCreate(PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess, PWSTR Security)
|
||||||
|
{
|
||||||
|
static GENERIC_MAPPING GenericMapping =
|
||||||
|
{
|
||||||
|
.GenericRead = FILE_GENERIC_READ,
|
||||||
|
.GenericWrite = FILE_GENERIC_WRITE,
|
||||||
|
.GenericExecute = FILE_GENERIC_EXECUTE,
|
||||||
|
.GenericAll = FILE_ALL_ACCESS,
|
||||||
|
};
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
|
UINT8 PrivilegeSetBuf[sizeof(PRIVILEGE_SET) + 15 * sizeof(LUID_AND_ATTRIBUTES)];
|
||||||
|
PPRIVILEGE_SET PrivilegeSet = (PVOID)PrivilegeSetBuf;
|
||||||
|
DWORD PrivilegeSetLength = sizeof PrivilegeSetBuf;
|
||||||
|
ULONG GrantedAccess;
|
||||||
|
BOOL AccessStatus;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(Security, SDDL_REVISION_1,
|
||||||
|
&SecurityDescriptor, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
|
||||||
|
&GenericMapping, PrivilegeSet, &PrivilegeSetLength, &GrantedAccess, &AccessStatus))
|
||||||
|
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
exit:
|
||||||
|
LocalFree(SecurityDescriptor);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
|
||||||
SVC_INSTANCE **PSvcInstance)
|
SVC_INSTANCE **PSvcInstance)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = 0;
|
SVC_INSTANCE *SvcInstance = 0;
|
||||||
HKEY RegKey = 0;
|
HKEY RegKey = 0;
|
||||||
DWORD RegResult, RegSize;
|
DWORD RegResult, RegSize, SecurityLen;
|
||||||
DWORD ClassNameSize, InstanceNameSize;
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
WCHAR Executable[MAX_PATH], CommandLine[512];
|
WCHAR Executable[MAX_PATH], CommandLine[512], Security[512] = L"O:SYG:SY";
|
||||||
STARTUPINFOW StartupInfo;
|
STARTUPINFOW StartupInfo;
|
||||||
PROCESS_INFORMATION ProcessInfo;
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -158,7 +195,7 @@ NTSTATUS SvcInstanceCreate(PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWST
|
|||||||
RegSize = sizeof Executable;
|
RegSize = sizeof Executable;
|
||||||
Executable[0] = L'\0';
|
Executable[0] = L'\0';
|
||||||
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
||||||
&Executable, &RegSize);
|
Executable, &RegSize);
|
||||||
if (ERROR_SUCCESS != RegResult)
|
if (ERROR_SUCCESS != RegResult)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(RegResult);
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
@ -168,7 +205,17 @@ NTSTATUS SvcInstanceCreate(PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWST
|
|||||||
RegSize = sizeof CommandLine;
|
RegSize = sizeof CommandLine;
|
||||||
CommandLine[0] = L'\0';
|
CommandLine[0] = L'\0';
|
||||||
RegResult = RegGetValueW(RegKey, ClassName, L"CommandLine", RRF_RT_REG_SZ, 0,
|
RegResult = RegGetValueW(RegKey, ClassName, L"CommandLine", RRF_RT_REG_SZ, 0,
|
||||||
&CommandLine, &RegSize);
|
CommandLine, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityLen = lstrlenW(Security);
|
||||||
|
RegSize = sizeof Security - SecurityLen * sizeof(WCHAR);
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"Security", RRF_RT_REG_SZ, 0,
|
||||||
|
Security + SecurityLen, &RegSize);
|
||||||
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
{
|
{
|
||||||
Result = FspNtStatusFromWin32(RegResult);
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
@ -178,6 +225,13 @@ NTSTATUS SvcInstanceCreate(PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWST
|
|||||||
RegCloseKey(RegKey);
|
RegCloseKey(RegKey);
|
||||||
RegKey = 0;
|
RegKey = 0;
|
||||||
|
|
||||||
|
if (L'\0' != Security)
|
||||||
|
{
|
||||||
|
Result = SvcInstanceAccessCheck(ClientToken, FILE_EXECUTE, Security);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
ClassNameSize = (lstrlenW(ClassName) + 1) * sizeof(WCHAR);
|
ClassNameSize = (lstrlenW(ClassName) + 1) * sizeof(WCHAR);
|
||||||
InstanceNameSize = (lstrlenW(InstanceName) + 1) * sizeof(WCHAR);
|
InstanceNameSize = (lstrlenW(InstanceName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
@ -266,11 +320,12 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Fired)
|
|||||||
SvcInstanceDelete(SvcInstance);
|
SvcInstanceDelete(SvcInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStart(PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv)
|
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance;
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
|
||||||
return SvcInstanceCreate(ClassName, InstanceName, Argc, Argv, &SvcInstance);
|
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, &SvcInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID SvcInstanceStop(PWSTR InstanceName)
|
VOID SvcInstanceStop(PWSTR InstanceName)
|
||||||
@ -353,7 +408,7 @@ static HANDLE SvcPipe = INVALID_HANDLE_VALUE;
|
|||||||
static OVERLAPPED SvcOverlapped;
|
static OVERLAPPED SvcOverlapped;
|
||||||
|
|
||||||
static DWORD WINAPI SvcPipeServer(PVOID Context);
|
static DWORD WINAPI SvcPipeServer(PVOID Context);
|
||||||
static VOID SvcPipeTransact(PWSTR PipeBuf, PULONG PSize);
|
static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize);
|
||||||
|
|
||||||
static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||||
{
|
{
|
||||||
@ -468,6 +523,7 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
|||||||
L"Error in service main loop (%s = %ld). Continuing...";
|
L"Error in service main loop (%s = %ld). Continuing...";
|
||||||
FSP_SERVICE *Service = Context;
|
FSP_SERVICE *Service = Context;
|
||||||
PWSTR PipeBuf = 0;
|
PWSTR PipeBuf = 0;
|
||||||
|
HANDLE ClientToken;
|
||||||
DWORD LastError, BytesTransferred;
|
DWORD LastError, BytesTransferred;
|
||||||
|
|
||||||
PipeBuf = MemAlloc(PIPE_BUFFER_SIZE);
|
PipeBuf = MemAlloc(PIPE_BUFFER_SIZE);
|
||||||
@ -505,26 +561,33 @@ static DWORD WINAPI SvcPipeServer(PVOID Context)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ImpersonateNamedPipeClient(SvcPipe))
|
ClientToken = 0;
|
||||||
|
if (!ImpersonateNamedPipeClient(SvcPipe) ||
|
||||||
|
!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &ClientToken) ||
|
||||||
|
!RevertToSelf())
|
||||||
{
|
{
|
||||||
LastError = GetLastError();
|
LastError = GetLastError();
|
||||||
|
if (0 == ClientToken)
|
||||||
|
{
|
||||||
|
CloseHandle(ClientToken);
|
||||||
DisconnectNamedPipe(SvcPipe);
|
DisconnectNamedPipe(SvcPipe);
|
||||||
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
||||||
L"ImpersonateNamedPipeClient", LastError);
|
L"ImpersonateNamedPipeClient||OpenThreadToken", LastError);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
SvcPipeTransact(PipeBuf, &BytesTransferred);
|
|
||||||
|
|
||||||
if (!RevertToSelf())
|
|
||||||
{
|
{
|
||||||
LastError = GetLastError();
|
CloseHandle(ClientToken);
|
||||||
DisconnectNamedPipe(SvcPipe);
|
DisconnectNamedPipe(SvcPipe);
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE, LoopErrorMessage,
|
FspServiceLog(EVENTLOG_ERROR_TYPE, LoopErrorMessage,
|
||||||
L"RevertToSelf", LastError);
|
L"RevertToSelf", LastError);
|
||||||
FspServiceSetExitCode(Service, LastError);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcPipeTransact(ClientToken, PipeBuf, &BytesTransferred);
|
||||||
|
|
||||||
|
CloseHandle(ClientToken);
|
||||||
|
|
||||||
LastError = SvcPipeWaitResult(
|
LastError = SvcPipeWaitResult(
|
||||||
WriteFile(SvcPipe, PipeBuf, BytesTransferred, &BytesTransferred, &SvcOverlapped),
|
WriteFile(SvcPipe, PipeBuf, BytesTransferred, &BytesTransferred, &SvcOverlapped),
|
||||||
@ -569,7 +632,7 @@ static inline PWSTR SvcPipeTransactGetPart(PWSTR *PP, PWSTR PipeBufEnd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID SvcPipeTransact(PWSTR PipeBuf, PULONG PSize)
|
static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||||
{
|
{
|
||||||
if (sizeof(WCHAR) > *PSize)
|
if (sizeof(WCHAR) > *PSize)
|
||||||
return;
|
return;
|
||||||
@ -592,7 +655,7 @@ static VOID SvcPipeTransact(PWSTR PipeBuf, PULONG PSize)
|
|||||||
|
|
||||||
Result = STATUS_UNSUCCESSFUL;
|
Result = STATUS_UNSUCCESSFUL;
|
||||||
if (0 != ClassName && 0 != InstanceName)
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
Result = SvcInstanceStart(ClassName, InstanceName, Argc, Argv);
|
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user