/* * @implemented */ NTSTATUS NTAPI RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group, IN BOOLEAN GroupDefaulted) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; /* Group being set or cleared */ Sd->Group = Group; /* Set if defaulted */ Sd->Control &= ~SE_GROUP_DEFAULTED; if (GroupDefaulted) Sd->Control |= SE_GROUP_DEFAULTED; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlGetAce(PACL Acl, ULONG AceIndex, PVOID *Ace) { ULONG i; PAGED_CODE_RTL(); if (Acl->AclRevision < MIN_ACL_REVISION || Acl->AclRevision > MAX_ACL_REVISION || AceIndex >= Acl->AceCount) { return(STATUS_INVALID_PARAMETER); } *Ace = (PVOID)((PACE)(Acl + 1)); for (i = 0; i < AceIndex; i++) { if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize) { return(STATUS_INVALID_PARAMETER); } *Ace = (PVOID)((PACE)((ULONG_PTR)(*Ace) + ((PACE)(*Ace))->Header.AceSize)); } if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize) { return(STATUS_INVALID_PARAMETER); } 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 */ NTSTATUS NTAPI RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN SaclPresent, IN PACL Sacl, IN BOOLEAN SaclDefaulted) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; /* Is there a SACL? */ if (!SaclPresent) { /* Caller is clearing the SACL, unset the flag and we're done */ Sd->Control = Sd->Control & ~SE_SACL_PRESENT; return STATUS_SUCCESS; } /* Caller is setting a new SACL, set it and the flag */ Sd->Sacl = Sacl; Sd->Control |= SE_SACL_PRESENT; /* Set if defaulted */ Sd->Control &= ~SE_SACL_DEFAULTED; if (SaclDefaulted) Sd->Control |= SE_SACL_DEFAULTED; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN SaclPresent, OUT PACL* Sacl, OUT PBOOLEAN SaclDefaulted) { 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 SACL? */ *SaclPresent = (Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT; if (*SaclPresent) { /* Yes, return it, and check if defaulted */ *Sacl = SepGetSaclFromDescriptor(Sd); *SaclDefaulted = (Sd->Control & SE_SACL_DEFAULTED) == SE_SACL_DEFAULTED; } /* All good */ return STATUS_SUCCESS; }
BOOLEAN NTAPI RtlFirstFreeAce(IN PACL Acl, OUT PACE* FirstFreeAce) { PACE Current; ULONG_PTR AclEnd; ULONG i; PAGED_CODE_RTL(); /* Assume failure */ *FirstFreeAce = NULL; /* Get the start and end pointers */ Current = (PACE)(Acl + 1); AclEnd = (ULONG_PTR)Acl + Acl->AclSize; /* Loop all the ACEs */ for (i = 0; i < Acl->AceCount; i++) { /* If any is beyond the DACL, bail out, otherwise keep going */ if ((ULONG_PTR)Current >= AclEnd) return FALSE; Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize); } /* If the last spot is empty and still valid, return it */ if ((ULONG_PTR)Current < AclEnd) *FirstFreeAce = Current; return TRUE; }
/* * @implemented */ NTSTATUS NTAPI RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Always return revision, even if invalid */ *Revision = Sd->Revision; /* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Mask out flags which are not attributes */ Control &= SE_DACL_UNTRUSTED | SE_SERVER_SECURITY | SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED | SE_DACL_PROTECTED | SE_SACL_PROTECTED; /* Call the newer API */ return RtlSetControlSecurityDescriptor(SecurityDescriptor, Control, Control); }
/* * @implemented */ NTSTATUS NTAPI RtlAllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, UCHAR SubAuthorityCount, ULONG SubAuthority0, ULONG SubAuthority1, ULONG SubAuthority2, ULONG SubAuthority3, ULONG SubAuthority4, ULONG SubAuthority5, ULONG SubAuthority6, ULONG SubAuthority7, PSID *Sid) { PISID pSid; PAGED_CODE_RTL(); if (SubAuthorityCount > 8) return STATUS_INVALID_SID; if (Sid == NULL) return STATUS_INVALID_PARAMETER; pSid = RtlpAllocateMemory(RtlLengthRequiredSid(SubAuthorityCount), TAG_SID); if (pSid == NULL) return STATUS_NO_MEMORY; pSid->Revision = SID_REVISION; pSid->SubAuthorityCount = SubAuthorityCount; memcpy(&pSid->IdentifierAuthority, IdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)); switch (SubAuthorityCount) { case 8: pSid->SubAuthority[7] = SubAuthority7; case 7: pSid->SubAuthority[6] = SubAuthority6; case 6: pSid->SubAuthority[5] = SubAuthority5; case 5: pSid->SubAuthority[4] = SubAuthority4; case 4: pSid->SubAuthority[3] = SubAuthority3; case 3: pSid->SubAuthority[2] = SubAuthority2; case 2: pSid->SubAuthority[1] = SubAuthority1; case 1: pSid->SubAuthority[0] = SubAuthority0; break; } *Sid = pSid; return STATUS_SUCCESS; }
/* * @implemented * * RETURNS * Docs says FreeSid does NOT return a value * even thou it's defined to return a PVOID... */ PVOID NTAPI RtlFreeSid(IN PSID Sid) { PAGED_CODE_RTL(); RtlpFreeMemory(Sid, TAG_SID); return NULL; }
/* * @implemented */ ULONG NTAPI RtlLengthRequiredSid(IN ULONG SubAuthorityCount) { PAGED_CODE_RTL(); return (ULONG)FIELD_OFFSET(SID, SubAuthority[SubAuthorityCount]); }
VOID NTAPI RtlCopyLuid(PLUID LuidDest, PLUID LuidSrc) { PAGED_CODE_RTL(); LuidDest->LowPart = LuidSrc->LowPart; LuidDest->HighPart = LuidSrc->HighPart; }
/* * @implemented */ BOOLEAN NTAPI RtlEqualLuid(PLUID Luid1, PLUID Luid2) { PAGED_CODE_RTL(); return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart); }
/* * @implemented */ PSID_IDENTIFIER_AUTHORITY NTAPI RtlIdentifierAuthoritySid(IN PSID Sid_) { PISID Sid = Sid_; PAGED_CODE_RTL(); return &Sid->IdentifierAuthority; }
/* * @implemented */ PUCHAR NTAPI RtlSubAuthorityCountSid(IN PSID Sid_) { PISID Sid = Sid_; PAGED_CODE_RTL(); return &Sid->SubAuthorityCount; }
/* * @implemented */ ULONG NTAPI RtlLengthSid(IN PSID Sid_) { PISID Sid = Sid_; PAGED_CODE_RTL(); return (ULONG)FIELD_OFFSET(SID, SubAuthority[Sid->SubAuthorityCount]); }
/* * @implemented */ PULONG NTAPI RtlSubAuthoritySid(IN PSID Sid_, IN ULONG SubAuthority) { PISID Sid = Sid_; PAGED_CODE_RTL(); return (PULONG)&Sid->SubAuthority[SubAuthority]; }
BOOLEAN NTAPI RtlValidSid(IN PSID Sid_) { PISID Sid = Sid_; PAGED_CODE_RTL(); if ((Sid->Revision != SID_REVISION) || (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)) { return FALSE; } return TRUE; }
/* * @implemented */ VOID NTAPI RtlCopyLuidAndAttributesArray(ULONG Count, PLUID_AND_ATTRIBUTES Src, PLUID_AND_ATTRIBUTES Dest) { ULONG i; PAGED_CODE_RTL(); for (i = 0; i < Count; i++) { RtlCopyMemory(&Dest[i], &Src[i], sizeof(LUID_AND_ATTRIBUTES)); } }
/* * @implemented */ NTSTATUS NTAPI RtlInitializeSid(IN PSID Sid_, IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount) { PISID Sid = Sid_; PAGED_CODE_RTL(); Sid->Revision = SID_REVISION; Sid->SubAuthorityCount = SubAuthorityCount; memcpy(&Sid->IdentifierAuthority, IdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)); return STATUS_SUCCESS; }
/* * @implemented */ ULONG NTAPI RtlRandom (IN OUT PULONG Seed) { ULONG Rand; int Pos; ULONG Result; PAGED_CODE_RTL(); Rand = (*Seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff; *Seed = (Rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff; Pos = *Seed & 0x7f; Result = SavedValue[Pos]; SavedValue[Pos] = Rand; return Result; }
/* * @implemented */ NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN PULONG BufferLength) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor; PAGED_CODE_RTL(); /* Can't already be relative */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_BAD_DESCRIPTOR_FORMAT; /* Call the other API */ return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, SelfRelativeSecurityDescriptor, BufferLength); }
/* * @implemented */ NTSTATUS NTAPI RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Revision) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Fail on invalid revisions */ if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Setup an empty SD */ RtlZeroMemory(Sd, sizeof(*Sd)); Sd->Revision = SECURITY_DESCRIPTOR_REVISION; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, IN ULONG Revision) { PAGED_CODE_RTL(); /* Fail on invalid revisions */ if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Setup an empty SD */ RtlZeroMemory(SecurityDescriptor, sizeof(*SecurityDescriptor)); SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION; SecurityDescriptor->Control = SE_SELF_RELATIVE; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlCopySid(ULONG BufferLength, PSID Dest, PSID Src) { PAGED_CODE_RTL(); if (BufferLength < RtlLengthSid(Src)) { return STATUS_UNSUCCESSFUL; } memmove(Dest, Src, RtlLengthSid(Src)); return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID* Group, OUT PBOOLEAN GroupDefaulted) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Get the group and if defaulted */ *Group = SepGetGroupFromDescriptor(Sd); *GroupDefaulted = (Sd->Control & SE_GROUP_DEFAULTED) == SE_GROUP_DEFAULTED; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ BOOLEAN NTAPI RtlEqualSid(IN PSID Sid1_, IN PSID Sid2_) { PISID Sid1 = Sid1_; PISID Sid2 = Sid2_; SIZE_T SidLen; PAGED_CODE_RTL(); if (Sid1->Revision != Sid2->Revision || (*RtlSubAuthorityCountSid(Sid1)) != (*RtlSubAuthorityCountSid(Sid2))) { return(FALSE); } SidLen = RtlLengthSid(Sid1); return RtlCompareMemory(Sid1, Sid2, SidLen) == SidLen; }
BOOLEAN NTAPI RtlFirstFreeAce(PACL Acl, PACE* Ace) { PACE Current; ULONG_PTR AclEnd; ULONG i; PAGED_CODE_RTL(); Current = (PACE)(Acl + 1); *Ace = NULL; if (Acl->AceCount == 0) { *Ace = Current; return(TRUE); } i = 0; AclEnd = (ULONG_PTR)Acl + Acl->AclSize; do { if ((ULONG_PTR)Current >= AclEnd) { return(FALSE); } if (Current->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE && Acl->AclRevision < ACL_REVISION3) { return(FALSE); } Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize); } while (++i < Acl->AceCount); if ((ULONG_PTR)Current < AclEnd) { *Ace = Current; } return(TRUE); }
/* * @implemented */ BOOLEAN NTAPI RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PUCHAR RMControl) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Check if there's no valid RM control */ if (!(Sd->Control & SE_RM_CONTROL_VALID)) { /* Fail and return nothing */ *RMControl = 0; return FALSE; } /* Return it, ironically the member is "should be zero" */ *RMControl = Sd->Sbz1; return TRUE; }
/* * @implemented */ NTSTATUS NTAPI RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision) { PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL(); /* Read current revision, even if invalid */ *Revision = Sd->Revision; /* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; /* Read current control */ *Control = Sd->Control; /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ BOOLEAN NTAPI RtlEqualPrefixSid(IN PSID Sid1_, IN PSID Sid2_) { PISID Sid1 = Sid1_; PISID Sid2 = Sid2_; SIZE_T SidLen; PAGED_CODE_RTL(); if (Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) { SidLen = FIELD_OFFSET(SID, SubAuthority[Sid1->SubAuthorityCount]); return RtlCompareMemory(Sid1, Sid2, SidLen) == SidLen; } return FALSE; }