diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/se/sep.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/private/ntos/se/sep.c b/private/ntos/se/sep.c new file mode 100644 index 000000000..9101f6af6 --- /dev/null +++ b/private/ntos/se/sep.c @@ -0,0 +1,231 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + Sep.c + +Abstract: + + This Module implements the private security routine that are defined + in sep.h + +Author: + + Gary Kimura (GaryKi) 9-Nov-1989 + +Environment: + + Kernel Mode + +Revision History: + +--*/ + +#include "sep.h" +#include "seopaque.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,SepCheckAcl) +#endif + + +#define LongAligned( ptr ) (LongAlign(ptr) == ((PVOID)(ptr))) +#define WordAligned( ptr ) (WordAlign(ptr) == ((PVOID)(ptr))) + + +BOOLEAN +SepCheckAcl ( + IN PACL Acl, + IN ULONG Length + ) + +/*++ + +Routine Description: + + This is a private routine that checks that an acl is well formed. + +Arguments: + + Acl - Supplies the acl to check + + Length - Supplies the real size of the acl. The internal acl size + must agree. + +Return Value: + + BOOLEAN - TRUE if the acl is well formed and FALSE otherwise + +--*/ +{ + PACE_HEADER Ace; + PISID Sid; + PISID Sid2; + ULONG i; + UCHAR AclRevision = ACL_REVISION2; + + if (!ValidAclRevision(Acl)) { + return(FALSE); + } + + + if (!LongAligned(Acl->AclSize)) { + return(FALSE); + } + + // + // Validate all of the ACEs. + // + + Ace = ((PVOID)((PUCHAR)(Acl) + sizeof(ACL))); + + for (i = 0; i < Acl->AceCount; i++) { + + // + // Check to make sure we haven't overrun the Acl buffer + // with our ace pointer. Make sure the ACE_HEADER is in + // the ACL also. + // + + if ((PUCHAR)Ace + sizeof(ACE_HEADER) >= ((PUCHAR)Acl + Acl->AclSize)) { + return(FALSE); + } + + if (!WordAligned(&Ace->AceSize)) { + return(FALSE); + } + + if ((PUCHAR)Ace + Ace->AceSize > ((PUCHAR)Acl + Acl->AclSize)) { + return(FALSE); + } + + // + // It is now safe to reference fields in the ACE header. + // + + // + // The ACE header fits into the ACL, if this is a known type of ACE, + // make sure the SID is within the bounds of the ACE + // + + if (IsKnownAceType(Ace)) { + + if (!LongAligned(Ace->AceSize)) { + return(FALSE); + } + + if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + sizeof(SID)) { + return(FALSE); + } + + // + // It's now safe to reference the parts of the SID structure, though + // not the SID itself. + // + + Sid = (PISID) & (((PKNOWN_ACE)Ace)->SidStart); + + if (Sid->Revision != SID_REVISION) { + return(FALSE); + } + + if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { + return(FALSE); + } + + // + // SeLengthSid computes the size of the SID based on the subauthority count, + // so it is safe to use even though we don't know that the body of the SID + // is safe to reference. + // + + if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + SeLengthSid( Sid )) { + return(FALSE); + } + + } else { + + // + // If it's a compound ACE, then perform roughly the same set of tests, but + // check the validity of both SIDs. + // + + if (IsCompoundAceType(Ace)) { + + // + // Save away the fact that we saw a compound ACE while traversing the ACL. + // + + AclRevision = ACL_REVISION3; + + if (!LongAligned(Ace->AceSize)) { + return(FALSE); + } + + if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + sizeof(SID)) { + return(FALSE); + } + + // + // The only currently defined Compound ACE is an Impersonation ACE. + // + + if (((PKNOWN_COMPOUND_ACE)Ace)->CompoundAceType != COMPOUND_ACE_IMPERSONATION) { + return(FALSE); + } + + // + // Examine the first SID and make sure it's structurally valid, + // and it lies within the boundaries of the ACE. + // + + Sid = (PISID) & (((PKNOWN_COMPOUND_ACE)Ace)->SidStart); + + if (Sid->Revision != SID_REVISION) { + return(FALSE); + } + + if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { + return(FALSE); + } + + // + // Compound ACEs contain two SIDs. Make sure this ACE is large enough to contain + // not only the first SID, but the body of the 2nd. + // + + if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + sizeof(SID)) { + return(FALSE); + } + + // + // It is safe to reference the interior of the 2nd SID. + // + + Sid2 = (PISID) ((PUCHAR)Sid + SeLengthSid( Sid )); + + if (Sid2->Revision != SID_REVISION) { + return(FALSE); + } + + if (Sid2->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { + return(FALSE); + } + + if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + SeLengthSid( Sid2 )) { + return(FALSE); + } + } + } + + // + // And move Ace to the next ace position + // + + Ace = ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize)); + } + + return(TRUE); +} |