1224 lines
33 KiB
C++
1224 lines
33 KiB
C++
|
//+--------------------------------------------------------------------------
|
||
|
// File: casd.cpp
|
||
|
// Contents: CCertificateAuthoritySD implementation
|
||
|
//---------------------------------------------------------------------------
|
||
|
#include <pch.cpp>
|
||
|
#include <sid.h>
|
||
|
#include <certsd.h>
|
||
|
#include <certacl.h>
|
||
|
#include <prvlg.h>
|
||
|
#include <sid.h>
|
||
|
//
|
||
|
// MessageId: CERTSRV_E_NO_CAADMIN_DEFINED
|
||
|
//
|
||
|
// MessageText:
|
||
|
//
|
||
|
// At least one security principal must have the permission to manage this CA.
|
||
|
//
|
||
|
#define CERTSRV_E_NO_CAADMIN_DEFINED _HRESULT_TYPEDEF_(0x8009400DL)
|
||
|
|
||
|
LPCWSTR const *CCertificateAuthoritySD::m_pcwszResources; // no free
|
||
|
|
||
|
using namespace CertSrv;
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::Set(
|
||
|
const PSECURITY_DESCRIPTOR pSD,
|
||
|
bool fSetDSSecurity)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
PSECURITY_DESCRIPTOR pSDCrt; // no free
|
||
|
PSECURITY_DESCRIPTOR pSDNew = NULL;
|
||
|
SECURITY_DESCRIPTOR_CONTROL sdc;
|
||
|
CPrivilegeManager PrivilegeMgr;
|
||
|
|
||
|
CSASSERT(NULL != pSD);
|
||
|
|
||
|
hr = LockGet(&pSDCrt);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
|
||
|
|
||
|
hr = myMergeSD(pSDCrt, pSD, DACL_SECURITY_INFORMATION, &pSDNew);
|
||
|
_JumpIfError(hr, error, "myMergeSD");
|
||
|
|
||
|
hr = Unlock();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
|
||
|
|
||
|
hr = CProtectedSecurityDescriptor::Set(pSDNew);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
|
||
|
|
||
|
hr = MapAndSetDaclOnObjects(fSetDSSecurity);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAndSetDaclOnObjects");
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pSDNew);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::MapAndSetDaclOnObjects(bool fSetDSSecurity)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
PACL pCADacl; // no free
|
||
|
PACL pDSAcl = NULL;
|
||
|
PACL pServiceAcl = NULL;
|
||
|
PSECURITY_DESCRIPTOR pCASD; // no free
|
||
|
BOOL fDaclPresent;
|
||
|
ACL_SIZE_INFORMATION CAAclInfo, DefaultDSAclInfo, DefaultServiceAclInfo;
|
||
|
DWORD dwIndex, dwIndex2, dwIndex3;
|
||
|
PVOID pAce;
|
||
|
DWORD dwDSAclSize=0, dwServiceAclSize=0;
|
||
|
DWORD dwTempSize;
|
||
|
|
||
|
hr = LockGet(&pCASD);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
pCASD,
|
||
|
&pCADacl);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
|
||
|
if(!GetAclInformation(pCADacl,
|
||
|
&CAAclInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
// calculate the DACL size
|
||
|
for(dwIndex = 0; dwIndex < CAAclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
if(!GetAce(pCADacl, dwIndex, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
hr = MapAclGetSize(pAce, ObjType_DS, dwTempSize);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclGetSize");
|
||
|
}
|
||
|
|
||
|
dwDSAclSize += dwTempSize;
|
||
|
|
||
|
hr = MapAclGetSize(pAce, ObjType_Service, dwTempSize);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclGetSize");
|
||
|
|
||
|
dwServiceAclSize += dwTempSize;
|
||
|
}
|
||
|
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
hr = SetDefaultAcl(ObjType_DS);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::SetDefaultAcl");
|
||
|
|
||
|
if(!GetAclInformation(m_pDefaultDSAcl,
|
||
|
&DefaultDSAclInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
CSASSERT(0==DefaultDSAclInfo.AclBytesFree);
|
||
|
|
||
|
dwDSAclSize += DefaultDSAclInfo.AclBytesInUse;
|
||
|
|
||
|
pDSAcl = (PACL)LocalAlloc(LMEM_FIXED, dwDSAclSize);
|
||
|
if(!pDSAcl)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if(!InitializeAcl(pDSAcl, dwDSAclSize, ACL_REVISION_DS ))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hr = SetDefaultAcl(ObjType_Service);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::SetDefaultAcl");
|
||
|
|
||
|
if(!GetAclInformation(m_pDefaultServiceAcl,
|
||
|
&DefaultServiceAclInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
CSASSERT(0==DefaultServiceAclInfo.AclBytesFree);
|
||
|
|
||
|
dwServiceAclSize += DefaultServiceAclInfo.AclBytesInUse;
|
||
|
|
||
|
pServiceAcl = (PACL)LocalAlloc(LMEM_FIXED, dwServiceAclSize);
|
||
|
if(!pServiceAcl)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if(!InitializeAcl(pServiceAcl, dwServiceAclSize, ACL_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
|
||
|
// copy deny aces from default service acl
|
||
|
for(dwIndex = 0; dwIndex < DefaultServiceAclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
if(!GetAce(m_pDefaultServiceAcl, dwIndex, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE)
|
||
|
continue;
|
||
|
|
||
|
if(!AddAce(
|
||
|
pServiceAcl,
|
||
|
ACL_REVISION,
|
||
|
MAXDWORD,
|
||
|
pAce,
|
||
|
((ACE_HEADER*)pAce)->AceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAce");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
// copy deny aces from default ds acl
|
||
|
for(dwIndex3 = 0; dwIndex3 < DefaultDSAclInfo.AceCount; dwIndex3++)
|
||
|
{
|
||
|
if(!GetAce(m_pDefaultDSAcl, dwIndex3, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE &&
|
||
|
((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_OBJECT_ACE_TYPE)
|
||
|
continue;
|
||
|
|
||
|
if(!AddAce(
|
||
|
pDSAcl,
|
||
|
ACL_REVISION_DS,
|
||
|
MAXDWORD,
|
||
|
pAce,
|
||
|
((ACE_HEADER*)pAce)->AceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAce");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// add mapped deny aces to the DACL
|
||
|
for(dwIndex2 = 0; dwIndex2 < CAAclInfo.AceCount; dwIndex2++)
|
||
|
{
|
||
|
if(!GetAce(pCADacl, dwIndex2, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_DENIED_ACE_TYPE)
|
||
|
continue;
|
||
|
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
hr = MapAclAddAce(pDSAcl, ObjType_DS, pAce);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
|
||
|
}
|
||
|
|
||
|
hr = MapAclAddAce(pServiceAcl, ObjType_Service, pAce);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
|
||
|
}
|
||
|
|
||
|
// continue with the allow aces from default service acl
|
||
|
for(dwIndex=0; dwIndex < DefaultServiceAclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
if(!GetAce(m_pDefaultServiceAcl, dwIndex, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE)
|
||
|
continue;
|
||
|
|
||
|
if(!AddAce(
|
||
|
pServiceAcl,
|
||
|
ACL_REVISION,
|
||
|
MAXDWORD,
|
||
|
pAce,
|
||
|
((ACE_HEADER*)pAce)->AceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAce");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// continue with the allow aces from default ds acl
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
for(dwIndex3=0; dwIndex3 < DefaultDSAclInfo.AceCount; dwIndex3++)
|
||
|
{
|
||
|
if(!GetAce(m_pDefaultDSAcl, dwIndex3, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE &&
|
||
|
((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_OBJECT_ACE_TYPE)
|
||
|
continue;
|
||
|
|
||
|
if(!AddAce(
|
||
|
pDSAcl,
|
||
|
ACL_REVISION_DS,
|
||
|
MAXDWORD,
|
||
|
pAce,
|
||
|
((ACE_HEADER*)pAce)->AceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAce");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// continue with the allow mapped aces to the DACL
|
||
|
for(dwIndex2=0;dwIndex2 < CAAclInfo.AceCount; dwIndex2++)
|
||
|
{
|
||
|
if(!GetAce(pCADacl, dwIndex2, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
hr = MapAclAddAce(pDSAcl, ObjType_DS, pAce);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
|
||
|
}
|
||
|
|
||
|
hr = MapAclAddAce(pServiceAcl, ObjType_Service, pAce);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclAddAce");
|
||
|
}
|
||
|
|
||
|
hr = Unlock();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
|
||
|
|
||
|
hr = MapAclSetOnService(pServiceAcl);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclSetOnService");
|
||
|
|
||
|
// set DACL on objects
|
||
|
if(fSetDSSecurity)
|
||
|
{
|
||
|
hr = MapAclSetOnDS(pDSAcl);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::MapAclSetOnDS");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pDSAcl);
|
||
|
LOCAL_FREE(pServiceAcl);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::MapAclGetSize(
|
||
|
PVOID pAce,
|
||
|
ObjType type,
|
||
|
DWORD& dwSize)
|
||
|
{
|
||
|
ACCESS_ALLOWED_ACE *pAllowAce = (ACCESS_ALLOWED_ACE*)pAce;
|
||
|
|
||
|
// CA acl should contain only ACCESS_ALLOWED_ACE_TYPE
|
||
|
// and ACCESS_DENIED_ACE_TYPE
|
||
|
if(ACCESS_ALLOWED_ACE_TYPE != pAllowAce->Header.AceType &&
|
||
|
ACCESS_DENIED_ACE_TYPE != pAllowAce->Header.AceType)
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
dwSize = 0;
|
||
|
|
||
|
switch(type)
|
||
|
{
|
||
|
case ObjType_DS:
|
||
|
// enroll access maps to enroll object ace on DS
|
||
|
if(pAllowAce->Mask & CA_ACCESS_ENROLL)
|
||
|
{
|
||
|
dwSize = sizeof(ACCESS_ALLOWED_OBJECT_ACE) - sizeof(DWORD)+
|
||
|
GetLengthSid((PSID)&(pAllowAce->SidStart));
|
||
|
}
|
||
|
break;
|
||
|
case ObjType_Service:
|
||
|
// ca admin maps to full control on service
|
||
|
if(pAllowAce->Mask & CA_ACCESS_ADMIN)
|
||
|
{
|
||
|
dwSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)+
|
||
|
GetLengthSid((PSID)&(pAllowAce->SidStart));
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
CSASSERT("Invalid object type" && 0);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::MapAclAddAce(
|
||
|
PACL pAcl,
|
||
|
ObjType type,
|
||
|
PVOID pAce)
|
||
|
{
|
||
|
ACCESS_ALLOWED_ACE *pCrtAce = (ACCESS_ALLOWED_ACE *)pAce;
|
||
|
bool fAllowAce = (pCrtAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE);
|
||
|
|
||
|
CSASSERT(pCrtAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ||
|
||
|
pCrtAce->Header.AceType == ACCESS_DENIED_ACE_TYPE);
|
||
|
|
||
|
switch(type)
|
||
|
{
|
||
|
case ObjType_DS:
|
||
|
// enroll access maps to enroll object ace on DS
|
||
|
if(pCrtAce->Mask & CA_ACCESS_ENROLL)
|
||
|
{
|
||
|
if(fAllowAce)
|
||
|
{
|
||
|
if(!AddAccessAllowedObjectAce(
|
||
|
pAcl,
|
||
|
ACL_REVISION_DS,
|
||
|
NO_INHERITANCE,
|
||
|
ACTRL_DS_CONTROL_ACCESS,
|
||
|
const_cast<GUID*>(&GUID_ENROLL),
|
||
|
NULL,
|
||
|
&pCrtAce->SidStart))
|
||
|
{
|
||
|
return myHLastError();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(!AddAccessDeniedObjectAce(
|
||
|
pAcl,
|
||
|
ACL_REVISION_DS,
|
||
|
NO_INHERITANCE,
|
||
|
ACTRL_DS_CONTROL_ACCESS,
|
||
|
const_cast<GUID*>(&GUID_ENROLL),
|
||
|
NULL,
|
||
|
&pCrtAce->SidStart))
|
||
|
{
|
||
|
return myHLastError();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ObjType_Service:
|
||
|
// ca admin maps to full control on service
|
||
|
if(pCrtAce->Mask & CA_ACCESS_ADMIN)
|
||
|
{
|
||
|
if(fAllowAce)
|
||
|
{
|
||
|
if(!AddAccessAllowedAce(
|
||
|
pAcl,
|
||
|
ACL_REVISION,
|
||
|
SERVICE_ALL_ACCESS,
|
||
|
&pCrtAce->SidStart))
|
||
|
{
|
||
|
return myHLastError();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(!AddAccessDeniedAce(
|
||
|
pAcl,
|
||
|
ACL_REVISION,
|
||
|
SERVICE_ALL_ACCESS,
|
||
|
&pCrtAce->SidStart))
|
||
|
{
|
||
|
return myHLastError();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
CSASSERT("Invalid object type" && 0);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::SetDefaultAcl(ObjType type)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
switch(type)
|
||
|
{
|
||
|
case ObjType_DS:
|
||
|
if(!m_pDefaultDSAcl)
|
||
|
{
|
||
|
hr = SetComputerSID();
|
||
|
_JumpIfError(hr, error, "SetComputerSID");
|
||
|
|
||
|
CSASSERT(!m_pDefaultDSSD);
|
||
|
hr = myGetSDFromTemplate(
|
||
|
WSZ_DEFAULT_DSENROLLMENT_SECURITY,
|
||
|
m_pwszComputerSID,
|
||
|
&m_pDefaultDSSD);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
m_pDefaultDSSD,
|
||
|
&m_pDefaultDSAcl);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ObjType_Service:
|
||
|
if(!m_pDefaultServiceAcl)
|
||
|
{
|
||
|
CSASSERT(!m_pDefaultServiceSD);
|
||
|
hr = myGetSDFromTemplate(
|
||
|
WSZ_DEFAULT_SERVICE_SECURITY,
|
||
|
NULL,
|
||
|
&m_pDefaultServiceSD);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
m_pDefaultServiceSD,
|
||
|
&m_pDefaultServiceAcl);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::SetComputerSID()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LPWSTR pwszDomainName = NULL;
|
||
|
DWORD cDomainName = 0;
|
||
|
LPWSTR pwszComputerName = NULL;
|
||
|
DWORD cbSid;
|
||
|
SID_NAME_USE SidUse;
|
||
|
PBYTE pComputerSID = NULL;
|
||
|
|
||
|
CSASSERT(!m_pwszComputerSID);
|
||
|
|
||
|
hr = myGetComputerObjectName(NameSamCompatible, &pwszComputerName);
|
||
|
_JumpIfError(hr, error, "myGetComputerObjectName");
|
||
|
|
||
|
LookupAccountName(
|
||
|
NULL,
|
||
|
pwszComputerName,
|
||
|
NULL,
|
||
|
&cbSid,
|
||
|
NULL,
|
||
|
&cDomainName,
|
||
|
&SidUse);
|
||
|
if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "LookupAccountName");
|
||
|
}
|
||
|
|
||
|
pwszDomainName = (LPWSTR)LocalAlloc(
|
||
|
LMEM_FIXED,
|
||
|
cDomainName*sizeof(WCHAR));
|
||
|
if(!pwszDomainName)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
pComputerSID = (LPBYTE)LocalAlloc(
|
||
|
LMEM_FIXED,
|
||
|
cbSid);
|
||
|
if(!pComputerSID)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if(!LookupAccountName(
|
||
|
NULL,
|
||
|
pwszComputerName,
|
||
|
pComputerSID,
|
||
|
&cbSid,
|
||
|
pwszDomainName,
|
||
|
&cDomainName,
|
||
|
&SidUse))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "LookupAccountName");
|
||
|
}
|
||
|
|
||
|
if(!myConvertSidToStringSid(
|
||
|
pComputerSID,
|
||
|
&m_pwszComputerSID))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "myConvertSidToStringSid");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pwszDomainName);
|
||
|
LOCAL_FREE(pComputerSID);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
typedef LPCWSTR (WINAPI FNCAGETDN)(
|
||
|
IN HCAINFO hCAInfo);
|
||
|
|
||
|
LPCWSTR
|
||
|
myCAGetDN(
|
||
|
IN HCAINFO hCAInfo)
|
||
|
{
|
||
|
HMODULE hModule;
|
||
|
static FNCAGETDN *s_pfn = NULL;
|
||
|
LPCWSTR pwszCADN = NULL;
|
||
|
|
||
|
if (NULL == s_pfn)
|
||
|
{
|
||
|
hModule = GetModuleHandle(TEXT("certcli.dll"));
|
||
|
if (NULL == hModule)
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
s_pfn = (FNCAGETDN *) GetProcAddress(hModule, "CAGetDN");
|
||
|
if (NULL == s_pfn)
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
}
|
||
|
pwszCADN = (*s_pfn)(hCAInfo);
|
||
|
|
||
|
error:
|
||
|
return(pwszCADN);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::MapAclSetOnDS(const PACL pAcl)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LPWSTR pwszSanitizedDSName = NULL;
|
||
|
HCAINFO hCAInfo;
|
||
|
LPCWSTR pwszCADN;
|
||
|
|
||
|
hr = mySanitizedNameToDSName(m_pcwszSanitizedName, &pwszSanitizedDSName);
|
||
|
_JumpIfError(hr, error, "mySanitizedNameToDSName");
|
||
|
|
||
|
hr = CAFindByName(
|
||
|
pwszSanitizedDSName,
|
||
|
NULL,
|
||
|
CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
|
||
|
&hCAInfo);
|
||
|
_JumpIfErrorStr(hr, error, "CAFindByName", pwszSanitizedDSName);
|
||
|
|
||
|
pwszCADN = myCAGetDN(hCAInfo);
|
||
|
if (NULL == pwszCADN)
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "myCAGetDN");
|
||
|
}
|
||
|
|
||
|
hr = SetNamedSecurityInfo(
|
||
|
const_cast<LPWSTR>(pwszCADN),
|
||
|
SE_DS_OBJECT_ALL,
|
||
|
DACL_SECURITY_INFORMATION,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
pAcl,
|
||
|
NULL);
|
||
|
if(ERROR_SUCCESS != hr)
|
||
|
{
|
||
|
|
||
|
if(ERROR_ACCESS_DENIED == hr)
|
||
|
{
|
||
|
// If we can't set the acl on ds enrollment object, notify
|
||
|
// the caller with a special error code so it can take action.
|
||
|
// See bug# 193388
|
||
|
hr = ERROR_CAN_NOT_COMPLETE;
|
||
|
}
|
||
|
|
||
|
hr = myHError(hr);
|
||
|
_JumpError(hr, error, "SetNamedSecurityInfo");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pwszSanitizedDSName);
|
||
|
if(hCAInfo)
|
||
|
CACloseCA(hCAInfo);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::MapAclSetOnService(const PACL pAcl)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
hr = SetNamedSecurityInfo(
|
||
|
wszSERVICE_NAME,
|
||
|
SE_SERVICE,
|
||
|
DACL_SECURITY_INFORMATION,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
pAcl,
|
||
|
NULL);
|
||
|
if(ERROR_SUCCESS != hr)
|
||
|
{
|
||
|
hr = myHError(hr);
|
||
|
_JumpError(hr, error, "SetNamedSecurityInfo");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::ResetSACL()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
PSECURITY_DESCRIPTOR pSaclSD = NULL;
|
||
|
PSECURITY_DESCRIPTOR pSDCrt; // no free
|
||
|
PSECURITY_DESCRIPTOR pSDNew = NULL;
|
||
|
|
||
|
hr = myGetSDFromTemplate(
|
||
|
CERTSRV_SACL_ON,
|
||
|
NULL,
|
||
|
&pSaclSD);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
|
||
|
hr = LockGet(&pSDCrt);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
|
||
|
|
||
|
hr = myMergeSD(pSDCrt, pSaclSD, SACL_SECURITY_INFORMATION, &pSDNew);
|
||
|
_JumpIfError(hr, error, "myMergeSD");
|
||
|
|
||
|
hr = Unlock();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
|
||
|
|
||
|
hr = CProtectedSecurityDescriptor::Set(pSDNew);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pSaclSD);
|
||
|
LOCAL_FREE(pSDNew);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Upgrade from CA security descriptor from win2k.
|
||
|
//
|
||
|
// Allow aces are mapped as follows:
|
||
|
// manage -> CA admin + officer
|
||
|
// enroll -> enroll
|
||
|
// read -> read
|
||
|
// revoke -> officer
|
||
|
// approve -> officer
|
||
|
// else -> read
|
||
|
//
|
||
|
// Deny aces are ignored.
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::UpgradeWin2k(
|
||
|
bool fUseEnterpriseAcl)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
PSECURITY_DESCRIPTOR pSDOld; // no free
|
||
|
PACL pAclOld; // no free
|
||
|
PSECURITY_DESCRIPTOR pSDNewDaclOnly = NULL;
|
||
|
PSECURITY_DESCRIPTOR pSDNewSaclOnly = NULL;
|
||
|
PSECURITY_DESCRIPTOR pSDNew = NULL;
|
||
|
PACL pAclNew = NULL;
|
||
|
ACL_SIZE_INFORMATION OldAclSizeInfo;
|
||
|
DWORD dwSizeAclNew = sizeof(ACL);
|
||
|
DWORD cAce;
|
||
|
PVOID pAce;
|
||
|
ACCESS_MASK dwAccessMask;
|
||
|
PSID pSid; // no free
|
||
|
|
||
|
hr = LockGet(&pSDOld);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::LockGet");
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
pSDOld,
|
||
|
&pAclOld);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
|
||
|
if(!GetAclInformation(pAclOld,
|
||
|
&OldAclSizeInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
for(cAce=0;cAce<OldAclSizeInfo.AceCount;cAce++)
|
||
|
{
|
||
|
if(!GetAce(pAclOld, cAce, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
dwSizeAclNew += GetUpgradeAceSizeAndType(pAce, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
// if no valid ACE found, fall back to a default SD
|
||
|
if(sizeof(ACL)==dwSizeAclNew)
|
||
|
{
|
||
|
hr= myGetSDFromTemplate(
|
||
|
fUseEnterpriseAcl?
|
||
|
WSZ_DEFAULT_CA_ENT_SECURITY:
|
||
|
WSZ_DEFAULT_CA_STD_SECURITY,
|
||
|
NULL,
|
||
|
&pSDNew);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pAclNew = (PACL)LocalAlloc(LMEM_FIXED, dwSizeAclNew);
|
||
|
if(!pAclNew)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
|
||
|
}
|
||
|
|
||
|
FillMemory(pAclNew, dwSizeAclNew, L' ');
|
||
|
if(!InitializeAcl(pAclNew, dwSizeAclNew, ACL_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
|
||
|
for(cAce=0;cAce<OldAclSizeInfo.AceCount;cAce++)
|
||
|
{
|
||
|
if(!GetAce(pAclOld, cAce, &pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(GetUpgradeAceSizeAndType(
|
||
|
pAce,
|
||
|
&dwAccessMask,
|
||
|
&pSid))
|
||
|
{
|
||
|
BYTE acetype = ((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType;
|
||
|
switch(acetype)
|
||
|
{
|
||
|
case ACCESS_ALLOWED_ACE_TYPE:
|
||
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
||
|
if(!AddAccessAllowedAce(
|
||
|
pAclNew,
|
||
|
ACL_REVISION,
|
||
|
dwAccessMask,
|
||
|
pSid))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAccessAllowed");
|
||
|
}
|
||
|
break;
|
||
|
case ACCESS_DENIED_ACE_TYPE:
|
||
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
||
|
if(!AddAccessDeniedAce(
|
||
|
pAclNew,
|
||
|
ACL_REVISION,
|
||
|
dwAccessMask,
|
||
|
pSid))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAccessAllowed");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Build a new SD based on this DACL
|
||
|
|
||
|
pSDNewDaclOnly = (PSECURITY_DESCRIPTOR)LocalAlloc(
|
||
|
LMEM_FIXED,
|
||
|
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||
|
if (!pSDNewDaclOnly)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(
|
||
|
pSDNewDaclOnly,
|
||
|
SECURITY_DESCRIPTOR_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
if(!SetSecurityDescriptorDacl(pSDNewDaclOnly,
|
||
|
TRUE,
|
||
|
pAclNew,
|
||
|
FALSE))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorDacl");
|
||
|
}
|
||
|
|
||
|
hr= myGetSDFromTemplate(
|
||
|
WSZ_DEFAULT_CA_STD_SECURITY,
|
||
|
NULL,
|
||
|
&pSDNewSaclOnly);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
|
||
|
// merge SACL & DACL in new SD
|
||
|
hr = myMergeSD(
|
||
|
pSDNewSaclOnly,
|
||
|
pSDNewDaclOnly,
|
||
|
DACL_SECURITY_INFORMATION,
|
||
|
&pSDNew);
|
||
|
_JumpIfError(hr, error, "myMergeSD");
|
||
|
|
||
|
CSASSERT(IsValidSecurityDescriptor(pSDNew));
|
||
|
}
|
||
|
|
||
|
hr = Unlock();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Unlock");
|
||
|
|
||
|
hr = CProtectedSecurityDescriptor::Set(pSDNew);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
|
||
|
|
||
|
error:
|
||
|
LOCAL_FREE(pSDNew);
|
||
|
LOCAL_FREE(pSDNewSaclOnly);
|
||
|
LOCAL_FREE(pSDNewDaclOnly);
|
||
|
LOCAL_FREE(pAclNew);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD CCertificateAuthoritySD::GetUpgradeAceSizeAndType(
|
||
|
PVOID pAce, DWORD *pdwType, PSID *ppSid)
|
||
|
{
|
||
|
DWORD dwSize = 0;
|
||
|
PSID pSid = NULL;
|
||
|
DWORD dwType = 0;
|
||
|
|
||
|
switch(((PACCESS_ALLOWED_ACE)pAce)->Header.AceType)
|
||
|
{
|
||
|
case ACCESS_ALLOWED_ACE_TYPE:
|
||
|
case ACCESS_DENIED_ACE_TYPE:
|
||
|
pSid = (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart);
|
||
|
dwSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+GetLengthSid(pSid);
|
||
|
|
||
|
switch(((PACCESS_ALLOWED_ACE)pAce)->Mask)
|
||
|
{
|
||
|
case ACTRL_CERTSRV_MANAGE:
|
||
|
dwType = CA_ACCESS_ADMIN | CA_ACCESS_OFFICER;
|
||
|
break;
|
||
|
default: // including ACTRL_CERTSRV_READ
|
||
|
dwType = CA_ACCESS_READ;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
||
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
||
|
|
||
|
PACCESS_ALLOWED_OBJECT_ACE pObjAce = (PACCESS_ALLOWED_OBJECT_ACE)pAce;
|
||
|
|
||
|
pSid = (PSID)(((BYTE*)(&pObjAce->ObjectType))+
|
||
|
((pObjAce->Flags&ACE_OBJECT_TYPE_PRESENT)?
|
||
|
sizeof(pObjAce->ObjectType):0)+
|
||
|
((pObjAce->Flags&ACE_INHERITED_OBJECT_TYPE_PRESENT)?
|
||
|
sizeof(pObjAce->InheritedObjectType):0));
|
||
|
|
||
|
dwSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+GetLengthSid(pSid);
|
||
|
|
||
|
REFGUID rGUID = (((PACCESS_ALLOWED_OBJECT_ACE)pAce)->ObjectType);
|
||
|
if(IsEqualGUID(rGUID, GUID_ENROLL))
|
||
|
{
|
||
|
dwType = CA_ACCESS_ENROLL;
|
||
|
} else
|
||
|
if(IsEqualGUID(rGUID, GUID_APPRV_REQ) ||
|
||
|
IsEqualGUID(rGUID, GUID_REVOKE))
|
||
|
{
|
||
|
dwType = CA_ACCESS_OFFICER;
|
||
|
} else
|
||
|
{
|
||
|
dwType = CA_ACCESS_READ;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// denied aces are not upgraded so ignore them
|
||
|
}
|
||
|
|
||
|
if(ppSid)
|
||
|
*ppSid = pSid;
|
||
|
if(pdwType)
|
||
|
*pdwType = dwType;
|
||
|
|
||
|
return dwSize;
|
||
|
}
|
||
|
|
||
|
// Returns:
|
||
|
// - E_INVALIDARG: invalid ACEs found,
|
||
|
// - S_FALSE: no admin ACE found (to avoid admins locking themselves out)
|
||
|
HRESULT CCertificateAuthoritySD::Validate(PSECURITY_DESCRIPTOR pSD)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
ACL_SIZE_INFORMATION AclInfo;
|
||
|
DWORD dwIndex;
|
||
|
PACCESS_ALLOWED_ACE pAce; // no free
|
||
|
PACL pDacl; // no free
|
||
|
bool fAdminAceFound = false;
|
||
|
DWORD dwKnownRights = CA_ACCESS_ADMIN |
|
||
|
CA_ACCESS_OFFICER |
|
||
|
CA_ACCESS_READ |
|
||
|
CA_ACCESS_ENROLL;
|
||
|
|
||
|
if(!IsValidSecurityDescriptor(pSD))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "IsValidSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
// get acl
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
pSD,
|
||
|
&pDacl);
|
||
|
_JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
|
||
|
|
||
|
if(!GetAclInformation(pDacl,
|
||
|
&AclInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
// only access allowed/denied aces and know rights are allowed
|
||
|
if((ACCESS_ALLOWED_ACE_TYPE!=pAce->Header.AceType &&
|
||
|
ACCESS_DENIED_ACE_TYPE !=pAce->Header.AceType) ||
|
||
|
(~dwKnownRights & pAce->Mask))
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
if((CA_ACCESS_ADMIN & pAce->Mask) &&
|
||
|
(ACCESS_ALLOWED_ACE_TYPE==pAce->Header.AceType))
|
||
|
{
|
||
|
fAdminAceFound = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// no caadmin allow ace found
|
||
|
hr = fAdminAceFound?S_OK:CERTSRV_E_NO_CAADMIN_DEFINED;
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CCertificateAuthoritySD::ConvertToString(
|
||
|
IN PSECURITY_DESCRIPTOR pSD,
|
||
|
OUT LPWSTR& rpwszSD)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LPCWSTR pcwszHeader = L"\n"; // start with a new line
|
||
|
DWORD dwBufSize = sizeof(WCHAR)*(wcslen(pcwszHeader)+1);
|
||
|
ACL_SIZE_INFORMATION AclInfo;
|
||
|
DWORD dwIndex;
|
||
|
PACCESS_ALLOWED_ACE pAce; // no free
|
||
|
PACL pDacl; // no free
|
||
|
LPWSTR pwszAce; // no free
|
||
|
|
||
|
rpwszSD = NULL;
|
||
|
|
||
|
hr = Validate(pSD);
|
||
|
_JumpIfError(hr, error, "CCertificateAuthoritySD::Validate");
|
||
|
|
||
|
// get acl
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
pSD,
|
||
|
&pDacl);
|
||
|
_JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
|
||
|
|
||
|
if(!GetAclInformation(pDacl,
|
||
|
&AclInfo,
|
||
|
sizeof(ACL_SIZE_INFORMATION),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
|
||
|
// calculate text size
|
||
|
|
||
|
for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
DWORD dwAceSize;
|
||
|
if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
hr = ConvertAceToString(
|
||
|
pAce,
|
||
|
&dwAceSize,
|
||
|
NULL);
|
||
|
_JumpIfError(hr, error, "ConvertAceToString");
|
||
|
|
||
|
dwBufSize += dwAceSize;
|
||
|
}
|
||
|
|
||
|
rpwszSD = (LPWSTR)LocalAlloc(LMEM_FIXED, dwBufSize);
|
||
|
_JumpIfAllocFailed(rpwszSD, error);
|
||
|
|
||
|
// build the output string
|
||
|
wcscpy(rpwszSD, pcwszHeader);
|
||
|
|
||
|
pwszAce = rpwszSD + wcslen(pcwszHeader);
|
||
|
|
||
|
for(dwIndex = 0; dwIndex < AclInfo.AceCount; dwIndex++)
|
||
|
{
|
||
|
DWORD dwAceSize;
|
||
|
if(!GetAce(pDacl, dwIndex, (LPVOID*)&pAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
hr = ConvertAceToString(
|
||
|
pAce,
|
||
|
&dwAceSize,
|
||
|
pwszAce);
|
||
|
_JumpIfError(hr, error, "ConvertAceToString");
|
||
|
|
||
|
pwszAce += dwAceSize/sizeof(WCHAR);
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Returned string has the following format:
|
||
|
//
|
||
|
// [Allow|Deny]\t[Name|SID]\n
|
||
|
// \tRole1\n
|
||
|
// \tRole2\n
|
||
|
// ...
|
||
|
//
|
||
|
// Example:
|
||
|
//
|
||
|
// Allow Administrators
|
||
|
// CA Administrator
|
||
|
// Certificate Manager
|
||
|
//
|
||
|
// If SID cannot be converted to friendly name it is displayed
|
||
|
// as a string SID
|
||
|
//
|
||
|
HRESULT CCertificateAuthoritySD::ConvertAceToString(
|
||
|
IN PACCESS_ALLOWED_ACE pAce,
|
||
|
OUT OPTIONAL PDWORD pdwSize,
|
||
|
IN OUT OPTIONAL LPWSTR pwszSD)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD dwSize = 1; // trailing '\0'
|
||
|
CSid sid((PSID)(&pAce->SidStart));
|
||
|
|
||
|
LPCWSTR pcwszAllow = m_pcwszResources[0];
|
||
|
LPCWSTR pcwszDeny = m_pcwszResources[1];
|
||
|
|
||
|
LPCWSTR pcwszPermissionType =
|
||
|
(ACCESS_ALLOWED_ACE_TYPE==pAce->Header.AceType)?
|
||
|
pcwszAllow:pcwszDeny;
|
||
|
LPCWSTR pcwszSid; // no free
|
||
|
|
||
|
DWORD dwRoles[] =
|
||
|
{
|
||
|
CA_ACCESS_ADMIN,
|
||
|
CA_ACCESS_OFFICER,
|
||
|
CA_ACCESS_READ,
|
||
|
CA_ACCESS_ENROLL,
|
||
|
};
|
||
|
|
||
|
// dwRoles and resources should match the roles
|
||
|
const LPCWSTR *pcwszRoles = &m_pcwszResources[2];
|
||
|
|
||
|
DWORD cRoles;
|
||
|
|
||
|
// asked for size and/or ace string
|
||
|
CSASSERT(pdwSize || pwszSD);
|
||
|
|
||
|
pcwszSid = sid.GetName();
|
||
|
if(!pcwszSid)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
dwSize = wcslen(pcwszSid);
|
||
|
|
||
|
dwSize += wcslen(pcwszPermissionType);
|
||
|
|
||
|
dwSize += 2; // '\t' between sid an permission and a '\n' after
|
||
|
|
||
|
if(pwszSD)
|
||
|
{
|
||
|
wcscat(pwszSD, pcwszPermissionType);
|
||
|
wcscat(pwszSD, L"\t");
|
||
|
wcscat(pwszSD, pcwszSid);
|
||
|
wcscat(pwszSD, L"\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
for(cRoles=0;cRoles<ARRAYSIZE(dwRoles);cRoles++)
|
||
|
{
|
||
|
if(pAce->Mask & dwRoles[cRoles])
|
||
|
{
|
||
|
dwSize += wcslen(pcwszRoles[cRoles]) + 2; // "\tRole\n"
|
||
|
if(pwszSD)
|
||
|
{
|
||
|
wcscat(pwszSD, L"\t");
|
||
|
wcscat(pwszSD, pcwszRoles[cRoles]);
|
||
|
wcscat(pwszSD, L"\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwSize *= sizeof(WCHAR);
|
||
|
|
||
|
if(pdwSize)
|
||
|
{
|
||
|
*pdwSize = dwSize;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|