2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/se/priv.c
|
|
|
|
* PURPOSE: Security manager
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: No programmer listed.
|
2000-01-26 10:07:30 +00:00
|
|
|
*/
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
2000-01-26 10:07:30 +00:00
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2003-06-20 18:19:29 +00:00
|
|
|
#define NDEBUG
|
2008-04-23 20:38:37 +00:00
|
|
|
#include <debug.h>
|
2000-01-26 10:07:30 +00:00
|
|
|
|
2005-11-28 23:25:31 +00:00
|
|
|
#if defined (ALLOC_PRAGMA)
|
|
|
|
#pragma alloc_text(INIT, SepInitPrivileges)
|
|
|
|
#endif
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2013-11-26 23:28:37 +00:00
|
|
|
#define CONST_LUID(x1, x2) {x1, x2}
|
|
|
|
const LUID SeCreateTokenPrivilege = CONST_LUID(SE_CREATE_TOKEN_PRIVILEGE, 0);
|
|
|
|
const LUID SeAssignPrimaryTokenPrivilege = CONST_LUID(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0);
|
|
|
|
const LUID SeLockMemoryPrivilege = CONST_LUID(SE_LOCK_MEMORY_PRIVILEGE, 0);
|
|
|
|
const LUID SeIncreaseQuotaPrivilege = CONST_LUID(SE_INCREASE_QUOTA_PRIVILEGE, 0);
|
|
|
|
const LUID SeUnsolicitedInputPrivilege = CONST_LUID(6, 0);
|
|
|
|
const LUID SeTcbPrivilege = CONST_LUID(SE_TCB_PRIVILEGE, 0);
|
|
|
|
const LUID SeSecurityPrivilege = CONST_LUID(SE_SECURITY_PRIVILEGE, 0);
|
|
|
|
const LUID SeTakeOwnershipPrivilege = CONST_LUID(SE_TAKE_OWNERSHIP_PRIVILEGE, 0);
|
|
|
|
const LUID SeLoadDriverPrivilege = CONST_LUID(SE_LOAD_DRIVER_PRIVILEGE, 0);
|
|
|
|
const LUID SeSystemProfilePrivilege = CONST_LUID(SE_SYSTEM_PROFILE_PRIVILEGE, 0);
|
|
|
|
const LUID SeSystemtimePrivilege = CONST_LUID(SE_SYSTEMTIME_PRIVILEGE, 0);
|
|
|
|
const LUID SeProfileSingleProcessPrivilege = CONST_LUID(SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0);
|
|
|
|
const LUID SeIncreaseBasePriorityPrivilege = CONST_LUID(SE_INC_BASE_PRIORITY_PRIVILEGE, 0);
|
|
|
|
const LUID SeCreatePagefilePrivilege = CONST_LUID(SE_CREATE_PAGEFILE_PRIVILEGE, 0);
|
|
|
|
const LUID SeCreatePermanentPrivilege = CONST_LUID(SE_CREATE_PERMANENT_PRIVILEGE, 0);
|
|
|
|
const LUID SeBackupPrivilege = CONST_LUID(SE_BACKUP_PRIVILEGE, 0);
|
|
|
|
const LUID SeRestorePrivilege = CONST_LUID(SE_RESTORE_PRIVILEGE, 0);
|
|
|
|
const LUID SeShutdownPrivilege = CONST_LUID(SE_SHUTDOWN_PRIVILEGE, 0);
|
|
|
|
const LUID SeDebugPrivilege = CONST_LUID(SE_DEBUG_PRIVILEGE, 0);
|
|
|
|
const LUID SeAuditPrivilege = CONST_LUID(SE_AUDIT_PRIVILEGE, 0);
|
|
|
|
const LUID SeSystemEnvironmentPrivilege = CONST_LUID(SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0);
|
|
|
|
const LUID SeChangeNotifyPrivilege = CONST_LUID(SE_CHANGE_NOTIFY_PRIVILEGE, 0);
|
|
|
|
const LUID SeRemoteShutdownPrivilege = CONST_LUID(SE_REMOTE_SHUTDOWN_PRIVILEGE, 0);
|
|
|
|
const LUID SeUndockPrivilege = CONST_LUID(SE_UNDOCK_PRIVILEGE, 0);
|
|
|
|
const LUID SeSyncAgentPrivilege = CONST_LUID(SE_SYNC_AGENT_PRIVILEGE, 0);
|
|
|
|
const LUID SeEnableDelegationPrivilege = CONST_LUID(SE_ENABLE_DELEGATION_PRIVILEGE, 0);
|
|
|
|
const LUID SeManageVolumePrivilege = CONST_LUID(SE_MANAGE_VOLUME_PRIVILEGE, 0);
|
|
|
|
const LUID SeImpersonatePrivilege = CONST_LUID(SE_IMPERSONATE_PRIVILEGE, 0);
|
|
|
|
const LUID SeCreateGlobalPrivilege = CONST_LUID(SE_CREATE_GLOBAL_PRIVILEGE, 0);
|
|
|
|
const LUID SeTrustedCredmanPrivilege = CONST_LUID(SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE, 0);
|
|
|
|
const LUID SeRelabelPrivilege = CONST_LUID(SE_RELABEL_PRIVILEGE, 0);
|
|
|
|
const LUID SeIncreaseWorkingSetPrivilege = CONST_LUID(SE_INC_WORKING_SET_PRIVILEGE, 0);
|
|
|
|
const LUID SeTimeZonePrivilege = CONST_LUID(SE_TIME_ZONE_PRIVILEGE, 0);
|
|
|
|
const LUID SeCreateSymbolicLinkPrivilege = CONST_LUID(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, 0);
|
|
|
|
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2000-01-26 10:07:30 +00:00
|
|
|
|
2005-09-13 23:28:21 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2010-05-28 16:28:27 +00:00
|
|
|
SepInitPrivileges(VOID)
|
2002-02-20 20:16:49 +00:00
|
|
|
{
|
2013-11-26 23:28:37 +00:00
|
|
|
|
2002-02-20 20:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-31 11:10:30 +00:00
|
|
|
BOOLEAN
|
2005-09-13 23:28:21 +00:00
|
|
|
NTAPI
|
2010-05-28 16:28:27 +00:00
|
|
|
SepPrivilegeCheck(PTOKEN Token,
|
|
|
|
PLUID_AND_ATTRIBUTES Privileges,
|
|
|
|
ULONG PrivilegeCount,
|
|
|
|
ULONG PrivilegeControl,
|
|
|
|
KPROCESSOR_MODE PreviousMode)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2008-04-23 20:38:37 +00:00
|
|
|
ULONG i;
|
|
|
|
ULONG j;
|
2011-01-15 14:35:26 +00:00
|
|
|
ULONG Required;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
DPRINT("SepPrivilegeCheck() called\n");
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
if (PreviousMode == KernelMode)
|
|
|
|
return TRUE;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2011-01-15 14:35:26 +00:00
|
|
|
/* Get the number of privileges that are required to match */
|
|
|
|
Required = (PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) ? PrivilegeCount : 1;
|
|
|
|
|
|
|
|
/* Loop all requested privileges until we found the required ones */
|
2014-01-11 15:23:53 +00:00
|
|
|
for (i = 0; i < PrivilegeCount; i++)
|
2003-05-31 11:10:30 +00:00
|
|
|
{
|
2011-01-15 14:35:26 +00:00
|
|
|
/* Loop the privileges of the token */
|
|
|
|
for (j = 0; j < Token->PrivilegeCount; j++)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
2011-01-15 14:35:26 +00:00
|
|
|
/* Check if the LUIDs match */
|
|
|
|
if (Token->Privileges[j].Luid.LowPart == Privileges[i].Luid.LowPart &&
|
|
|
|
Token->Privileges[j].Luid.HighPart == Privileges[i].Luid.HighPart)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
2011-01-15 14:35:26 +00:00
|
|
|
DPRINT("Found privilege. Attributes: %lx\n",
|
|
|
|
Token->Privileges[j].Attributes);
|
|
|
|
|
|
|
|
/* Check if the privilege is enabled */
|
|
|
|
if (Token->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
2011-01-15 14:35:26 +00:00
|
|
|
Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
|
|
|
|
Required--;
|
2014-01-11 15:23:53 +00:00
|
|
|
|
|
|
|
/* Check if we have found all privileges */
|
|
|
|
if (Required == 0)
|
|
|
|
{
|
|
|
|
/* We're done! */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
2011-01-15 14:35:26 +00:00
|
|
|
|
|
|
|
/* Leave the inner loop */
|
|
|
|
break;
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
|
|
|
}
|
2003-05-31 11:10:30 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2014-01-11 15:23:53 +00:00
|
|
|
/* When we reached this point, we did not find all privileges */
|
|
|
|
NT_ASSERT(Required > 0);
|
|
|
|
return FALSE;
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
|
|
|
|
2003-05-31 11:10:30 +00:00
|
|
|
NTSTATUS
|
2005-09-13 23:28:21 +00:00
|
|
|
NTAPI
|
2010-05-28 16:28:27 +00:00
|
|
|
SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
|
|
|
|
ULONG PrivilegeCount,
|
|
|
|
KPROCESSOR_MODE PreviousMode,
|
|
|
|
PLUID_AND_ATTRIBUTES AllocatedMem,
|
|
|
|
ULONG AllocatedLength,
|
|
|
|
POOL_TYPE PoolType,
|
|
|
|
BOOLEAN CaptureIfKernel,
|
|
|
|
PLUID_AND_ATTRIBUTES *Dest,
|
|
|
|
PULONG Length)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2007-04-02 15:08:54 +00:00
|
|
|
ULONG BufferSize;
|
2006-01-22 22:46:23 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
if (PrivilegeCount == 0)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2006-01-22 22:46:23 +00:00
|
|
|
*Dest = 0;
|
|
|
|
*Length = 0;
|
|
|
|
return STATUS_SUCCESS;
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
if (PreviousMode == KernelMode && !CaptureIfKernel)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2006-01-22 22:46:23 +00:00
|
|
|
*Dest = Src;
|
|
|
|
return STATUS_SUCCESS;
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
/* FIXME - check PrivilegeCount for a valid number so we don't
|
2008-04-23 20:38:37 +00:00
|
|
|
cause an integer overflow or exhaust system resources! */
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
|
|
|
|
*Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
/* probe the buffer */
|
|
|
|
if (PreviousMode != KernelMode)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2006-01-22 22:46:23 +00:00
|
|
|
{
|
|
|
|
ProbeForRead(Src,
|
|
|
|
BufferSize,
|
|
|
|
sizeof(ULONG));
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2006-01-22 22:46:23 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2006-01-22 22:46:23 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
/* allocate enough memory or check if the provided buffer is
|
2008-04-23 20:38:37 +00:00
|
|
|
large enough to hold the array */
|
2006-01-22 22:46:23 +00:00
|
|
|
if (AllocatedMem != NULL)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2006-01-22 22:46:23 +00:00
|
|
|
if (AllocatedLength < BufferSize)
|
|
|
|
{
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
*Dest = AllocatedMem;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*Dest = ExAllocatePool(PoolType,
|
|
|
|
BufferSize);
|
2009-08-26 17:41:01 +00:00
|
|
|
if (*Dest == NULL)
|
2006-01-22 22:46:23 +00:00
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 23:28:37 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
/* copy the array to the buffer */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2006-01-22 22:46:23 +00:00
|
|
|
{
|
|
|
|
RtlCopyMemory(*Dest,
|
|
|
|
Src,
|
|
|
|
BufferSize);
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2006-01-22 22:46:23 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2006-01-22 22:46:23 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
if (!NT_SUCCESS(Status) && AllocatedMem == NULL)
|
|
|
|
{
|
|
|
|
ExFreePool(*Dest);
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
return Status;
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
VOID
|
2005-09-13 23:28:21 +00:00
|
|
|
NTAPI
|
2010-05-28 16:28:27 +00:00
|
|
|
SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
|
|
|
|
KPROCESSOR_MODE PreviousMode,
|
|
|
|
BOOLEAN CaptureIfKernel)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2006-01-22 22:46:23 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2006-01-22 22:46:23 +00:00
|
|
|
if (Privilege != NULL &&
|
|
|
|
(PreviousMode != KernelMode || CaptureIfKernel))
|
|
|
|
{
|
|
|
|
ExFreePool(Privilege);
|
|
|
|
}
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
2003-05-31 11:10:30 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/*
|
2010-05-28 19:36:57 +00:00
|
|
|
* @implemented
|
2008-04-23 20:38:37 +00:00
|
|
|
*/
|
|
|
|
NTSTATUS
|
2008-11-29 20:47:48 +00:00
|
|
|
NTAPI
|
2010-05-28 19:36:57 +00:00
|
|
|
SeAppendPrivileges(IN OUT PACCESS_STATE AccessState,
|
|
|
|
IN PPRIVILEGE_SET Privileges)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2010-05-28 19:36:57 +00:00
|
|
|
PAUX_ACCESS_DATA AuxData;
|
|
|
|
ULONG OldPrivilegeSetSize;
|
|
|
|
ULONG NewPrivilegeSetSize;
|
|
|
|
PPRIVILEGE_SET PrivilegeSet;
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the Auxiliary Data */
|
|
|
|
AuxData = AccessState->AuxData;
|
|
|
|
|
|
|
|
/* Calculate the size of the old privilege set */
|
|
|
|
OldPrivilegeSetSize = sizeof(PRIVILEGE_SET) +
|
|
|
|
(AuxData->PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES);
|
|
|
|
|
|
|
|
if (AuxData->PrivilegeSet->PrivilegeCount +
|
|
|
|
Privileges->PrivilegeCount > INITIAL_PRIVILEGE_COUNT)
|
|
|
|
{
|
|
|
|
/* Calculate the size of the new privilege set */
|
|
|
|
NewPrivilegeSetSize = OldPrivilegeSetSize +
|
|
|
|
Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
|
|
|
|
|
|
|
|
/* Allocate a new privilege set */
|
|
|
|
PrivilegeSet = ExAllocatePool(PagedPool, NewPrivilegeSetSize);
|
|
|
|
if (PrivilegeSet == NULL)
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
|
|
|
/* Copy original privileges from the acess state */
|
|
|
|
RtlCopyMemory(PrivilegeSet,
|
|
|
|
AuxData->PrivilegeSet,
|
|
|
|
OldPrivilegeSetSize);
|
|
|
|
|
|
|
|
/* Append privileges from the privilege set*/
|
|
|
|
RtlCopyMemory((PVOID)((ULONG_PTR)PrivilegeSet + OldPrivilegeSetSize),
|
|
|
|
(PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
|
|
|
|
Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
|
|
|
|
|
|
|
|
/* Adjust the number of privileges in the new privilege set */
|
|
|
|
PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
|
|
|
|
|
|
|
|
/* Free the old privilege set if it was allocated */
|
|
|
|
if (AccessState->PrivilegesAllocated == TRUE)
|
|
|
|
ExFreePool(AuxData->PrivilegeSet);
|
|
|
|
|
|
|
|
/* Now we are using an allocated privilege set */
|
|
|
|
AccessState->PrivilegesAllocated = TRUE;
|
|
|
|
|
|
|
|
/* Assign the new privileges to the access state */
|
|
|
|
AuxData->PrivilegeSet = PrivilegeSet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Append privileges */
|
|
|
|
RtlCopyMemory((PVOID)((ULONG_PTR)AuxData->PrivilegeSet + OldPrivilegeSetSize),
|
|
|
|
(PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
|
|
|
|
Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
|
|
|
|
|
|
|
|
/* Adjust the number of privileges in the target privilege set */
|
|
|
|
AuxData->PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/*
|
2010-05-28 15:03:09 +00:00
|
|
|
* @implemented
|
2008-04-23 20:38:37 +00:00
|
|
|
*/
|
|
|
|
VOID
|
2008-11-29 20:47:48 +00:00
|
|
|
NTAPI
|
2008-04-23 20:38:37 +00:00
|
|
|
SeFreePrivileges(IN PPRIVILEGE_SET Privileges)
|
|
|
|
{
|
2010-05-28 15:03:09 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
ExFreePool(Privileges);
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
2003-05-31 11:10:30 +00:00
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2010-05-28 16:28:27 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
SePrivilegeCheck(PPRIVILEGE_SET Privileges,
|
|
|
|
PSECURITY_SUBJECT_CONTEXT SubjectContext,
|
|
|
|
KPROCESSOR_MODE PreviousMode)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2008-04-23 20:38:37 +00:00
|
|
|
PACCESS_TOKEN Token = NULL;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
if (SubjectContext->ClientToken == NULL)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2008-04-23 20:38:37 +00:00
|
|
|
Token = SubjectContext->PrimaryToken;
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2008-04-23 20:38:37 +00:00
|
|
|
else
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2008-04-23 20:38:37 +00:00
|
|
|
Token = SubjectContext->ClientToken;
|
|
|
|
if (SubjectContext->ImpersonationLevel < 2)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
return SepPrivilegeCheck(Token,
|
|
|
|
Privileges->Privilege,
|
|
|
|
Privileges->PrivilegeCount,
|
|
|
|
Privileges->Control,
|
|
|
|
PreviousMode);
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2010-05-28 16:28:27 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
|
|
|
|
IN KPROCESSOR_MODE PreviousMode)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2008-04-23 20:38:37 +00:00
|
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
|
|
|
PRIVILEGE_SET Priv;
|
|
|
|
BOOLEAN Result;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
SeCaptureSubjectContext(&SubjectContext);
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
Priv.PrivilegeCount = 1;
|
|
|
|
Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
|
|
|
Priv.Privilege[0].Luid = PrivilegeValue;
|
|
|
|
Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
Result = SePrivilegeCheck(&Priv,
|
|
|
|
&SubjectContext,
|
|
|
|
PreviousMode);
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
2003-06-17 10:42:37 +00:00
|
|
|
{
|
2000-01-26 10:07:30 +00:00
|
|
|
#if 0
|
2010-05-28 16:28:27 +00:00
|
|
|
SePrivilegedServiceAuditAlarm(0,
|
|
|
|
&SubjectContext,
|
|
|
|
&PrivilegeValue);
|
2000-01-26 10:07:30 +00:00
|
|
|
#endif
|
2003-06-17 10:42:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
SeReleaseSubjectContext(&SubjectContext);
|
|
|
|
|
2012-02-18 23:59:31 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
SeCheckPrivilegedObject(IN LUID PrivilegeValue,
|
|
|
|
IN HANDLE ObjectHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN KPROCESSOR_MODE PreviousMode)
|
|
|
|
{
|
|
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
|
|
|
PRIVILEGE_SET Priv;
|
|
|
|
BOOLEAN Result;
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
SeCaptureSubjectContext(&SubjectContext);
|
|
|
|
|
|
|
|
Priv.PrivilegeCount = 1;
|
|
|
|
Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
|
|
|
Priv.Privilege[0].Luid = PrivilegeValue;
|
|
|
|
Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
|
|
|
|
Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode);
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
SePrivilegeObjectAuditAlarm(ObjectHandle,
|
|
|
|
&SubjectContext,
|
|
|
|
DesiredAccess,
|
|
|
|
&PrivilegeValue,
|
|
|
|
Result,
|
|
|
|
PreviousMode);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
SeReleaseSubjectContext(&SubjectContext);
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
return Result;
|
|
|
|
}
|
2003-06-17 10:42:37 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* SYSTEM CALLS ***************************************************************/
|
2003-06-17 10:42:37 +00:00
|
|
|
|
2010-05-28 16:28:27 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtPrivilegeCheck(IN HANDLE ClientToken,
|
|
|
|
IN PPRIVILEGE_SET RequiredPrivileges,
|
|
|
|
OUT PBOOLEAN Result)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
|
|
|
PLUID_AND_ATTRIBUTES Privileges;
|
|
|
|
PTOKEN Token;
|
|
|
|
ULONG PrivilegeCount = 0;
|
|
|
|
ULONG PrivilegeControl = 0;
|
|
|
|
ULONG Length;
|
|
|
|
BOOLEAN CheckResult;
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
2009-08-26 17:31:02 +00:00
|
|
|
NTSTATUS Status;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PAGED_CODE();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PreviousMode = KeGetPreviousMode();
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* probe the buffers */
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
|
|
|
ProbeForWrite(RequiredPrivileges,
|
|
|
|
FIELD_OFFSET(PRIVILEGE_SET,
|
|
|
|
Privilege),
|
|
|
|
sizeof(ULONG));
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
PrivilegeCount = RequiredPrivileges->PrivilegeCount;
|
|
|
|
PrivilegeControl = RequiredPrivileges->Control;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* Check PrivilegeCount to avoid an integer overflow! */
|
|
|
|
if (FIELD_OFFSET(PRIVILEGE_SET,
|
|
|
|
Privilege[PrivilegeCount]) /
|
|
|
|
sizeof(RequiredPrivileges->Privilege[0]) != PrivilegeCount)
|
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
_SEH2_YIELD(return STATUS_INVALID_PARAMETER);
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* probe all of the array */
|
|
|
|
ProbeForWrite(RequiredPrivileges,
|
|
|
|
FIELD_OFFSET(PRIVILEGE_SET,
|
|
|
|
Privilege[PrivilegeCount]),
|
|
|
|
sizeof(ULONG));
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
ProbeForWriteBoolean(Result);
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PrivilegeCount = RequiredPrivileges->PrivilegeCount;
|
|
|
|
PrivilegeControl = RequiredPrivileges->Control;
|
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* reference the token and make sure we're
|
|
|
|
not doing an anonymous impersonation */
|
2010-05-28 16:28:27 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ClientToken,
|
|
|
|
TOKEN_QUERY,
|
2012-04-21 06:35:45 +00:00
|
|
|
SeTokenObjectType,
|
2010-05-28 16:28:27 +00:00
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Token,
|
|
|
|
NULL);
|
2008-04-23 20:38:37 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
if (Token->TokenType == TokenImpersonation &&
|
|
|
|
Token->ImpersonationLevel < SecurityIdentification)
|
|
|
|
{
|
2010-05-28 16:28:27 +00:00
|
|
|
ObDereferenceObject(Token);
|
2008-04-23 20:38:37 +00:00
|
|
|
return STATUS_BAD_IMPERSONATION_LEVEL;
|
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* capture the privileges */
|
2010-05-28 16:28:27 +00:00
|
|
|
Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege,
|
|
|
|
PrivilegeCount,
|
|
|
|
PreviousMode,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
PagedPool,
|
|
|
|
TRUE,
|
|
|
|
&Privileges,
|
|
|
|
&Length);
|
2008-04-23 20:38:37 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ObDereferenceObject (Token);
|
|
|
|
return Status;
|
|
|
|
}
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
CheckResult = SepPrivilegeCheck(Token,
|
|
|
|
Privileges,
|
|
|
|
PrivilegeCount,
|
|
|
|
PrivilegeControl,
|
|
|
|
PreviousMode);
|
|
|
|
|
|
|
|
ObDereferenceObject(Token);
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
/* return the array */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
|
|
|
RtlCopyMemory(RequiredPrivileges->Privilege,
|
|
|
|
Privileges,
|
|
|
|
PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
|
|
|
|
*Result = CheckResult;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2008-04-23 20:38:37 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2008-04-23 20:38:37 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2010-05-28 16:28:27 +00:00
|
|
|
|
|
|
|
SeReleaseLuidAndAttributesArray(Privileges,
|
|
|
|
PreviousMode,
|
|
|
|
TRUE);
|
|
|
|
|
2008-04-23 20:38:37 +00:00
|
|
|
return Status;
|
2000-01-26 10:07:30 +00:00
|
|
|
}
|
|
|
|
|
2003-05-31 11:10:30 +00:00
|
|
|
/* EOF */
|