// AccessAttributes.cpp: implementation of the CAccessAttributes class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AccessAttributes.h"
#include <lmcons.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAccessAttributes::CAccessAttributes(PACL pAcl)
{
// Initialise our security attributes to give access to
// anyone (including LocalService).
memset(&m_sa, 0, sizeof(m_sa));
m_sa.nLength = sizeof(m_sa);
InitializeSecurityDescriptor(&m_sd, SECURITY_DESCRIPTOR_REVISION);
m_pGroupSid = m_pOwnerSid = PSID(NULL);
SetOwner();
SetDACL(pAcl);
}
CAccessAttributes::~CAccessAttributes()
{
delete m_pGroupSid;
delete m_pOwnerSid;
}
void CAccessAttributes::SetDACL(PACL pAcl)
{
SetSecurityDescriptorDacl(&m_sd, TRUE, pAcl, FALSE);
m_sa.lpSecurityDescriptor = &m_sd;
}
void CAccessAttributes::SetSACL(PACL pAcl)
{
SetSecurityDescriptorSacl(&m_sd, TRUE, pAcl, FALSE);
m_sa.lpSecurityDescriptor = &m_sd;
}
bool CAccessAttributes::SetOwner(LPCTSTR pszOwner, LPCTSTR pszServer)
{
TCHAR tszOwner[UNLEN + 1];
DWORD dwLen = UNLEN;
PSID pSid = PSID(NULL);
if (pszOwner == NULL)
// Default setting, make ourselves the owner
GetUserName(tszOwner, &dwLen);
else
_tcsncpy(tszOwner, pszOwner, UNLEN);
if ((pSid = GetSid(tszOwner, pszServer)) != PSID(NULL))
{
delete m_pOwnerSid;
m_pOwnerSid = pSid;
SetSecurityDescriptorOwner(&m_sd, m_pOwnerSid, FALSE);
return true;
}
return false;
}
bool CAccessAttributes::SetGroup(LPCTSTR pszGroup, LPCTSTR pszServer)
{
PSID pSid = PSID(NULL);
if ((pSid = GetSid(pszGroup, pszServer)) != PSID(NULL))
{
delete m_pGroupSid;
m_pGroupSid = pSid;
SetSecurityDescriptorGroup(&m_sd, m_pGroupSid, FALSE);
return true;
}
return false;
}
// Global function to get a SID given a name and a server
PSID GetSid(LPCTSTR pszName, LPCTSTR pszServer)
{
PSID pSid = PSID(NULL);
TCHAR ptszDomainName[256];
DWORD dwSIDSize = 0,
dwDomainNameSize = sizeof(ptszDomainName);
SID_NAME_USE snuType = SidTypeUnknown;
LookupAccountName(pszServer, pszName, NULL, &dwSIDSize, NULL, &dwDomainNameSize, &snuType);
if (dwSIDSize)
{
// Success, now allocate our buffers
pSid = (PSID) new BYTE[dwSIDSize];
if (!LookupAccountName(NULL, pszName, pSid, &dwSIDSize, ptszDomainName, &dwDomainNameSize, &snuType))
{
delete pSid;
pSid = PSID(NULL);
}
}
return pSid;
}
// Helper class
CAccessControlList::CAccessEntry::CAccessEntry(eAceType type, PSID pSid, UINT uiRights)
{
m_type = type;
m_pSid = pSid;
m_uiRights = uiRights;
}
CAccessControlList::CAccessEntry::~CAccessEntry()
{
delete m_pSid;
}
// The access control list itself
CAccessControlList::CAccessControlList()
{
m_pAcl = PACL(NULL);
m_uiAclSize = sizeof(ACL);
}
CAccessControlList::~CAccessControlList()
{
list<CAccessEntry *>::const_iterator it = m_lAce.begin();
CAccessEntry *ae;
while (it != m_lAce.end())
{
ae = *it++;
delete ae;
}
delete m_pAcl;
}
bool CAccessControlList::Allow(LPCTSTR pszName, UINT uiRights, LPCTSTR pszServer)
{
assert(pszName);
PSID pSid = GetSid(pszName, pszServer);
if (pSid != PSID(NULL) && IsValidSid(pSid))
{
m_uiAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
m_lAce.push_back(new CAccessEntry(eAllow, pSid, uiRights));
return true;
}
return false;
}
bool CAccessControlList::Deny(LPCTSTR pszName, UINT uiRights, LPCTSTR pszServer)
{
assert(pszName);
PSID pSid = GetSid(pszName, pszServer);
if (pSid != PSID(NULL) && IsValidSid(pSid))
{
m_uiAclSize += sizeof(ACCESS_DENIED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
m_lAce.push_back(new CAccessEntry(eDeny, pSid, uiRights));
return true;
}
return false;
}
PACL CAccessControlList::operator&()
{
delete m_pAcl;
m_pAcl = (PACL) new BYTE[m_uiAclSize];
// Change the ACL_REVISION_DS constant to ACL_REVISION if you want to support
// Windows NT 4.0 or earlier
InitializeAcl(m_pAcl, m_uiAclSize, ACL_REVISION_DS);
AddAces(eDeny);
AddAces(eAllow);
return m_pAcl;
}
void CAccessControlList::AddAces(eAceType type)
{
list<CAccessEntry *>::const_iterator it = m_lAce.begin();
CAccessEntry *ae;
// Change the ACL_REVISION_DS constant to ACL_REVISION if you want to support
// Windows NT 4.0 or earlier
while (it != m_lAce.end())
{
ae = *it++;
if (ae->m_type == type)
{
switch (type)
{
case eDeny:
AddAccessDeniedAce(m_pAcl, ACL_REVISION_DS, ae->m_uiRights, ae->m_pSid);
break;
case eAllow:
AddAccessAllowedAce(m_pAcl, ACL_REVISION_DS, ae->m_uiRights, ae->m_pSid);
break;
}
}
}
}