mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: security: turns out that the AccessToken is not needed
This commit is contained in:
parent
418c454a4a
commit
4b024ebe74
@ -354,7 +354,6 @@ typedef struct
|
|||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
UINT32 SecurityInformation;
|
UINT32 SecurityInformation;
|
||||||
UINT64 AccessToken; /* request access token (HANDLE) */
|
|
||||||
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
|
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
|
||||||
} SetSecurity;
|
} SetSecurity;
|
||||||
struct
|
struct
|
||||||
|
@ -594,9 +594,6 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* be modified.
|
* be modified.
|
||||||
* @param ModificationDescriptor
|
* @param ModificationDescriptor
|
||||||
* Describes the modifications to apply to the file or directory security descriptor.
|
* Describes the modifications to apply to the file or directory security descriptor.
|
||||||
* @param AccessToken
|
|
||||||
* A handle to a token that can be used to verify whether the requested modifications
|
|
||||||
* are allowed.
|
|
||||||
* @return
|
* @return
|
||||||
* STATUS_SUCCESS or error code.
|
* STATUS_SUCCESS or error code.
|
||||||
* @see
|
* @see
|
||||||
@ -605,8 +602,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
*/
|
*/
|
||||||
NTSTATUS (*SetSecurity)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*SetSecurity)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext,
|
PVOID FileContext,
|
||||||
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor,
|
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor);
|
||||||
HANDLE AccessToken);
|
|
||||||
/**
|
/**
|
||||||
* Read a directory.
|
* Read a directory.
|
||||||
*
|
*
|
||||||
@ -1285,10 +1281,6 @@ FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
* @param ModificationDescriptor
|
* @param ModificationDescriptor
|
||||||
* Describes the modifications to apply to the InputDescriptor. This should contain
|
* Describes the modifications to apply to the InputDescriptor. This should contain
|
||||||
* the same value passed to the SetSecurity ModificationDescriptor parameter.
|
* the same value passed to the SetSecurity ModificationDescriptor parameter.
|
||||||
* @param AccessToken
|
|
||||||
* A handle to a token that can be used to verify whether the requested modifications
|
|
||||||
* are allowed. This should contain the same value passed to the SetSecurity AccessToken
|
|
||||||
* parameter.
|
|
||||||
* @param PSecurityDescriptor [out]
|
* @param PSecurityDescriptor [out]
|
||||||
* Pointer to a memory location that will receive the resulting security descriptor.
|
* Pointer to a memory location that will receive the resulting security descriptor.
|
||||||
* This security descriptor can be later freed using FspDeleteSecurityDescriptor.
|
* This security descriptor can be later freed using FspDeleteSecurityDescriptor.
|
||||||
@ -1302,7 +1294,6 @@ FSP_API NTSTATUS FspSetSecurityDescriptor(
|
|||||||
PSECURITY_DESCRIPTOR InputDescriptor,
|
PSECURITY_DESCRIPTOR InputDescriptor,
|
||||||
SECURITY_INFORMATION SecurityInformation,
|
SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR ModificationDescriptor,
|
PSECURITY_DESCRIPTOR ModificationDescriptor,
|
||||||
HANDLE AccessToken,
|
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
/**
|
/**
|
||||||
* Delete security descriptor.
|
* Delete security descriptor.
|
||||||
|
@ -603,7 +603,7 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||||
&Sddl, 0);
|
&Sddl, 0);
|
||||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
||||||
"SecurityInformation=%lx, AccessToken=%p, Security=%s%s%s\n",
|
"SecurityInformation=%lx, Security=%s%s%s\n",
|
||||||
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
FspDiagIdent(), GetCurrentThreadId(), Request->Hint,
|
||||||
Request->FileName.Size ? "\"" : "",
|
Request->FileName.Size ? "\"" : "",
|
||||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||||
@ -612,7 +612,6 @@ FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
Request->Req.SetSecurity.UserContext, Request->Req.SetSecurity.UserContext2,
|
Request->Req.SetSecurity.UserContext, Request->Req.SetSecurity.UserContext2,
|
||||||
UserContextBuf),
|
UserContextBuf),
|
||||||
Request->Req.SetSecurity.SecurityInformation,
|
Request->Req.SetSecurity.SecurityInformation,
|
||||||
(PVOID)Request->Req.SetSecurity.AccessToken,
|
|
||||||
Sddl ? "\"" : "",
|
Sddl ? "\"" : "",
|
||||||
Sddl ? Sddl : "NULL",
|
Sddl ? Sddl : "NULL",
|
||||||
Sddl ? "\"" : "");
|
Sddl ? "\"" : "");
|
||||||
|
@ -1208,8 +1208,7 @@ FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return FileSystem->Interface->SetSecurity(FileSystem,
|
return FileSystem->Interface->SetSecurity(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.SetSecurity),
|
(PVOID)ValOfFileContext(Request->Req.SetSecurity),
|
||||||
Request->Req.SetSecurity.SecurityInformation,
|
Request->Req.SetSecurity.SecurityInformation,
|
||||||
(PSECURITY_DESCRIPTOR)Request->Buffer,
|
(PSECURITY_DESCRIPTOR)Request->Buffer);
|
||||||
(HANDLE)Request->Req.SetSecurity.AccessToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemOpQueryStreamInformation(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpQueryStreamInformation(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
@ -143,8 +143,6 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileName = (PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset);
|
FileName = (PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset);
|
||||||
Token = (HANDLE)Request->Req.SetInformation.Info.Rename.AccessToken;
|
Token = (HANDLE)Request->Req.SetInformation.Info.Rename.AccessToken;
|
||||||
}
|
}
|
||||||
else if (FspFsctlTransactSetSecurityKind == Request->Kind)
|
|
||||||
Token = (HANDLE)Request->Req.SetSecurity.AccessToken;
|
|
||||||
|
|
||||||
if (0 != FileName)
|
if (0 != FileName)
|
||||||
{
|
{
|
||||||
@ -1516,8 +1514,7 @@ static NTSTATUS fsp_fuse_intf_GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode,
|
PVOID FileNode,
|
||||||
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor,
|
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor)
|
||||||
HANDLE AccessToken)
|
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||||
@ -1548,7 +1545,6 @@ static NTSTATUS fsp_fuse_intf_SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SecurityDescriptor,
|
SecurityDescriptor,
|
||||||
SecurityInformation,
|
SecurityInformation,
|
||||||
ModificationDescriptor,
|
ModificationDescriptor,
|
||||||
AccessToken,
|
|
||||||
&NewSecurityDescriptor);
|
&NewSecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -402,7 +402,6 @@ FSP_API NTSTATUS FspSetSecurityDescriptor(
|
|||||||
PSECURITY_DESCRIPTOR InputDescriptor,
|
PSECURITY_DESCRIPTOR InputDescriptor,
|
||||||
SECURITY_INFORMATION SecurityInformation,
|
SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR ModificationDescriptor,
|
PSECURITY_DESCRIPTOR ModificationDescriptor,
|
||||||
HANDLE AccessToken,
|
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
{
|
{
|
||||||
*PSecurityDescriptor = 0;
|
*PSecurityDescriptor = 0;
|
||||||
|
@ -120,7 +120,6 @@ NTSTATUS DriverEntry(
|
|||||||
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
||||||
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
||||||
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
||||||
FspIopPrepareFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityPrepare;
|
|
||||||
FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete;
|
FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete;
|
||||||
|
|
||||||
/* setup fast I/O and resource acquisition */
|
/* setup fast I/O and resource acquisition */
|
||||||
|
@ -321,7 +321,6 @@ FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
|
|||||||
FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
|
||||||
FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare;
|
FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
|
||||||
FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare;
|
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete;
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete;
|
||||||
|
@ -23,7 +23,6 @@ FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete;
|
|||||||
static FSP_IOP_REQUEST_FINI FspFsvolQuerySecurityRequestFini;
|
static FSP_IOP_REQUEST_FINI FspFsvolQuerySecurityRequestFini;
|
||||||
static NTSTATUS FspFsvolSetSecurity(
|
static NTSTATUS FspFsvolSetSecurity(
|
||||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare;
|
|
||||||
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete;
|
||||||
static FSP_IOP_REQUEST_FINI FspFsvolSetSecurityRequestFini;
|
static FSP_IOP_REQUEST_FINI FspFsvolSetSecurityRequestFini;
|
||||||
FSP_DRIVER_DISPATCH FspQuerySecurity;
|
FSP_DRIVER_DISPATCH FspQuerySecurity;
|
||||||
@ -34,7 +33,6 @@ FSP_DRIVER_DISPATCH FspSetSecurity;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQuerySecurityComplete)
|
#pragma alloc_text(PAGE, FspFsvolQuerySecurityComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQuerySecurityRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolQuerySecurityRequestFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetSecurity)
|
#pragma alloc_text(PAGE, FspFsvolSetSecurity)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetSecurityPrepare)
|
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetSecurityComplete)
|
#pragma alloc_text(PAGE, FspFsvolSetSecurityComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetSecurityRequestFini)
|
#pragma alloc_text(PAGE, FspFsvolSetSecurityRequestFini)
|
||||||
#pragma alloc_text(PAGE, FspQuerySecurity)
|
#pragma alloc_text(PAGE, FspQuerySecurity)
|
||||||
@ -49,8 +47,6 @@ enum
|
|||||||
|
|
||||||
/* SetSecurity */
|
/* SetSecurity */
|
||||||
//RequestFileNode = 0,
|
//RequestFileNode = 0,
|
||||||
RequestAccessToken = 2,
|
|
||||||
RequestProcess = 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQuerySecurity(
|
static NTSTATUS FspFsvolQuerySecurity(
|
||||||
@ -244,53 +240,6 @@ static NTSTATUS FspFsvolSetSecurity(
|
|||||||
return FSP_STATUS_IOQ_POST;
|
return FSP_STATUS_IOQ_POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFsvolSetSecurityPrepare(
|
|
||||||
PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
NTSTATUS Result;
|
|
||||||
SECURITY_SUBJECT_CONTEXT SecuritySubjectContext;
|
|
||||||
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
|
|
||||||
SECURITY_CLIENT_CONTEXT SecurityClientContext;
|
|
||||||
HANDLE UserModeAccessToken;
|
|
||||||
PEPROCESS Process;
|
|
||||||
|
|
||||||
/* duplicate the subject context access token into an impersonation token */
|
|
||||||
SecurityQualityOfService.Length = sizeof SecurityQualityOfService;
|
|
||||||
SecurityQualityOfService.ImpersonationLevel = SecurityIdentification;
|
|
||||||
SecurityQualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
|
||||||
SecurityQualityOfService.EffectiveOnly = FALSE;
|
|
||||||
SeCaptureSubjectContext(&SecuritySubjectContext);
|
|
||||||
SeLockSubjectContext(&SecuritySubjectContext);
|
|
||||||
Result = SeCreateClientSecurityFromSubjectContext(&SecuritySubjectContext,
|
|
||||||
&SecurityQualityOfService, FALSE, &SecurityClientContext);
|
|
||||||
SeUnlockSubjectContext(&SecuritySubjectContext);
|
|
||||||
SeReleaseSubjectContext(&SecuritySubjectContext);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
|
|
||||||
ASSERT(TokenImpersonation == SeTokenType(SecurityClientContext.ClientToken));
|
|
||||||
|
|
||||||
/* get a user-mode handle to the impersonation token */
|
|
||||||
Result = ObOpenObjectByPointer(SecurityClientContext.ClientToken,
|
|
||||||
0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken);
|
|
||||||
SeDeleteClientSecurity(&SecurityClientContext);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
|
|
||||||
/* get a pointer to the current process so that we can close the impersonation token later */
|
|
||||||
Process = PsGetCurrentProcess();
|
|
||||||
ObReferenceObject(Process);
|
|
||||||
|
|
||||||
/* send the user-mode handle to the user-mode file system */
|
|
||||||
FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken;
|
|
||||||
FspIopRequestContext(Request, RequestProcess) = Process;
|
|
||||||
Request->Req.SetSecurity.AccessToken = (UINT_PTR)UserModeAccessToken;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS FspFsvolSetSecurityComplete(
|
NTSTATUS FspFsvolSetSecurityComplete(
|
||||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
@ -339,35 +288,9 @@ static VOID FspFsvolSetSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOI
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
|
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
|
||||||
HANDLE AccessToken = Context[RequestAccessToken];
|
|
||||||
PEPROCESS Process = Context[RequestProcess];
|
|
||||||
|
|
||||||
if (0 != FileNode)
|
if (0 != FileNode)
|
||||||
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
|
|
||||||
if (0 != AccessToken)
|
|
||||||
{
|
|
||||||
KAPC_STATE ApcState;
|
|
||||||
BOOLEAN Attach;
|
|
||||||
|
|
||||||
ASSERT(0 != Process);
|
|
||||||
Attach = Process != PsGetCurrentProcess();
|
|
||||||
|
|
||||||
if (Attach)
|
|
||||||
KeStackAttachProcess(Process, &ApcState);
|
|
||||||
#if DBG
|
|
||||||
NTSTATUS Result0;
|
|
||||||
Result0 = ObCloseHandle(AccessToken, UserMode);
|
|
||||||
if (!NT_SUCCESS(Result0))
|
|
||||||
DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0));
|
|
||||||
#else
|
|
||||||
ObCloseHandle(AccessToken, UserMode);
|
|
||||||
#endif
|
|
||||||
if (Attach)
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspQuerySecurity(
|
NTSTATUS FspQuerySecurity(
|
||||||
|
@ -1245,8 +1245,7 @@ static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0,
|
PVOID FileNode0,
|
||||||
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor,
|
SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor)
|
||||||
HANDLE AccessToken)
|
|
||||||
{
|
{
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor, FileSecurity;
|
PSECURITY_DESCRIPTOR NewSecurityDescriptor, FileSecurity;
|
||||||
@ -1262,7 +1261,6 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileNode->FileSecurity,
|
FileNode->FileSecurity,
|
||||||
SecurityInformation,
|
SecurityInformation,
|
||||||
ModificationDescriptor,
|
ModificationDescriptor,
|
||||||
AccessToken,
|
|
||||||
&NewSecurityDescriptor);
|
&NewSecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user