232 lines
5.5 KiB
C
232 lines
5.5 KiB
C
/*++
|
||
|
||
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);
|
||
}
|