/*****************************************************************************/ /* Copyright (c) 1999-2002 Microsoft Corporation, All Rights Reserved / /*****************************************************************************/ /* * CSACL.cpp - implementation file for CAccessEntry class. */ #include "precomp.h" #include "aclapi.h" #include "AccessEntryList.h" #include "SACL.h" #include #include "wbemnetapi32.h" #include "SecUtils.h" /////////////////////////////////////////////////////////////////// // // Function: CSACL::CSACL // // Default class constructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSACL::CSACL( void ) : m_SACLSections(NULL) { } /////////////////////////////////////////////////////////////////// // // Function: CSACL::~CSACL // // Class destructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSACL::~CSACL( void ) { Clear(); } /////////////////////////////////////////////////////////////////// // // Function: CSCL::Init // // Initializes the SACL member list. // // Inputs: // // // Outputs: // None. // // Returns: // DWORD Success/Failure // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CSACL::Init(PACL a_pSACL) { DWORD t_dwRes = E_FAIL; if(a_pSACL == NULL) { return ERROR_INVALID_PARAMETER; } if(m_SACLSections != NULL) { delete m_SACLSections; m_SACLSections = NULL; } try { m_SACLSections = new CAccessEntryList; } catch(...) { if(m_SACLSections != NULL) { delete m_SACLSections; m_SACLSections = NULL; } throw; } t_dwRes = m_SACLSections->InitFromWin32ACL(a_pSACL); return t_dwRes; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::AddSACLEntry // // Adds a System Audit entry to the ACL. By default, these go // to the front of the list. // // Inputs: // PSID psid - PSID // DWORD dwAccessMask - Access Mask // BYTE bAceFlags - Flags // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // /////////////////////////////////////////////////////////////////// bool CSACL::AddSACLEntry( PSID psid, SACLTYPE SaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = true; BYTE bACEType; // Sid must be valid if ( (psid != NULL) && IsValidSid( psid ) ) { switch(SaclType) { case ENUM_SYSTEM_AUDIT_ACE_TYPE: bACEType = SYSTEM_AUDIT_ACE_TYPE; break; /********************************* type not yet supported under w2k ******************************************** case ENUM_SYSTEM_ALARM_ACE_TYPE: bACEType = SYSTEM_ALARM_ACE_TYPE; break; /********************************* type not yet supported under w2k ********************************************/ case ENUM_SYSTEM_AUDIT_OBJECT_ACE_TYPE: bACEType = SYSTEM_AUDIT_OBJECT_ACE_TYPE; break; /********************************* type not yet supported under w2k ******************************************** case ENUM_SYSTEM_ALARM_OBJECT_ACE_TYPE: bACEType = SYSTEM_ALARM_OBJECT_ACE_TYPE; break; /********************************* type not yet supported under w2k ********************************************/ default: fReturn = false; break; } // We will overwrite the Access Mask of a duplicate entry. if(fReturn) { if(m_SACLSections == NULL) { try { m_SACLSections = new CAccessEntryList; } catch(...) { if(m_SACLSections != NULL) { delete m_SACLSections; m_SACLSections = NULL; } throw; } if(m_SACLSections != NULL) { fReturn = m_SACLSections->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid ); } } else { fReturn = m_SACLSections->AppendNoDup( psid, bACEType, bAceFlags, dwAccessMask, pguidObjGuid, pguidInhObjGuid ); } } } else { fReturn = true; } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::RemoveSACLEntry // // Removes a system audit 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 CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, DWORD dwAccessMask, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = false; // We need an ACE to compare CAccessEntry ACE( &sid, SYSTEM_AUDIT_ACE_TYPE, bAceFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask ); ACLPOSITION pos; if ( m_SACLSections->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ; CAccessEntry* pACE = NULL; try { // For loop will try to find a matching ACE in the list for ( CAccessEntry* pACE = m_SACLSections->GetNext( pos ); NULL != pACE || ACE == *pACE; pACE = m_SACLSections->GetNext( pos ) ); } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } // If we got a match, delete the ACE. if ( NULL != pACE ) { m_SACLSections->Remove( pACE ); delete pACE; fReturn = true; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::RemoveSACLEntry // // Removes a system audit 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 CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, BYTE bAceFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid ) { bool fReturn = false; // We need an ACE to compare ACLPOSITION pos; if ( m_SACLSections->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ; // For loop will try to find a matching ACE in the list CAccessEntry* pACE = NULL; try { for ( pACE = m_SACLSections->GetNext( pos ); NULL != pACE; pACE = m_SACLSections->GetNext( pos ) ) { CAccessEntry caeTemp(sid, SaclType, bAceFlags, pguidObjGuid, pguidInhObjGuid, pACE->GetAccessMask()); // If we got a match, delete the ACE. if (*pACE == caeTemp) { m_SACLSections->Remove( pACE ); fReturn = true; break; } delete pACE; } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::RemoveSACLEntry // // Removes a system audit entry from the ACL. // // Inputs: // CSid& sid - PSID // DWORD dwIndex - Index to remove. // // Outputs: // None. // // Returns: // BOOL Success/Failure // // Comments: // // Removes dwIndex entry matching sid. // /////////////////////////////////////////////////////////////////// bool CSACL::RemoveSACLEntry( CSid& sid, SACLTYPE SaclType, DWORD dwIndex /*= 0*/ ) { bool fReturn = false; // We need an ACE to compare CSid tempsid; ACLPOSITION pos; DWORD dwCtr = 0; if ( m_SACLSections->BeginEnum( pos ) ) { ON_BLOCK_EXIT_OBJ ( *m_SACLSections, CAccessEntryList::EndEnum, ByRef ( pos ) ) ; // For each ACE we find, see if it is an SYSTEM_AUDIT_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_SACLSections->GetNext( pos ); NULL != pACE; pACE = m_SACLSections->GetNext( pos ) ) { if ( SYSTEM_AUDIT_ACE_TYPE == pACE->GetACEType() ) { pACE->GetSID( tempsid ); if ( sid == tempsid ) { if ( dwCtr == dwIndex ) { m_SACLSections->Remove( pACE ); fReturn = true; break; } else { ++dwCtr; } } delete pACE; } } } catch(...) { if(pACE != NULL) { delete pACE; pACE = NULL; } throw; } } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::Find // // Finds the specified ace in the dacl // // // Returns: // true if found it. // // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CSACL::Find( const CSid& sid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { return m_SACLSections->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } /////////////////////////////////////////////////////////////////// // // Function: CSACL::Find // // Finds the specified ace in the dacl // // // Returns: // true if found it. // // Comments: // // Helps support NT 5 canonical order in DACLs. // /////////////////////////////////////////////////////////////////// bool CSACL::Find( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace ) { return m_SACLSections->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace ); } /////////////////////////////////////////////////////////////////// // // Function: CSACL::::ConfigureSACL // // Configures a Win32 PACL with SACL information. // // Inputs: // None. // // Outputs: // PACL& pSacl - Pointer to a SACL. // // Returns: // DWORD ERROR_SUCCESS if successful. // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CSACL::ConfigureSACL( PACL& pSacl ) { DWORD dwReturn = ERROR_SUCCESS, dwSACLLength = 0; if ( CalculateSACLSize( &dwSACLLength ) ) { if ( 0 != dwSACLLength ) { pSacl = NULL; try { pSacl = (PACL) malloc( dwSACLLength ); if ( NULL != pSacl ) { if ( !InitializeAcl( (PACL) pSacl, dwSACLLength, ACL_REVISION ) ) { dwReturn = ::GetLastError(); } } // If NULL != pSACL } catch(...) { if(pSacl != NULL) { free(pSacl); pSacl = NULL; } throw; } } // If 0 != dwSACLLength } // If Calcaulate SACL Size else { dwReturn = ERROR_INVALID_PARAMETER; // One or more of the SACLs is bad } if ( ERROR_SUCCESS == dwReturn ) { dwReturn = FillSACL( pSacl ); } if ( ERROR_SUCCESS != dwReturn ) { free( pSacl ); pSacl = NULL; } return dwReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::::CalculateSACLSize // // Obtains the size necessary to populate a SACL. // // Inputs: // None. // // Outputs: // LPDWORD pdwSACLLength - Calculated Length. // // Returns: // BOOL TRUE/FALSE // // Comments: // /////////////////////////////////////////////////////////////////// BOOL CSACL::CalculateSACLSize( LPDWORD pdwSACLLength ) { BOOL fReturn = FALSE; *pdwSACLLength = 0; if ( NULL != m_SACLSections ) { fReturn = m_SACLSections->CalculateWin32ACLSize( pdwSACLLength ); } return fReturn; } /////////////////////////////////////////////////////////////////// // // Function: CSACL::FillSACL // // Fills out a SACL. // // Inputs: // PACL pSacl - Sacl to fill out. // // Outputs: // None. // // Returns: // BOOL TRUE/FALSE // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CSACL::FillSACL( PACL pSACL ) { DWORD dwReturn = ERROR_SUCCESS; if ( NULL != m_SACLSections ) { dwReturn = m_SACLSections->FillWin32ACL( pSACL ); } return dwReturn; } void CSACL::Clear() { if ( NULL != m_SACLSections ) { delete m_SACLSections; m_SACLSections = NULL; } } bool CSACL::GetMergedACL ( CAccessEntryList& a_aclIn ) { // Actually somewhat of a misnomer for the time being (until the // day when the sacl ordering matters, and we have multiple sections // as we do in dacl for that reason). We just hand back our // member acl, if it is not null: bool fRet = false; if(m_SACLSections != NULL) { fRet = a_aclIn.Copy(*m_SACLSections); } return fRet; } void CSACL::DumpSACL(LPCWSTR wstrFilename) { Output(L"SACL contents follow...", wstrFilename); if(m_SACLSections != NULL) { m_SACLSections->DumpAccessEntryList(wstrFilename); } }