/* * @implemented */ NTSTATUS NTAPI RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN DaclPresent, OUT PACL* Dacl, OUT PBOOLEAN DaclDefaulted) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Fail on invalid revisions */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Is there a DACL? */ *DaclPresent = (Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT; if (*DaclPresent) { /* Yes, return it, and check if defaulted */ *Dacl = SepGetDaclFromDescriptor(Sd); *DaclDefaulted = (Sd->Control & SE_DACL_DEFAULTED) == SE_DACL_DEFAULTED; } /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ ULONG NTAPI RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) { PISECURITY_DESCRIPTOR Sd; PSID Owner, Group; PACL Sacl, Dacl; ULONG Length; PAGED_CODE_RTL(); /* Start with the initial length of the SD itself */ Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; if (Sd->Control & SE_SELF_RELATIVE) { Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); } else { Length = sizeof(SECURITY_DESCRIPTOR); } /* Add the length of the individual subcomponents */ Owner = SepGetOwnerFromDescriptor(Sd); if (Owner) Length += ROUND_UP(RtlLengthSid(Owner), sizeof(ULONG)); Group = SepGetGroupFromDescriptor(Sd); if (Group) Length += ROUND_UP(RtlLengthSid(Group), sizeof(ULONG)); Dacl = SepGetDaclFromDescriptor(Sd); if (Dacl) Length += ROUND_UP(Dacl->AclSize, sizeof(ULONG)); Sacl = SepGetSaclFromDescriptor(Sd); if (Sacl) Length += ROUND_UP(Sacl->AclSize, sizeof(ULONG)); /* Return the final length */ return Length; }
/* * @implemented */ BOOLEAN NTAPI RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PSID Owner, Group; PACL Sacl, Dacl; PAGED_CODE_RTL(); _SEH2_TRY { /* Fail on bad revisions */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return FALSE; /* Owner SID must be valid if present */ Owner = SepGetOwnerFromDescriptor(Sd); if ((Owner) && (!RtlValidSid(Owner))) return FALSE; /* Group SID must be valid if present */ Group = SepGetGroupFromDescriptor(Sd); if ((Owner) && (!RtlValidSid(Group))) return FALSE; /* DACL must be valid if present */ Dacl = SepGetDaclFromDescriptor(Sd); if ((Dacl) && (!RtlValidAcl(Dacl))) return FALSE; /* SACL must be valid if present */ Sacl = SepGetSaclFromDescriptor(Sd); if ((Sacl) && (!RtlValidAcl(Sacl))) return FALSE; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Access fault, bail out */ return FALSE; } _SEH2_END; /* All good */ return TRUE; }
VOID NTAPI RtlpQuerySecurityDescriptor(IN PISECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PULONG OwnerSize, OUT PSID *PrimaryGroup, OUT PULONG PrimaryGroupSize, OUT PACL *Dacl, OUT PULONG DaclSize, OUT PACL *Sacl, OUT PULONG SaclSize) { PAGED_CODE_RTL(); /* Get the owner */ *Owner = SepGetOwnerFromDescriptor(SecurityDescriptor); if (*Owner) { /* There's an owner, so align the size */ *OwnerSize = ROUND_UP(RtlLengthSid(*Owner), sizeof(ULONG)); } else { /* No owner, no size */ *OwnerSize = 0; } /* Get the group */ *PrimaryGroup = SepGetGroupFromDescriptor(SecurityDescriptor); if (*PrimaryGroup) { /* There's a group, so align the size */ *PrimaryGroupSize = ROUND_UP(RtlLengthSid(*PrimaryGroup), sizeof(ULONG)); } else { /* No group, no size */ *PrimaryGroupSize = 0; } /* Get the DACL */ *Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); if (*Dacl) { /* There's a DACL, align the size */ *DaclSize = ROUND_UP((*Dacl)->AclSize, sizeof(ULONG)); } else { /* No DACL, no size */ *DaclSize = 0; } /* Get the SACL */ *Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); if (*Sacl) { /* There's a SACL, align the size */ *SaclSize = ROUND_UP((*Sacl)->AclSize, sizeof(ULONG)); } else { /* No SACL, no size */ *SaclSize = 0; } }
/* * @implemented */ BOOLEAN NTAPI SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PACCESS_STATE AccessState, IN ACCESS_MASK DesiredAccess, IN KPROCESSOR_MODE AccessMode) { PACL Dacl; ULONG AceIndex; PKNOWN_ACE Ace; PAGED_CODE(); NT_ASSERT(AccessMode != KernelMode); if (SecurityDescriptor == NULL) return FALSE; /* Get DACL */ Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); /* If no DACL, grant access */ if (Dacl == NULL) return TRUE; /* No ACE -> Deny */ if (!Dacl->AceCount) return FALSE; /* Can't perform the check on restricted token */ if (AccessState->Flags & TOKEN_IS_RESTRICTED) return FALSE; /* Browse the ACEs */ for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL)); AceIndex < Dacl->AceCount; AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize)) { if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) continue; /* If access-allowed ACE */ if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE) { /* Check if all accesses are granted */ if (!(Ace->Mask & DesiredAccess)) continue; /* Check SID and grant access if matching */ if (RtlEqualSid(SeWorldSid, &(Ace->SidStart))) return TRUE; } /* If access-denied ACE */ else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE) { /* Here, only check if it denies all the access wanted and deny if so */ if (Ace->Mask & DesiredAccess) return FALSE; } } /* Faulty, deny */ return FALSE; }