VOID
INIT_FUNCTION
NTAPI
-SepInitPrivileges (VOID)
+SepInitPrivileges(VOID)
{
SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
SeCreateTokenPrivilege.HighPart = 0;
BOOLEAN
NTAPI
-SepPrivilegeCheck (PTOKEN Token,
- PLUID_AND_ATTRIBUTES Privileges,
- ULONG PrivilegeCount,
- ULONG PrivilegeControl,
- KPROCESSOR_MODE PreviousMode)
+SepPrivilegeCheck(PTOKEN Token,
+ PLUID_AND_ATTRIBUTES Privileges,
+ ULONG PrivilegeCount,
+ ULONG PrivilegeControl,
+ KPROCESSOR_MODE PreviousMode)
{
ULONG i;
ULONG j;
- ULONG k;
-
- DPRINT ("SepPrivilegeCheck() called\n");
-
+ ULONG Required;
+
+ DPRINT("SepPrivilegeCheck() called\n");
+
PAGED_CODE();
-
+
if (PreviousMode == KernelMode)
- {
return TRUE;
- }
-
- k = 0;
- if (PrivilegeCount > 0)
+
+ /* 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 */
+ for (i = 0; i < PrivilegeCount && Required > 0; i++)
{
- for (i = 0; i < Token->PrivilegeCount; i++)
+ /* Loop the privileges of the token */
+ for (j = 0; j < Token->PrivilegeCount; j++)
{
- for (j = 0; j < PrivilegeCount; j++)
+ /* Check if the LUIDs match */
+ if (Token->Privileges[j].Luid.LowPart == Privileges[i].Luid.LowPart &&
+ Token->Privileges[j].Luid.HighPart == Privileges[i].Luid.HighPart)
{
- if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
- Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
+ DPRINT("Found privilege. Attributes: %lx\n",
+ Token->Privileges[j].Attributes);
+
+ /* Check if the privilege is enabled */
+ if (Token->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED)
{
- 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++;
- }
+ Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
+ Required--;
}
+
+ /* Leave the inner loop */
+ break;
}
}
}
-
- if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
- PrivilegeCount == k)
- {
- return TRUE;
- }
-
- if (k > 0 &&
- !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
- {
- return TRUE;
- }
-
- return FALSE;
+
+ /* Return whether we found all required privileges */
+ return (Required == 0);
}
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)
+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)
{
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_END;
}
-
+
/* allocate enough memory or check if the provided buffer is
large enough to hold the array */
if (AllocatedMem != NULL)
{
return STATUS_BUFFER_TOO_SMALL;
}
-
+
*Dest = AllocatedMem;
}
else
{
*Dest = ExAllocatePool(PoolType,
BufferSize);
-
if (*Dest == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
-
+
if (!NT_SUCCESS(Status) && AllocatedMem == NULL)
{
ExFreePool(*Dest);
}
-
+
return Status;
}
VOID
NTAPI
-SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
- KPROCESSOR_MODE PreviousMode,
- BOOLEAN CaptureIfKernel)
+SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
+ KPROCESSOR_MODE PreviousMode,
+ BOOLEAN CaptureIfKernel)
{
PAGED_CODE();
-
+
if (Privilege != NULL &&
(PreviousMode != KernelMode || CaptureIfKernel))
{
/* PUBLIC FUNCTIONS ***********************************************************/
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
-SeAppendPrivileges(PACCESS_STATE AccessState,
- PPRIVILEGE_SET Privileges)
+SeAppendPrivileges(IN OUT PACCESS_STATE AccessState,
+ IN PPRIVILEGE_SET Privileges)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ 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;
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
NTAPI
SeFreePrivileges(IN PPRIVILEGE_SET Privileges)
{
- UNIMPLEMENTED;
+ PAGED_CODE();
+ ExFreePool(Privileges);
}
/*
* @implemented
*/
-BOOLEAN NTAPI
-SePrivilegeCheck (PPRIVILEGE_SET Privileges,
- PSECURITY_SUBJECT_CONTEXT SubjectContext,
- KPROCESSOR_MODE PreviousMode)
+BOOLEAN
+NTAPI
+SePrivilegeCheck(PPRIVILEGE_SET Privileges,
+ PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ KPROCESSOR_MODE PreviousMode)
{
PACCESS_TOKEN Token = NULL;
-
+
PAGED_CODE();
-
+
if (SubjectContext->ClientToken == NULL)
{
Token = SubjectContext->PrimaryToken;
return FALSE;
}
}
-
- return SepPrivilegeCheck (Token,
- Privileges->Privilege,
- Privileges->PrivilegeCount,
- Privileges->Control,
- PreviousMode);
+
+ return SepPrivilegeCheck(Token,
+ Privileges->Privilege,
+ Privileges->PrivilegeCount,
+ Privileges->Control,
+ PreviousMode);
}
/*
* @implemented
*/
-BOOLEAN NTAPI
-SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
+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
+ SePrivilegedServiceAuditAlarm(0,
+ &SubjectContext,
+ &PrivilegeValue);
+#endif
+ }
+
+ SeReleaseSubjectContext(&SubjectContext);
+
+ 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);
-
+
+ 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);
-
+
+ Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode);
if (PreviousMode != KernelMode)
{
#if 0
- SePrivilegedServiceAuditAlarm (0,
- &SubjectContext,
- &PrivilegeValue);
+ SePrivilegeObjectAuditAlarm(ObjectHandle,
+ &SubjectContext,
+ DesiredAccess,
+ &PrivilegeValue,
+ Result,
+ PreviousMode);
#endif
}
-
- SeReleaseSubjectContext (&SubjectContext);
-
+
+ SeReleaseSubjectContext(&SubjectContext);
+
return Result;
}
/* SYSTEM CALLS ***************************************************************/
-NTSTATUS NTAPI
-NtPrivilegeCheck (IN HANDLE ClientToken,
- IN PPRIVILEGE_SET RequiredPrivileges,
- OUT PBOOLEAN Result)
+NTSTATUS
+NTAPI
+NtPrivilegeCheck(IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET RequiredPrivileges,
+ OUT PBOOLEAN Result)
{
PLUID_AND_ATTRIBUTES Privileges;
PTOKEN Token;
BOOLEAN CheckResult;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
-
+
PAGED_CODE();
-
+
PreviousMode = KeGetPreviousMode();
-
+
/* probe the buffers */
if (PreviousMode != KernelMode)
{
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]) /
{
_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)
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);
+ Status = ObReferenceObjectByHandle(ClientToken,
+ TOKEN_QUERY,
+ SeTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
-
+
if (Token->TokenType == TokenImpersonation &&
Token->ImpersonationLevel < SecurityIdentification)
{
- ObDereferenceObject (Token);
+ ObDereferenceObject(Token);
return STATUS_BAD_IMPERSONATION_LEVEL;
}
-
+
/* capture the privileges */
- Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
- PrivilegeCount,
- PreviousMode,
- NULL,
- 0,
- PagedPool,
- TRUE,
- &Privileges,
- &Length);
+ 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);
-
+
+ CheckResult = SepPrivilegeCheck(Token,
+ Privileges,
+ PrivilegeCount,
+ PrivilegeControl,
+ PreviousMode);
+
+ ObDereferenceObject(Token);
+
/* return the array */
_SEH2_TRY
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
-
- SeReleaseLuidAndAttributesArray (Privileges,
- PreviousMode,
- TRUE);
-
+
+ SeReleaseLuidAndAttributesArray(Privileges,
+ PreviousMode,
+ TRUE);
+
return Status;
}
-
/* EOF */