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.
2058 lines
46 KiB
2058 lines
46 KiB
/*****************************************************************************/
|
|
|
|
/* Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved /
|
|
/*****************************************************************************/
|
|
|
|
/*
|
|
* SecurityDescriptor.cpp - implementation file for CSecurityDescriptor 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 "AccessEntry.h" // CAccessEntry class
|
|
#include "AccessEntryList.h"
|
|
#include "aclapi.h"
|
|
#include "DACL.h" // CDACL class
|
|
#include "SACL.h" // CSACL class
|
|
|
|
|
|
#include "SecurityDescriptor.h"
|
|
#include "TokenPrivilege.h"
|
|
#include "AdvApi32Api.h"
|
|
#include "accctrl.h"
|
|
#include "wbemnetapi32.h"
|
|
#include "SecUtils.h"
|
|
|
|
|
|
/*
|
|
* This constructor is the default
|
|
*/
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::CSecurityDescriptor
|
|
//
|
|
// Default class constructor.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CSecurityDescriptor::CSecurityDescriptor()
|
|
: m_pOwnerSid( NULL ),
|
|
m_pGroupSid( NULL ),
|
|
m_pSACL( NULL ),
|
|
m_pDACL(NULL),
|
|
m_fOwnerDefaulted( false ),
|
|
m_fGroupDefaulted( false ),
|
|
m_fDACLDefaulted( false ),
|
|
m_fSACLDefaulted( false ),
|
|
m_fDaclAutoInherited( false ),
|
|
m_fSaclAutoInherited( false ),
|
|
m_SecurityDescriptorControl(0)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::CSecurityDescriptor
|
|
//
|
|
// Alternate class constructor.
|
|
//
|
|
// Inputs:
|
|
// PSECURITY_DESCRIPTOR psd - descriptor to initialize
|
|
// from.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CSecurityDescriptor::CSecurityDescriptor( PSECURITY_DESCRIPTOR psd )
|
|
: m_pOwnerSid( NULL ),
|
|
m_pGroupSid( NULL ),
|
|
m_pSACL( NULL ),
|
|
m_pDACL(NULL),
|
|
m_fOwnerDefaulted( false ),
|
|
m_fGroupDefaulted( false ),
|
|
m_fDACLDefaulted( false ),
|
|
m_fSACLDefaulted( false ),
|
|
m_fDaclAutoInherited( false ),
|
|
m_fSaclAutoInherited( false ),
|
|
m_SecurityDescriptorControl(0)
|
|
{
|
|
InitSecurity( psd );
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::CSecurityDescriptor
|
|
//
|
|
// Alternate class constructor.
|
|
//
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
CSecurityDescriptor::CSecurityDescriptor
|
|
(
|
|
CSid* a_psidOwner,
|
|
bool a_fOwnerDefaulted,
|
|
CSid* a_psidGroup,
|
|
bool a_fGroupDefaulted,
|
|
CDACL* a_pDacl,
|
|
bool a_fDaclDefaulted,
|
|
bool a_fDaclAutoInherited,
|
|
CSACL* a_pSacl,
|
|
bool a_fSaclDefaulted,
|
|
bool a_fSaclAutoInherited
|
|
)
|
|
: m_pOwnerSid( NULL ),
|
|
m_pGroupSid( NULL ),
|
|
m_pSACL( NULL ),
|
|
m_pDACL(NULL),
|
|
m_fOwnerDefaulted( false ),
|
|
m_fGroupDefaulted( false ),
|
|
m_fDACLDefaulted( false ),
|
|
m_fSACLDefaulted( false ),
|
|
m_fDaclAutoInherited( false ),
|
|
m_fSaclAutoInherited( false ),
|
|
m_SecurityDescriptorControl(0)
|
|
{
|
|
try
|
|
{
|
|
bool fRet = true;
|
|
if(a_psidOwner != NULL )
|
|
{
|
|
fRet = (SetOwner(*a_psidOwner) == ERROR_SUCCESS);
|
|
if(fRet)
|
|
{
|
|
m_fOwnerDefaulted = a_fOwnerDefaulted;
|
|
}
|
|
}
|
|
|
|
if(fRet)
|
|
{
|
|
if(a_psidGroup != NULL )
|
|
{
|
|
fRet = (SetGroup(*a_psidGroup) == ERROR_SUCCESS);
|
|
if(fRet)
|
|
{
|
|
m_fGroupDefaulted = a_fGroupDefaulted;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fRet)
|
|
{
|
|
// Handle the DACL
|
|
if(a_pDacl != NULL)
|
|
{
|
|
fRet = InitDACL(a_pDacl);
|
|
if(fRet)
|
|
{
|
|
m_fDACLDefaulted = a_fDaclDefaulted;
|
|
m_fDaclAutoInherited = a_fDaclAutoInherited;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle the SACL
|
|
if(fRet)
|
|
{
|
|
if(a_pSacl != NULL)
|
|
{
|
|
fRet = InitSACL(a_pSacl);
|
|
if(fRet)
|
|
{
|
|
m_fSACLDefaulted = a_fSaclDefaulted;
|
|
m_fSaclAutoInherited = a_fSaclAutoInherited;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clean us up if something beefed
|
|
if(!fRet)
|
|
{
|
|
Clear();
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
Clear();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::~CSecurityDescriptor
|
|
//
|
|
// Class Destructor.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CSecurityDescriptor::~CSecurityDescriptor( void )
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::IsNT5
|
|
//
|
|
// Tells us if we're running on NT 5 or not, in which case
|
|
// we need to do some special handling.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::InitSecurity
|
|
//
|
|
// Initializes the class with data from the supplied security
|
|
// descriptor.
|
|
//
|
|
// Inputs:
|
|
// PSECURITY_DESCRIPTOR psd - Security Descriptor
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// TRUE/FALSE Success/Failure.
|
|
//
|
|
// Comments:
|
|
//
|
|
// Keep this function protected so only derived classes have
|
|
// access to laying waste to our internals.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CSecurityDescriptor::InitSecurity( PSECURITY_DESCRIPTOR psd )
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
PSID psid = NULL;
|
|
DWORD dwRevision = 0;
|
|
SECURITY_DESCRIPTOR_CONTROL Control;
|
|
BOOL bTemp;
|
|
|
|
// Clean up existing values.
|
|
Clear();
|
|
|
|
// Get the security descriptor Owner Sid.
|
|
fReturn = GetSecurityDescriptorOwner( psd, &psid, &bTemp );
|
|
if ( fReturn )
|
|
{
|
|
// As long as we have a psid, intialize the owner member
|
|
if ( NULL != psid )
|
|
{
|
|
if(SetOwner(CSid(psid)) != ERROR_SUCCESS)
|
|
{
|
|
fReturn = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bTemp = FALSE;
|
|
}
|
|
|
|
bTemp ? m_fOwnerDefaulted = true : m_fOwnerDefaulted = false;
|
|
|
|
fReturn = GetSecurityDescriptorGroup (psd, &psid, &bTemp );
|
|
if ( fReturn )
|
|
{
|
|
// as long as we have a psid, initialize the group member
|
|
if ( NULL != psid )
|
|
{
|
|
if(SetGroup(CSid(psid)) != ERROR_SUCCESS)
|
|
{
|
|
fReturn = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bTemp = FALSE;
|
|
}
|
|
|
|
bTemp ? m_fGroupDefaulted = true : m_fGroupDefaulted = false;
|
|
|
|
fReturn = GetSecurityDescriptorControl( psd, &Control, &dwRevision);
|
|
if (fReturn)
|
|
{
|
|
SetControl( &Control );
|
|
// BAD, BAD, BAD, BAD
|
|
}
|
|
|
|
// Handle the DACL and then the SACL
|
|
if ( fReturn )
|
|
{
|
|
fReturn = InitDACL( psd );
|
|
}
|
|
|
|
if ( fReturn )
|
|
{
|
|
fReturn = InitSACL( psd );
|
|
}
|
|
|
|
// Clean us up if something beefed
|
|
if ( !fReturn )
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
return fReturn;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::InitDACL
|
|
//
|
|
// Initializes the DACL data member.
|
|
//
|
|
// Inputs:
|
|
// PSECURITY_DESCRIPTOR psd - Security Descriptor
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// TRUE/FALSE Success/Failure.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CSecurityDescriptor::InitDACL ( PSECURITY_DESCRIPTOR psd )
|
|
{
|
|
BOOL fReturn = FALSE,
|
|
fDACLPresent = FALSE,
|
|
fDACLDefaulted = FALSE;
|
|
|
|
PACL pDACL = NULL;
|
|
|
|
if ( GetSecurityDescriptorDacl( psd, &fDACLPresent, &pDACL, &fDACLDefaulted ) )
|
|
{
|
|
ACE_HEADER* pACEHeader = NULL;
|
|
DWORD dwAceIndex = 0;
|
|
BOOL fGotACE = FALSE;
|
|
|
|
// Be optimistic. Shut up, be happy, etc.
|
|
fReturn = TRUE;
|
|
|
|
// Note that although fDACLPresent is SUPPOSED to tell us whether or not the
|
|
// DACL is there, I'm seeing cases when this is returning TRUE, but the pDACL
|
|
// value is NULL. Not what the documenetation sez, but I'll take reality.
|
|
|
|
if (fDACLPresent && (pDACL != NULL))
|
|
{
|
|
// Create a working dacl and initialize it with all ace entries...
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pDACL != NULL)
|
|
{
|
|
if(m_pDACL->Init(pDACL) == ERROR_SUCCESS)
|
|
{
|
|
fReturn = TRUE;
|
|
// Allocated a dacl for that type only if an entry of that type was present.
|
|
|
|
// If we had an empty dacl (dacl present, yet empty), we won't have allocated
|
|
// any dacls in the array m_rgDACLPtrArray. This won't be confused with a NULL
|
|
// DACL, as this module knows that it always represents a NULL DACL as all of
|
|
// the elements of m_rgDACLPtrArray as null except for ACCESS_ALLOWED_OBJECT,
|
|
// which will have one entry - namely, the Everyone ace.
|
|
}
|
|
}
|
|
} // IF fDACL Present
|
|
else
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pDACL != NULL)
|
|
{
|
|
fReturn = m_pDACL->CreateNullDACL(); // No DACL, so gin up an Empty Dacl
|
|
}
|
|
}
|
|
|
|
} // IF Got DACL
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
// Another version
|
|
bool CSecurityDescriptor::InitDACL( CDACL* a_pDACL )
|
|
{
|
|
bool fRet = false;
|
|
if (a_pDACL != NULL)
|
|
{
|
|
// Create a working dacl and initialize it with all ace entries...
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pDACL != NULL)
|
|
{
|
|
if(m_pDACL->CopyDACL(*a_pDACL))
|
|
{
|
|
fRet = true;
|
|
// Allocated a dacl for that type only if an entry of that type was present.
|
|
|
|
// If we had an empty dacl (dacl present, yet empty), we won't have allocated
|
|
// any dacls in the array m_rgDACLPtrArray. This won't be confused with a NULL
|
|
// DACL, as this module knows that it always represents a NULL DACL as all of
|
|
// the elements of m_rgDACLPtrArray as null except for ACCESS_ALLOWED_OBJECT,
|
|
// which will have one entry - namely, the Everyone ace.
|
|
}
|
|
}
|
|
} // IF fDACL Present
|
|
else
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pDACL != NULL)
|
|
{
|
|
fRet = m_pDACL->CreateNullDACL(); // No DACL, so gin up an Empty Dacl
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::InitSACL
|
|
//
|
|
// Initializes the SACL data member.
|
|
//
|
|
// Inputs:
|
|
// PSECURITY_DESCRIPTOR psd - Security Descriptor
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// TRUE/FALSE Success/Failure.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CSecurityDescriptor::InitSACL ( PSECURITY_DESCRIPTOR psd )
|
|
{
|
|
BOOL fReturn = FALSE,
|
|
fSACLPresent = FALSE,
|
|
fSACLDefaulted = FALSE;
|
|
|
|
PACL pSACL = NULL;
|
|
|
|
if ( GetSecurityDescriptorSacl( psd, &fSACLPresent, &pSACL, &fSACLDefaulted ) )
|
|
{
|
|
|
|
// Be optimistic. Shut up, be happy, etc.
|
|
fReturn = TRUE;
|
|
|
|
// Note that although fSACLPresent is SUPPOSED to tell us whether or not the
|
|
// SACL is there, I'm seeing cases when this is returning TRUE, but the pSACL
|
|
// value is NULL. Not what the documenetation sez, but I'll take reality
|
|
// for a thousand, Alex.
|
|
|
|
if ( fSACLPresent
|
|
&& NULL != pSACL )
|
|
{
|
|
// Allocate SACL although it may stay empty
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pSACL = new CSACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pSACL != NULL)
|
|
{
|
|
if(m_pSACL->Init(pSACL) == ERROR_SUCCESS)
|
|
{
|
|
fReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
} // IF fSACL Present
|
|
else
|
|
{
|
|
fReturn = TRUE; // No SACL, so no worries
|
|
}
|
|
|
|
} // IF Got SACL
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
// Another version...
|
|
bool CSecurityDescriptor::InitSACL( CSACL* a_pSACL )
|
|
{
|
|
bool fRet = false;
|
|
|
|
if (a_pSACL != NULL)
|
|
{
|
|
// Allocate SACL although it may stay empty
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
m_pSACL = new CSACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(m_pSACL != NULL)
|
|
{
|
|
if(m_pSACL->CopySACL(*a_pSACL))
|
|
{
|
|
fRet = true;
|
|
}
|
|
}
|
|
|
|
} // IF fSACL Present
|
|
else
|
|
{
|
|
fRet = true; // No SACL, so no worries
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::SecureObject
|
|
//
|
|
// Private entry point function which takes an Absolute Security
|
|
// Descriptor, and depending on the user supplied security
|
|
// information flags, divvies the actual object security handling
|
|
// out to the appropriate WriteOwner() and WriteAcls() virtual
|
|
// functions.
|
|
//
|
|
// Inputs:
|
|
// PSECURITY_DESCRIPTOR pAbsoluteSD - Security Descriptor
|
|
// SECURITY_INFORMATION securityinfo - Security flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// DWORD ERROR_SUCCESS if ok.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CSecurityDescriptor::SecureObject( PSECURITY_DESCRIPTOR pAbsoluteSD, SECURITY_INFORMATION securityinfo )
|
|
{
|
|
DWORD dwReturn = ERROR_SUCCESS;
|
|
|
|
// We might need this guy to handle some special access stuff
|
|
CTokenPrivilege restorePrivilege( SE_RESTORE_NAME );
|
|
|
|
//try to set the owner first, since setting the dacl may preclude setting the owner, depending on what access we set
|
|
if ( securityinfo & OWNER_SECURITY_INFORMATION )
|
|
{
|
|
dwReturn = WriteOwner( pAbsoluteSD ) ;
|
|
|
|
if ( ERROR_INVALID_OWNER == dwReturn )
|
|
{
|
|
// If we enable the privilege, retry setting the owner info
|
|
if ( ERROR_SUCCESS == restorePrivilege.Enable() )
|
|
{
|
|
dwReturn = WriteOwner( pAbsoluteSD );
|
|
|
|
// Clear the privilege
|
|
restorePrivilege.Enable( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we need to write sacl/dacl information, try to write that piece now
|
|
if ( dwReturn == ERROR_SUCCESS && ( securityinfo & DACL_SECURITY_INFORMATION ||
|
|
securityinfo & SACL_SECURITY_INFORMATION ||
|
|
securityinfo & PROTECTED_DACL_SECURITY_INFORMATION ||
|
|
securityinfo & PROTECTED_SACL_SECURITY_INFORMATION ||
|
|
securityinfo & UNPROTECTED_DACL_SECURITY_INFORMATION ||
|
|
securityinfo & UNPROTECTED_SACL_SECURITY_INFORMATION) )
|
|
{
|
|
SECURITY_INFORMATION daclsecinfo = 0;
|
|
|
|
// Fill out security information with only the appropriate DACL/SACL values.
|
|
if ( securityinfo & DACL_SECURITY_INFORMATION )
|
|
{
|
|
daclsecinfo |= DACL_SECURITY_INFORMATION;
|
|
}
|
|
|
|
if ( securityinfo & SACL_SECURITY_INFORMATION )
|
|
{
|
|
daclsecinfo |= SACL_SECURITY_INFORMATION;
|
|
}
|
|
|
|
#if NTONLY >= 5
|
|
if(securityinfo & PROTECTED_DACL_SECURITY_INFORMATION)
|
|
{
|
|
daclsecinfo |= PROTECTED_DACL_SECURITY_INFORMATION;
|
|
}
|
|
if(securityinfo & PROTECTED_SACL_SECURITY_INFORMATION)
|
|
{
|
|
daclsecinfo |= PROTECTED_SACL_SECURITY_INFORMATION;
|
|
}
|
|
if(securityinfo & UNPROTECTED_DACL_SECURITY_INFORMATION)
|
|
{
|
|
daclsecinfo |= UNPROTECTED_DACL_SECURITY_INFORMATION;
|
|
}
|
|
if(securityinfo & UNPROTECTED_SACL_SECURITY_INFORMATION)
|
|
{
|
|
daclsecinfo |= UNPROTECTED_SACL_SECURITY_INFORMATION;
|
|
}
|
|
#endif
|
|
|
|
|
|
dwReturn = WriteAcls( pAbsoluteSD, daclsecinfo );
|
|
}
|
|
return dwReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::SetOwner
|
|
//
|
|
// Sets the owner data member to the supplied SID.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - New Owner.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// DWORD ERROR_SUCCESS if ok.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CSecurityDescriptor::SetOwner( CSid& sid )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
// Make sure the new sid is valid
|
|
if ( sid.IsValid() )
|
|
{
|
|
|
|
// We will write in the sid, if the Owner is NULL, or the
|
|
// sids are not equal.
|
|
|
|
if ( NULL == m_pOwnerSid
|
|
|| !( *m_pOwnerSid == sid ) )
|
|
{
|
|
|
|
if ( NULL != m_pOwnerSid )
|
|
{
|
|
delete m_pOwnerSid;
|
|
}
|
|
|
|
m_pOwnerSid = NULL;
|
|
try
|
|
{
|
|
m_pOwnerSid = new CSid( sid );
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pOwnerSid != NULL)
|
|
{
|
|
delete m_pOwnerSid;
|
|
m_pOwnerSid = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if ( NULL == m_pOwnerSid )
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
m_fOwnerDefaulted = FALSE;
|
|
}
|
|
|
|
} // IF NULL == m_pOwnerSid || !SidsEqual
|
|
|
|
} // IF IsValidSid
|
|
else
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::SetGroup
|
|
//
|
|
// Sets the group data member to the supplied SID.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - New Group.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// DWORD ERROR_SUCCESS if ok.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CSecurityDescriptor::SetGroup( CSid& sid )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
// Make sure the new sid is valid
|
|
if ( sid.IsValid() )
|
|
{
|
|
|
|
// We will write in the sid, if the Owner is NULL, or the
|
|
// sids are not equal.
|
|
|
|
if ( NULL == m_pGroupSid
|
|
|| !( *m_pGroupSid == sid ) )
|
|
{
|
|
|
|
if ( NULL != m_pGroupSid )
|
|
{
|
|
delete m_pGroupSid;
|
|
}
|
|
|
|
m_pGroupSid = NULL;
|
|
try
|
|
{
|
|
m_pGroupSid = new CSid( sid );
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pGroupSid != NULL)
|
|
{
|
|
delete m_pGroupSid;
|
|
m_pGroupSid = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
|
|
if ( NULL == m_pGroupSid )
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
m_fGroupDefaulted = FALSE;
|
|
}
|
|
|
|
} // IF NULL == m_pOwnerSid || !SidsEqual
|
|
|
|
} // IF IsValidSid
|
|
else
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::AddDACLEntry
|
|
//
|
|
// Adds an entry to our DACL. Replaces an
|
|
// existing entry if it meets the matching criteria.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwAccessMask - The access mask
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::AddDACLEntry( CSid& sid, DACL_Types DaclType, DWORD dwAccessMask, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if(m_pDACL == NULL)
|
|
{
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
if(m_pDACL != NULL)
|
|
{
|
|
fReturn = m_pDACL->AddDACLEntry(sid.GetPSid(), DaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fReturn = m_pDACL->AddDACLEntry(sid.GetPSid(), DaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::AddSACLEntry
|
|
//
|
|
// Adds an entry to our SACL. Replaces an
|
|
// existing entry if it meets the matching criteria.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwAccessMask - The access mask
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::AddSACLEntry( CSid& sid, SACL_Types SaclType, DWORD dwAccessMask, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if(m_pSACL == NULL)
|
|
{
|
|
try
|
|
{
|
|
m_pSACL = new CSACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
if(m_pSACL != NULL)
|
|
{
|
|
fReturn = m_pSACL->AddSACLEntry(sid.GetPSid(), SaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fReturn = m_pSACL->AddSACLEntry(sid.GetPSid(), SaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveDACLEntry
|
|
//
|
|
// Removes a DACL entry from our DACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwAccessMask - The access mask
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// The entry that is removed must match all specified criteria.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveDACLEntry( CSid& sid, DACL_Types DaclType, DWORD dwAccessMask, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
fReturn = m_pDACL->RemoveDACLEntry( sid, DaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveDACLEntry
|
|
//
|
|
// Removes a DACL entry from our DACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// The entry that is removed must match only the specified criteria.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveDACLEntry( CSid& sid, DACL_Types DaclType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
fReturn = m_pDACL->RemoveDACLEntry( sid, DaclType, bACEFlags, pguidObjGuid, pguidInhObjGuid );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveDACLEntry
|
|
//
|
|
// Removes a DACL entry from our DACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwIndex - Index of entry.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// Removes the dwIndex instance of a SID in the SACL.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveDACLEntry( CSid& sid, DACL_Types DaclType, DWORD dwIndex )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
fReturn = m_pDACL->RemoveDACLEntry( sid, DaclType, dwIndex );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveSACLEntry
|
|
//
|
|
// Removes a SACL entry from our SACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwAccessMask - The access mask
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// The entry that is removed must match all specified criteria.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveSACLEntry( CSid& sid, SACL_Types SaclType, DWORD dwAccessMask, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
fReturn = m_pSACL->RemoveSACLEntry( sid, SaclType, dwAccessMask, bACEFlags, pguidObjGuid, pguidInhObjGuid );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveSACLEntry
|
|
//
|
|
// Removes a SACL entry from our SACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// BOOL bACEFlags - ACE Flags.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// The entry that is removed must match only the specified criteria.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveSACLEntry( CSid& sid, SACL_Types SaclType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
fReturn = m_pSACL->RemoveSACLEntry( sid, SaclType, bACEFlags, pguidObjGuid, pguidInhObjGuid );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::RemoveSACLEntry
|
|
//
|
|
// Removes a SACL entry from our SACL.
|
|
//
|
|
// Inputs:
|
|
// CSid& sid - Sid for the entry.
|
|
// DWORD dwIndex - Index of entry.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// Removes the dwIndex instance of a SID in the SACL.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::RemoveSACLEntry( CSid& sid, SACL_Types SaclType, DWORD dwIndex )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
fReturn = m_pSACL->RemoveSACLEntry( sid, SaclType, dwIndex );
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::FindACE
|
|
//
|
|
// Locates an ACE in either the SACL or DACL based on the supplied
|
|
// criteria.
|
|
//
|
|
// Inputs:
|
|
// const CSid& sid - Sid for the entry.
|
|
// BYTE bACEType - ACE Type
|
|
// DWORD dwMask - Access Mask
|
|
// BYTE bACEFlags - Flags
|
|
//
|
|
// Outputs:
|
|
// CAccessEntry& ace - Filled out with located values.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// Locates an ACE that matches ALL supplied criteria
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::FindACE( const CSid& sid, BYTE bACEType, DWORD dwMask, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, CAccessEntry& ace )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( SYSTEM_AUDIT_ACE_TYPE == bACEType ||
|
|
SYSTEM_AUDIT_OBJECT_ACE_TYPE == bACEType /* ||
|
|
SYSTEM_ALARM_ACE_TYPE == bACEType || <- ALARM ACE TYPES NOT YET SUPPORTED UNDER W2K
|
|
SYSTEM_ALARM_OBJECT_ACE_TYPE == bACEType */ )
|
|
{
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
fReturn = m_pSACL->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask, ace );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
fReturn = m_pDACL->Find( sid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwMask, ace );
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::FindACE
|
|
//
|
|
// Locates an ACE in either the SACL or DACL based on the supplied
|
|
// criteria.
|
|
//
|
|
// Inputs:
|
|
// const CSid& sid - Sid for the entry.
|
|
// BYTE bACEType - ACE Type
|
|
// BYTE bACEFlags - Flags
|
|
//
|
|
// Outputs:
|
|
// CAccessEntry& ace - Filled out with located values.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// Locates an ACE that matches ALL supplied criteria
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
bool CSecurityDescriptor::FindACE( PSID psid, BYTE bACEType, BYTE bACEFlags, GUID *pguidObjGuid, GUID *pguidInhObjGuid, DWORD dwAccessMask, CAccessEntry& ace )
|
|
{
|
|
bool fReturn = false;
|
|
|
|
if ( SYSTEM_AUDIT_ACE_TYPE == bACEType ||
|
|
SYSTEM_AUDIT_OBJECT_ACE_TYPE == bACEType ||
|
|
SYSTEM_ALARM_ACE_TYPE == bACEType ||
|
|
SYSTEM_ALARM_OBJECT_ACE_TYPE == bACEType)
|
|
{
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
fReturn = m_pSACL->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
fReturn = m_pDACL->Find( psid, bACEType, bACEFlags, pguidObjGuid, pguidInhObjGuid, dwAccessMask, ace );
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::ApplySecurity
|
|
//
|
|
// Using the user specified flags, builds an appropriate descriptor
|
|
// and loads it with the necessary information, then passes this
|
|
// descriptor off to SecureObject() which will farm out the
|
|
// actual setting of security to the virtual Write functions.
|
|
//
|
|
// Inputs:
|
|
// SECURITY_INFORMATION securityinfo - flags to control
|
|
// how the descriptor is used.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// DWORD ERROR_SUCCESS if successful.
|
|
//
|
|
// Comments:
|
|
//
|
|
// This should be the only public method for applying security
|
|
// to an object.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CSecurityDescriptor::ApplySecurity( SECURITY_INFORMATION securityinfo )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
PSID pOwnerSid = NULL;
|
|
PACL pDacl = NULL,
|
|
pSacl = NULL;
|
|
|
|
// Allocate and initialize the security descriptor
|
|
PSECURITY_DESCRIPTOR pAbsoluteSD = NULL;
|
|
try
|
|
{
|
|
pAbsoluteSD = new SECURITY_DESCRIPTOR;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(pAbsoluteSD != NULL)
|
|
{
|
|
delete pAbsoluteSD;
|
|
pAbsoluteSD = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if ( NULL != pAbsoluteSD )
|
|
{
|
|
if ( !InitializeSecurityDescriptor( pAbsoluteSD, SECURITY_DESCRIPTOR_REVISION ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// If we're supposed to set the owner, place the sid from the internal
|
|
// value in the absoluteSD.
|
|
|
|
if ( ERROR_SUCCESS == dwError
|
|
&& securityinfo & OWNER_SECURITY_INFORMATION )
|
|
{
|
|
if ( NULL != m_pOwnerSid )
|
|
{
|
|
pOwnerSid = m_pOwnerSid->GetPSid();
|
|
}
|
|
|
|
if ( !SetSecurityDescriptorOwner( pAbsoluteSD, pOwnerSid, m_fOwnerDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
}
|
|
|
|
// If we're supposed to set the DACL, this is a non-trivial operation so
|
|
// call out for reinforcements.
|
|
|
|
if ( ERROR_SUCCESS == dwError
|
|
&& securityinfo & DACL_SECURITY_INFORMATION || securityinfo & PROTECTED_DACL_SECURITY_INFORMATION || securityinfo & UNPROTECTED_DACL_SECURITY_INFORMATION
|
|
&& m_pDACL != NULL)
|
|
{
|
|
|
|
if ( ( dwError = m_pDACL->ConfigureDACL( pDacl ) ) == ERROR_SUCCESS )
|
|
{
|
|
|
|
if ( !SetSecurityDescriptorDacl( pAbsoluteSD,
|
|
( NULL != pDacl ), // Set Dacl present flag
|
|
pDacl,
|
|
m_fDACLDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we're supposed to set the SACL, this also is a non-trivial operation so
|
|
// call out for reinforcements.
|
|
|
|
if (ERROR_SUCCESS == dwError)
|
|
{
|
|
if((securityinfo & SACL_SECURITY_INFORMATION || securityinfo & PROTECTED_SACL_SECURITY_INFORMATION || securityinfo & UNPROTECTED_SACL_SECURITY_INFORMATION)
|
|
&& (m_pSACL != NULL))
|
|
{
|
|
|
|
if ( ( dwError = m_pSACL->ConfigureSACL( pSacl ) ) == ERROR_SUCCESS )
|
|
{
|
|
|
|
if ( !SetSecurityDescriptorSacl( pAbsoluteSD,
|
|
( NULL != pSacl ), // Set Sacl present flag
|
|
pSacl,
|
|
m_fSACLDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// If we're OK, let the object try to secure itself, the default implementation
|
|
// fails with ERROR_INVALID_FUNCTION.
|
|
|
|
if ( ERROR_SUCCESS == dwError )
|
|
{
|
|
ASSERT_BREAK( IsValidSecurityDescriptor( pAbsoluteSD ) );
|
|
dwError = SecureObject( pAbsoluteSD, securityinfo );
|
|
}
|
|
|
|
// Clean up allocated memory
|
|
if ( NULL != pAbsoluteSD )
|
|
{
|
|
delete pAbsoluteSD;
|
|
}
|
|
|
|
if ( NULL != pDacl )
|
|
{
|
|
// This guy gets malloced in ConfigureDACL
|
|
free( pDacl );
|
|
}
|
|
|
|
if ( NULL != pSacl )
|
|
{
|
|
// This guy gets malloced in ConfigureSACL
|
|
free( pSacl );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::Clear
|
|
//
|
|
// Empties out our class, freeing up all allocated memory.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// None.
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
void CSecurityDescriptor::Clear( void )
|
|
{
|
|
if ( NULL != m_pOwnerSid )
|
|
{
|
|
delete m_pOwnerSid;
|
|
m_pOwnerSid = NULL;
|
|
}
|
|
|
|
m_fOwnerDefaulted = FALSE;
|
|
|
|
if ( NULL != m_pDACL )
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
if ( NULL != m_pSACL )
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
|
|
if ( NULL != m_pGroupSid )
|
|
{
|
|
delete m_pGroupSid;
|
|
m_pGroupSid = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::GetDACL
|
|
//
|
|
// Makes a copy of our DACL entries and places them in the supplied
|
|
// DACL, in proper canonical order.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// CDACL& DACL - Dacl to copy into.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::GetDACL ( CDACL& DACL )
|
|
{
|
|
bool fRet = false;
|
|
if(m_pDACL != NULL)
|
|
{
|
|
fRet = DACL.CopyDACL( *m_pDACL );
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::GetSACL
|
|
//
|
|
// Makes a copy of our SACL entries and places them in the supplied
|
|
// SACL.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// CSACL& SACL - Sacl to copy into.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::GetSACL ( CSACL& SACL )
|
|
{
|
|
bool fRet = false;
|
|
if(m_pSACL != NULL)
|
|
{
|
|
fRet = SACL.CopySACL( *m_pSACL );
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::EmptyDACL
|
|
//
|
|
// Clears our DACL lists, allocating them if they DO NOT exist.
|
|
//
|
|
// 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.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
void CSecurityDescriptor::EmptyDACL()
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
m_pDACL->Clear();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::EmptySACL
|
|
//
|
|
// Clears our SACL lists, allocating it if it DOES NOT exist
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// In the case of a sacl, there is no distinction between a NULL
|
|
// and an Empty. So we will consider this sacl Empty if its data
|
|
// member is NULL.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
void CSecurityDescriptor::EmptySACL()
|
|
{
|
|
if(m_pSACL != NULL)
|
|
{
|
|
m_pSACL->Clear();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::ClearSACL
|
|
//
|
|
// Deletes our SACL list.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL TRUE/FALSE
|
|
//
|
|
// Comments:
|
|
//
|
|
// In the case of a sacl, there is no distinction between a NULL
|
|
// and an Empty. So we will consider this sacl Empty if its data
|
|
// member is NULL.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool CSecurityDescriptor::MakeSACLNull()
|
|
{
|
|
bool fReturn = false;
|
|
if(m_pSACL == NULL)
|
|
{
|
|
try
|
|
{
|
|
m_pSACL = new CSACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pSACL != NULL)
|
|
{
|
|
delete m_pSACL;
|
|
m_pSACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
if(m_pSACL != NULL)
|
|
{
|
|
m_pSACL->Clear();
|
|
fReturn = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pSACL->Clear();
|
|
m_pSACL->Clear();
|
|
fReturn = true;
|
|
}
|
|
|
|
return fReturn;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::MakeDACLNull
|
|
//
|
|
// 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 CSecurityDescriptor::MakeDACLNull( void )
|
|
{
|
|
bool fReturn = false;
|
|
if(m_pDACL == NULL)
|
|
{
|
|
try
|
|
{
|
|
m_pDACL = new CDACL;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(m_pDACL != NULL)
|
|
{
|
|
delete m_pDACL;
|
|
m_pDACL = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
if(m_pDACL != NULL)
|
|
{
|
|
m_pDACL->CreateNullDACL();
|
|
fReturn = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pDACL->Clear();
|
|
fReturn = m_pDACL->CreateNullDACL();
|
|
fReturn = true;
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 CSecurityDescriptor::IsNULLDACL()
|
|
{
|
|
bool fRet = false;
|
|
if(m_pDACL != NULL)
|
|
{
|
|
fRet = m_pDACL->IsNULLDACL();
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void CSecurityDescriptor::DumpDescriptor(LPCWSTR wstrFilename)
|
|
{
|
|
CHString chstrTemp;
|
|
|
|
Output(L"Security descriptor contents follow...", wstrFilename);
|
|
// Output the control flags
|
|
chstrTemp.Format(L"Control Flags (hex): %x", m_SecurityDescriptorControl);
|
|
Output(chstrTemp, wstrFilename);
|
|
|
|
// Ouput the owner
|
|
Output(L"Owner contents: ", wstrFilename);
|
|
if(m_pOwnerSid != NULL)
|
|
{
|
|
m_pOwnerSid->DumpSid(wstrFilename);
|
|
}
|
|
else
|
|
{
|
|
Output(L"(Owner is null)", wstrFilename);
|
|
}
|
|
|
|
|
|
// Output the group
|
|
Output(L"Group contents: ", wstrFilename);
|
|
if(m_pGroupSid != NULL)
|
|
{
|
|
m_pGroupSid->DumpSid(wstrFilename);
|
|
}
|
|
else
|
|
{
|
|
Output(L"(Group is null)", wstrFilename);
|
|
}
|
|
|
|
// Output the DACL
|
|
Output(L"DACL contents: ", wstrFilename);
|
|
if(m_pDACL != NULL)
|
|
{
|
|
m_pDACL->DumpDACL(wstrFilename);
|
|
}
|
|
else
|
|
{
|
|
Output(L"(DACL is null)", wstrFilename);
|
|
}
|
|
|
|
// Output the SACL
|
|
Output(L"SACL contents: ", wstrFilename);
|
|
if(m_pSACL != NULL)
|
|
{
|
|
m_pSACL->DumpSACL(wstrFilename);
|
|
}
|
|
else
|
|
{
|
|
Output(L"(SACL is null)", wstrFilename);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: CSecurityDescriptor::GetPSD
|
|
//
|
|
// Takes our internal members and constructs a PSECURITY_DESCRIPTOR,
|
|
// which the caller must free.
|
|
//
|
|
// 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.
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CSecurityDescriptor::GetSelfRelativeSD(
|
|
SECURITY_INFORMATION securityinfo,
|
|
PSECURITY_DESCRIPTOR psd)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
PSID pOwnerSid = NULL;
|
|
PACL pDacl = NULL,
|
|
pSacl = NULL;
|
|
|
|
// Allocate and initialize the security descriptor
|
|
PSECURITY_DESCRIPTOR pAbsoluteSD = NULL;
|
|
try
|
|
{
|
|
pAbsoluteSD = new SECURITY_DESCRIPTOR;
|
|
}
|
|
catch(...)
|
|
{
|
|
if(pAbsoluteSD != NULL)
|
|
{
|
|
delete pAbsoluteSD;
|
|
pAbsoluteSD = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if ( NULL != pAbsoluteSD )
|
|
{
|
|
if ( !::InitializeSecurityDescriptor( pAbsoluteSD, SECURITY_DESCRIPTOR_REVISION ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// If we're supposed to set the owner, place the sid from the internal
|
|
// value in the absoluteSD.
|
|
|
|
if ( ERROR_SUCCESS == dwError
|
|
&& securityinfo & OWNER_SECURITY_INFORMATION )
|
|
{
|
|
if ( NULL != m_pOwnerSid )
|
|
{
|
|
pOwnerSid = m_pOwnerSid->GetPSid();
|
|
}
|
|
|
|
if ( !::SetSecurityDescriptorOwner( pAbsoluteSD, pOwnerSid, m_fOwnerDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
}
|
|
|
|
// If we're supposed to set the DACL, this is a non-trivial operation so
|
|
// call out for reinforcements.
|
|
|
|
if ( ERROR_SUCCESS == dwError
|
|
&& securityinfo & DACL_SECURITY_INFORMATION || securityinfo & PROTECTED_DACL_SECURITY_INFORMATION || securityinfo & UNPROTECTED_DACL_SECURITY_INFORMATION
|
|
&& m_pDACL != NULL)
|
|
{
|
|
|
|
if ( ( dwError = m_pDACL->ConfigureDACL( pDacl ) ) == ERROR_SUCCESS )
|
|
{
|
|
|
|
if ( !::SetSecurityDescriptorDacl( pAbsoluteSD,
|
|
( NULL != pDacl ), // Set Dacl present flag
|
|
pDacl,
|
|
m_fDACLDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we're supposed to set the SACL, this also is a non-trivial operation so
|
|
// call out for reinforcements.
|
|
|
|
if (ERROR_SUCCESS == dwError)
|
|
{
|
|
if((securityinfo & SACL_SECURITY_INFORMATION || securityinfo & PROTECTED_SACL_SECURITY_INFORMATION || securityinfo & UNPROTECTED_SACL_SECURITY_INFORMATION)
|
|
&& (m_pSACL != NULL))
|
|
{
|
|
|
|
if ( ( dwError = m_pSACL->ConfigureSACL( pSacl ) ) == ERROR_SUCCESS )
|
|
{
|
|
|
|
if ( !::SetSecurityDescriptorSacl( pAbsoluteSD,
|
|
( NULL != pSacl ), // Set Sacl present flag
|
|
pSacl,
|
|
m_fSACLDefaulted ) )
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// If we're OK, let the object try to secure itself, the default implementation
|
|
// fails with ERROR_INVALID_FUNCTION.
|
|
|
|
if ( ERROR_SUCCESS == dwError )
|
|
{
|
|
ASSERT_BREAK( ::IsValidSecurityDescriptor( pAbsoluteSD ) );
|
|
|
|
// Now make it self relative... Caller frees this...
|
|
DWORD dwSize = 0L;
|
|
if(!::MakeSelfRelativeSD(
|
|
pAbsoluteSD,
|
|
NULL,
|
|
&dwSize) &&
|
|
(dwError = ::GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
PSECURITY_DESCRIPTOR pSelfRelSD = NULL;
|
|
pSelfRelSD = new BYTE[dwSize];
|
|
|
|
if(pSelfRelSD &&
|
|
!::MakeSelfRelativeSD(
|
|
pAbsoluteSD,
|
|
pSelfRelSD,
|
|
&dwSize))
|
|
{
|
|
dwError = ::GetLastError();
|
|
}
|
|
else
|
|
{
|
|
psd = pSelfRelSD;
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clean up allocated memory
|
|
if ( NULL != pAbsoluteSD )
|
|
{
|
|
delete pAbsoluteSD;
|
|
}
|
|
|
|
if ( NULL != pDacl )
|
|
{
|
|
// This guy gets malloced in ConfigureDACL
|
|
free( pDacl );
|
|
}
|
|
|
|
if ( NULL != pSacl )
|
|
{
|
|
// This guy gets malloced in ConfigureSACL
|
|
free( pSacl );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|