-/* $Id: priv.c,v 1.4 2002/09/07 15:13:06 chorns Exp $
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/se/priv.c
+ * PURPOSE: Security manager
*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * PURPOSE: Security manager
- * FILE: kernel/se/priv.c
- * PROGRAMER: ?
- * REVISION HISTORY:
- * 26/07/98: Added stubs for security functions
+ * PROGRAMMERS: No programmer listed.
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
-
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, SepInitPrivileges)
+#endif
-/* GLOBALS *******************************************************************/
+/* GLOBALS ********************************************************************/
LUID SeCreateTokenPrivilege;
LUID SeAssignPrimaryTokenPrivilege;
LUID SeSystemEnvironmentPrivilege;
LUID SeChangeNotifyPrivilege;
LUID SeRemoteShutdownPrivilege;
+LUID SeUndockPrivilege;
+LUID SeSyncAgentPrivilege;
+LUID SeEnableDelegationPrivilege;
-
-/* FUNCTIONS ***************************************************************/
+/* PRIVATE FUNCTIONS **********************************************************/
VOID
-SepInitPrivileges(VOID)
+INIT_FUNCTION
+NTAPI
+SepInitPrivileges (VOID)
{
- SeCreateTokenPrivilege.QuadPart = SE_CREATE_TOKEN_PRIVILEGE;
- SeAssignPrimaryTokenPrivilege.QuadPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE;
- SeLockMemoryPrivilege.QuadPart = SE_LOCK_MEMORY_PRIVILEGE;
- SeIncreaseQuotaPrivilege.QuadPart = SE_INCREASE_QUOTA_PRIVILEGE;
- SeUnsolicitedInputPrivilege.QuadPart = SE_UNSOLICITED_INPUT_PRIVILEGE;
- SeTcbPrivilege.QuadPart = SE_TCB_PRIVILEGE;
- SeSecurityPrivilege.QuadPart = SE_SECURITY_PRIVILEGE;
- SeTakeOwnershipPrivilege.QuadPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
- SeLoadDriverPrivilege.QuadPart = SE_LOAD_DRIVER_PRIVILEGE;
- SeSystemProfilePrivilege.QuadPart = SE_SYSTEM_PROFILE_PRIVILEGE;
- SeSystemtimePrivilege.QuadPart = SE_SYSTEMTIME_PRIVILEGE;
- SeProfileSingleProcessPrivilege.QuadPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE;
- SeIncreaseBasePriorityPrivilege.QuadPart = SE_INC_BASE_PRIORITY_PRIVILEGE;
- SeCreatePagefilePrivilege.QuadPart = SE_CREATE_PAGEFILE_PRIVILEGE;
- SeCreatePermanentPrivilege.QuadPart = SE_CREATE_PERMANENT_PRIVILEGE;
- SeBackupPrivilege.QuadPart = SE_BACKUP_PRIVILEGE;
- SeRestorePrivilege.QuadPart = SE_RESTORE_PRIVILEGE;
- SeShutdownPrivilege.QuadPart = SE_SHUTDOWN_PRIVILEGE;
- SeDebugPrivilege.QuadPart = SE_DEBUG_PRIVILEGE;
- SeAuditPrivilege.QuadPart = SE_AUDIT_PRIVILEGE;
- SeSystemEnvironmentPrivilege.QuadPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
- SeChangeNotifyPrivilege.QuadPart = SE_CHANGE_NOTIFY_PRIVILEGE;
- SeRemoteShutdownPrivilege.QuadPart = SE_REMOTE_SHUTDOWN_PRIVILEGE;
+ SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
+ SeCreateTokenPrivilege.HighPart = 0;
+ SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE;
+ SeAssignPrimaryTokenPrivilege.HighPart = 0;
+ SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE;
+ SeLockMemoryPrivilege.HighPart = 0;
+ SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE;
+ SeIncreaseQuotaPrivilege.HighPart = 0;
+ SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE;
+ SeUnsolicitedInputPrivilege.HighPart = 0;
+ SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE;
+ SeTcbPrivilege.HighPart = 0;
+ SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE;
+ SeSecurityPrivilege.HighPart = 0;
+ SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
+ SeTakeOwnershipPrivilege.HighPart = 0;
+ SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE;
+ SeLoadDriverPrivilege.HighPart = 0;
+ SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE;
+ SeSystemProfilePrivilege.HighPart = 0;
+ SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE;
+ SeSystemtimePrivilege.HighPart = 0;
+ SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE;
+ SeProfileSingleProcessPrivilege.HighPart = 0;
+ SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE;
+ SeIncreaseBasePriorityPrivilege.HighPart = 0;
+ SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE;
+ SeCreatePagefilePrivilege.HighPart = 0;
+ SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE;
+ SeCreatePermanentPrivilege.HighPart = 0;
+ SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE;
+ SeBackupPrivilege.HighPart = 0;
+ SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE;
+ SeRestorePrivilege.HighPart = 0;
+ SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE;
+ SeShutdownPrivilege.HighPart = 0;
+ SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE;
+ SeDebugPrivilege.HighPart = 0;
+ SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE;
+ SeAuditPrivilege.HighPart = 0;
+ SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
+ SeSystemEnvironmentPrivilege.HighPart = 0;
+ SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE;
+ SeChangeNotifyPrivilege.HighPart = 0;
+ SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE;
+ SeRemoteShutdownPrivilege.HighPart = 0;
+ SeUndockPrivilege.LowPart = SE_UNDOCK_PRIVILEGE;
+ SeUndockPrivilege.HighPart = 0;
+ SeSyncAgentPrivilege.LowPart = SE_SYNC_AGENT_PRIVILEGE;
+ SeSyncAgentPrivilege.HighPart = 0;
+ SeEnableDelegationPrivilege.LowPart = SE_ENABLE_DELEGATION_PRIVILEGE;
+ SeEnableDelegationPrivilege.HighPart = 0;
}
-BOOLEAN SepPrivilegeCheck(PIACCESS_TOKEN Token,
- PLUID_AND_ATTRIBUTES Privileges,
- ULONG PrivilegeCount,
- ULONG PrivilegeControl,
- KPROCESSOR_MODE PreviousMode)
+BOOLEAN
+NTAPI
+SepPrivilegeCheck (PTOKEN Token,
+ PLUID_AND_ATTRIBUTES Privileges,
+ ULONG PrivilegeCount,
+ ULONG PrivilegeControl,
+ KPROCESSOR_MODE PreviousMode)
{
- ULONG i;
- PLUID_AND_ATTRIBUTES_ARRAY Current;
- ULONG j;
- ULONG k;
-
- if (PreviousMode == KernelMode)
- {
- return(TRUE);
- }
-
- j = 0;
- if (PrivilegeCount != 0)
- {
- k = PrivilegeCount;
- do
- {
- i = Token->PrivilegeCount;
- Current = Token->Privileges;
- for (i = 0; i < Token->PrivilegeCount; i++)
- {
- if (!(Current[i]->Attributes & SE_PRIVILEGE_ENABLED) &&
- Privileges[i].Luid.u.LowPart ==
- Current[i]->Luid.u.LowPart &&
- Privileges[i].Luid.u.HighPart ==
- Current[i]->Luid.u.HighPart)
- {
- Privileges[i].Attributes =
- Privileges[i].Attributes |
- SE_PRIVILEGE_USED_FOR_ACCESS;
- j++;
- break;
- }
- }
- k--;
- } while (k > 0);
- }
-
- if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
- PrivilegeCount == j)
- {
- return(TRUE);
- }
-
- if (j > 0 &&
- !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
- {
- return(TRUE);
- }
-
- return(FALSE);
+ ULONG i;
+ ULONG j;
+ ULONG k;
+
+ DPRINT ("SepPrivilegeCheck() called\n");
+
+ PAGED_CODE();
+
+ if (PreviousMode == KernelMode)
+ {
+ return TRUE;
+ }
+
+ k = 0;
+ if (PrivilegeCount > 0)
+ {
+ for (i = 0; i < Token->PrivilegeCount; i++)
+ {
+ for (j = 0; j < PrivilegeCount; j++)
+ {
+ if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
+ Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
+ {
+ DPRINT ("Found privilege\n");
+ DPRINT ("Privilege attributes %lx\n",
+ Token->Privileges[i].Attributes);
+
+ if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
+ {
+ Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
+ k++;
+ }
+ }
+ }
+ }
+ }
+
+ if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
+ PrivilegeCount == k)
+ {
+ return TRUE;
+ }
+
+ if (k > 0 &&
+ !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
}
-
-NTSTATUS SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
- ULONG PrivilegeCount,
- KPROCESSOR_MODE PreviousMode,
- PLUID_AND_ATTRIBUTES AllocatedMem,
- ULONG AllocatedLength,
- POOL_TYPE PoolType,
- ULONG d,
- PLUID_AND_ATTRIBUTES* Dest,
- PULONG Length)
+NTSTATUS
+NTAPI
+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)
{
- PLUID_AND_ATTRIBUTES* NewMem;
- ULONG SrcLength;
-
- if (PrivilegeCount == 0)
- {
- *Dest = 0;
- *Length = 0;
- return(STATUS_SUCCESS);
- }
- if (PreviousMode == 0 && d == 0)
- {
- *Dest = Src;
- return(STATUS_SUCCESS);
- }
- SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
- *Length = SrcLength;
- if (AllocatedMem == NULL)
- {
- NewMem = ExAllocatePool(PoolType, SrcLength);
- *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
- if (NewMem == NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- }
- else
- {
- if (SrcLength > AllocatedLength)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- *Dest = AllocatedMem;
- }
- memmove(*Dest, Src, SrcLength);
- return(STATUS_SUCCESS);
+ ULONG BufferSize;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ if (PrivilegeCount == 0)
+ {
+ *Dest = 0;
+ *Length = 0;
+ return STATUS_SUCCESS;
+ }
+
+ if (PreviousMode == KernelMode && !CaptureIfKernel)
+ {
+ *Dest = Src;
+ return STATUS_SUCCESS;
+ }
+
+ /* FIXME - check PrivilegeCount for a valid number so we don't
+ cause an integer overflow or exhaust system resources! */
+
+ BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+ *Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */
+
+ /* probe the buffer */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead(Src,
+ BufferSize,
+ sizeof(ULONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
+ /* allocate enough memory or check if the provided buffer is
+ large enough to hold the array */
+ if (AllocatedMem != NULL)
+ {
+ if (AllocatedLength < BufferSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ *Dest = AllocatedMem;
+ }
+ else
+ {
+ *Dest = ExAllocatePool(PoolType,
+ BufferSize);
+
+ if (*Dest == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ /* copy the array to the buffer */
+ _SEH2_TRY
+ {
+ RtlCopyMemory(*Dest,
+ Src,
+ BufferSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status) && AllocatedMem == NULL)
+ {
+ ExFreePool(*Dest);
+ }
+
+ return Status;
}
VOID
-SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
- KPROCESSOR_MODE PreviousMode,
- ULONG a)
+NTAPI
+SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
+ KPROCESSOR_MODE PreviousMode,
+ BOOLEAN CaptureIfKernel)
{
- ExFreePool(Privilege);
+ PAGED_CODE();
+
+ if (Privilege != NULL &&
+ (PreviousMode != KernelMode || CaptureIfKernel))
+ {
+ ExFreePool(Privilege);
+ }
}
-NTSTATUS STDCALL
-NtPrivilegeCheck(IN HANDLE ClientToken,
- IN PPRIVILEGE_SET RequiredPrivileges,
- IN PBOOLEAN Result)
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+SeAppendPrivileges(PACCESS_STATE AccessState,
+ PPRIVILEGE_SET Privileges)
{
- NTSTATUS Status;
- PIACCESS_TOKEN iToken;
- ULONG PrivilegeCount;
- BOOLEAN TResult;
- ULONG PrivilegeControl;
- PLUID_AND_ATTRIBUTES Privilege;
- ULONG Length;
-
- Status = ObReferenceObjectByHandle(ClientToken,
- 0,
- SepTokenObjectType,
- UserMode,
- (PVOID*)&iToken,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- if (iToken->TokenType == TokenImpersonation &&
- iToken->ImpersonationLevel < SecurityAnonymous)
- {
- ObDereferenceObject(iToken);
- return(STATUS_UNSUCCESSFUL);
- }
- PrivilegeCount = RequiredPrivileges->PrivilegeCount;
- PrivilegeControl = RequiredPrivileges->Control;
- Privilege = 0;
- Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege,
- PrivilegeCount,
- 1,
- 0,
- 0,
- 1,
- 1,
- &Privilege,
- &Length);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(iToken);
- return(STATUS_UNSUCCESSFUL);
- }
- TResult = SepPrivilegeCheck(iToken,
- Privilege,
- PrivilegeCount,
- PrivilegeControl,
- UserMode);
- memmove(RequiredPrivileges->Privilege, Privilege, Length);
- *Result = TResult;
- SeReleaseLuidAndAttributesArray(Privilege, UserMode, 1);
- return(STATUS_SUCCESS);
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
}
-BOOLEAN STDCALL
-SePrivilegeCheck(PPRIVILEGE_SET Privileges,
- PSECURITY_SUBJECT_CONTEXT SubjectContext,
- KPROCESSOR_MODE PreviousMode)
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeFreePrivileges(IN PPRIVILEGE_SET Privileges)
{
- PIACCESS_TOKEN iToken = NULL;
-
- if (SubjectContext->ClientToken == NULL)
- {
- iToken = SubjectContext->PrimaryToken;
- }
- else
- {
- iToken = SubjectContext->ClientToken;
- if (SubjectContext->ImpersonationLevel < 2)
- {
- return(FALSE);
- }
- }
-
- return(SepPrivilegeCheck(iToken,
- Privileges->Privilege,
- Privileges->PrivilegeCount,
- Privileges->Control,
- PreviousMode));
+ PAGED_CODE();
+ ExFreePool(Privileges);
}
-BOOLEAN STDCALL
-SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
- IN KPROCESSOR_MODE PreviousMode)
+/*
+ * @implemented
+ */
+BOOLEAN NTAPI
+SePrivilegeCheck (PPRIVILEGE_SET Privileges,
+ PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ KPROCESSOR_MODE PreviousMode)
{
- SECURITY_SUBJECT_CONTEXT SubjectContext;
- BOOLEAN r;
- PRIVILEGE_SET Priv;
-
- SeCaptureSubjectContext(&SubjectContext);
-
- Priv.PrivilegeCount = 1;
- Priv.Control = 1;
- Priv.Privilege[0].Luid = PrivilegeValue;
- Priv.Privilege[0].Attributes = 0;
-
- r = SePrivilegeCheck(&Priv,
- &SubjectContext,
- PreviousMode);
-
- if (PreviousMode != KernelMode)
- {
+ PACCESS_TOKEN Token = NULL;
+
+ PAGED_CODE();
+
+ if (SubjectContext->ClientToken == NULL)
+ {
+ Token = SubjectContext->PrimaryToken;
+ }
+ else
+ {
+ Token = SubjectContext->ClientToken;
+ if (SubjectContext->ImpersonationLevel < 2)
+ {
+ return FALSE;
+ }
+ }
+
+ return SepPrivilegeCheck (Token,
+ Privileges->Privilege,
+ Privileges->PrivilegeCount,
+ Privileges->Control,
+ PreviousMode);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN NTAPI
+SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
+ 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
- SePrivilegeServiceAuditAlarm(0,
- &SubjectContext,
- &PrivilegeValue);
+ SePrivilegedServiceAuditAlarm (0,
+ &SubjectContext,
+ &PrivilegeValue);
#endif
- }
- SeReleaseSubjectContext(&SubjectContext);
- return(r);
+ }
+
+ SeReleaseSubjectContext (&SubjectContext);
+
+ return Result;
}
+/* SYSTEM CALLS ***************************************************************/
+
+NTSTATUS NTAPI
+NtPrivilegeCheck (IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET RequiredPrivileges,
+ OUT PBOOLEAN Result)
+{
+ PLUID_AND_ATTRIBUTES Privileges;
+ PTOKEN Token;
+ ULONG PrivilegeCount = 0;
+ ULONG PrivilegeControl = 0;
+ ULONG Length;
+ BOOLEAN CheckResult;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
+
+ /* probe the buffers */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(RequiredPrivileges,
+ FIELD_OFFSET(PRIVILEGE_SET,
+ Privilege),
+ sizeof(ULONG));
+
+ PrivilegeCount = RequiredPrivileges->PrivilegeCount;
+ PrivilegeControl = RequiredPrivileges->Control;
+
+ /* Check PrivilegeCount to avoid an integer overflow! */
+ if (FIELD_OFFSET(PRIVILEGE_SET,
+ Privilege[PrivilegeCount]) /
+ sizeof(RequiredPrivileges->Privilege[0]) != PrivilegeCount)
+ {
+ _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
+ }
+
+ /* probe all of the array */
+ ProbeForWrite(RequiredPrivileges,
+ FIELD_OFFSET(PRIVILEGE_SET,
+ Privilege[PrivilegeCount]),
+ sizeof(ULONG));
+
+ ProbeForWriteBoolean(Result);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ PrivilegeCount = RequiredPrivileges->PrivilegeCount;
+ PrivilegeControl = RequiredPrivileges->Control;
+ }
+
+ /* reference the token and make sure we're
+ not doing an anonymous impersonation */
+ Status = ObReferenceObjectByHandle (ClientToken,
+ TOKEN_QUERY,
+ SepTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ if (Token->TokenType == TokenImpersonation &&
+ Token->ImpersonationLevel < SecurityIdentification)
+ {
+ ObDereferenceObject (Token);
+ return STATUS_BAD_IMPERSONATION_LEVEL;
+ }
+
+ /* capture the privileges */
+ Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
+ PrivilegeCount,
+ PreviousMode,
+ NULL,
+ 0,
+ PagedPool,
+ TRUE,
+ &Privileges,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (Token);
+ return Status;
+ }
+
+ CheckResult = SepPrivilegeCheck (Token,
+ Privileges,
+ PrivilegeCount,
+ PrivilegeControl,
+ PreviousMode);
+
+ ObDereferenceObject (Token);
+
+ /* return the array */
+ _SEH2_TRY
+ {
+ RtlCopyMemory(RequiredPrivileges->Privilege,
+ Privileges,
+ PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
+ *Result = CheckResult;
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ SeReleaseLuidAndAttributesArray (Privileges,
+ PreviousMode,
+ TRUE);
+
+ return Status;
+}
+
+
+/* EOF */