969 lines
23 KiB
C++
969 lines
23 KiB
C++
|
/*---------------------------------------------------------------------------
|
||
|
File: SD.cpp
|
||
|
Comments: class for manipulating security descriptors
|
||
|
This class provides a thin wrapper around the security descriptor APIs, and
|
||
|
also helps us with some of our processing heuristics.
|
||
|
|
||
|
The NT APIs to read and write security descriptors for files, etc. generally
|
||
|
return a self-relative SD when reading, but expect an absolute SD when writing
|
||
|
|
||
|
Thus, we keep the original data of the SD as read, in self-relative form in m_relSD,
|
||
|
and store any changes in absolute form in m_absSD. This allows us to easily track
|
||
|
which parts of the SD have been modified, and to compare the before and after versions
|
||
|
of the SD.
|
||
|
|
||
|
As an optimization in our ACL translation, we can compare each SD to the initial
|
||
|
state of the last SD we processed. If it is the same, we can simply write the
|
||
|
result we have already calculated, instead of calculating it again.
|
||
|
|
||
|
(c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved
|
||
|
Proprietary and confidential to Mission Critical Software, Inc.
|
||
|
|
||
|
REVISION LOG ENTRY
|
||
|
Revision By: Christy Boles
|
||
|
Revised on 01-Oct-98 15:51:41
|
||
|
|
||
|
---------------------------------------------------------------------------
|
||
|
*/
|
||
|
#include <windows.h>
|
||
|
#include "McsDebug.h"
|
||
|
#include "McsDbgU.h"
|
||
|
#include "SD.hpp"
|
||
|
|
||
|
TSD::TSD(
|
||
|
SECURITY_DESCRIPTOR * pSD, // in - pointer to self-relative security descriptor
|
||
|
SecuredObjectType objectType, // in - type of object this security descriptor secures
|
||
|
BOOL bResponsibleForDelete // in - if TRUE, this class will delete the memory for pSD
|
||
|
)
|
||
|
{
|
||
|
m_absSD = MakeAbsSD(pSD);
|
||
|
m_bOwnerChanged = FALSE;
|
||
|
m_bGroupChanged = FALSE;
|
||
|
m_bDACLChanged = FALSE;
|
||
|
m_bSACLChanged = FALSE;
|
||
|
m_bNeedToFreeSD = TRUE;
|
||
|
m_bNeedToFreeOwner = TRUE;
|
||
|
m_bNeedToFreeGroup = TRUE;
|
||
|
m_bNeedToFreeDacl = TRUE;
|
||
|
m_bNeedToFreeSacl = TRUE;
|
||
|
m_ObjectType = objectType;
|
||
|
|
||
|
if ( bResponsibleForDelete )
|
||
|
{
|
||
|
free(pSD);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TSD::TSD(
|
||
|
TSD * pSD // in - another security descriptor
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(pSD);
|
||
|
|
||
|
if ( pSD )
|
||
|
{
|
||
|
m_absSD = pSD->MakeAbsSD();
|
||
|
m_bOwnerChanged = FALSE;
|
||
|
m_bGroupChanged = FALSE;
|
||
|
m_bDACLChanged = FALSE;
|
||
|
m_bSACLChanged = FALSE;
|
||
|
m_bNeedToFreeSD = TRUE;
|
||
|
m_bNeedToFreeOwner = TRUE;
|
||
|
m_bNeedToFreeGroup = TRUE;
|
||
|
m_bNeedToFreeDacl = TRUE;
|
||
|
m_bNeedToFreeSacl = TRUE;
|
||
|
m_ObjectType = pSD->GetType();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TSD::~TSD()
|
||
|
{
|
||
|
MCSVERIFY(m_absSD);
|
||
|
|
||
|
if ( m_bNeedToFreeSD )
|
||
|
{
|
||
|
if (m_absSD)
|
||
|
FreeAbsSD(m_absSD,FALSE);
|
||
|
m_absSD = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSD::FreeAbsSD(
|
||
|
SECURITY_DESCRIPTOR * pSD, // in - pointer to security descriptor to free
|
||
|
BOOL bAll // in - flag whether to free all parts of the SD, or only those
|
||
|
// allocated by this class
|
||
|
)
|
||
|
{
|
||
|
PSID sid = NULL;
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted;
|
||
|
BOOL present;
|
||
|
|
||
|
GetSecurityDescriptorOwner(pSD,&sid,&defaulted);
|
||
|
|
||
|
if ( sid && ( m_bNeedToFreeOwner || bAll ) )
|
||
|
{
|
||
|
free(sid);
|
||
|
sid = NULL;
|
||
|
}
|
||
|
|
||
|
GetSecurityDescriptorGroup(pSD,&sid,&defaulted);
|
||
|
if ( sid && ( m_bNeedToFreeGroup || bAll ) )
|
||
|
{
|
||
|
free(sid);
|
||
|
sid = NULL;
|
||
|
}
|
||
|
|
||
|
GetSecurityDescriptorDacl(pSD,&present,&acl,&defaulted);
|
||
|
if ( acl && (m_bNeedToFreeDacl || bAll ) )
|
||
|
{
|
||
|
free(acl);
|
||
|
acl = NULL;
|
||
|
}
|
||
|
|
||
|
GetSecurityDescriptorSacl(pSD,&present,&acl,&defaulted);
|
||
|
if ( acl && ( m_bNeedToFreeSacl || bAll ) )
|
||
|
{
|
||
|
free(acl);
|
||
|
acl = NULL;
|
||
|
}
|
||
|
|
||
|
free(pSD);
|
||
|
}
|
||
|
|
||
|
|
||
|
SECURITY_DESCRIPTOR * // ret- copy of the SD, in Absolute format
|
||
|
TSD::MakeAbsSD(
|
||
|
SECURITY_DESCRIPTOR * pSD // in - security descriptor to copy
|
||
|
) const
|
||
|
{
|
||
|
DWORD sd_size = (sizeof SECURITY_DESCRIPTOR);
|
||
|
DWORD dacl_size = 0;
|
||
|
DWORD sacl_size = 0;
|
||
|
DWORD owner_size = 0;
|
||
|
DWORD group_size = 0;
|
||
|
|
||
|
// Allocate space for the SD and its parts
|
||
|
SECURITY_DESCRIPTOR * absSD = (SECURITY_DESCRIPTOR *) malloc(sd_size);
|
||
|
if (!absSD || !pSD)
|
||
|
{
|
||
|
if (absSD)
|
||
|
{
|
||
|
free(absSD);
|
||
|
absSD = NULL;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
PACL absDacl = NULL;
|
||
|
PACL absSacl = NULL;
|
||
|
PSID absOwner = NULL;
|
||
|
PSID absGroup = NULL;
|
||
|
|
||
|
if ( ! MakeAbsoluteSD(pSD,absSD,&sd_size,absDacl,&dacl_size,absSacl,&sacl_size
|
||
|
,absOwner,&owner_size,absGroup,&group_size) )
|
||
|
{
|
||
|
// DWORD rc = GetLastError();
|
||
|
// didn't work: increase sizes and try again
|
||
|
|
||
|
if ( sd_size > (sizeof SECURITY_DESCRIPTOR) )
|
||
|
{
|
||
|
free(absSD);
|
||
|
absSD = (SECURITY_DESCRIPTOR *) malloc(sd_size);
|
||
|
if (!absSD)
|
||
|
return NULL;
|
||
|
}
|
||
|
if ( dacl_size )
|
||
|
{
|
||
|
absDacl = (PACL)malloc(dacl_size);
|
||
|
if (!absDacl)
|
||
|
{
|
||
|
free(absSD);
|
||
|
absSD = NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
if ( sacl_size )
|
||
|
{
|
||
|
absSacl = (PACL)malloc(sacl_size);
|
||
|
if (!absSacl)
|
||
|
{
|
||
|
free(absSD);
|
||
|
free(absDacl);
|
||
|
absSD = NULL;
|
||
|
absDacl = NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
if ( owner_size )
|
||
|
{
|
||
|
absOwner = (PSID)malloc(owner_size);
|
||
|
if (!absOwner)
|
||
|
{
|
||
|
free(absSD);
|
||
|
free(absDacl);
|
||
|
free(absSacl);
|
||
|
absSD = NULL;
|
||
|
absDacl = NULL;
|
||
|
absSacl = NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
if ( group_size )
|
||
|
{
|
||
|
absGroup = (PSID)malloc(group_size);
|
||
|
if (!absGroup)
|
||
|
{
|
||
|
free(absSD);
|
||
|
free(absDacl);
|
||
|
free(absSacl);
|
||
|
free(absOwner);
|
||
|
absSD = NULL;
|
||
|
absDacl = NULL;
|
||
|
absSacl = NULL;
|
||
|
absOwner = NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// try again with bigger buffers
|
||
|
if ( ! MakeAbsoluteSD(pSD,absSD,&sd_size,absDacl,&dacl_size,absSacl,&sacl_size
|
||
|
,absOwner,&owner_size,absGroup,&group_size) )
|
||
|
{
|
||
|
free(absSD);
|
||
|
free(absDacl);
|
||
|
free(absSacl);
|
||
|
free(absOwner);
|
||
|
free(absGroup);
|
||
|
absSD = NULL;
|
||
|
absDacl = NULL;
|
||
|
absSacl = NULL;
|
||
|
absOwner = NULL;
|
||
|
absGroup = NULL;
|
||
|
}
|
||
|
}
|
||
|
return absSD;
|
||
|
}
|
||
|
|
||
|
SECURITY_DESCRIPTOR * // ret- copy of the SD, in Absolute format
|
||
|
TSD::MakeAbsSD() const
|
||
|
{
|
||
|
SECURITY_DESCRIPTOR * absSD = NULL;
|
||
|
SECURITY_DESCRIPTOR * relSD = MakeRelSD();
|
||
|
if (relSD)
|
||
|
{
|
||
|
absSD = MakeAbsSD(relSD);
|
||
|
free(relSD);
|
||
|
}
|
||
|
|
||
|
return absSD;
|
||
|
}
|
||
|
|
||
|
SECURITY_DESCRIPTOR * // ret- copy of the SD, in self-relative form
|
||
|
TSD::MakeRelSD() const
|
||
|
{
|
||
|
DWORD nBytes;
|
||
|
SECURITY_DESCRIPTOR * relSD = NULL;
|
||
|
|
||
|
nBytes = GetSecurityDescriptorLength(m_absSD);
|
||
|
relSD = (SECURITY_DESCRIPTOR *)malloc(nBytes);
|
||
|
if (!relSD)
|
||
|
return NULL;
|
||
|
|
||
|
if (! MakeSelfRelativeSD(m_absSD,relSD,&nBytes) )
|
||
|
{
|
||
|
free(relSD);
|
||
|
relSD = NULL;
|
||
|
}
|
||
|
return relSD;
|
||
|
}
|
||
|
|
||
|
PSID const // ret- sid for security descriptor owner field
|
||
|
TSD::GetOwner() const
|
||
|
{
|
||
|
PSID ownersid = NULL;
|
||
|
BOOL ownerDefaulted;
|
||
|
|
||
|
GetSecurityDescriptorOwner(m_absSD,&ownersid,&ownerDefaulted);
|
||
|
|
||
|
return ownersid;
|
||
|
}
|
||
|
void
|
||
|
TSD::SetOwner(
|
||
|
PSID pNewOwner // in - new value for owner field
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(IsValidSecurityDescriptor(m_absSD));
|
||
|
|
||
|
if ( IsValidSid(pNewOwner) )
|
||
|
{
|
||
|
if ( m_bNeedToFreeOwner )
|
||
|
{
|
||
|
PSID old = GetOwner();
|
||
|
|
||
|
free(old);
|
||
|
}
|
||
|
|
||
|
SetSecurityDescriptorOwner(m_absSD,pNewOwner,FALSE);
|
||
|
m_bOwnerChanged = TRUE;
|
||
|
m_bNeedToFreeOwner = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSVERIFY(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PSID const // ret- sid for security descriptor owner field
|
||
|
TSD::GetGroup() const
|
||
|
{
|
||
|
PSID grpsid = NULL;
|
||
|
BOOL grpDefaulted;
|
||
|
|
||
|
MCSVERIFY(IsValidSecurityDescriptor(m_absSD));
|
||
|
GetSecurityDescriptorGroup(m_absSD,&grpsid,&grpDefaulted);
|
||
|
|
||
|
return grpsid;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSD::SetGroup(
|
||
|
PSID pNewGroup // in - new value for primary group field.
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(IsValidSecurityDescriptor(m_absSD));
|
||
|
|
||
|
if ( IsValidSid(pNewGroup) )
|
||
|
{
|
||
|
if ( m_bNeedToFreeGroup )
|
||
|
{
|
||
|
PSID old = GetGroup();
|
||
|
|
||
|
free(old);
|
||
|
}
|
||
|
SetSecurityDescriptorGroup(m_absSD,pNewGroup,FALSE);
|
||
|
m_bGroupChanged = TRUE;
|
||
|
m_bNeedToFreeGroup = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSVERIFY(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PACL const // ret- pointer to DACL
|
||
|
TSD::GetDacl() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted;
|
||
|
BOOL present;
|
||
|
|
||
|
GetSecurityDescriptorDacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return acl;
|
||
|
}
|
||
|
void
|
||
|
TSD::SetDacl(
|
||
|
PACL pNewAcl, // in - new DACL
|
||
|
BOOL present // in - flag, TRUE means DACL is present.
|
||
|
)
|
||
|
{
|
||
|
BOOL defaulted = FALSE;
|
||
|
|
||
|
if ( IsValidAcl(pNewAcl) )
|
||
|
{
|
||
|
if ( m_bNeedToFreeDacl )
|
||
|
{
|
||
|
PACL old = GetDacl();
|
||
|
|
||
|
if ( old != pNewAcl )
|
||
|
{
|
||
|
free(old);
|
||
|
}
|
||
|
}
|
||
|
if (! SetSecurityDescriptorDacl(m_absSD,present,pNewAcl,defaulted) )
|
||
|
{
|
||
|
// DWORD rc = GetLastError();
|
||
|
}
|
||
|
m_bDACLChanged = TRUE;
|
||
|
m_bNeedToFreeDacl = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSVERIFY(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PACL const // ret- pointer to SACL
|
||
|
TSD::GetSacl() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted;
|
||
|
BOOL present;
|
||
|
|
||
|
GetSecurityDescriptorSacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return acl;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSD::SetSacl(
|
||
|
PACL pNewAcl, // in - new SACL
|
||
|
BOOL present // in - flag, TRUE means SACL is present
|
||
|
)
|
||
|
{
|
||
|
BOOL defaulted = FALSE;
|
||
|
|
||
|
if ( IsValidAcl(pNewAcl) )
|
||
|
{
|
||
|
if ( m_bNeedToFreeSacl )
|
||
|
{
|
||
|
PACL old = GetSacl();
|
||
|
|
||
|
if ( old != pNewAcl )
|
||
|
{
|
||
|
free(old);
|
||
|
}
|
||
|
}
|
||
|
SetSecurityDescriptorSacl(m_absSD,present,pNewAcl,defaulted);
|
||
|
m_bSACLChanged = TRUE;
|
||
|
m_bNeedToFreeSacl = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSVERIFY(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
TSD::IsOwnerDefaulted() const
|
||
|
{
|
||
|
PSID ownersid = NULL;
|
||
|
BOOL ownerDefaulted = FALSE;
|
||
|
|
||
|
GetSecurityDescriptorOwner(m_absSD,&ownersid,&ownerDefaulted);
|
||
|
|
||
|
return ownerDefaulted;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TSD::IsGroupDefaulted() const
|
||
|
{
|
||
|
PSID groupsid = NULL;
|
||
|
BOOL groupDefaulted = FALSE;
|
||
|
|
||
|
GetSecurityDescriptorGroup(m_absSD,&groupsid,&groupDefaulted);
|
||
|
|
||
|
return groupDefaulted;
|
||
|
|
||
|
}
|
||
|
BOOL
|
||
|
TSD::IsDaclDefaulted() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted = FALSE;
|
||
|
BOOL present;
|
||
|
|
||
|
GetSecurityDescriptorDacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return defaulted;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TSD::IsDaclPresent() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted;
|
||
|
BOOL present = FALSE;
|
||
|
|
||
|
GetSecurityDescriptorDacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return present;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TSD::IsSaclDefaulted() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted = FALSE;
|
||
|
BOOL present;
|
||
|
|
||
|
GetSecurityDescriptorSacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return defaulted;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TSD::IsSaclPresent() const
|
||
|
{
|
||
|
PACL acl = NULL;
|
||
|
BOOL defaulted;
|
||
|
BOOL present = FALSE;
|
||
|
|
||
|
GetSecurityDescriptorSacl(m_absSD,&present,&acl,&defaulted);
|
||
|
|
||
|
return present;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TSD::operator == (TSD & otherSD)
|
||
|
{
|
||
|
return EqualSD(&otherSD);
|
||
|
}
|
||
|
|
||
|
// Compares the relative SDs (relSD) for 2 TSecurityDescriptor's.
|
||
|
// true -> SDs are equal, false -> SDs are not equal
|
||
|
BOOL // ret -true iff *(this->relSD) == *(otherSD->relSD)
|
||
|
TSD::EqualSD(
|
||
|
TSD * otherSD // in -TSecurityDescriptor to compare this SD to
|
||
|
)
|
||
|
{
|
||
|
PSID ps1;
|
||
|
PSID ps2;
|
||
|
PACL acl1;
|
||
|
PACL acl2;
|
||
|
BOOL diffound = FALSE;
|
||
|
|
||
|
|
||
|
// both must be valid SD's
|
||
|
|
||
|
ps1 = NULL;
|
||
|
ps2 = NULL;
|
||
|
// if GetSecurityDescriptor* fails, EqualSid, or ACLCompare will fail
|
||
|
|
||
|
// Compare owners
|
||
|
ps1 = GetOwner();
|
||
|
ps2 = otherSD->GetOwner();
|
||
|
if ((ps1) && (ps2) && (! EqualSid(ps1,ps2)))
|
||
|
{
|
||
|
diffound = TRUE;
|
||
|
}
|
||
|
ps1 = NULL;
|
||
|
ps2 = NULL;
|
||
|
// Compare Groups
|
||
|
if ( ! diffound )
|
||
|
{
|
||
|
ps1 = GetGroup();
|
||
|
ps2 = otherSD->GetGroup();
|
||
|
if ((ps1) && (ps2) && (! EqualSid(ps1,ps2)))
|
||
|
{
|
||
|
diffound = TRUE;
|
||
|
}
|
||
|
acl1 = NULL;
|
||
|
acl2 = NULL;
|
||
|
}
|
||
|
// Compare DACLs
|
||
|
if ( ! diffound )
|
||
|
{
|
||
|
acl1 = GetDacl();
|
||
|
acl2 = otherSD->GetDacl();
|
||
|
|
||
|
if ((acl1) && (acl2) &&
|
||
|
(!ACLCompare(acl1,IsDaclPresent(),acl2,otherSD->IsDaclPresent())))
|
||
|
{
|
||
|
diffound = TRUE;
|
||
|
}
|
||
|
}
|
||
|
// Compare SACLs
|
||
|
if ( ! diffound )
|
||
|
{
|
||
|
acl1 = GetSacl();
|
||
|
acl2 = otherSD->GetSacl();
|
||
|
|
||
|
if ((acl1) && (acl2))
|
||
|
diffound = (! ACLCompare(acl1,IsSaclPresent(),acl2,otherSD->IsSaclPresent()) );
|
||
|
}
|
||
|
return ! diffound;
|
||
|
}
|
||
|
|
||
|
BOOL // ret- TRUE if both ACLs are the same
|
||
|
TSD::ACLCompare(
|
||
|
PACL acl1, // in -ptr to first acl to compare
|
||
|
BOOL present1, // in -present flag for acl1
|
||
|
PACL acl2, // in -ptr to second acl to compare
|
||
|
BOOL present2 // in -present flag for acl2
|
||
|
)
|
||
|
{
|
||
|
DWORD size1;
|
||
|
DWORD size2;
|
||
|
bool same = true;
|
||
|
|
||
|
if ( present1 && present2 )
|
||
|
{
|
||
|
if ( ( !acl1 && acl2 )
|
||
|
|| ( acl1 && ! acl2 ) )
|
||
|
{
|
||
|
same = false;
|
||
|
}
|
||
|
if ( acl1 && acl2)
|
||
|
{
|
||
|
size1 = acl1->AclSize;
|
||
|
size2 = acl2->AclSize;
|
||
|
if ( size1 != size2 )
|
||
|
{
|
||
|
same = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( memcmp(acl1,acl2,size1) )
|
||
|
{
|
||
|
same = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( present1 || present2 )
|
||
|
{
|
||
|
same = false;
|
||
|
}
|
||
|
}
|
||
|
return same;
|
||
|
}
|
||
|
|
||
|
int // ret- number of aces in the ACL
|
||
|
TSD::ACLGetNumAces(
|
||
|
PACL acl // in - DACL or SACL
|
||
|
)
|
||
|
{
|
||
|
int nAces = 0;
|
||
|
ACL_SIZE_INFORMATION info;
|
||
|
|
||
|
if ( acl )
|
||
|
{
|
||
|
if ( GetAclInformation(acl,&info,(sizeof info),AclSizeInformation) )
|
||
|
{
|
||
|
nAces = info.AceCount;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// DWORD rc=GetLastError();
|
||
|
}
|
||
|
}
|
||
|
return nAces;
|
||
|
}
|
||
|
|
||
|
DWORD // ret- number of free bytes in the ACL
|
||
|
TSD::ACLGetFreeBytes(
|
||
|
PACL acl // in - DACL or SACL
|
||
|
)
|
||
|
{
|
||
|
int nFree = 0;
|
||
|
|
||
|
ACL_SIZE_INFORMATION info;
|
||
|
|
||
|
if ( acl )
|
||
|
{
|
||
|
if ( GetAclInformation(acl,&info,(sizeof info),AclSizeInformation) )
|
||
|
{
|
||
|
nFree = info.AclBytesFree;
|
||
|
}
|
||
|
}
|
||
|
return nFree;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD // ret- number of used bytes in the ACL
|
||
|
TSD::ACLGetBytesInUse(
|
||
|
PACL acl // in - DACL or SACL
|
||
|
)
|
||
|
{
|
||
|
int nBytes = 0;
|
||
|
|
||
|
ACL_SIZE_INFORMATION info;
|
||
|
|
||
|
if ( acl )
|
||
|
{
|
||
|
if ( GetAclInformation(acl,&info,(sizeof info),AclSizeInformation) )
|
||
|
{
|
||
|
nBytes = info.AclBytesInUse;
|
||
|
}
|
||
|
}
|
||
|
return nBytes;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void * // ret- pointer to ace
|
||
|
TSD::ACLGetAce(
|
||
|
PACL acl, // in - DACL or SACL
|
||
|
int ndx // in - index of ace to retrieve
|
||
|
)
|
||
|
{
|
||
|
void * ace = NULL;
|
||
|
|
||
|
if ( ndx < ACLGetNumAces(acl) )
|
||
|
{
|
||
|
if ( ! GetAce(acl,ndx,(void**)&ace) )
|
||
|
{
|
||
|
ace = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSASSERT(FALSE); // you specified a non-existant index
|
||
|
}
|
||
|
return ace;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSD::ACLDeleteAce(
|
||
|
PACL acl, // in - DACL or SACL
|
||
|
int ndx // in - index of ace to delete
|
||
|
)
|
||
|
{
|
||
|
int nAces = ACLGetNumAces(acl);
|
||
|
|
||
|
if ( ndx < nAces )
|
||
|
{
|
||
|
DeleteAce(acl,ndx);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MCSASSERT(FALSE); // you specified an invalid index
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Access allowed aces are added at the beginning of the list, access denied aces are added at the end of the list
|
||
|
void
|
||
|
TSD::ACLAddAce(
|
||
|
PACL * ppAcl, // i/o- DACL or SACL (this function may reallocate if the acl doesn't have room
|
||
|
TACE * pAce, // in - ACE to add
|
||
|
int pos // in - position
|
||
|
)
|
||
|
{
|
||
|
DWORD ndx = (DWORD)pos;
|
||
|
DWORD rc;
|
||
|
PACL acl = (*ppAcl);
|
||
|
PACL newAcl;
|
||
|
DWORD numaces = ACLGetNumAces(acl);
|
||
|
DWORD freebytes = ACLGetFreeBytes(acl);
|
||
|
|
||
|
if (!pAce->GetBuffer())
|
||
|
return;
|
||
|
|
||
|
// allocate a new ACL if it doesn't already exist
|
||
|
if ( ! acl )
|
||
|
{
|
||
|
acl = (PACL) malloc(SD_DEFAULT_ACL_SIZE);
|
||
|
if (!acl)
|
||
|
return;
|
||
|
InitializeAcl(acl,SD_DEFAULT_ACL_SIZE,ACL_REVISION);
|
||
|
numaces = ACLGetNumAces(acl);
|
||
|
freebytes = ACLGetFreeBytes(acl);
|
||
|
}
|
||
|
|
||
|
if ( pos == -1 )
|
||
|
{
|
||
|
if ( pAce->IsAccessAllowedAce() )
|
||
|
{
|
||
|
ndx = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ndx = MAXDWORD; // insert at end of the list
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WORD currAceSize = pAce->GetSize();
|
||
|
|
||
|
if ( freebytes < currAceSize ) // we must allocate more space for the ace
|
||
|
{
|
||
|
//make a bigger acl
|
||
|
newAcl = (ACL*)malloc(ACLGetBytesInUse(acl) + freebytes + currAceSize);
|
||
|
if (!newAcl)
|
||
|
{
|
||
|
free(acl);
|
||
|
acl = NULL;
|
||
|
return;
|
||
|
}
|
||
|
memcpy(newAcl,acl,ACLGetBytesInUse(acl) + freebytes);
|
||
|
newAcl->AclSize +=currAceSize;
|
||
|
free(acl);
|
||
|
|
||
|
acl = newAcl;
|
||
|
}
|
||
|
|
||
|
if (! AddAce(acl,ACL_REVISION,ndx,pAce->GetBuffer(),currAceSize) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
}
|
||
|
(*ppAcl) = acl;
|
||
|
}
|
||
|
|
||
|
// creates a new ace with the specified properties
|
||
|
TACE::TACE(
|
||
|
BYTE type, // in - type of ace (ACCESS_ALLOWED_ACE_TYPE, etc.)
|
||
|
BYTE flags, // in - ace flags (controls inheritance, etc. use 0 for files)
|
||
|
DWORD mask, // in - access control mask (see constants in sd.hpp)
|
||
|
PSID sid // in - pointer to sid for this ace
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(sid);
|
||
|
// allocate memory for the new ace
|
||
|
DWORD size = (sizeof ACCESS_ALLOWED_ACE) + GetLengthSid(sid) - (sizeof DWORD);
|
||
|
|
||
|
m_pAce = (ACCESS_ALLOWED_ACE *)malloc(size);
|
||
|
|
||
|
// Initialize the ACE
|
||
|
if (m_pAce)
|
||
|
{
|
||
|
m_bNeedToFree = TRUE;
|
||
|
m_pAce->Header.AceType = type;
|
||
|
m_pAce->Header.AceFlags = flags;
|
||
|
m_pAce->Header.AceSize = (WORD) size;
|
||
|
m_pAce->Mask = mask;
|
||
|
memcpy(&m_pAce->SidStart,sid,GetLengthSid(sid));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BYTE // ret- ace type (ACCESS_ALLOWED_ACE_TYPE, etc.)
|
||
|
TACE::GetType()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
BYTE type = ACCESS_ALLOWED_ACE_TYPE;
|
||
|
|
||
|
if (m_pAce)
|
||
|
type = m_pAce->Header.AceType;
|
||
|
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
BYTE // ret- ace flags (OBJECT_INHERIT_ACE, etc.)
|
||
|
TACE::GetFlags()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
BYTE flags = OBJECT_INHERIT_ACE;
|
||
|
|
||
|
if (m_pAce)
|
||
|
flags = m_pAce->Header.AceFlags;
|
||
|
|
||
|
return flags;
|
||
|
}
|
||
|
|
||
|
DWORD // ret- access control mask
|
||
|
TACE::GetMask()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
DWORD mask = 0;
|
||
|
|
||
|
if (m_pAce)
|
||
|
mask = m_pAce->Mask;
|
||
|
|
||
|
return mask;
|
||
|
|
||
|
}
|
||
|
|
||
|
PSID // ret- sid for this ace
|
||
|
TACE::GetSid()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
PSID pSid = NULL;
|
||
|
|
||
|
if (m_pAce)
|
||
|
pSid = &m_pAce->SidStart;
|
||
|
|
||
|
return pSid;
|
||
|
}
|
||
|
|
||
|
WORD // ret- size of the ace, in bytes
|
||
|
TACE::GetSize()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
WORD size = 0;
|
||
|
|
||
|
if (m_pAce)
|
||
|
size = m_pAce->Header.AceSize;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
TACE::SetType(
|
||
|
BYTE newType // in -new type for ace
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
if (!m_pAce)
|
||
|
return FALSE;
|
||
|
|
||
|
MCSASSERT( newType=ACCESS_ALLOWED_ACE_TYPE ||
|
||
|
newType==ACCESS_DENIED_ACE_TYPE ||
|
||
|
newType==SYSTEM_AUDIT_ACE_TYPE );
|
||
|
|
||
|
m_pAce->Header.AceType = newType;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TACE::SetFlags(
|
||
|
BYTE newFlags // in - new flags for ace
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
if (!m_pAce)
|
||
|
return FALSE;
|
||
|
|
||
|
m_pAce->Header.AceFlags = newFlags;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TACE::SetMask(
|
||
|
DWORD newMask // in - new access control mask
|
||
|
)
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
if (!m_pAce)
|
||
|
return FALSE;
|
||
|
|
||
|
m_pAce->Mask = newMask;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TACE::SetSid(
|
||
|
PSID sid // in - new SID for this ace
|
||
|
)
|
||
|
{
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
MCSVERIFY( m_pAce );
|
||
|
MCSASSERT( IsValidSid(sid) );
|
||
|
MCSASSERT( GetLengthSid(sid) == GetLengthSid(GetSid()) );
|
||
|
|
||
|
if (!m_pAce)
|
||
|
return FALSE;
|
||
|
|
||
|
if ( GetLengthSid(sid) <= GetLengthSid(GetSid()) )
|
||
|
{
|
||
|
memcpy(&m_pAce->SidStart,sid,GetLengthSid(sid));
|
||
|
result = TRUE;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
TACE::IsAccessAllowedAce()
|
||
|
{
|
||
|
MCSVERIFY(m_pAce);
|
||
|
|
||
|
return ( GetType() == ACCESS_ALLOWED_ACE_TYPE );
|
||
|
}
|