windows-nt/Source/XPSP1/NT/shell/osshell/security/aclui/ace.cpp

503 lines
14 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: ace.cpp
//
// This file contains the implementation of the CAce class
//
//--------------------------------------------------------------------------
#include "aclpriv.h"
#include "sddl.h" // ConvertSidToStringSid
CAce::CAce(PACE_HEADER pAce):pszInheritSourceName(NULL),
iInheritSourceLevel(0)
{
ULONG nSidLength = 0;
ULONG nAceLength = SIZEOF(KNOWN_ACE) - SIZEOF(ULONG);
ZeroMemory(this, SIZEOF(CAce));
sidType = SidTypeInvalid;
InheritedObjectType = GUID_NULL;
if (pAce != NULL)
{
PSID psidT;
// Copy the header and mask
*(PACE_HEADER)this = *pAce;
Mask = ((PKNOWN_ACE)pAce)->Mask;
// Is this an object ACE?
if (IsObjectAceType(pAce))
{
GUID *pGuid;
nAceLength = SIZEOF(KNOWN_OBJECT_ACE) - SIZEOF(ULONG);
// Copy the object type guid if present
pGuid = RtlObjectAceObjectType(pAce);
if (pGuid)
{
Flags |= ACE_OBJECT_TYPE_PRESENT;
ObjectType = *pGuid;
nAceLength += SIZEOF(GUID);
}
//
//ACE_INHERITED_OBJECT_TYPE_PRESENT is invalid without
//either of container inherit or object inherit flags.
//NTRAID#NTBUG9-287737-2001/01/23-hiteshr
//
if (pAce->AceFlags & ACE_INHERIT_ALL)
{
//Copy the inherit type guid if present
pGuid = RtlObjectAceInheritedObjectType(pAce);
if (pGuid)
{
Flags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
InheritedObjectType = *pGuid;
nAceLength += SIZEOF(GUID);
}
}
}
// Copy the SID
psidT = GetAceSid(pAce);
nSidLength = GetLengthSid(psidT);
psid = (PSID)LocalAlloc(LPTR, nSidLength);
if (psid)
CopyMemory(psid, psidT, nSidLength);
}
AceSize = (USHORT)(nAceLength + nSidLength);
}
CAce::~CAce()
{
if (psid != NULL)
LocalFree(psid);
LocalFreeString(&pszName);
LocalFreeString(&pszType);
LocalFreeString(&pszAccessType);
LocalFreeString(&pszInheritType);
LocalFreeString(&pszInheritSourceName);
}
void
CAce::SetInheritSourceInfo(LPCTSTR psz, INT level)
{
#define MAX_BUFFER 1000
iInheritSourceLevel = level;
if(psz != NULL)
{
SetString(&pszInheritSourceName,psz);
}
else
{
WCHAR Buffer[MAX_BUFFER];
if(IsInheritedAce())
{
LoadString(::hModule, IDS_FROM_PARENT, Buffer, ARRAYSIZE(Buffer));
SetString(&pszInheritSourceName,Buffer);
iInheritSourceLevel = -1;
}
else
{
LoadString(::hModule, IDS_NOT_INHERITED, Buffer, ARRAYSIZE(Buffer));
SetString(&pszInheritSourceName,Buffer);
iInheritSourceLevel = 0;
}
}
}
LPTSTR
CAce::LookupName(LPCTSTR pszServer, LPSECURITYINFO2 psi2)
{
if (SidTypeInvalid == sidType)
{
PUSER_LIST pUserList = NULL;
LPCTSTR pszN = NULL;
LPCTSTR pszL = NULL;
sidType = SidTypeUnknown;
if (LookupSid(psid, pszServer, psi2, &pUserList))
{
sidType = pUserList->rgUsers[0].SidType;
pszN = pUserList->rgUsers[0].pszName;
pszL = pUserList->rgUsers[0].pszLogonName;
}
SetName(pszN, pszL);
if (pUserList)
LocalFree(pUserList);
}
return pszName;
}
void
CAce::SetName(LPCTSTR pszN, LPCTSTR pszL)
{
LocalFreeString(&pszName);
if (!BuildUserDisplayName(&pszName, pszN, pszL) && psid)
ConvertSidToStringSid(psid, &pszName);
}
void
CAce::SetSid(PSID p, LPCTSTR pszName, LPCTSTR pszLogonName, SID_NAME_USE type)
{
ULONG nSidLength = 0;
ULONG nAceLength = SIZEOF(KNOWN_ACE) - SIZEOF(ULONG);
if (psid != NULL)
{
LocalFree(psid);
psid = NULL;
}
if (p != NULL)
{
nSidLength = GetLengthSid(p);
psid = (PSID)LocalAlloc(LPTR, nSidLength);
if (psid)
CopyMemory(psid, p, nSidLength);
}
if (Flags != 0)
{
nAceLength = SIZEOF(KNOWN_OBJECT_ACE) - SIZEOF(ULONG);
if (Flags & ACE_OBJECT_TYPE_PRESENT)
nAceLength += SIZEOF(GUID);
if (Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
nAceLength += SIZEOF(GUID);
}
AceSize = (USHORT)(nAceLength + nSidLength);
sidType = type;
SetName(pszName, pszLogonName);
}
void
CAce::SetString(LPTSTR *ppszDest, LPCTSTR pszSrc)
{
LocalFreeString(ppszDest);
if (NULL != pszSrc)
LocalAllocString(ppszDest, pszSrc);
}
PACE_HEADER
CAce::Copy() const
{
PACE_HEADER pAceCopy = (PACE_HEADER)LocalAlloc(LPTR, AceSize);
CopyTo(pAceCopy);
return pAceCopy;
}
void
CAce::CopyTo(PACE_HEADER pAceDest) const
{
if (pAceDest)
{
ULONG nAceLength = SIZEOF(KNOWN_ACE) - SIZEOF(ULONG);
ULONG nSidLength;
// Copy the header and mask
*pAceDest = *(PACE_HEADER)this;
((PKNOWN_ACE)pAceDest)->Mask = Mask;
// Is this an object ACE?
if (IsObjectAceType(this))
{
GUID *pGuid;
nAceLength = SIZEOF(KNOWN_OBJECT_ACE) - SIZEOF(ULONG);
// Copy the object flags
((PKNOWN_OBJECT_ACE)pAceDest)->Flags = Flags;
// Copy the object type guid if present
pGuid = RtlObjectAceObjectType(pAceDest);
if (pGuid)
{
*pGuid = ObjectType;
nAceLength += SIZEOF(GUID);
}
// Copy the inherit type guid if present
pGuid = RtlObjectAceInheritedObjectType(pAceDest);
if (pGuid)
{
*pGuid = InheritedObjectType;
nAceLength += SIZEOF(GUID);
}
}
// Copy the SID
nSidLength = GetLengthSid(psid);
CopyMemory(GetAceSid(pAceDest), psid, nSidLength);
// The size should already be correct, but set it here to be sure.
pAceDest->AceSize = (USHORT)(nAceLength + nSidLength);
}
}
int
CAce::CompareType(const CAce *pAceCompare) const
{
//
// Determine which ACE preceeds the other in canonical ordering.
//
// Return negative if this ACE preceeds pAceCompare, positive if
// pAceCompare preceeds this ACE, and 0 if they are equivalent in
// canonical ordering.
//
BOOL b1;
BOOL b2;
//
// First check inheritance. Inherited ACEs follow non-inherited ACEs.
//
b1 = AceFlags & INHERITED_ACE;
b2 = pAceCompare->AceFlags & INHERITED_ACE;
if (b1 != b2)
{
// One (and only one) of the ACEs is inherited.
return (b1 ? 1 : -1);
}
//
// Next, Allow ACEs follow Deny ACEs.
// Note that allow/deny has no effect on the ordering of Audit ACEs.
//
b1 = (AceType == ACCESS_ALLOWED_ACE_TYPE ||
AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE);
b2 = (pAceCompare->AceType == ACCESS_ALLOWED_ACE_TYPE ||
pAceCompare->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE);
if (b1 != b2)
{
// One of the ACEs is an Allow ACE.
return (b1 ? 1 : -1);
}
//
// Next, Object ACEs follow non-object ACEs.
//
b1 = (AceType >= ACCESS_MIN_MS_OBJECT_ACE_TYPE &&
AceType <= ACCESS_MAX_MS_OBJECT_ACE_TYPE);
b2 = (pAceCompare->AceType >= ACCESS_MIN_MS_OBJECT_ACE_TYPE &&
pAceCompare->AceType <= ACCESS_MAX_MS_OBJECT_ACE_TYPE);
if (b1 != b2)
{
// One of the ACEs is an Object ACE.
return (b1 ? 1 : -1);
}
return 0;
}
DWORD
CAce::Merge(const CAce *pAce2)
{
DWORD dwStatus;
DWORD dwMergeFlags = 0;
DWORD dwResult;
if (pAce2 == NULL)
return MERGE_FAIL;
//if either of the ace is inherited and they are not from the same parent
if( GetInheritSourceLevel() != pAce2->GetInheritSourceLevel() )
return MERGE_FAIL;
//
// The ACEs have to be the same basic type and have the same SID or
// there's no hope.
//
if (!IsEqualACEType(AceType, pAce2->AceType) ||
!EqualSid(psid, pAce2->psid))
return MERGE_FAIL;
if (!IsEqualGUID(InheritedObjectType, pAce2->InheritedObjectType))
return MERGE_FAIL; // incompatible inherit object types
if (Flags & ACE_OBJECT_TYPE_PRESENT)
dwMergeFlags |= MF_OBJECT_TYPE_1_PRESENT;
if (pAce2->Flags & ACE_OBJECT_TYPE_PRESENT)
dwMergeFlags |= MF_OBJECT_TYPE_2_PRESENT;
if (IsEqualGUID(ObjectType, pAce2->ObjectType))
dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
if (IsAuditAlarmACE(AceType))
dwMergeFlags |= MF_AUDIT_ACE_TYPE;
dwStatus = MergeAceHelper(AceFlags,
Mask,
pAce2->AceFlags,
pAce2->Mask,
dwMergeFlags,
&dwResult);
switch (dwStatus)
{
case MERGE_MODIFIED_FLAGS:
AceFlags = (UCHAR)dwResult;
break;
case MERGE_MODIFIED_MASK:
Mask = dwResult;
break;
}
return dwStatus;
}
BOOL
IsEqualACEType(DWORD dwType1, DWORD dwType2)
{
if (dwType1 >= ACCESS_MIN_MS_OBJECT_ACE_TYPE &&
dwType1 <= ACCESS_MAX_MS_OBJECT_ACE_TYPE)
dwType1 -= (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE);
if (dwType2 >= ACCESS_MIN_MS_OBJECT_ACE_TYPE &&
dwType2 <= ACCESS_MAX_MS_OBJECT_ACE_TYPE)
dwType2 -= (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE);
return (dwType1 == dwType2);
}
DWORD
MergeAceHelper(DWORD dwAceFlags1,
DWORD dwMask1,
DWORD dwAceFlags2,
DWORD dwMask2,
DWORD dwMergeFlags,
LPDWORD pdwResult)
{
// Assumptions:
// The ACEs are the same basic type.
// The SIDs are the same for both.
// The Inherit object type is the same for both.
if (pdwResult == NULL)
return MERGE_FAIL;
*pdwResult = 0;
if (dwMergeFlags & MF_OBJECT_TYPE_EQUAL)
{
if (dwAceFlags1 == dwAceFlags2)
{
//
// Everything matches except maybe the mask, which
// can be combined here.
//
if (AllFlagsOn(dwMask1, dwMask2))
return MERGE_OK_1;
else if (AllFlagsOn(dwMask2, dwMask1))
return MERGE_OK_2;
*pdwResult = dwMask1 | dwMask2;
return MERGE_MODIFIED_MASK;
}
else if ((dwAceFlags1 & VALID_INHERIT_FLAGS) == (dwAceFlags2 & VALID_INHERIT_FLAGS) &&
dwMask1 == dwMask2)
{
// If 2 audit aces are identical except for the audit
// type (success/fail), the flags can be combined.
if (dwMergeFlags & MF_AUDIT_ACE_TYPE)
{
*pdwResult = dwAceFlags1 | dwAceFlags2;
return MERGE_MODIFIED_FLAGS;
}
}
else if ((dwAceFlags1 & (NO_PROPAGATE_INHERIT_ACE | INHERITED_ACE | FAILED_ACCESS_ACE_FLAG | SUCCESSFUL_ACCESS_ACE_FLAG))
== (dwAceFlags2 & (NO_PROPAGATE_INHERIT_ACE | INHERITED_ACE | FAILED_ACCESS_ACE_FLAG | SUCCESSFUL_ACCESS_ACE_FLAG)))
{
// The NO_PROPAGATE_INHERIT_ACE bit is the same for both
if (dwMask1 == dwMask2)
{
// The masks are the same, so we can combine inherit flags
*pdwResult = dwAceFlags1;
// INHERIT_ONLY_ACE should be turned on only if it is
// already on in both ACEs, otherwise leave it off.
if (!(dwAceFlags2 & INHERIT_ONLY_ACE))
*pdwResult &= ~INHERIT_ONLY_ACE;
// Combine the remaining inherit flags and return
*pdwResult |= dwAceFlags2 & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
return MERGE_MODIFIED_FLAGS;
}
else if (AllFlagsOn(dwMask1, dwMask2))
{
// mask1 contains mask2. If Ace1 is inherited onto all of the
// same things that Ace2 is, then Ace2 is redundant.
if ((!(dwAceFlags1 & INHERIT_ONLY_ACE) || (dwAceFlags2 & INHERIT_ONLY_ACE))
&& AllFlagsOn(dwAceFlags1 & ACE_INHERIT_ALL, dwAceFlags2 & ACE_INHERIT_ALL))
return MERGE_OK_1;
}
else if (AllFlagsOn(dwMask2, dwMask1))
{
// Same as above, reversed.
if ((!(dwAceFlags2 & INHERIT_ONLY_ACE) || (dwAceFlags1 & INHERIT_ONLY_ACE))
&& AllFlagsOn(dwAceFlags2 & ACE_INHERIT_ALL, dwAceFlags1 & ACE_INHERIT_ALL))
return MERGE_OK_2;
}
}
}
else if (dwAceFlags1 == dwAceFlags2)
{
if (!(dwMergeFlags & MF_OBJECT_TYPE_1_PRESENT) &&
AllFlagsOn(dwMask1, dwMask2))
{
//
// The other ACE has a non-NULL object type but this ACE has no object
// type and a mask that includes all of the bits in the other one.
// I.e. This ACE implies the other ACE.
//
return MERGE_OK_1;
}
else if (!(dwMergeFlags & MF_OBJECT_TYPE_2_PRESENT) &&
AllFlagsOn(dwMask2, dwMask1))
{
//
// This ACE has a non-NULL object type but the other ACE has no object
// type and a mask that includes all of the bits in this one.
// I.e. The other ACE implies this ACE.
//
return MERGE_OK_2;
}
}
return MERGE_FAIL;
}