You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
643 lines
14 KiB
643 lines
14 KiB
/*****************************************************************************/
|
|
/* 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 <accctrl.h>
|
|
#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);
|
|
}
|
|
}
|
|
|