implemented SeCaptureSecurityDescriptor() and
SeReleaseSecurityDescriptor(), thanks also to Alex
Modified: trunk/reactos/ntoskrnl/se/sd.c
_____
Modified: trunk/reactos/ntoskrnl/se/sd.c
--- trunk/reactos/ntoskrnl/se/sd.c 2005-01-20 23:25:05 UTC (rev
13174)
+++ trunk/reactos/ntoskrnl/se/sd.c 2005-01-21 02:14:52 UTC (rev
13175)
@@ -110,7 +110,7 @@
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
STDCALL
@@ -122,8 +122,250 @@
OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ SECURITY_DESCRIPTOR DescriptorCopy;
+ PSECURITY_DESCRIPTOR NewDescriptor;
+ ULONG OwnerSAC = 0, GroupSAC = 0;
+ ULONG OwnerSize = 0, GroupSize = 0;
+ ULONG SaclSize = 0, DaclSize = 0;
+ ULONG DescriptorSize;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if(OriginalSecurityDescriptor != NULL)
+ {
+ if(CurrentMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(OriginalSecurityDescriptor,
+ sizeof(SECURITY_DESCRIPTOR),
+ sizeof(ULONG));
+
+ /* make a copy on the stack */
+ DescriptorCopy = *OriginalSecurityDescriptor;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ /* make a copy on the stack */
+ DescriptorCopy = *OriginalSecurityDescriptor;
+ }
+
+ if(CurrentMode == KernelMode && !CaptureIfKernel)
+ {
+ *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
+ return STATUS_SUCCESS;
+ }
+
+ if(DescriptorCopy.Revision != SECURITY_DESCRIPTOR_REVISION1)
+ {
+ return STATUS_UNKNOWN_REVISION;
+ }
+
+ if(DescriptorCopy.Control & SE_SELF_RELATIVE)
+ {
+ /* in case we're dealing with a self-relative descriptor, do a
basic convert
+ to an absolute descriptor. We do this so we can simply access
the data
+ using the pointers without calculating them again. */
+ DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
+ if(DescriptorCopy.Owner != NULL)
+ {
+ DescriptorCopy.Owner =
(PSID)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Owner);
+ }
+ if(DescriptorCopy.Group != NULL)
+ {
+ DescriptorCopy.Group =
(PSID)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Group);
+ }
+ if(DescriptorCopy.Dacl != NULL)
+ {
+ DescriptorCopy.Dacl =
(PACL)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Dacl);
+ }
+ if(DescriptorCopy.Sacl != NULL)
+ {
+ DescriptorCopy.Sacl =
(PACL)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Sacl);
+ }
+ }
+
+ /* determine the size of the SIDs */
+#define DetermineSIDSize(SidType)
\
+ do {
\
+ if(DescriptorCopy.SidType != NULL)
\
+ {
\
+ SID *SidType = (SID*)DescriptorCopy.SidType;
\
+
\
+ if(CurrentMode != KernelMode)
\
+ {
\
+ /* securely access the buffers! */
\
+ _SEH_TRY
\
+ {
\
+ ProbeForRead(&SidType->SubAuthorityCount,
\
+ sizeof(SidType->SubAuthorityCount),
\
+ 1);
\
+ SidType##SAC = SidType->SubAuthorityCount;
\
+ SidType##Size = RtlLengthRequiredSid(SidType##SAC);
\
+ ProbeForRead(SidType,
\
+ SidType##Size,
\
+ sizeof(ULONG));
\
+ if(!RtlValidSid(SidType))
\
+ {
\
+ Status = STATUS_INVALID_SID;
\
+ }
\
+ }
\
+ _SEH_HANDLE
\
+ {
\
+ Status = _SEH_GetExceptionCode();
\
+ }
\
+ _SEH_END;
\
+
\
+ if(!NT_SUCCESS(Status))
\
+ {
\
+ return Status;
\
+ }
\
+ }
\
+ else
\
+ {
\
+ SidType##SAC = SidType->SubAuthorityCount;
\
+ SidType##Size = RtlLengthRequiredSid(SidType##SAC);
\
+ }
\
+ }
\
+ } while(0)
+
+ DetermineSIDSize(Owner);
+ DetermineSIDSize(Group);
+
+ /* determine the size of the ACLs */
+#define DetermineACLSize(AclType, AclFlag)
\
+ do {
\
+ if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) &&
\
+ DescriptorCopy.AclType != NULL)
\
+ {
\
+ PACL AclType = (PACL)DescriptorCopy.AclType;
\
+
\
+ if(CurrentMode != KernelMode)
\
+ {
\
+ /* securely access the buffers! */
\
+ _SEH_TRY
\
+ {
\
+ ProbeForRead(&AclType->AclSize,
\
+ sizeof(AclType->AclSize),
\
+ 1);
\
+ AclType##Size = AclType->AclSize;
\
+ ProbeForRead(AclType,
\
+ AclType##Size,
\
+ sizeof(ULONG));
\
+ if(!RtlValidAcl(AclType))
\
+ {
\
+ Status = STATUS_INVALID_ACL;
\
+ }
\
+ }
\
+ _SEH_HANDLE
\
+ {
\
+ Status = _SEH_GetExceptionCode();
\
+ }
\
+ _SEH_END;
\
+
\
+ if(!NT_SUCCESS(Status))
\
+ {
\
+ return Status;
\
+ }
\
+ }
\
+ else
\
+ {
\
+ AclType##Size = AclType->AclSize;
\
+ }
\
+ }
\
+ else
\
+ {
\
+ DescriptorCopy.AclType = NULL;
\
+ }
\
+ } while(0)
+
+ DetermineACLSize(Sacl, SACL);
+ DetermineACLSize(Dacl, DACL);
+
+ /* allocate enough memory to store a complete copy of a
self-relative
+ security descriptor */
+ DescriptorSize = sizeof(SECURITY_DESCRIPTOR) +
+ ROUND_UP(OwnerSize, sizeof(ULONG)) +
+ ROUND_UP(GroupSize, sizeof(ULONG)) +
+ ROUND_UP(SaclSize, sizeof(ULONG)) +
+ ROUND_UP(DaclSize, sizeof(ULONG));
+
+ NewDescriptor = ExAllocatePool(PagedPool,
+ DescriptorSize);
+ if(NewDescriptor != NULL)
+ {
+ ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
+
+ NewDescriptor->Revision = DescriptorCopy.Revision;
+ NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
+ NewDescriptor->Control = DescriptorCopy.Control |
SE_SELF_RELATIVE;
+
+ /* setup the offsets to the SIDs and ACLs */
+ NewDescriptor->Owner = (PVOID)Offset;
+ Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
+ NewDescriptor->Group = (PVOID)Offset;
+ Offset += ROUND_UP(GroupSize, sizeof(ULONG));
+ NewDescriptor->Sacl = (PVOID)Offset;
+ Offset += ROUND_UP(SaclSize, sizeof(ULONG));
+ NewDescriptor->Dacl = (PVOID)Offset;
+
+ _SEH_TRY
+ {
+ /* copy the SIDs and ACLs to the new self-relative security
descriptor */
+ RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor +
(ULONG_PTR)NewDescriptor->Owner),
+ DescriptorCopy.Owner,
+ OwnerSize);
+ RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor +
(ULONG_PTR)NewDescriptor->Group),
+ DescriptorCopy.Group,
+ GroupSize);
+ RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor +
(ULONG_PTR)NewDescriptor->Sacl),
+ DescriptorCopy.Sacl,
+ SaclSize);
+ RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor +
(ULONG_PTR)NewDescriptor->Dacl),
+ DescriptorCopy.Dacl,
+ DaclSize);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ /* we're finally done! copy the pointer to the captured
descriptor to
+ to the caller */
+ *CapturedSecurityDescriptor = NewDescriptor;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* we failed to copy the data to the new descriptor */
+ ExFreePool(NewDescriptor);
+ }
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else
+ {
+ /* nothing to do... */
+ *CapturedSecurityDescriptor = NULL;
+ }
+
+ return Status;
}
/*
@@ -262,7 +504,7 @@
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
STDCALL
@@ -272,8 +514,18 @@
IN BOOLEAN CaptureIfKernelMode
)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ /* WARNING! You need to call this function with the same value for
CurrentMode
+ and CaptureIfKernelMode that you previously passed to
+ SeCaptureSecurityDescriptor() in order to avoid memory
leaks! */
+ if(CapturedSecurityDescriptor != NULL &&
+ (CurrentMode == UserMode ||
+ (CurrentMode == KernelMode && CaptureIfKernelMode)))
+ {
+ /* only delete the descriptor when SeCaptureSecurityDescriptor()
allocated one! */
+ ExFreePool(CapturedSecurityDescriptor);
+ }
+
+ return STATUS_SUCCESS;
}
/*
Show replies by date