sys, dll: QuerySecurity, SetSecurity

This commit is contained in:
Bill Zissimopoulos
2016-02-19 14:07:41 -08:00
parent 12bbddfb19
commit 7e90092028
8 changed files with 252 additions and 23 deletions

View File

@ -47,6 +47,9 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
if (0 != PSecurityDescriptor)
*PSecurityDescriptor = 0;
if (FspFsctlTransactCreateKind != Request->Kind)
return STATUS_INVALID_PARAMETER;
if (0 == FileSystem->Interface->GetSecurityByName ||
(!Request->Req.Create.UserMode && 0 == PSecurityDescriptor))
{
@ -202,13 +205,16 @@ exit:
return Result;
}
FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem,
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request,
PSECURITY_DESCRIPTOR ParentDescriptor,
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
{
*PSecurityDescriptor = 0;
if (FspFsctlTransactCreateKind != Request->Kind)
return STATUS_INVALID_PARAMETER;
if (!CreatePrivateObjectSecurity(
ParentDescriptor,
0 != Request->Req.Create.SecurityDescriptor.Offset ?
@ -224,11 +230,75 @@ FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspSetSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request,
PSECURITY_DESCRIPTOR InputDescriptor,
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
{
*PSecurityDescriptor = 0;
if (FspFsctlTransactSetSecurityKind != Request->Kind)
return STATUS_INVALID_PARAMETER;
if (0 == InputDescriptor)
return STATUS_NO_SECURITY_ON_OBJECT;
/*
* SetPrivateObjectSecurity is a broken API. It assumes that the passed
* descriptor resides on memory allocated by CreatePrivateObjectSecurity
* or SetPrivateObjectSecurity and frees the descriptor on success.
*
* In our case the security descriptor comes from the user mode file system,
* which may conjure it any way it sees fit. So we have to somehow make a copy
* of the InputDescriptor and place it in memory that SetPrivateObjectSecurity
* can then free. To complicate matters there is no API that can be used for
* this purpose. What a PITA!
*/
/* !!!: HACK! HACK! HACK!
*
* Turns out that SetPrivateObjectSecurity and friends really use RtlProcessHeap
* internally, which is just another name for GetProcessHeap().
*
* I wish there was a cleaner way to do this!
*/
HANDLE ProcessHeap = GetProcessHeap();
DWORD InputDescriptorSize = GetSecurityDescriptorLength(InputDescriptor);
PSECURITY_DESCRIPTOR CopiedDescriptor;
CopiedDescriptor = HeapAlloc(ProcessHeap, 0, InputDescriptorSize);
if (0 == CopiedDescriptor)
return STATUS_INSUFFICIENT_RESOURCES;
memcpy(CopiedDescriptor, InputDescriptor, InputDescriptorSize);
InputDescriptor = CopiedDescriptor;
if (!SetPrivateObjectSecurity(
Request->Req.SetSecurity.SecurityInformation,
(PVOID)Request->Buffer,
&InputDescriptor,
&FspFileGenericMapping,
(HANDLE)Request->Req.SetSecurity.AccessToken))
{
HeapFree(ProcessHeap, 0, CopiedDescriptor);
return FspNtStatusFromWin32(GetLastError());
}
/* CopiedDescriptor has been freed by SetPrivateObjectSecurity! */
*PSecurityDescriptor = InputDescriptor;
DEBUGLOGSD("SDDL=%s", *PSecurityDescriptor);
return STATUS_SUCCESS;
}
FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
NTSTATUS(*CreateFunc)())
NTSTATUS (*CreateFunc)())
{
if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc)
MemFree(SecurityDescriptor);
else if ((NTSTATUS (*)())FspAssignSecurity == CreateFunc)
else
if ((NTSTATUS (*)())FspCreateSecurityDescriptor == CreateFunc ||
(NTSTATUS (*)())FspSetSecurityDescriptor == CreateFunc)
DestroyPrivateObjectSecurity(&SecurityDescriptor);
}

View File

@ -83,7 +83,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
return Result;
Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx);
if (!NT_SUCCESS(Result))
return Result;
@ -94,7 +94,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
@ -171,7 +171,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
return Result;
Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx);
if (!NT_SUCCESS(Result))
return Result;
@ -182,7 +182,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
}
@ -261,7 +261,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
if (!NT_SUCCESS(Result))
return Result;
Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor);
FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx);
if (!NT_SUCCESS(Result))
return Result;
@ -272,7 +272,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
}
@ -544,22 +544,32 @@ FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{
NTSTATUS Result;
SIZE_T SecurityDescriptorSize;
if (0 == FileSystem->Interface->GetSecurity)
return STATUS_INVALID_DEVICE_REQUEST;
(VOID)Result;
return STATUS_INVALID_DEVICE_REQUEST;
SecurityDescriptorSize = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof *Response;
Result = FileSystem->Interface->GetSecurity(FileSystem, Request,
(PVOID)Request->Req.QuerySecurity.UserContext,
Response->Buffer, &SecurityDescriptorSize);
if (!NT_SUCCESS(Result))
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_INVALID_SECURITY_DESCR;
Response->Size = (UINT16)(sizeof *Response + SecurityDescriptorSize);
Response->Rsp.QuerySecurity.SecurityDescriptor.Offset = 0;
Response->Rsp.QuerySecurity.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize;
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{
NTSTATUS Result;
if (0 == FileSystem->Interface->SetSecurity)
return STATUS_INVALID_DEVICE_REQUEST;
(VOID)Result;
return STATUS_INVALID_DEVICE_REQUEST;
return FileSystem->Interface->SetSecurity(FileSystem, Request,
(PVOID)Request->Req.SetSecurity.UserContext,
Request->Req.SetSecurity.SecurityInformation,
(PSECURITY_DESCRIPTOR)Request->Buffer);
}