diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index ce51a20b..6e5dcf20 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -251,7 +251,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) struct fuse_conn_info conn; NTSTATUS Result; - context = fsp_fuse_get_context(f->env); + context = fsp_fuse_get_context(0); if (0 == context) { Result = STATUS_INSUFFICIENT_RESOURCES; @@ -259,6 +259,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) } context->fuse = f; context->private_data = f->data; + context->uid = context->gid = -1; memset(&conn, 0, sizeof conn); conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */ @@ -376,7 +377,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) fsp_fuse_op_query_security); FspFileSystemSetOperation(f->FileSystem, FspFsctlTransactSetSecurityKind, fsp_fuse_op_set_security); - //FspFileSystemSetOperationGuard(f->FileSystem, 0, 0); + FspFileSystemSetOperationGuard(f->FileSystem, fsp_fuse_op_enter, fsp_fuse_op_leave); FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog); @@ -623,7 +624,7 @@ FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env, FspServiceStop(f->Service); } -FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) +FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *reserved) { struct fuse_context *context; @@ -639,6 +640,7 @@ FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) return 0; memset(context, 0, sizeof *context); + context->pid = -1; TlsSetValue(fsp_fuse_tlskey, context); } diff --git a/src/dll/fuse/fuseop.c b/src/dll/fuse/fuseop.c index 9d83de63..14b947d6 100644 --- a/src/dll/fuse/fuseop.c +++ b/src/dll/fuse/fuseop.c @@ -17,12 +17,182 @@ #include +static NTSTATUS fsp_fuse_op_set_context(FSP_FILE_SYSTEM *FileSystem, HANDLE Token) +{ + struct fuse_context *context; + UINT32 Uid = -1, Gid = -1; + union + { + TOKEN_USER V; + UINT8 B[128]; + } UserInfoBuf; + PTOKEN_USER UserInfo = &UserInfoBuf.V; + union + { + TOKEN_PRIMARY_GROUP V; + UINT8 B[128]; + } GroupInfoBuf; + PTOKEN_PRIMARY_GROUP GroupInfo = &GroupInfoBuf.V; + DWORD Size; + NTSTATUS Result; + + context = fsp_fuse_get_context(0); + if (0 == context) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (0 != Token) + { + 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; + } + } + + if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, sizeof GroupInfoBuf, &Size)) + { + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + GroupInfo = MemAlloc(Size); + if (0 == UserInfo) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + if (!GetTokenInformation(Token, TokenPrimaryGroup, GroupInfo, Size, &Size)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + } + + Result = FspPosixMapSidToUid(UserInfo->User.Sid, &Uid); + if (!NT_SUCCESS(Result)) + goto exit; + + Result = FspPosixMapSidToUid(GroupInfo->PrimaryGroup, &Gid); + if (!NT_SUCCESS(Result)) + goto exit; + } + + context->fuse = FileSystem->UserContext; + context->uid = Uid; + context->gid = Gid; + + Result = STATUS_SUCCESS; + +exit: + if (UserInfo != &UserInfoBuf.V) + MemFree(UserInfo); + + if (GroupInfo != &GroupInfoBuf.V) + MemFree(GroupInfo); + + return Result; +} + +VOID fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) +{ +} + +VOID fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) +{ + struct fuse_context *context; + + context = fsp_fuse_get_context(0); + context->fuse = 0; + context->uid = -1; + context->gid = -1; +} + NTSTATUS fsp_fuse_op_get_security_by_name(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes, - PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) + PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize) { - /* not a true file system op, required for access checks! */ - return STATUS_INVALID_DEVICE_REQUEST; + struct fuse *f = FileSystem->UserContext; + char *PosixPath = 0; + PSECURITY_DESCRIPTOR SecurityDescriptor = 0; + SIZE_T SecurityDescriptorSize; + struct fuse_stat stbuf; + int err; + NTSTATUS Result; + + if (0 == f->ops.getattr) + return STATUS_INVALID_DEVICE_REQUEST; + + Result = FspPosixMapWindowsToPosixPath(FileName, &PosixPath); + if (!NT_SUCCESS(Result)) + goto exit; + + memset(&stbuf, 0, sizeof stbuf); + err = f->ops.getattr(PosixPath, (void *)&stbuf); + if (0 != err) + { + Result = fsp_fuse_ntstatus_from_errno(f->env, err); + goto exit; + } + + if (0 != PFileAttributes) + *PFileAttributes = (stbuf.st_mode & 0040000) ? + FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + + if (0 != PSecurityDescriptorSize) + { + Result = FspPosixMapPermissionsToSecurityDescriptor( + stbuf.st_uid, stbuf.st_gid, stbuf.st_mode, &SecurityDescriptor); + if (!NT_SUCCESS(Result)) + goto exit; + + SecurityDescriptorSize = GetSecurityDescriptorLength(SecurityDescriptor); + + if (SecurityDescriptorSize > *PSecurityDescriptorSize) + { + *PSecurityDescriptorSize = SecurityDescriptorSize; + Result = STATUS_BUFFER_OVERFLOW; + goto exit; + } + + *PSecurityDescriptorSize = SecurityDescriptorSize; + if (0 != SecurityDescriptorBuf) + memcpy(SecurityDescriptorBuf, SecurityDescriptor, SecurityDescriptorSize); + } + + Result = STATUS_SUCCESS; + +exit: + if (0 != SecurityDescriptor) + FspDeleteSecurityDescriptor(SecurityDescriptor, + FspPosixMapPermissionsToSecurityDescriptor); + + if (0 != PosixPath) + FspPosixDeletePath(PosixPath); + + return Result; } NTSTATUS fsp_fuse_op_create(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/dll/fuse/library.h b/src/dll/fuse/library.h index 542c0579..c753fb1e 100644 --- a/src/dll/fuse/library.h +++ b/src/dll/fuse/library.h @@ -37,6 +37,10 @@ struct fuse BOOLEAN fsinit; }; +VOID fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); +VOID fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); NTSTATUS fsp_fuse_op_get_security_by_name(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PUINT32 PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize);