|
|
/*****************************************************************************/ /* Copyright (c) 1999-2002 Microsoft Corporation, All Rights Reserved /
/*****************************************************************************/
/*
* CAccessEntry.cpp - implementation file for CAccessEntry class. * * Created: 12-14-1997 by Sanjeev Surati * (based on classes from Windows NT Security by Nik Okuntseff) */ #include "precomp.h"
#include <assertbreak.h>
#include "AccessEntryList.h"
#include "DACL.h"
#include "SACL.h"
#include "securitydescriptor.h"
#include "AdvApi32Api.h"
#include <accctrl.h>
#include "wbemnetapi32.h"
#include "SecUtils.h"
#ifndef MAXDWORD
#define MAXDWORD MAXULONG
#endif
// We're using STL, so this is a requirement
using namespace std;
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CAccessEntryList
//
// Default class constructor.
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CAccessEntryList::CAccessEntryList( void ) : m_ACL() { }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CAccessEntryList
//
// Class constructor.
//
// Inputs:
// PACL pWin32ACL - ACL to initialize from.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CAccessEntryList::CAccessEntryList( PACL pWin32ACL, bool fLookup /* = true */ ) : m_ACL() { InitFromWin32ACL( pWin32ACL, ALL_ACE_TYPES, fLookup ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::~CAccessEntryList
//
// Class destructor
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CAccessEntryList::~CAccessEntryList( void ) { Clear(); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Add
//
// Adds a CAccessEntry* pointer to the front of the list.
//
// Inputs:
// CAccessEntry* pACE - ACE to add to the list
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
void CAccessEntryList::Add( CAccessEntry* pACE ) { // Add to the front of the list
m_ACL.push_front( pACE ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Append
//
// Appends a CAccessEntry* pointer to the end of the list.
//
// Inputs:
// CAccessEntry* pACE - ACE to add to the list
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
void CAccessEntryList::Append( CAccessEntry* pACE ) { // Add to the end of the list
m_ACL.push_back( pACE ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Find
//
// Locates a CAccessEntry* pointer in our list
//
// Inputs:
// CAccessEntry* pACE - ACE to find in the list
//
// Outputs:
// None.
//
// Returns:
// ACLIter iterator pointing at entry we found
//
// Comments:
//
///////////////////////////////////////////////////////////////////
ACLIter CAccessEntryList::Find( CAccessEntry* pACE ) { for ( ACLIter acliter = m_ACL.begin(); acliter != m_ACL.end() && *acliter != pACE; acliter++ );
return acliter;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Find
//
// Locates a CAccessEntry* pointer in our list whose contents match
// the supplied ACE.
//
// Inputs:
// const CAccessEntry& ace - ACE to find in the list
//
// Outputs:
// None.
//
// Returns:
// CAccessEntry* pointer to matchiong ace.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CAccessEntry* CAccessEntryList::Find( const CAccessEntry& ace ) { for ( ACLIter acliter = m_ACL.begin(); acliter != m_ACL.end() && !( *(*acliter) == ace ); acliter++ );
return ( acliter == m_ACL.end() ? NULL : *acliter );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Find
//
// Locates a CAccessEntry* pointer in our list based on PSID,
// bACEType and bACEFlags.
//
// Inputs:
// PSID psid - SID
// BYTE bACEType - ACE Type to find.
// BYTE bACEFlags - ACE flags.
//
// Outputs:
// None.
//
// Returns:
// CAccessEntry* Pointer to object we found.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CAccessEntry* CAccessEntryList::Find( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, bool fLookup /* = true */ ) {
// Traverse the list until we find an element matching the psid, ACE Type and
// ACE Flags, or run out of elements.
for(ACLIter acliter = m_ACL.begin(); acliter != m_ACL.end(); acliter++) { CAccessEntry tempace(psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, NULL, fLookup); CAccessEntry *ptempace2 = *acliter; if(*ptempace2 == tempace) break; } return ( acliter == m_ACL.end() ? NULL : *acliter ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::AddNoDup
//
// Locates a CAccessEntry* pointer in our list based on PSID,
// bACEType and bACEFlags. If one is found, we replace the
// values of that object. Otherwise, we add the new object to
// the list.
//
// Inputs:
// PSID psid - SID
// BYTE bACEType - ACE Type to find.
// BYTE bACEFlags - ACE flags.
// DWORD dwMask - Access Mask.
// BOOL fMerge - Merge flag.
//
// Outputs:
// None.
//
// Returns:
// BOOL success/failure.
//
// Comments:
// If fMerge is TRUE, if we find a value, we or the
// access masks together, otherwise, we replace
// the mask.
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::AddNoDup( PSID psid, BYTE bACEType, BYTE bACEFlags, DWORD dwMask, GUID *pguidObjGuid, GUID *pguidInhObjGuid, bool fMerge /* = false */ ) { bool fReturn = true;
// Look for a duplicate entry in our linked list. This means that
// the sid, the ACEType and the flags are the same. If this happens,
// we merge the entries by ORing in the new mask or overwrite (based
// on the merge mask). Otherwise, we should add the new entry to the
// front of the list
CAccessEntry* pAccessEntry = Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask );
if ( NULL == pAccessEntry ) { // NOT found, so we need to add a new entry.
try { pAccessEntry = new CAccessEntry( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask ); if ( NULL != pAccessEntry ) { Add( pAccessEntry ); } else { fReturn = false; } } catch(...) { if(pAccessEntry != NULL) { delete pAccessEntry; pAccessEntry = NULL; } throw; }
} else { if ( fMerge ) { // OR in any new values.
pAccessEntry->MergeAccessMask( dwMask ); } else { pAccessEntry->SetAccessMask( dwMask ); } }
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::AppendNoDup
//
// Locates a CAccessEntry* pointer in our list based on PSID,
// bACEType and bACEFlags. If one is found, we replace the
// values of that object. Otherwise, we append the new object to
// the list.
//
// Inputs:
// PSID psid - SID
// BYTE bACEType - ACE Type to find.
// BYTE bACEFlags - ACE flags.
// DWORD dwMask - Access Mask.
// BOOL fMerge - Merge flag.
//
// Outputs:
// None.
//
// Returns:
// BOOL success/failure.
//
// Comments:
// If fMerge is TRUE, if we find a value, we or the
// access masks together, otherwise, we replace
// the mask.
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::AppendNoDup( PSID psid, BYTE bACEType, BYTE bACEFlags, DWORD dwMask, GUID *pguidObjGuid, GUID *pguidInhObjGuid, bool fMerge /* = false */ ) { bool fReturn = true;
// Look for a duplicate entry in our linked list. This means that
// the sid, the ACEType and the flags are the same. If this happens,
// we merge the entries by ORing in the new mask or overwrite (based
// on the merge mask). Otherwise, we should add the new entry to the
// end of the list
CAccessEntry* pAccessEntry = Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask );
if ( NULL == pAccessEntry ) { // NOT found, so we need to append a new entry.
try { pAccessEntry = new CAccessEntry( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask ); if ( NULL != pAccessEntry ) { Append( pAccessEntry ); } else { fReturn = false; } } catch(...) { if(pAccessEntry != NULL) { delete pAccessEntry; pAccessEntry = NULL; } throw; }
} else { if ( fMerge ) { // OR in any new values.
pAccessEntry->MergeAccessMask( dwMask ); } else { pAccessEntry->SetAccessMask( dwMask ); } }
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::AppendNoDup
//
// Locates a CAccessEntry* pointer in our list based on PSID,
// bACEType and bACEFlags. If one is found, we replace the
// values of that object. Otherwise, we append the new object to
// the list.
//
// Inputs:
// PSID psid - SID
// BYTE bACEType - ACE Type to find.
// BYTE bACEFlags - ACE flags.
// DWORD dwMask - Access Mask.
// BOOL fMerge - Merge flag.
//
// Outputs:
// None.
//
// Returns:
// BOOL success/failure.
//
// Comments:
// If fMerge is TRUE, if we find a value, we or the
// access masks together, otherwise, we replace
// the mask.
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::AppendNoDup( PSID psid, BYTE bACEType, BYTE bACEFlags, DWORD dwMask, GUID *pguidObjGuid, GUID *pguidInhObjGuid, bool fMerge, bool fLookup ) { bool fReturn = true;
// Look for a duplicate entry in our linked list. This means that
// the sid, the ACEType and the flags are the same. If this happens,
// we merge the entries by ORing in the new mask or overwrite (based
// on the merge mask). Otherwise, we should add the new entry to the
// end of the list
CAccessEntry* pAccessEntry = Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask, fLookup );
if ( NULL == pAccessEntry ) { // NOT found, so we need to append a new entry.
try { pAccessEntry = new CAccessEntry( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask, NULL, fLookup ); if ( NULL != pAccessEntry ) { Append( pAccessEntry ); } else { fReturn = false; } } catch(...) { if(pAccessEntry != NULL) { delete pAccessEntry; pAccessEntry = NULL; } throw; }
} else { if ( fMerge ) { // OR in any new values.
pAccessEntry->MergeAccessMask( dwMask ); } else { pAccessEntry->SetAccessMask( dwMask ); } }
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Remove
//
// Removes the specified pointer from our list.
//
// Inputs:
// CAccessEntry* pACE - ACE to remove.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
// We DO NOT free the pointer.
//
///////////////////////////////////////////////////////////////////
void CAccessEntryList::Remove( CAccessEntry* pACE ) { ACLIter acliter = Find( pACE );
if ( acliter != m_ACL.end() ) { m_ACL.erase( acliter ); }
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Clear
//
// Clears and empties out the list. Frees the pointers as they
// are located.
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
void CAccessEntryList::Clear( void ) {
// Delete all list entries and then clear out the list.
for ( ACLIter acliter = m_ACL.begin(); acliter != m_ACL.end(); acliter++ ) { delete *acliter; }
m_ACL.erase( m_ACL.begin(), m_ACL.end() ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Find
//
// Locates an ACE in our list matching the specified criteria.
//
// Inputs:
// const CSid& sid - SID
// BYTE bACEType - ACE Type
// DWORD dwAccessMask - Access Mask
// BYTE bACEFlags - ACE Flags
//
// Outputs:
// CAccessEntry& ace
//
// Returns:
// BOOL success/failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::Find( const CSid& sid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { CAccessEntry tempace( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask );
CAccessEntry* pACE = NULL; try { pACE = Find( tempace );
if ( NULL != pACE ) { ace = *pACE; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
return ( NULL != pACE ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Find
//
// Locates an ACE in our list matching the specified criteria.
//
// Inputs:
// PSID psid - PSID.
// BYTE bACEType - ACE Type
// BYTE bACEFlags - ACE Flags
//
// Outputs:
// CAccessEntry& ace
//
// Returns:
// BOOL success/failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::Find( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { CAccessEntry* pACE = NULL; try { CAccessEntry* pACE = Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask);
if ( NULL != pACE ) { ace = *pACE; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
return ( NULL != pACE ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::Copy
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor.
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::Copy( CAccessEntryList& ACL ) {
// Dump out our existing entries
Clear();
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { CAccessEntry* pACE = NULL; try { pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CopyACEs
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor. This
// function ONLY copies non-Inherited ACEs
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
// BYTE bACEType - ACE type to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::CopyACEs( CAccessEntryList& ACL, BYTE bACEType ) {
// Dump out our existing entries
Clear();
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { // We don't want inherited ACEs
if ( (*acliter)->GetACEType() == bACEType && !(*acliter)->IsInherited() ) { CAccessEntry* pACE = NULL; try { pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } }
catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
} }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CopyInheritedACEs
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor. This
// function ONLY copies Inherited ACEs
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
// BYTE bACEType - ACE type to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::CopyInheritedACEs( CAccessEntryList& ACL, BYTE bACEType ) {
// Dump out our existing entries
Clear();
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { // We want inherited ACEs
if ( (*acliter)->GetACEType() == bACEType && (*acliter)->IsInherited() ) { CAccessEntry* pACE = NULL; try { CAccessEntry* pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
} }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CopyAllowedACEs
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor. This
// function ONLY copies Allowed ACEs
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::CopyAllowedACEs( CAccessEntryList& ACL ) {
// Dump out our existing entries
Clear();
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { // We want allowed ACEs
if ( (*acliter)->IsAllowed() ) { CAccessEntry* pACE = NULL; try { CAccessEntry* pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
} }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CopyDeniedACEs
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor. This
// function ONLY copies Denied ACEs
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
// BYTE bACEType - ACE type to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::CopyDeniedACEs( CAccessEntryList& ACL ) {
// Dump out our existing entries
Clear();
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { // We want denied ACEs
if ( (*acliter)->IsDenied() ) { CAccessEntry* pACE = NULL; try { CAccessEntry* pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
} }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::CopyByACEType
//
// Copies list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor. This
// function ONLY copies ACEs of the specified type and inheritence.
//
// Inputs:
// const CAccessEntryList& ACL - ACL to copy.
// BYTE bACEType - ACE type to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::CopyByACEType(CAccessEntryList& ACL, BYTE bACEType, bool fInherited) { // Dump out our existing entries
Clear(); bool fIsInh; fInherited ? fIsInh = true : fIsInh = false;
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { // We want inherited ACEs
if ( ( (*acliter)->GetACEType() == bACEType ) && ( ((*acliter)->IsInherited() != 0) == fIsInh ) ) { CAccessEntry* pACE = NULL; try { CAccessEntry* pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } }
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::AppendList
//
// Appends list into another one. Pointers are not copied, as we
// new more CAccessEntry objects using the Copy Constructor.
//
// Inputs:
// const CAccessEntryList& ACL - ACL to append.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::AppendList( CAccessEntryList& ACL ) {
// Now iterate our list, duping the ACEs into the ACL
for ( ACLIter acliter = ACL.m_ACL.begin(); acliter != ACL.m_ACL.end(); acliter++ ) { CAccessEntry* pACE = NULL; try { pACE = new CAccessEntry( *(*acliter) );
if ( NULL != pACE ) { Append( pACE ); } else { break; } }
catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
}
// We should be at the end of the source list
return ( acliter == ACL.m_ACL.end() );
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::BeginEnum
//
// Call to establish an ACLPOSIION& value for continung enumerations.
//
// Inputs:
// None.
//
// Outputs:
// ACLPOSITION& pos - Beginning position.
//
// Returns:
// BOOL Success/Failure.
//
// Comments:
//
// User MUST call EndEnum() on pos.
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::BeginEnum( ACLPOSITION& pos ) { // Allocate a new iterator and stick it at the beginning
ACLIter* pACLIter = NULL; try { pACLIter = new ACLIter; } catch(...) { if(pACLIter != NULL) { delete pACLIter; pACLIter = NULL; } throw; }
if ( NULL != pACLIter ) { *pACLIter = m_ACL.begin(); }
pos = (ACLPOSITION) pACLIter;
return ( NULL != pACLIter ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::GetNext
//
// Enumeration call using ACLPOSITION.
//
// Inputs:
// None.
//
// Outputs:
// ACLPOSITION& pos - Beginning position.
// CAccessEntry& ACE - enumed value.
//
// Returns:
// BOOL Success/Failure.
//
// Comments:
//
// Because it returns copies, this function is FOR public use.
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::GetNext( ACLPOSITION& pos, CAccessEntry& ACE ) { CAccessEntry* pACE = NULL; try { pACE = GetNext( pos ); } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; }
if ( NULL != pACE ) { ACE = *pACE; }
// TRUE/FALSE return based on whether we got back a pointer or not.
return ( NULL != pACE ); }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList::GetNext
//
// Enumeration call using ACLPOSITION.
//
// Inputs:
// None.
//
// Outputs:
// ACLPOSITION& pos - Beginning position.
//
// Returns:
// CAccessEntry* enumed pointer
//
// Comments:
//
// Because it returns actual pointers, DO NOT make this function
// public.
//
///////////////////////////////////////////////////////////////////
CAccessEntry* CAccessEntryList::GetNext( ACLPOSITION& pos ) { CAccessEntry* pACE = NULL; ACLIter* pACLIter = (ACLIter*) pos;
// We'll want to get the current value and increment
// if we're anywhere but the end.
if ( *pACLIter != m_ACL.end() ) { // Get the ACE out
pACE = *(*pACLIter); (*pACLIter)++; }
return pACE; }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:EndEnum
//
// Enumeration End call.
//
// Inputs:
// None.
//
// Outputs:
// ACLPOSITION& pos - Position to end on.
//
// Returns:
// None.
//
// Comments:
//
// ACLPOSITION passed in will be invalidated.
//
///////////////////////////////////////////////////////////////////
void CAccessEntryList::EndEnum( ACLPOSITION& pos ) { ACLIter* pACLIter = (ACLIter*) pos;
delete pACLIter; }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:GetAt
//
// Locates ACE at specified index.
//
// Inputs:
// DWORD dwIndex - Index to find.
//
// Outputs:
// CAccessEntry& ace - ACE located at dwIndex.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::GetAt( DWORD dwIndex, CAccessEntry& ace ) { bool fReturn = false;
if ( dwIndex < m_ACL.size() ) { ACLIter acliter = m_ACL.begin();
// Enum the list until we hit the index or run out of values.
// we should hit the index since we verified that dwIndex is
// indeed < m_ACL.size().
for ( DWORD dwCtr = 0; dwCtr < dwIndex && acliter != m_ACL.end(); acliter++, dwCtr++ );
if ( acliter != m_ACL.end() ) { // Copy the ACE
ace = *(*acliter); fReturn = true; }
}
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:SetAt
//
// Locates ACE at specified index and overwrites it.
//
// Inputs:
// DWORD dwIndex - Index to find.
// CAccessEntry& ace - ACE to set at dwIndex.
//
// Outputs:
// None.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::SetAt( DWORD dwIndex, const CAccessEntry& ace ) { bool fReturn = false;
if ( dwIndex < m_ACL.size() ) { ACLIter acliter = m_ACL.begin();
// Enum the list until we hit the index, at which point we will
// replace the existing entry data with the supplied data.
for ( DWORD dwCtr = 0; dwCtr < dwIndex && acliter != m_ACL.end(); acliter++, dwCtr++ );
if ( acliter != m_ACL.end() ) { // Copy the ACE
*(*acliter) = ace; fReturn = true; }
}
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:RemoveAt
//
// Locates ACE at specified index and removes it.
//
// Inputs:
// DWORD dwIndex - Index to find.
//
// Outputs:
// None.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
bool CAccessEntryList::RemoveAt( DWORD dwIndex ) { bool fReturn = false;
if ( dwIndex < m_ACL.size() ) { ACLIter acliter = m_ACL.begin();
// Enum the list until we hit the index, at which point we will
// delete the pointer at the entry and erase it from the list.
for ( DWORD dwCtr = 0; dwCtr < dwIndex && acliter != m_ACL.end(); acliter++, dwCtr++ );
if ( acliter != m_ACL.end() ) { delete *acliter; m_ACL.erase( acliter ); fReturn = true; }
}
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:CalculateWin32ACLSize
//
// Traverses our list and calculates the size of a Win32ACL
// containing corresponding values.
//
// Inputs:
// None.
//
// Outputs:
// LPDWORD pdwACLSize - ACL Size.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
BOOL CAccessEntryList::CalculateWin32ACLSize( LPDWORD pdwACLSize ) { BOOL fReturn = TRUE;
if ( 0 == *pdwACLSize ) { *pdwACLSize = sizeof(ACL); }
// Objects for internal manipulations and gyrationships
CAccessEntry* pAce = NULL; CSid sid; ACLPOSITION pos;
if ( BeginEnum( pos ) ) { try { while ( fReturn && ( pAce = GetNext( pos ) ) != NULL ) { // Different structures for different ACEs
switch ( pAce->GetACEType() ) { case ACCESS_ALLOWED_ACE_TYPE: *pdwACLSize += sizeof( ACCESS_ALLOWED_ACE ); break; case ACCESS_DENIED_ACE_TYPE: *pdwACLSize += sizeof( ACCESS_DENIED_ACE ); break; case SYSTEM_AUDIT_ACE_TYPE: *pdwACLSize += sizeof( SYSTEM_AUDIT_ACE ); break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: *pdwACLSize += sizeof( ACCESS_ALLOWED_OBJECT_ACE ); break; //case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: *pdwACLSize += sizeof( ACCESS_ALLOWED_COMPOUND_ACE ); break;
case ACCESS_DENIED_OBJECT_ACE_TYPE: *pdwACLSize += sizeof( ACCESS_DENIED_OBJECT_ACE ); break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: *pdwACLSize += sizeof( SYSTEM_AUDIT_OBJECT_ACE ); break; //case SYSTEM_ALARM_ACE_TYPE: *pdwACLSize += sizeof( SYSTEM_ALARM_ACE_TYPE ); break;
//case SYSTEM_ALARM_OBJECT_ACE_TYPE: *pdwACLSize += sizeof( SYSTEM_ALARM_OBJECT_ACE ); break;
default: ASSERT_BREAK(0); fReturn = FALSE; break; }
pAce->GetSID( sid );
// Calculate the storage required for the Sid using the formula
// from the security reference code samples
*pdwACLSize += GetLengthSid( sid.GetPSid() ) - sizeof( DWORD );
}
} catch(...) { if(pAce != NULL) { delete pAce; pAce = NULL; } throw; } EndEnum( pos ); }
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:FillWin32ACL
//
// Traverses our list and adds ACE entries to a Win32 ACL.
//
// Inputs:
// PACL pACL - ACL to add ACEs to.
//
// Outputs:
// None.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
///////////////////////////////////////////////////////////////////
DWORD CAccessEntryList::FillWin32ACL( PACL pACL ) { DWORD dwReturn = ERROR_SUCCESS;
if(pACL == NULL) { return E_POINTER; }
// Objects for internal manipulations and gyrationships
CAccessEntry* pACE = NULL; ACLPOSITION pos; ACE_HEADER* pAceHeader = NULL;
#if NTONLY >= 5
CAdvApi32Api *t_pAdvApi32 = NULL; t_pAdvApi32 = (CAdvApi32Api*) CResourceManager::sm_TheResourceManager.GetResource(g_guidAdvApi32Api, NULL); #endif
// Enumerate the List.
if ( BeginEnum( pos ) ) { while ( ERROR_SUCCESS == dwReturn && ( pACE = GetNext( pos ) ) != NULL ) { #if NTONLY >= 5
if(pACE->GetACEType() == ACCESS_ALLOWED_OBJECT_ACE_TYPE) { if(t_pAdvApi32 != NULL) { // Call the new function AddAccessAllowedObjectAce...
CSid sid; pACE->GetSID(sid); BOOL fRetval = FALSE; GUID guidObjType, guidInhObjType; GUID *pguidObjType = NULL; GUID *pguidInhObjType = NULL;
if(pACE->GetObjType(guidObjType)) pguidObjType = &guidObjType; if(pACE->GetInhObjType(guidInhObjType)) pguidInhObjType = &guidInhObjType;
if(!t_pAdvApi32->AddAccessAllowedObjectAce(pACL, ACL_REVISION_DS, pACE->GetACEFlags(), pACE->GetAccessMask(), pguidObjType, pguidInhObjType, sid.GetPSid(), &fRetval)) { dwReturn = ERROR_PROC_NOT_FOUND; } else // fn exists in dll
{ if(!fRetval) { dwReturn = ::GetLastError(); } } } else { dwReturn = E_FAIL; } } else if(pACE->GetACEType() == ACCESS_DENIED_OBJECT_ACE_TYPE) { if(t_pAdvApi32 != NULL) { // Call the new function AddAccessDeniedObjectAce...
CSid sid; pACE->GetSID(sid); BOOL fRetval = FALSE; GUID guidObjType, guidInhObjType; GUID *pguidObjType = NULL; GUID *pguidInhObjType = NULL;
if(pACE->GetObjType(guidObjType)) pguidObjType = &guidObjType; if(pACE->GetInhObjType(guidInhObjType)) pguidInhObjType = &guidInhObjType; if(!t_pAdvApi32->AddAccessDeniedObjectAce(pACL, ACL_REVISION_DS, pACE->GetACEFlags(), pACE->GetAccessMask(), pguidObjType, pguidInhObjType, sid.GetPSid(), &fRetval)) { dwReturn = ERROR_PROC_NOT_FOUND; } else // fn exists in dll
{ if(!fRetval) { dwReturn = ::GetLastError(); } } } else { dwReturn = E_FAIL; } } else if(pACE->GetACEType() == SYSTEM_AUDIT_OBJECT_ACE_TYPE) { if(t_pAdvApi32 != NULL) { // Call the new function AddAccessDeniedObjectAce...
CSid sid; pACE->GetSID(sid); BOOL fRetval = FALSE; if(!t_pAdvApi32->AddAuditAccessObjectAce(pACL, ACL_REVISION_DS, pACE->GetACEFlags(), pACE->GetAccessMask(), NULL, NULL, sid.GetPSid(), FALSE, // we pick this up through the third argument
FALSE, // we pick this up through the third argument
&fRetval)) { if(!fRetval) { dwReturn = ::GetLastError(); } else { dwReturn = ERROR_PROC_NOT_FOUND; } } } else { dwReturn = E_FAIL; } } else #endif
{ // For Each ACE we enum, allocate a Win32 ACE, and stick that bad boy at the
// end of the Win32 ACL.
if ( pACE->AllocateACE( &pAceHeader ) ) { if ( !::AddAce( pACL, pACL->AclRevision, MAXDWORD, (void*) pAceHeader, pAceHeader->AceSize ) ) { dwReturn = ::GetLastError(); }
// Cleanup the memory block
pACE->FreeACE( pAceHeader ); } else { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } } }
EndEnum( pos ); }
#if NTONLY >= 5
if(t_pAdvApi32 != NULL) { CResourceManager::sm_TheResourceManager.ReleaseResource(g_guidAdvApi32Api, t_pAdvApi32); t_pAdvApi32 = NULL; } #endif
return dwReturn; }
///////////////////////////////////////////////////////////////////
//
// Function: CAccessEntryList:InitFromWin32ACL
//
// Traverses a Win32ACL and copies ACEs into our list.
//
// Inputs:
// PACL pACL - ACL to add ACEs to.
// BYTE bACEFilter - ACEs to filter on.
// bool fLookup - whether the sids should be
// resolved to their domain and name values.
//
// Outputs:
// None.
//
// Returns:
// BOOL Success/Failure
//
// Comments:
//
// If bACEFilter is not ALL_ACE_TYPES, then we will only copy out
// ACEs of the specified type.
//
///////////////////////////////////////////////////////////////////
DWORD CAccessEntryList::InitFromWin32ACL( PACL pWin32ACL, BYTE bACEFilter /* = ALL_ACE_TYPES */, bool fLookup /* = true */ ) { DWORD dwError = 0; ACE_HEADER* pACEHeader = NULL; DWORD dwAceIndex = 0; BOOL fGotACE = FALSE; DWORD dwMask = 0; PSID psid = NULL; GUID *pguidObjType = NULL; GUID *pguidInhObjType = NULL;
// Empty out
Clear();
// For each ACE we find, get the values necessary to initialize our
// CAccessEntries
do { fGotACE = ::GetAce( pWin32ACL, dwAceIndex, (LPVOID*) &pACEHeader );
if ( fGotACE ) { switch ( pACEHeader->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: { ACCESS_ALLOWED_ACE* pACE = (ACCESS_ALLOWED_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; } break;
case ACCESS_DENIED_ACE_TYPE: { ACCESS_DENIED_ACE* pACE = (ACCESS_DENIED_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; } break;
case SYSTEM_AUDIT_ACE_TYPE: { SYSTEM_AUDIT_ACE* pACE = (SYSTEM_AUDIT_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; } break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: { ACCESS_ALLOWED_OBJECT_ACE* pACE = (ACCESS_ALLOWED_OBJECT_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; if(pACE->Flags & ACE_OBJECT_TYPE_PRESENT) { try { pguidObjType = new GUID; if(pguidObjType != NULL) { memcpy(pguidObjType,&pACE->ObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidObjType != NULL) { delete pguidObjType; pguidObjType = NULL; } throw; } } if(pACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { try { pguidInhObjType = new GUID; if(pguidInhObjType != NULL) { memcpy(pguidInhObjType,&pACE->InheritedObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidInhObjType != NULL) { delete pguidInhObjType; pguidInhObjType = NULL; } throw; } } } break; /********************************* type not yet supported under w2k ********************************************
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: { ACCESS_ALLOWED_COMPOUND_ACE_TYPE* pACE = (ACCESS_ALLOWED_COMPOUND_ACE_TYPE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; } break; ***************************************************************************************************************/ case ACCESS_DENIED_OBJECT_ACE_TYPE: { ACCESS_DENIED_OBJECT_ACE* pACE = (ACCESS_DENIED_OBJECT_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; if(pACE->Flags & ACE_OBJECT_TYPE_PRESENT) { try { pguidObjType = new GUID; if(pguidObjType != NULL) { memcpy(pguidObjType,&pACE->ObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidObjType != NULL) { delete pguidObjType; pguidObjType = NULL; } throw; } } if(pACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { try { pguidInhObjType = new GUID; if(pguidInhObjType != NULL) { memcpy(pguidInhObjType,&pACE->InheritedObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidInhObjType != NULL) { delete pguidInhObjType; pguidInhObjType = NULL; } throw; } } } break;
case SYSTEM_AUDIT_OBJECT_ACE_TYPE: { SYSTEM_AUDIT_OBJECT_ACE* pACE = (SYSTEM_AUDIT_OBJECT_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; if(pACE->Flags & ACE_OBJECT_TYPE_PRESENT) { try { pguidObjType = new GUID; if(pguidObjType != NULL) { memcpy(pguidObjType,&pACE->ObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidObjType != NULL) { delete pguidObjType; pguidObjType = NULL; } throw; } } if(pACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { try { pguidInhObjType = new GUID; if(pguidInhObjType != NULL) { memcpy(pguidInhObjType,&pACE->InheritedObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidInhObjType != NULL) { delete pguidInhObjType; pguidInhObjType = NULL; } throw; } } } break;
/********************************* type not yet supported under w2k ********************************************
case SYSTEM_ALARM_ACE_TYPE: { SYSTEM_ALARM_ACE* pACE = (SYSTEM_ALARM_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; } break; /********************************* type not yet supported under w2k ********************************************/
/********************************* type not yet supported under w2k ********************************************
case SYSTEM_ALARM_OBJECT_ACE_TYPE: { SYSTEM_ALARM_OBJECT_ACE* pACE = (SYSTEM_ALARM_OBJECT_ACE*) pACEHeader; psid = (PSID) &pACE->SidStart; dwMask = pACE->Mask; if(pACE->Flags & ACE_OBJECT_TYPE_PRESENT) { try { pguidObjType = new GUID; if(pguidObjType != NULL) { memcpy(pguidObjType,&pACE->ObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidObjType != NULL) { delete pguidObjType; pguidObjType = NULL; } throw; } } if(pACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { try { pguidInhObjType = new GUID; if(pguidInhObjType != NULL) { memcpy(pguidInhObjType,&pACE->InheritedObjectType, sizeof(GUID)); } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } catch(...) { if(pguidInhObjType != NULL) { delete pguidInhObjType; pguidInhObjType = NULL; } throw; } } } break; /********************************* type not yet supported under w2k ********************************************/
default: { ASSERT_BREAK(0); // BAD, we don't know what this is!
dwError = ERROR_INVALID_PARAMETER; } }
// We must have no errors, and the filter MUST accept all ACE Types
// or the ACE Type must match the filter.
if ( ERROR_SUCCESS == dwError && ( ALL_ACE_TYPES == bACEFilter || bACEFilter == pACEHeader->AceType ) ) {
// We merge duplicate entries during initialization
if ( !AppendNoDup( psid, pACEHeader->AceType, pACEHeader->AceFlags, dwMask, pguidObjType, pguidInhObjType, true, // Merge flag
fLookup ) ) // whether to resolve domain and name of sid
{ dwError = ERROR_NOT_ENOUGH_MEMORY; }
}
} // IF fGot ACE
// Get the next ACE
++dwAceIndex;
} while ( fGotACE && ERROR_SUCCESS == dwError );
return dwError; }
void CAccessEntryList::DumpAccessEntryList(LPCWSTR wstrFilename) { Output(L"AccessEntryList contents follow...", wstrFilename);
// Run through the list, outputting each...
CAccessEntry* pACE = NULL; ACLPOSITION pos;
if(BeginEnum(pos)) { while((pACE = GetNext(pos)) != NULL) { pACE->DumpAccessEntry(wstrFilename); } EndEnum(pos); } }
|