|
|
//+-------------------------------------------------------------------------
//
// 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; }
|