mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
777 lines
22 KiB
777 lines
22 KiB
/**************************** Module Header ********************************\
|
|
* Module Name: security.c
|
|
*
|
|
* Copyright 1985-91, Microsoft Corporation
|
|
*
|
|
* Securable Object Routines
|
|
*
|
|
* History:
|
|
* 12-31-90 JimA Created.
|
|
* 04-14-92 RichardW Changed ACE_HEADER
|
|
\***************************************************************************/
|
|
|
|
#define _SECURITY 1
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* General security stuff
|
|
*/
|
|
PSECURITY_DESCRIPTOR gpsdInitWinSta = NULL;
|
|
|
|
PRIVILEGE_SET psTcb = { 1, PRIVILEGE_SET_ALL_NECESSARY,
|
|
{ SE_TCB_PRIVILEGE, 0 }
|
|
};
|
|
|
|
/*
|
|
* windowstation generic mapping
|
|
*/
|
|
GENERIC_MAPPING WinStaMapping = {
|
|
WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | WINSTA_ENUMERATE |
|
|
WINSTA_READSCREEN | STANDARD_RIGHTS_READ,
|
|
|
|
WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES |
|
|
STANDARD_RIGHTS_WRITE,
|
|
|
|
WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS | STANDARD_RIGHTS_EXECUTE,
|
|
|
|
WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | WINSTA_ENUMERATE |
|
|
WINSTA_READSCREEN | WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP |
|
|
WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS |
|
|
WINSTA_EXITWINDOWS | STANDARD_RIGHTS_REQUIRED
|
|
};
|
|
|
|
/*
|
|
* desktop generic mapping
|
|
*/
|
|
GENERIC_MAPPING DesktopMapping = {
|
|
DESKTOP_READOBJECTS | DESKTOP_ENUMERATE | STANDARD_RIGHTS_READ,
|
|
|
|
DESKTOP_WRITEOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU |
|
|
DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD |
|
|
DESKTOP_JOURNALPLAYBACK | STANDARD_RIGHTS_WRITE,
|
|
|
|
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_EXECUTE,
|
|
|
|
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS | DESKTOP_ENUMERATE |
|
|
DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL |
|
|
DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK |
|
|
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED
|
|
};
|
|
|
|
/***************************************************************************\
|
|
* AllocAce
|
|
*
|
|
* Allocates and initializes an ACE list.
|
|
*
|
|
* History:
|
|
* 04-25-91 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
PACCESS_ALLOWED_ACE AllocAce(
|
|
PACCESS_ALLOWED_ACE pace,
|
|
BYTE bType,
|
|
BYTE bFlags,
|
|
ACCESS_MASK am,
|
|
PSID psid,
|
|
LPDWORD lpdwLength)
|
|
{
|
|
PACCESS_ALLOWED_ACE paceNew;
|
|
DWORD iEnd;
|
|
DWORD dwLength, dwLengthSid;
|
|
|
|
/*
|
|
* Allocate space for the ACE.
|
|
*/
|
|
dwLengthSid = RtlLengthSid(psid);
|
|
dwLength = dwLengthSid + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
|
|
if (pace == NULL) {
|
|
iEnd = 0;
|
|
pace = UserAllocPoolWithQuota(dwLength, TAG_SECURITY);
|
|
if (pace == NULL)
|
|
return NULL;
|
|
} else {
|
|
iEnd = *lpdwLength;
|
|
paceNew = UserAllocPoolWithQuota(iEnd + dwLength, TAG_SECURITY);
|
|
if (paceNew == NULL)
|
|
return NULL;
|
|
RtlCopyMemory(paceNew, pace, iEnd);
|
|
UserFreePool(pace);
|
|
pace = paceNew;
|
|
}
|
|
*lpdwLength = dwLength + iEnd;
|
|
|
|
/*
|
|
* Insert the new ACE.
|
|
*/
|
|
paceNew = (PACCESS_ALLOWED_ACE)((PBYTE)pace + iEnd);
|
|
paceNew->Header.AceType = bType;
|
|
paceNew->Header.AceSize = (USHORT)dwLength;
|
|
paceNew->Header.AceFlags = bFlags;
|
|
paceNew->Mask = am;
|
|
RtlCopySid(dwLengthSid, &paceNew->SidStart, psid);
|
|
return pace;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CreateSecurityDescriptor
|
|
*
|
|
* Allocates and initializes a security descriptor.
|
|
*
|
|
* History:
|
|
* 04-25-91 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
PSECURITY_DESCRIPTOR CreateSecurityDescriptor(
|
|
PACCESS_ALLOWED_ACE paceList,
|
|
DWORD cAce,
|
|
DWORD cbAce,
|
|
BOOLEAN fDaclDefaulted)
|
|
{
|
|
PSECURITY_DESCRIPTOR psd;
|
|
PACL pacl;
|
|
NTSTATUS Status;
|
|
|
|
/*
|
|
* Allocate the security descriptor
|
|
*/
|
|
psd = (PSECURITY_DESCRIPTOR)UserAllocPoolWithQuota(
|
|
cbAce + sizeof(ACL) + SECURITY_DESCRIPTOR_MIN_LENGTH,
|
|
TAG_SECURITY);
|
|
if (psd == NULL)
|
|
return NULL;
|
|
RtlCreateSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
/*
|
|
* Initialize the ACL
|
|
*/
|
|
pacl = (PACL)((PBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
Status = RtlCreateAcl(pacl, sizeof(ACL) + cbAce, ACL_REVISION);
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
/*
|
|
* Add the ACEs to the ACL.
|
|
*/
|
|
Status = RtlAddAce(pacl, ACL_REVISION, MAXULONG, paceList, cbAce);
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
/*
|
|
* Initialize the SD
|
|
*/
|
|
Status = RtlSetDaclSecurityDescriptor(psd, (BOOLEAN)TRUE,
|
|
pacl, fDaclDefaulted);
|
|
RtlSetSaclSecurityDescriptor(psd, (BOOLEAN)FALSE, NULL,
|
|
(BOOLEAN)FALSE);
|
|
RtlSetOwnerSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
|
|
RtlSetGroupSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
UserFreePool(psd);
|
|
return NULL;
|
|
}
|
|
|
|
return psd;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* InitSecurity
|
|
*
|
|
* Initialize global security information.
|
|
*
|
|
* History:
|
|
* 01-29-91 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL InitSecurity(
|
|
VOID)
|
|
{
|
|
PACCESS_ALLOWED_ACE paceList = NULL, pace;
|
|
DWORD dwLength;
|
|
|
|
/*
|
|
* Get access to exported constants
|
|
*/
|
|
SeEnableAccessToExports();
|
|
|
|
/*
|
|
* Create ACE list.
|
|
*/
|
|
paceList = AllocAce(NULL,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE,
|
|
WinStaMapping.GenericAll,
|
|
SeExports->SeWorldSid,
|
|
&dwLength);
|
|
if (paceList == NULL)
|
|
return FALSE;
|
|
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
|
|
OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
|
|
GENERIC_ALL, SeExports->SeWorldSid, &dwLength);
|
|
if (pace == NULL) {
|
|
UserFreePool(paceList);
|
|
return FALSE;
|
|
}
|
|
paceList = pace;
|
|
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
|
|
0, DIRECTORY_QUERY | DIRECTORY_CREATE_OBJECT,
|
|
SeExports->SeAliasAdminsSid, &dwLength);
|
|
if (pace == NULL) {
|
|
UserFreePool(paceList);
|
|
return FALSE;
|
|
}
|
|
paceList = pace;
|
|
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
|
|
0, DIRECTORY_TRAVERSE, SeExports->SeWorldSid, &dwLength);
|
|
if (pace == NULL) {
|
|
UserFreePool(paceList);
|
|
return FALSE;
|
|
}
|
|
paceList = pace;
|
|
|
|
/*
|
|
* Create the SD
|
|
*/
|
|
gpsdInitWinSta = CreateSecurityDescriptor(paceList, 4, dwLength, FALSE);
|
|
UserFreePool(paceList);
|
|
|
|
if (gpsdInitWinSta == NULL) {
|
|
RIPMSG0(RIP_WARNING, "Initial windowstation security was not created!");
|
|
}
|
|
|
|
return (BOOL)(gpsdInitWinSta != NULL);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* TestForInteractiveUser
|
|
*
|
|
* Returns STATUS_SUCCESS if the LUID passed represents an
|
|
* interactiveUser user logged on by winlogon, otherwise FALSE
|
|
*
|
|
* History:
|
|
* 03-08-95 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
NTSTATUS
|
|
TestForInteractiveUser(
|
|
PLUID pluidCaller
|
|
)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
/*
|
|
* !!!
|
|
*
|
|
* This relies on the fact that there is only ONE interactive
|
|
* windowstation and that it is the first one in the list.
|
|
* If multiple windowstations are ever supported
|
|
* a lookup will have to be done here.
|
|
*/
|
|
pwinsta = grpwinstaList;
|
|
|
|
/*
|
|
* Compare it with the id of the logged on user.
|
|
*/
|
|
if (RtlEqualLuid(pluidCaller, &pwinsta->luidUser))
|
|
return STATUS_SUCCESS;
|
|
else
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* _UserTestForWinStaAccess
|
|
*
|
|
* Returns STATUS_SUCCESS if the current user has GENERIC_EXECUTE access on
|
|
* WindowStation pstrWinSta
|
|
*
|
|
*
|
|
* History:
|
|
* 06-05-96 Created SalimC
|
|
\***************************************************************************/
|
|
NTSTATUS
|
|
_UserTestForWinStaAccess(
|
|
PUNICODE_STRING pstrWinSta,
|
|
BOOL fInherit
|
|
)
|
|
{
|
|
|
|
PTOKEN_STATISTICS pStats;
|
|
ULONG BytesRequired;
|
|
PWINDOWSTATION pwinsta;
|
|
HWINSTA hwsta = NULL;
|
|
POBJECT_ATTRIBUTES ObjAttr = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
NTSTATUS NtStatust ;
|
|
DWORD cbObjA;
|
|
UNICODE_STRING strDefWinSta;
|
|
HANDLE htoken;
|
|
LUID SystemLuid = SYSTEM_LUID;
|
|
|
|
CheckCritIn();
|
|
|
|
|
|
|
|
/*
|
|
* If we are testing against Default WindowStation (WinSta0) retreive
|
|
* pwinsta from the top of the grpwinstaList instead of doing an
|
|
* OpenWindowStation()
|
|
*
|
|
* !!!
|
|
*
|
|
* This relies on the fact that there is only ONE interactive
|
|
* windowstation and that it is the first one in the list.
|
|
* If multiple windowstations are ever supported
|
|
* a lookup will have to be done instead.
|
|
*/
|
|
RtlInitUnicodeString(&strDefWinSta,DEFAULT_WINSTA);
|
|
if (RtlEqualUnicodeString(pstrWinSta,&strDefWinSta,TRUE)) {
|
|
//WinSta0 is at the top of the grpwinstaList
|
|
pwinsta = grpwinstaList;
|
|
|
|
|
|
if (!NT_SUCCESS(Status = OpenEffectiveToken(&htoken))) {
|
|
return Status;
|
|
}
|
|
|
|
Status = ZwQueryInformationToken(
|
|
htoken, // Handle
|
|
TokenStatistics, // TokenInformationClass
|
|
NULL, // TokenInformation
|
|
0, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
|
ZwClose(htoken);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the user info
|
|
//
|
|
|
|
pStats = (PTOKEN_STATISTICS)UserAllocPoolWithQuota(BytesRequired, TAG_SECURITY);
|
|
if (pStats == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
ZwClose(htoken);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Read in the user info
|
|
//
|
|
|
|
if (!NT_SUCCESS(Status = ZwQueryInformationToken(
|
|
htoken, // Handle
|
|
TokenStatistics, // TokenInformationClass
|
|
pStats, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
))) {
|
|
ZwClose(htoken);
|
|
UserFreePool(pStats);
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
* Make sure that current process has access to this window station
|
|
*
|
|
*/
|
|
|
|
Status = STATUS_ACCESS_DENIED;
|
|
if(fInherit) {
|
|
if ( (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) ||
|
|
(RtlEqualLuid(&pStats->AuthenticationId, &SystemLuid)) ||
|
|
(AccessCheckObject(pwinsta,GENERIC_EXECUTE)) ) {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
}
|
|
else {
|
|
/* Bug 42905. Service Controller clears the flag
|
|
* ScStartupInfo.dwFlags &= (~STARTF_DESKTOPINHERIT) to make services
|
|
* running under the context of system non-interactive. Hence if fInherit
|
|
* is false don't do the SystemLuid and AccessCheckObject tests.
|
|
*/
|
|
|
|
if (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
}
|
|
|
|
ZwClose(htoken);
|
|
UserFreePool(pStats);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Since we don't have a pointer to the WindowStation Object we will do
|
|
* a OpenWindowStation() to make sure we have the desired access.
|
|
*/
|
|
|
|
cbObjA = sizeof(*ObjAttr);
|
|
if (NT_SUCCESS(Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
|
&ObjAttr, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE))) {
|
|
InitializeObjectAttributes( ObjAttr,
|
|
pstrWinSta,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
hwsta = _OpenWindowStation(ObjAttr, GENERIC_EXECUTE);
|
|
} else {
|
|
return Status;
|
|
}
|
|
|
|
if (ObjAttr != NULL) {
|
|
ZwFreeVirtualMemory(NtCurrentProcess(), &ObjAttr, &cbObjA,
|
|
MEM_RELEASE);
|
|
}
|
|
|
|
|
|
if (!hwsta) {
|
|
Status = STATUS_ACCESS_DENIED;
|
|
return Status;
|
|
}
|
|
|
|
|
|
NtStatust = ZwClose(hwsta);
|
|
UserAssert(NtStatust == STATUS_SUCCESS);
|
|
return Status;
|
|
}
|
|
/***************************************************************************\
|
|
* CheckGrantedAccess
|
|
*
|
|
* Confirms all requested accesses are granted and sets error status.
|
|
*
|
|
* History:
|
|
* 06-26-95 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL CheckGrantedAccess(
|
|
ACCESS_MASK amGranted,
|
|
ACCESS_MASK amRequest)
|
|
{
|
|
|
|
/*
|
|
* Check the granted access.
|
|
*/
|
|
if (!RtlAreAllAccessesGranted(amGranted, amRequest)) {
|
|
RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CheckWinstaWriteAttributesAccess
|
|
*
|
|
* Checks if the current process has WINSTA_WRITEATTRIBUTES access
|
|
* to its windowstation, and whether that windowstation is an
|
|
* interactive windowstation.
|
|
*
|
|
* History:
|
|
* 06-Jun-1996 adams Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL CheckWinstaWriteAttributesAccess(void)
|
|
{
|
|
PPROCESSINFO ppiCurrent = PpiCurrent();
|
|
|
|
if (!RtlAreAllAccessesGranted(ppiCurrent->amwinsta, WINSTA_WRITEATTRIBUTES)) {
|
|
RIPERR0(ERROR_ACCESS_DENIED,
|
|
RIP_WARNING,
|
|
"WINSTA_WRITEATTRIBUTES access to WindowStation denied.");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(ppiCurrent->W32PF_Flags & W32PF_IOWINSTA)) {
|
|
RIPERR0(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION,
|
|
RIP_WARNING,
|
|
"Operation invalid on a non-interactive WindowStation.");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* AccessCheckObject
|
|
*
|
|
* Performs an access check on an object
|
|
*
|
|
* History:
|
|
* 12-31-90 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL AccessCheckObject(
|
|
PVOID pobj,
|
|
ACCESS_MASK amRequest)
|
|
{
|
|
NTSTATUS Status;
|
|
ACCESS_STATE AccessState;
|
|
BOOLEAN fAccessGranted;
|
|
POBJECT_HEADER pHead;
|
|
PGENERIC_MAPPING pGenericMapping;
|
|
AUX_ACCESS_DATA AuxData;
|
|
|
|
pHead = OBJECT_TO_OBJECT_HEADER(pobj);
|
|
if (pHead->Type == *ExWindowStationObjectType) {
|
|
pGenericMapping = &WinStaMapping;
|
|
} else {
|
|
pGenericMapping = &DesktopMapping;
|
|
}
|
|
SeCreateAccessState(&AccessState, &AuxData, amRequest, pGenericMapping);
|
|
fAccessGranted = ObCheckObjectAccess(
|
|
pobj,
|
|
&AccessState,
|
|
FALSE,
|
|
KeGetPreviousMode(),
|
|
&Status);
|
|
SeDeleteAccessState(&AccessState);
|
|
return (BOOL)(fAccessGranted == TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* IsPrivileged
|
|
*
|
|
* Check to see if the client has the specified privileges
|
|
*
|
|
* History:
|
|
* 01-02-91 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL IsPrivileged(
|
|
PPRIVILEGE_SET ppSet)
|
|
{
|
|
SECURITY_SUBJECT_CONTEXT Context;
|
|
BOOLEAN bHeld;
|
|
|
|
SeCaptureSubjectContext(&Context);
|
|
SeLockSubjectContext(&Context);
|
|
|
|
bHeld = SePrivilegeCheck(ppSet, &Context, UserMode);
|
|
SePrivilegeObjectAuditAlarm(NULL, &Context, 0, ppSet, bHeld, UserMode);
|
|
|
|
SeUnlockSubjectContext(&Context);
|
|
SeReleaseSubjectContext(&Context);
|
|
|
|
if (!bHeld)
|
|
RIPERR0(ERROR_PRIVILEGE_NOT_HELD, RIP_VERBOSE, "");
|
|
|
|
/*
|
|
* Return result of privilege check
|
|
*/
|
|
return (BOOL)bHeld;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* _GetUserObjectInformation (API)
|
|
*
|
|
* Gets information about a secure USER object
|
|
*
|
|
* History:
|
|
* 04-25-94 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL _GetUserObjectInformation(
|
|
HANDLE h,
|
|
int nIndex,
|
|
PVOID pvInfo,
|
|
DWORD nLength,
|
|
LPDWORD lpnLengthNeeded)
|
|
{
|
|
PUSEROBJECTFLAGS puof;
|
|
BOOL fSuccess = TRUE;
|
|
PVOID pObject;
|
|
POBJECT_HEADER pHead;
|
|
DWORD dwLengthNeeded = 0;
|
|
OBJECT_HANDLE_INFORMATION ohi;
|
|
PUNICODE_STRING pstrInfo;
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
/*
|
|
* Validate the object
|
|
*/
|
|
if (!NT_SUCCESS(ObReferenceObjectByHandle(
|
|
h,
|
|
0,
|
|
NULL,
|
|
KeGetPreviousMode(),
|
|
&pObject,
|
|
&ohi))) {
|
|
return FALSE;
|
|
}
|
|
|
|
pHead = OBJECT_TO_OBJECT_HEADER(pObject);
|
|
if (pHead->Type != *ExWindowStationObjectType &&
|
|
pHead->Type != *ExDesktopObjectType) {
|
|
RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
|
|
ObDereferenceObject(pObject);
|
|
return FALSE;
|
|
}
|
|
|
|
try {
|
|
switch (nIndex) {
|
|
case UOI_FLAGS:
|
|
dwLengthNeeded = sizeof(USEROBJECTFLAGS);
|
|
if (nLength < sizeof(USEROBJECTFLAGS)) {
|
|
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
puof = pvInfo;
|
|
puof->fInherit = (ohi.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE;
|
|
puof->fReserved = 0;
|
|
puof->dwFlags = 0;
|
|
if (pHead->Type == *ExDesktopObjectType) {
|
|
if (CheckDesktopHookFlag(PpiCurrent(), h))
|
|
puof->dwFlags |= DF_ALLOWOTHERACCOUNTHOOK;
|
|
} else {
|
|
if (!(((PWINDOWSTATION)pObject)->dwFlags & WSF_NOIO))
|
|
puof->dwFlags |= WSF_VISIBLE;
|
|
}
|
|
break;
|
|
|
|
case UOI_NAME:
|
|
pstrInfo = POBJECT_NAME(pObject);
|
|
goto docopy;
|
|
|
|
case UOI_TYPE:
|
|
pstrInfo = &pHead->Type->Name;
|
|
docopy:
|
|
if (pstrInfo) {
|
|
dwLengthNeeded = pstrInfo->Length + sizeof(WCHAR);
|
|
if (dwLengthNeeded > nLength) {
|
|
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
RtlCopyMemory(pvInfo, pstrInfo->Buffer, pstrInfo->Length);
|
|
*(PWCHAR)((PBYTE)pvInfo + pstrInfo->Length) = 0;
|
|
} else {
|
|
dwLengthNeeded = 0;
|
|
}
|
|
break;
|
|
|
|
case UOI_USER_SID:
|
|
if (pHead->Type == *ExWindowStationObjectType)
|
|
pwinsta = pObject;
|
|
else
|
|
pwinsta = ((PDESKTOP)pObject)->rpwinstaParent;
|
|
if (pwinsta->psidUser == NULL) {
|
|
dwLengthNeeded = 0;
|
|
} else {
|
|
dwLengthNeeded = RtlLengthSid(pwinsta->psidUser);
|
|
if (dwLengthNeeded > nLength) {
|
|
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
RtlCopyMemory(pvInfo, pwinsta->psidUser, dwLengthNeeded);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
RIPNTERR0(GetExceptionCode(), RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
}
|
|
|
|
*lpnLengthNeeded = dwLengthNeeded;
|
|
|
|
ObDereferenceObject(pObject);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* _SetUserObjectInformation (API)
|
|
*
|
|
* Sets information about a secure USER object
|
|
*
|
|
* History:
|
|
* 04-25-94 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL _SetUserObjectInformation(
|
|
HANDLE h,
|
|
int nIndex,
|
|
PVOID pvInfo,
|
|
DWORD nLength)
|
|
{
|
|
PUSEROBJECTFLAGS puof;
|
|
BOOL fSuccess = TRUE;
|
|
PVOID pObject;
|
|
POBJECT_HEADER pHead;
|
|
DWORD dwLengthNeeded = 0;
|
|
OBJECT_HANDLE_INFORMATION ohi;
|
|
OBJECT_HANDLE_FLAG_INFORMATION ofi;
|
|
|
|
/*
|
|
* Validate the object
|
|
*/
|
|
if (!NT_SUCCESS(ObReferenceObjectByHandle(
|
|
h,
|
|
0,
|
|
NULL,
|
|
KeGetPreviousMode(),
|
|
&pObject,
|
|
&ohi))) {
|
|
return FALSE;
|
|
}
|
|
pHead = OBJECT_TO_OBJECT_HEADER(pObject);
|
|
if (pHead->Type != *ExWindowStationObjectType &&
|
|
pHead->Type != *ExDesktopObjectType) {
|
|
RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
|
|
ObDereferenceObject(pObject);
|
|
return FALSE;
|
|
}
|
|
|
|
try {
|
|
switch (nIndex) {
|
|
case UOI_FLAGS:
|
|
if (nLength < sizeof(USEROBJECTFLAGS)) {
|
|
RIPERR0(ERROR_INVALID_DATA, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
puof = pvInfo;
|
|
ZwQueryObject(h, ObjectHandleFlagInformation,
|
|
&ofi, sizeof(ofi), NULL);
|
|
ofi.Inherit = puof->fInherit;
|
|
ZwSetInformationObject(h, ObjectHandleFlagInformation,
|
|
&ofi, sizeof(ofi));
|
|
if (pHead->Type == *ExDesktopObjectType) {
|
|
SetDesktopHookFlag(PpiCurrent(), h,
|
|
puof->dwFlags & DF_ALLOWOTHERACCOUNTHOOK);
|
|
}
|
|
break;
|
|
default:
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
break;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
RIPNTERR0(GetExceptionCode(), RIP_VERBOSE, "");
|
|
fSuccess = FALSE;
|
|
}
|
|
|
|
ObDereferenceObject(pObject);
|
|
|
|
return fSuccess;
|
|
}
|