Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1485 lines
41 KiB

/*****************************************************************************/
/* 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 <accctrl.h>
#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);
}
}