/*****************************************************************************/ /* Copyright (c) 1999-2002 Microsoft Corporation, All Rights Reserved / /*****************************************************************************/ /* * CAccessEntry.cpp - implementation file for CAccessEntry class. */ #include "precomp.h" #include "AccessEntryList.h" #include "aclapi.h" #include "DACL.h" #include #include "wbemnetapi32.h" #include "SecUtils.h" /////////////////////////////////////////////////////////////////// // // Function: CDACL::CDACL // // Default class constructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CDACL::CDACL( void ) { for(short s = 0; s < NUM_DACL_TYPES; s++) { m_rgDACLSections[s] = NULL; } } /////////////////////////////////////////////////////////////////// // // Function: CDACL::~CDACL // // Class destructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CDACL::~CDACL( void ) { Clear(); } /////////////////////////////////////////////////////////////////// // // Function: CDACL::Init // // Initializes the DACL member lists. // // Inputs: // // // Outputs: // None. // // Returns: // DWORD Success/Failure // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CDACL::Init(PACL a_pDACL) { DWORD t_dwRes = E_FAIL; if(a_pDACL == NULL) { return ERROR_INVALID_PARAMETER; } CAccessEntryList t_aclTemp; t_dwRes = t_aclTemp.InitFromWin32ACL(a_pDACL); if(t_dwRes == ERROR_SUCCESS) { if(!SplitIntoCanonicalSections(t_aclTemp)) { for(short s = 0; s < NUM_DACL_TYPES; s++) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } t_dwRes = ERROR_SUCCESS; } } return t_dwRes; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::AddDACLEntry // // Adds an access allowed entry to the ACL. By default, these go // to the end of the list. // // Inputs: // PSID psid - PSID // DWORD dwAccessMask - Access Mask // BYTE bAceFlags - Flags // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // /////////////////////////////////////////////////////////////////// bool CDACL::AddDACLEntry( PSID psid, DACLTYPE DaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = true; BYTE bACEType; // Sid must be valid if ( (psid != NULL) && IsValidSid( psid ) ) { switch(DaclType) { case ENUM_ACCESS_DENIED_ACE_TYPE: bACEType = ACCESS_DENIED_ACE_TYPE; break; case ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE: bACEType = ACCESS_DENIED_OBJECT_ACE_TYPE; break; case ENUM_ACCESS_ALLOWED_ACE_TYPE: bACEType = ACCESS_ALLOWED_ACE_TYPE; break; case ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: bACEType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE; break; case ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE: bACEType = ACCESS_ALLOWED_OBJECT_ACE_TYPE; break; case ENUM_INH_ACCESS_DENIED_ACE_TYPE: bACEType = ACCESS_DENIED_ACE_TYPE; break; case ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE: bACEType = ACCESS_DENIED_OBJECT_ACE_TYPE; break; case ENUM_INH_ACCESS_ALLOWED_ACE_TYPE: bACEType = ACCESS_ALLOWED_ACE_TYPE; break; case ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: bACEType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE; break; case ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE: bACEType = ACCESS_ALLOWED_OBJECT_ACE_TYPE; break; default: fReturn = false; break; } if(fReturn) { if(m_rgDACLSections[DaclType] == NULL) { try { m_rgDACLSections[DaclType] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[DaclType] != NULL) { delete m_rgDACLSections[DaclType]; m_rgDACLSections[DaclType] = NULL; } throw; } if(m_rgDACLSections[DaclType] != NULL) { fReturn = m_rgDACLSections[DaclType]->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid ); } } else { fReturn = m_rgDACLSections[DaclType]->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid ); } } } else { fReturn = false; } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::RemoveDACLEntry // // Removes an access allowed entry from the ACL. // // Inputs: // CSID& sid - PSID // DWORD dwAccessMask - Access Mask // BYTE bAceFlags - Flags // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // // Removed entry MUST match the supplied parameters. // /////////////////////////////////////////////////////////////////// bool CDACL::RemoveDACLEntry( CSid& sid, DACLTYPE DaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = false; // We need an ACE to compare CAccessEntry ACE( &sid, DaclType, bAceFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask); ACLPOSITION pos; if ( m_rgDACLSections[DaclType]->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_rgDACLSections [ DaclType ], CAccessEntryList::EndEnum, ByRef ( pos ) ) ; // For loop will try to find a matching ACE in the list CAccessEntry* pACE = NULL; try { for ( pACE = m_rgDACLSections[DaclType]->GetNext( pos ); NULL != pACE && !(ACE == *pACE); pACE = m_rgDACLSections[DaclType]->GetNext( pos ) ); // If we got a match, delete the ACE. if ( NULL != pACE ) { m_rgDACLSections[DaclType]->Remove( pACE ); delete pACE; fReturn = true; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::RemoveDACLEntry // // Removes an access allowed entry from the ACL. // // Inputs: // CSID& sid - PSID // BYTE bAceFlags - Flags // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // // Removed entry MUST match the supplied parameters. // /////////////////////////////////////////////////////////////////// bool CDACL::RemoveDACLEntry( CSid& sid, DACLTYPE DaclType, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = false; // We need an ACE to compare ACLPOSITION pos; if ( m_rgDACLSections[DaclType]->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_rgDACLSections [ DaclType ], CAccessEntryList::EndEnum, ByRef ( pos ) ) ; // For loop will try to find a matching ACE in the list CAccessEntry* pACE = NULL; try { for ( CAccessEntry* pACE = m_rgDACLSections[DaclType]->GetNext( pos ); NULL != pACE; pACE = m_rgDACLSections[DaclType]->GetNext( pos ) ) { CAccessEntry caeTemp(sid, DaclType, bAceFlags, pguidObjGuid, pguidInhObjGuid, pACE->GetAccessMask()); // If we got a match, delete the ACE. if (*pACE == caeTemp) { m_rgDACLSections[DaclType]->Remove( pACE ); fReturn = true; break; } delete pACE; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::RemoveDACLEntry // // Removes an access allowed entry from the ACL. // // Inputs: // CSID& sid - PSID // DWORD dwIndex - Index to remove. // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // // Removed entry MUST be dwIndex entry matching CSid. // /////////////////////////////////////////////////////////////////// bool CDACL::RemoveDACLEntry( CSid& sid, DACLTYPE DaclType, DWORD dwIndex /*= 0*/ ) { bool fReturn = false; // We need an ACE to compare CSid tempsid; ACLPOSITION pos; DWORD dwCtr = 0; if ( m_rgDACLSections[DaclType]->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_rgDACLSections [ DaclType ], CAccessEntryList::EndEnum, ByRef ( pos ) ) ; // For each ACE we find, see if it is an ACCESS_ALLOWED_ACE_TYPE, // and if the Sid matches the one passed in. If it does, increment // the counter, then if we're on the right index remove the ACE, // delete it and quit. CAccessEntry* pACE = NULL; try { for ( pACE = m_rgDACLSections[DaclType]->GetNext( pos ); NULL != pACE; pACE = m_rgDACLSections[DaclType]->GetNext( pos ) ) { if ( DaclType == pACE->GetACEType() ) { pACE->GetSID( tempsid ); if ( sid == tempsid ) { if ( dwCtr == dwIndex ) { m_rgDACLSections[DaclType]->Remove( pACE ); fReturn = true; break; } else { ++dwCtr; } } delete pACE; } } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::Find // // Finds the specified ace in the dacl // // // Returns: // true if found it. // // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CDACL::Find( const CSid& sid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { bool fReturn = false; switch(bACEType) { case ACCESS_DENIED_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_DENIED_OBJECT_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_OBJECT_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } default: { fReturn = false; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::Find // // Finds the specified ace in the dacl // // // Returns: // true if found it. // // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CDACL::Find( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { bool fReturn = false; switch(bACEType) { case ACCESS_DENIED_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_DENIED_OBJECT_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } case ACCESS_ALLOWED_OBJECT_ACE_TYPE: { if(bACEFlags & INHERITED_ACE) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } else { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } } break; } default: { fReturn = false; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::ConfigureDACL // // Configures a Win32 PACL with DACL information, maintaining // proper canonical order. // // Inputs: // None. // // Outputs: // PACL& pDacl - Pointer to a DACL. // // Returns: // DWORD ERROR_SUCCESS if successful. // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CDACL::ConfigureDACL( PACL& pDacl ) { DWORD dwReturn = ERROR_SUCCESS, dwDaclLength = 0; // Since we actually fake a NULL DACL with full control access for everyone. // If that's what we have, then we have what we call a NULL DACL, so we // shouldn't allocate a PACL. if ( !IsNULLDACL() ) { if ( CalculateDACLSize( &dwDaclLength ) ) { if ( 0 != dwDaclLength ) { pDacl = NULL; try { pDacl = (PACL) malloc( dwDaclLength ); if ( NULL != pDacl ) { if ( !InitializeAcl( (PACL) pDacl, dwDaclLength, ACL_REVISION ) ) { dwReturn = ::GetLastError(); } } // If NULL != pDacl } catch(...) { if(pDacl != NULL) { free(pDacl); pDacl = NULL; } throw; } } // If 0 != dwDaclLength else // we have an empty dacl { pDacl = NULL; try { pDacl = (PACL) malloc( sizeof(ACL) ); if ( NULL != pDacl ) { if ( !InitializeAcl( (PACL) pDacl, sizeof(ACL), ACL_REVISION ) ) { dwReturn = ::GetLastError(); } } // If NULL != pDacl } catch(...) { if(pDacl != NULL) { free(pDacl); pDacl = NULL; } throw; } } } // If Calcaulate DACL Size else { dwReturn = ERROR_INVALID_PARAMETER; // One or more of the DACLs is bad } if ( ERROR_SUCCESS == dwReturn ) { dwReturn = FillDACL( pDacl ); } if ( ERROR_SUCCESS != dwReturn ) { free( pDacl ); pDacl = NULL; } } // IF !IsNULLDACL return dwReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::CalculateDACLSize // // Obtains the size necessary to populate a DACL. // // Inputs: // None. // // Outputs: // LPDWORD pdwDaclLength - Calculated Length. // // Returns: // BOOL TRUE/FALSE // // Comments: // /////////////////////////////////////////////////////////////////// BOOL CDACL::CalculateDACLSize( LPDWORD pdwDaclLength ) { BOOL fReturn = TRUE; *pdwDaclLength = 0; for(short s = 0; s < NUM_DACL_TYPES && fReturn; s++) { if(m_rgDACLSections[s] != NULL) { fReturn = m_rgDACLSections[s]->CalculateWin32ACLSize( pdwDaclLength ); } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::FillDACL // // Fills out a DACL, maintaining proper canonical order. // // Inputs: // PACL pDacl - Dacl to fill out. // // Outputs: // None. // // Returns: // BOOL TRUE/FALSE // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CDACL::FillDACL( PACL pDacl ) { DWORD dwReturn = E_FAIL; // For NT 5, we need to split out Inherited ACEs and add those in after the // current ones (which override). The real trick here, is that the canonical // order of Access Denied, Access Denied Object, Access Allowed, Access Allowed Compound, Access Allowed Object, // Inherited Access Denied, Inherrited Access Denied Object, Inherited Access Allowed, Inherrited Access Allowed Compound, // and Inherrited Access Allowed Object must be maintained. // For prior versions, the only canonical order is Access Denied followed // by Access Allowed. // Create a working dacl CAccessEntryList t_daclCombined; ReassembleFromCanonicalSections(t_daclCombined); dwReturn = t_daclCombined.FillWin32ACL(pDacl); return dwReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::SplitIntoCanonicalSections // // Splits a DACL by into its canonical parts. // // Inputs: accessentrylist to split up. Results stored with // this CDACL. // // // Returns: // None. // // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CDACL::SplitIntoCanonicalSections ( CAccessEntryList& a_aclIn ) { for(short s = 0; s < NUM_DACL_TYPES; s++) { if(m_rgDACLSections[s] != NULL) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } } CAccessEntryList t_aclTemp; bool fRet = false; fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_DENIED_ACE_TYPE, false); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_DENIED_OBJECT_ACE_TYPE, false); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_ACE_TYPE, false); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]!= NULL) { delete m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_COMPOUND_ACE_TYPE, false); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_OBJECT_ACE_TYPE, false); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_DENIED_ACE_TYPE, true); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE]; m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_DENIED_OBJECT_ACE_TYPE, true); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE]; m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_ACE_TYPE, true); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE]; m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_COMPOUND_ACE_TYPE, true); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]; m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } if(fRet) { fRet = t_aclTemp.CopyByACEType(a_aclIn, ACCESS_ALLOWED_OBJECT_ACE_TYPE, true); if(!t_aclTemp.IsEmpty()) { try { m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE]; m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] = NULL; } throw; } m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE]->Copy(t_aclTemp); t_aclTemp.Clear(); } } return fRet; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::ReassembleFromCanonicalSections // // Reassembles a DACL by from its canonical parts. // // Inputs: reference to accessentrylist that gets built up. // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CDACL::ReassembleFromCanonicalSections ( CAccessEntryList& a_aclIn ) { bool fRet = true; // and reassemble a new one (we rely on the fact that the enumeration // was layed out in the proper order) ... for(short s = 0; s < NUM_DACL_TYPES; s++) { if(m_rgDACLSections[s] != NULL) { fRet = a_aclIn.AppendList(*m_rgDACLSections[s]); } } return fRet; } bool CDACL::PutInNT5CanonicalOrder() { bool t_fRet = false; CAccessEntryList t_ael; if(SplitIntoCanonicalSections(t_ael)) { t_fRet = ReassembleFromCanonicalSections(t_ael); } return t_fRet; } bool CDACL::GetMergedACL ( CAccessEntryList& a_aclIn ) { return ReassembleFromCanonicalSections(a_aclIn); } void CDACL::Clear() { for(short s = 0; s < NUM_DACL_TYPES; s++) { if(m_rgDACLSections[s] != NULL) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } } } bool CDACL::CopyDACL ( CDACL& dacl ) { bool fRet = true; Clear(); for(short s = 0; s < NUM_DACL_TYPES && fRet; s++) { if(dacl.m_rgDACLSections[s] != NULL) { try { m_rgDACLSections[s] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[s] != NULL) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } throw; } if(m_rgDACLSections[s] != NULL) { fRet = m_rgDACLSections[s]->Copy(*(dacl.m_rgDACLSections[s])); } else { fRet = false; } } } return fRet; } bool CDACL::AppendDACL ( CDACL& dacl ) { bool fRet = true; for(short s = 0; s < NUM_DACL_TYPES && fRet; s++) { if(dacl.m_rgDACLSections[s] != NULL) { if(m_rgDACLSections[s] == NULL) { try { m_rgDACLSections[s] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[s] != NULL) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } throw; } } if(m_rgDACLSections[s] != NULL) { fRet = m_rgDACLSections[s]->AppendList(*(dacl.m_rgDACLSections[s])); } else { fRet = false; } } } return fRet; } /////////////////////////////////////////////////////////////////// // // Function: CSecurityDescriptor::IsNULLDACL // // Checks our DACL Lists to see if we have a NULL DACL. Which // means that all our lists are NULL, except for the // ACCESS_ALLOWED_ACE_TYPE list, which will have exactly one entry // in it - namely, an ACE for Everyone. // // Inputs: // None. // // Outputs: // None. // // Returns: // BOOL TRUE/FALSE // // Comments: // // Remember, a NULL DACL is the same as "Everyone" has Full Control, // so if a single Access Allowed entry exists that meets these // criteria, we consider ourselves to be NULL. // /////////////////////////////////////////////////////////////////// bool CDACL::IsNULLDACL() { bool fReturn = false; // We have a NULL DACL if all the elements of our DACL array // are NULL if (m_rgDACLSections[ENUM_ACCESS_DENIED_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_INH_ACCESS_DENIED_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE] == NULL && m_rgDACLSections[ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE] == NULL) { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] != NULL) { // There can be only one. if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->NumEntries() == 1) { CSid sid(_T("Everyone")); CAccessEntry ace; // Get the entry and check that it is "Everyone" with // Full Control and no flags if (m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->GetAt( 0, ace ) ) { CSid aceSID; ace.GetSID( aceSID ); fReturn = ( sid == aceSID && ace.GetAccessMask() == AllAccessMask() && ace.GetACEFlags() == 0 ); } } // IF only one entry } } // If we had entries in other lists, no go. return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::IsEmpty // // Checks if our various lists are empty. // // Inputs: // None. // // Outputs: // None. // // Returns: // bool true if we have at least one entry in at // least one of our lists. // // Comments: // // /////////////////////////////////////////////////////////////////// bool CDACL::IsEmpty() { bool fIsEmpty = true; for(short s = 0; s < NUM_DACL_TYPES && fIsEmpty; s++) { if(m_rgDACLSections[s] != NULL) { fIsEmpty = m_rgDACLSections[s]->IsEmpty(); } } return fIsEmpty; } /////////////////////////////////////////////////////////////////// // // Function: CDACL::CreateNullDacl // // NULLs out our DACL Lists except for the ACCESS_ALLOWED_ACE_TYPE // list, which it clears, then enters an Everybody ace into. // // Inputs: // None. // // Outputs: // None. // // Returns: // BOOL TRUE/FALSE // // Comments: // // Remember, an empty DACL is different from a NULL DACL, in that // empty means nobody has access and NULL means everyone has // full control. // /////////////////////////////////////////////////////////////////// bool CDACL::CreateNullDACL() { bool fReturn = false; // Clear out our DACLs first... for(short s = 0; s < NUM_DACL_TYPES; s++) { if(m_rgDACLSections[s] != NULL) { delete m_rgDACLSections[s]; m_rgDACLSections[s] = NULL; } } // then allocate an ACCESS_ALLOWED_ACE_TYPE dacl... try { m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] = new CAccessEntryList; } catch(...) { if(m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] != NULL) { delete m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]; m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] = NULL; } throw; } // then fake a null dacl by adding an Everyone entry... if (m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE] != NULL) { CSid sid( _T("Everyone") ); if(sid.IsOK() && sid.IsValid()) { fReturn = m_rgDACLSections[ENUM_ACCESS_ALLOWED_ACE_TYPE]->AppendNoDup(sid.GetPSid(), ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, AllAccessMask(), NULL, NULL, false, false); } } return fReturn; } DWORD CDACL::AllAccessMask() { return GENERIC_ALL; //return 0x01FFFFFF; } void CDACL::DumpDACL(LPCWSTR wstrFilename) { CAccessEntryList aelCombo; Output(L"DACL contents follow...", wstrFilename); if(ReassembleFromCanonicalSections(aelCombo)) { aelCombo.DumpAccessEntryList(wstrFilename); } }