#define NDEBUG
#include <debug.h>
+#define TAG_SID_AND_ATTRIBUTES 'aSeS'
+
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, SepInitSecurityIDs)
#endif
PSID SeAuthenticatedUsersSid = NULL;
PSID SeRestrictedSid = NULL;
PSID SeAnonymousLogonSid = NULL;
+PSID SeLocalServiceSid = NULL;
+PSID SeNetworkServiceSid = NULL;
/* FUNCTIONS ******************************************************************/
SeAuthenticatedUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeRestrictedSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeAnonymousLogonSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
+ SeLocalServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
+ SeNetworkServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
if (SeNullSid == NULL || SeWorldSid == NULL ||
SeLocalSid == NULL || SeCreatorOwnerSid == NULL ||
SeAliasAccountOpsSid == NULL || SeAliasSystemOpsSid == NULL ||
SeAliasPrintOpsSid == NULL || SeAliasBackupOpsSid == NULL ||
SeAuthenticatedUsersSid == NULL || SeRestrictedSid == NULL ||
- SeAnonymousLogonSid == NULL)
+ SeAnonymousLogonSid == NULL || SeLocalServiceSid == NULL ||
+ SeNetworkServiceSid == NULL)
{
FreeInitializedSids();
return FALSE;
RtlInitializeSid(SeAuthenticatedUsersSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeRestrictedSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeAnonymousLogonSid, &SeNtSidAuthority, 1);
+ RtlInitializeSid(SeLocalServiceSid, &SeNtSidAuthority, 1);
+ RtlInitializeSid(SeNetworkServiceSid, &SeNtSidAuthority, 1);
SubAuthority = RtlSubAuthoritySid(SeNullSid, 0);
*SubAuthority = SECURITY_NULL_RID;
*SubAuthority = SECURITY_RESTRICTED_CODE_RID;
SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid, 0);
*SubAuthority = SECURITY_ANONYMOUS_LOGON_RID;
+ SubAuthority = RtlSubAuthoritySid(SeLocalServiceSid, 0);
+ *SubAuthority = SECURITY_LOCAL_SERVICE_RID;
+ SubAuthority = RtlSubAuthoritySid(SeNetworkServiceSid, 0);
+ *SubAuthority = SECURITY_NETWORK_SERVICE_RID;
return TRUE;
}
{
ULONG SidSize = 0;
PISID NewSid, Sid = (PISID)InputSid;
- NTSTATUS Status;
PAGED_CODE();
{
_SEH2_TRY
{
- ProbeForRead(Sid,
- FIELD_OFFSET(SID,
- SubAuthority),
- sizeof(UCHAR));
+ ProbeForRead(Sid, FIELD_OFFSET(SID, SubAuthority), sizeof(UCHAR));
SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
- ProbeForRead(Sid,
- SidSize,
- sizeof(UCHAR));
+ ProbeForRead(Sid, SidSize, sizeof(UCHAR));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_END;
/* allocate a SID and copy it */
- NewSid = ExAllocatePool(PoolType,
- SidSize);
- if (NewSid != NULL)
+ NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID);
+ if (!NewSid)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ _SEH2_TRY
{
- _SEH2_TRY
- {
- RtlCopyMemory(NewSid,
- Sid,
- SidSize);
+ RtlCopyMemory(NewSid, Sid, SidSize);
- *CapturedSid = NewSid;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Free the SID and return the exception code */
- ExFreePoolWithTag(NewSid, TAG_SID);
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
+ *CapturedSid = NewSid;
}
- else
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = STATUS_INSUFFICIENT_RESOURCES;
+ /* Free the SID and return the exception code */
+ ExFreePoolWithTag(NewSid, TAG_SID);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
+ _SEH2_END;
}
else if (!CaptureIfKernel)
{
*CapturedSid = InputSid;
- return STATUS_SUCCESS;
}
else
{
SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
/* allocate a SID and copy it */
- NewSid = ExAllocatePool(PoolType,
- SidSize);
- if (NewSid != NULL)
- {
- RtlCopyMemory(NewSid,
- Sid,
- SidSize);
+ NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID);
+ if (NewSid == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
- *CapturedSid = NewSid;
- }
- else
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
+ RtlCopyMemory(NewSid, Sid, SidSize);
+
+ *CapturedSid = NewSid;
}
- return Status;
+ return STATUS_SUCCESS;
}
VOID
}
}
+NTSTATUS
+NTAPI
+SeCaptureSidAndAttributesArray(
+ _In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes,
+ _In_ ULONG AttributeCount,
+ _In_ KPROCESSOR_MODE PreviousMode,
+ _In_opt_ PVOID AllocatedMem,
+ _In_ ULONG AllocatedLength,
+ _In_ POOL_TYPE PoolType,
+ _In_ BOOLEAN CaptureIfKernel,
+ _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes,
+ _Out_ PULONG ResultLength)
+{
+ ULONG ArraySize, RequiredLength, SidLength, i;
+ PSID_AND_ATTRIBUTES SidAndAttributes;
+ PUCHAR CurrentDest;
+ PISID Sid;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ *CapturedSidAndAttributes = NULL;
+ *ResultLength = 0;
+
+ if (AttributeCount == 0)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ if (AttributeCount > 0x1000)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((PreviousMode == KernelMode) && !CaptureIfKernel)
+ {
+ *CapturedSidAndAttributes = SrcSidAndAttributes;
+ return STATUS_SUCCESS;
+ }
+
+ ArraySize = AttributeCount * sizeof(SID_AND_ATTRIBUTES);
+ RequiredLength = ALIGN_UP_BY(ArraySize, sizeof(ULONG));
+
+ /* Check for user mode data */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ /* First probe the whole array */
+ ProbeForRead(SrcSidAndAttributes, ArraySize, sizeof(ULONG));
+
+ /* Loop the array elements */
+ for (i = 0; i < AttributeCount; i++)
+ {
+ /* Get the SID and probe the minimal structure */
+ Sid = SrcSidAndAttributes[i].Sid;
+ ProbeForRead(Sid, sizeof(*Sid), sizeof(ULONG));
+
+ /* Verify that the SID is valid */
+ if (((Sid->Revision & 0xF) != SID_REVISION) ||
+ (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES))
+ {
+ return STATUS_INVALID_SID;
+ }
+
+ /* Calculate the SID length and probe the full SID */
+ SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+ ProbeForRead(Sid, SidLength, sizeof(ULONG));
+
+ /* Add the aligned length to the required length */
+ RequiredLength += ALIGN_UP_BY(SidLength, sizeof(ULONG));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ return _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Loop the array elements */
+ for (i = 0; i < AttributeCount; i++)
+ {
+ /* Get the SID and it's length */
+ Sid = SrcSidAndAttributes[i].Sid;
+ SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+
+ /* Add the aligned length to the required length */
+ RequiredLength += ALIGN_UP_BY(SidLength, sizeof(ULONG));
+ }
+ }
+
+ /* Assume success */
+ Status = STATUS_SUCCESS;
+ *ResultLength = RequiredLength;
+
+ /* Check if we have no buffer */
+ if (AllocatedMem == NULL)
+ {
+ /* Allocate a new buffer */
+ SidAndAttributes = ExAllocatePoolWithTag(PoolType,
+ RequiredLength,
+ TAG_SID_AND_ATTRIBUTES);
+ if (SidAndAttributes == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ /* Otherwise check if the buffer is large enough */
+ else if (AllocatedLength >= RequiredLength)
+ {
+ /* Buffer is large enough, use it */
+ SidAndAttributes = AllocatedMem;
+ }
+ else
+ {
+ /* Buffer is too small, fail */
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ *CapturedSidAndAttributes = SidAndAttributes;
+
+ /* Check again for user mode */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ /* The rest of the data starts after the array */
+ CurrentDest = (PUCHAR)SidAndAttributes;
+ CurrentDest += ALIGN_UP_BY(ArraySize, sizeof(ULONG));
+
+ /* Loop the array elements */
+ for (i = 0; i < AttributeCount; i++)
+ {
+ /* Get the SID and it's length */
+ Sid = SrcSidAndAttributes[i].Sid;
+ SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+
+ /* Copy attributes */
+ SidAndAttributes[i].Attributes = SrcSidAndAttributes[i].Attributes;
+
+ /* Copy the SID to the current destination address */
+ SidAndAttributes[i].Sid = (PSID)CurrentDest;
+ RtlCopyMemory(CurrentDest, SrcSidAndAttributes[i].Sid, SidLength);
+
+ /* Sanity checks */
+ NT_ASSERT(RtlLengthSid(SidAndAttributes[i].Sid) == SidLength);
+ NT_ASSERT(RtlValidSid(SidAndAttributes[i].Sid));
+
+ /* Update the current destination address */
+ CurrentDest += ALIGN_UP_BY(SidLength, sizeof(ULONG));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* The rest of the data starts after the array */
+ CurrentDest = (PUCHAR)SidAndAttributes;
+ CurrentDest += ALIGN_UP_BY(ArraySize, sizeof(ULONG));
+
+ /* Loop the array elements */
+ for (i = 0; i < AttributeCount; i++)
+ {
+ /* Get the SID and it's length */
+ Sid = SrcSidAndAttributes[i].Sid;
+ SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+
+ /* Copy attributes */
+ SidAndAttributes[i].Attributes = SrcSidAndAttributes[i].Attributes;
+
+ /* Copy the SID to the current destination address */
+ SidAndAttributes[i].Sid = (PSID)CurrentDest;
+ RtlCopyMemory(CurrentDest, SrcSidAndAttributes[i].Sid, SidLength);
+
+ /* Update the current destination address */
+ CurrentDest += ALIGN_UP_BY(SidLength, sizeof(ULONG));
+ }
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Check if we allocated a new array */
+ if (SidAndAttributes != AllocatedMem)
+ {
+ /* Free the array */
+ ExFreePoolWithTag(SidAndAttributes, TAG_SID_AND_ATTRIBUTES);
+ }
+
+ /* Set returned address to NULL */
+ *CapturedSidAndAttributes = NULL ;
+ }
+
+ return Status;
+}
+
+VOID
+NTAPI
+SeReleaseSidAndAttributesArray(
+ _In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes,
+ _In_ KPROCESSOR_MODE AccessMode,
+ _In_ BOOLEAN CaptureIfKernel)
+{
+ PAGED_CODE();
+
+ if ((CapturedSidAndAttributes != NULL) &&
+ ((AccessMode != KernelMode) || CaptureIfKernel))
+ {
+ ExFreePoolWithTag(CapturedSidAndAttributes, TAG_SID_AND_ATTRIBUTES);
+ }
+}
+
+
/* EOF */