711 lines
18 KiB
C++
711 lines
18 KiB
C++
|
//+--------------------------------------------------------------------------
|
||
|
// File: officer.cpp
|
||
|
// Contents: officer rights implementation
|
||
|
//---------------------------------------------------------------------------
|
||
|
#include <pch.cpp>
|
||
|
#include <certsd.h>
|
||
|
#include <certacl.h>
|
||
|
#include <sid.h>
|
||
|
|
||
|
using namespace CertSrv;
|
||
|
|
||
|
HRESULT
|
||
|
COfficerRightsSD::Merge(
|
||
|
PSECURITY_DESCRIPTOR pOfficerSD,
|
||
|
PSECURITY_DESCRIPTOR pCASD)
|
||
|
{
|
||
|
|
||
|
HRESULT hr;
|
||
|
PACL pCAAcl; // no free
|
||
|
PACL pOfficerAcl; // no free
|
||
|
PACL pNewOfficerAcl = NULL;
|
||
|
ACL_SIZE_INFORMATION CAAclInfo, OfficerAclInfo;
|
||
|
PBOOL pCAFound = NULL, pOfficerFound = NULL;
|
||
|
DWORD cCAAce, cOfficerAce;
|
||
|
PACCESS_ALLOWED_ACE pCAAce;
|
||
|
PACCESS_ALLOWED_CALLBACK_ACE pOfficerAce;
|
||
|
PACCESS_ALLOWED_CALLBACK_ACE pNewAce = NULL;
|
||
|
DWORD dwNewAclSize = sizeof(ACL);
|
||
|
PSID pSidEveryone = NULL, pSidBuiltinAdministrators = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_WORLD_SID_AUTHORITY;
|
||
|
DWORD dwSidEveryoneSize, dwAceSize, dwSidSize;
|
||
|
PSID_LIST pSidList;
|
||
|
PSECURITY_DESCRIPTOR pNewOfficerSD = NULL;
|
||
|
ACL EmptyAcl;
|
||
|
SECURITY_DESCRIPTOR EmptySD;
|
||
|
|
||
|
CSASSERT(NULL==pOfficerSD || IsValidSecurityDescriptor(pOfficerSD));
|
||
|
CSASSERT(IsValidSecurityDescriptor(pCASD));
|
||
|
|
||
|
// allow NULL officer SD, in that case build an empty SD and use it
|
||
|
if(NULL==pOfficerSD)
|
||
|
{
|
||
|
if(!InitializeAcl(&EmptyAcl, sizeof(ACL), ACL_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(&EmptySD, SECURITY_DESCRIPTOR_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
if(!SetSecurityDescriptorDacl(
|
||
|
&EmptySD,
|
||
|
TRUE, // DACL present
|
||
|
&EmptyAcl,
|
||
|
FALSE)) // DACL defaulted
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorControl");
|
||
|
}
|
||
|
|
||
|
pOfficerSD = &EmptySD;
|
||
|
}
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(pCASD, &pCAAcl);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
|
||
|
hr = myGetSecurityDescriptorDacl(pOfficerSD, &pOfficerAcl);
|
||
|
_JumpIfError(hr, error, "myGetSecurityDescriptorDacl");
|
||
|
|
||
|
// allocate a bool array for each DACL
|
||
|
|
||
|
if(!GetAclInformation(pCAAcl,
|
||
|
&CAAclInfo,
|
||
|
sizeof(CAAclInfo),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
if(!GetAclInformation(pOfficerAcl,
|
||
|
&OfficerAclInfo,
|
||
|
sizeof(OfficerAclInfo),
|
||
|
AclSizeInformation))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAclInformation");
|
||
|
}
|
||
|
|
||
|
pCAFound = (PBOOL)LocalAlloc(LMEM_FIXED, sizeof(BOOL)*CAAclInfo.AceCount);
|
||
|
if(!pCAFound)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
ZeroMemory(pCAFound, sizeof(BOOL)*CAAclInfo.AceCount);
|
||
|
|
||
|
pOfficerFound = (PBOOL)LocalAlloc(LMEM_FIXED, sizeof(BOOL)*OfficerAclInfo.AceCount);
|
||
|
if(!pOfficerFound)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
ZeroMemory(pOfficerFound, sizeof(BOOL)*OfficerAclInfo.AceCount);
|
||
|
|
||
|
hr = GetEveryoneSID(&pSidEveryone);
|
||
|
_JumpIfError(hr, error, "GetEveryoneSID");
|
||
|
|
||
|
dwSidEveryoneSize = GetLengthSid(pSidEveryone);
|
||
|
|
||
|
// mark in the bool arrays each ace whose SID is found in both DACLs;
|
||
|
// also mark CA ACEs we are not interested in (denied ACEs and
|
||
|
// non-officer ACEs)
|
||
|
|
||
|
for(cCAAce=0; cCAAce<CAAclInfo.AceCount; cCAAce++)
|
||
|
{
|
||
|
if(!GetAce(pCAAcl, cCAAce, (PVOID*)&pCAAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
// process only officer allow aces
|
||
|
if(0==(pCAAce->Mask & CA_ACCESS_OFFICER))
|
||
|
{
|
||
|
pCAFound[cCAAce] = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// compare SIDs in each officer ace with current CA ace and mark
|
||
|
// corresponding bool in arrays if equal
|
||
|
for(cOfficerAce=0; cOfficerAce<OfficerAclInfo.AceCount; cOfficerAce++)
|
||
|
{
|
||
|
if(!GetAce(pOfficerAcl, cOfficerAce, (PVOID*)&pOfficerAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
if(EqualSid((PSID)&pOfficerAce->SidStart,
|
||
|
(PSID)&pCAAce->SidStart))
|
||
|
{
|
||
|
pCAFound[cCAAce] = TRUE;
|
||
|
pOfficerFound[cOfficerAce] = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if the officer is found in the CA ACL but not in the officer ACL,
|
||
|
// we will add a new ACE allowing him to manage certs for Everyone
|
||
|
if(!pCAFound[cCAAce])
|
||
|
{
|
||
|
dwNewAclSize += sizeof(ACCESS_ALLOWED_CALLBACK_ACE)+
|
||
|
GetLengthSid((PSID)&pCAAce->SidStart)+
|
||
|
dwSidEveryoneSize;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Calculate the size of the new officer ACL; we already added in the header
|
||
|
// size and the size of the new ACEs to be added. Now we add the ACEs to be
|
||
|
// copied over from the old ACL
|
||
|
for(cOfficerAce=0; cOfficerAce<OfficerAclInfo.AceCount; cOfficerAce++)
|
||
|
{
|
||
|
if(pOfficerFound[cOfficerAce])
|
||
|
{
|
||
|
if(!GetAce(pOfficerAcl, cOfficerAce, (PVOID*)&pOfficerAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
dwNewAclSize += pOfficerAce->Header.AceSize;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// allocate a new DACL
|
||
|
|
||
|
pNewOfficerAcl = (PACL)LocalAlloc(LMEM_FIXED, dwNewAclSize);
|
||
|
if(!pNewOfficerAcl)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
ZeroMemory(pNewOfficerAcl, dwNewAclSize);
|
||
|
#endif
|
||
|
|
||
|
if(!InitializeAcl(pNewOfficerAcl, dwNewAclSize, ACL_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
|
||
|
// build the new DACL
|
||
|
|
||
|
// traverse officer DACL and add only marked ACEs (whose SID was found
|
||
|
// in the CA DACL, ie principal is an officer)
|
||
|
for(cOfficerAce=0; cOfficerAce<OfficerAclInfo.AceCount; cOfficerAce++)
|
||
|
{
|
||
|
if(pOfficerFound[cOfficerAce])
|
||
|
{
|
||
|
if(!GetAce(pOfficerAcl, cOfficerAce, (PVOID*)&pOfficerAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
if(!AddAce(
|
||
|
pNewOfficerAcl,
|
||
|
ACL_REVISION,
|
||
|
MAXDWORD,
|
||
|
pOfficerAce,
|
||
|
pOfficerAce->Header.AceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CSASSERT(IsValidAcl(pNewOfficerAcl));
|
||
|
|
||
|
hr = GetBuiltinAdministratorsSID(&pSidBuiltinAdministrators);
|
||
|
_JumpIfError(hr, error, "GetBuiltinAdministratorsSID");
|
||
|
|
||
|
// traverse the CA DACL and add a new officer to list, allowed to manage
|
||
|
// Everyone
|
||
|
for(cCAAce=0; cCAAce<CAAclInfo.AceCount; cCAAce++)
|
||
|
{
|
||
|
if(pCAFound[cCAAce])
|
||
|
continue;
|
||
|
|
||
|
if(!GetAce(pCAAcl, cCAAce, (PVOID*)&pCAAce))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetAce");
|
||
|
}
|
||
|
|
||
|
// create a new ACE
|
||
|
dwSidSize = GetLengthSid((PSID)&pCAAce->SidStart);
|
||
|
|
||
|
dwAceSize = sizeof(ACCESS_ALLOWED_CALLBACK_ACE)+
|
||
|
dwSidEveryoneSize+dwSidSize;
|
||
|
|
||
|
pNewAce = (ACCESS_ALLOWED_CALLBACK_ACE*) LocalAlloc(LMEM_FIXED, dwAceSize);
|
||
|
if(!pNewAce)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
#ifdef _DEBUG
|
||
|
ZeroMemory(pNewAce, dwAceSize);
|
||
|
#endif
|
||
|
|
||
|
pNewAce->Header.AceType = ACCESS_ALLOWED_CALLBACK_ACE_TYPE;
|
||
|
pNewAce->Header.AceFlags= 0;
|
||
|
pNewAce->Header.AceSize = (USHORT)dwAceSize;
|
||
|
pNewAce->Mask = DELETE;
|
||
|
CopySid(dwSidSize,
|
||
|
(PSID)&pNewAce->SidStart,
|
||
|
(PSID)&pCAAce->SidStart);
|
||
|
pSidList = (PSID_LIST)(((BYTE*)&pNewAce->SidStart)+dwSidSize);
|
||
|
pSidList->dwSidCount = 1;
|
||
|
|
||
|
CopySid(dwSidEveryoneSize,
|
||
|
(PSID)&pSidList->SidListStart,
|
||
|
pSidEveryone);
|
||
|
|
||
|
CSASSERT(IsValidSid((PSID)&pNewAce->SidStart));
|
||
|
|
||
|
if(!AddAce(
|
||
|
pNewOfficerAcl,
|
||
|
ACL_REVISION,
|
||
|
MAXDWORD,
|
||
|
pNewAce,
|
||
|
dwAceSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AddAce");
|
||
|
}
|
||
|
|
||
|
LocalFree(pNewAce);
|
||
|
pNewAce = NULL;
|
||
|
}
|
||
|
|
||
|
CSASSERT(IsValidAcl(pNewOfficerAcl));
|
||
|
|
||
|
// setup the new security descriptor
|
||
|
|
||
|
pNewOfficerSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED,
|
||
|
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||
|
if (pNewOfficerSD == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
#ifdef _DEBUG
|
||
|
ZeroMemory(pNewOfficerSD, SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||
|
#endif
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(pNewOfficerSD, SECURITY_DESCRIPTOR_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
if(!SetSecurityDescriptorOwner(
|
||
|
pNewOfficerSD,
|
||
|
pSidBuiltinAdministrators,
|
||
|
FALSE))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorControl");
|
||
|
}
|
||
|
|
||
|
if(!SetSecurityDescriptorDacl(
|
||
|
pNewOfficerSD,
|
||
|
TRUE, // DACL present
|
||
|
pNewOfficerAcl,
|
||
|
FALSE)) // DACL defaulted
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorDacl");
|
||
|
}
|
||
|
|
||
|
CSASSERT(IsValidSecurityDescriptor(pNewOfficerSD));
|
||
|
|
||
|
hr = Set(pNewOfficerSD);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
|
||
|
|
||
|
error:
|
||
|
if(pNewAce)
|
||
|
{
|
||
|
LocalFree(pNewAce);
|
||
|
}
|
||
|
|
||
|
if(pSidEveryone)
|
||
|
{
|
||
|
FreeSid(pSidEveryone);
|
||
|
}
|
||
|
|
||
|
if(pSidBuiltinAdministrators)
|
||
|
{
|
||
|
FreeSid(pSidBuiltinAdministrators);
|
||
|
}
|
||
|
|
||
|
if(pNewOfficerAcl)
|
||
|
{
|
||
|
LocalFree(pNewOfficerAcl);
|
||
|
}
|
||
|
|
||
|
if(pNewOfficerSD)
|
||
|
{
|
||
|
LocalFree(pNewOfficerSD);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
COfficerRightsSD::Adjust(PSECURITY_DESCRIPTOR pCASD)
|
||
|
{
|
||
|
return Merge(Get(), pCASD);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
COfficerRightsSD::InitializeEmpty()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
ACL Acl;
|
||
|
SECURITY_DESCRIPTOR SD;
|
||
|
|
||
|
hr = Init(NULL);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Init");
|
||
|
|
||
|
if(!InitializeAcl(&Acl, sizeof(ACL), ACL_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeAcl");
|
||
|
}
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
if(!SetSecurityDescriptorDacl(
|
||
|
&SD,
|
||
|
TRUE, // DACL present
|
||
|
&Acl,
|
||
|
FALSE)) // DACL defaulted
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorControl");
|
||
|
}
|
||
|
|
||
|
m_fInitialized = true;
|
||
|
|
||
|
hr = Set(&SD);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Set");
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT COfficerRightsSD::Save()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if(IsEnabled())
|
||
|
{
|
||
|
hr = CProtectedSecurityDescriptor::Save();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Save");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = CProtectedSecurityDescriptor::Delete();
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Delete");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT COfficerRightsSD::Load()
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = CProtectedSecurityDescriptor::Load();
|
||
|
if(S_OK==hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)==hr)
|
||
|
{
|
||
|
SetEnable(S_OK==hr);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Save");
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT COfficerRightsSD::Initialize(LPCWSTR pwszSanitizedName)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = CProtectedSecurityDescriptor::Initialize(pwszSanitizedName);
|
||
|
_JumpIfError(hr, error, "CProtectedSecurityDescriptor::Save");
|
||
|
|
||
|
SetEnable(NULL!=m_pSD);
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT COfficerRightsSD::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_CALLBACK_ACE pAce; // no free
|
||
|
PACL pDacl; // no free
|
||
|
LPWSTR pwszAce; // no free
|
||
|
|
||
|
CSASSERT(IsValidSecurityDescriptor(pSD));
|
||
|
|
||
|
rpwszSD = NULL;
|
||
|
|
||
|
// 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[OfficerName|SID]\n
|
||
|
// \t[Client1Name|SID]\n
|
||
|
// \t[Client2Name|SID]\n
|
||
|
// ...
|
||
|
//
|
||
|
// Example:
|
||
|
//
|
||
|
// Allow OfficerGroup1
|
||
|
// ClientGroup1
|
||
|
// ClientGroup2
|
||
|
//
|
||
|
// If SID cannot be converted to friendly name it is displayed
|
||
|
// as a string SID
|
||
|
//
|
||
|
HRESULT COfficerRightsSD::ConvertAceToString(
|
||
|
IN PACCESS_ALLOWED_CALLBACK_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));
|
||
|
PSID_LIST pSidList = (PSID_LIST) (((BYTE*)&pAce->SidStart)+
|
||
|
GetLengthSid(&pAce->SidStart));
|
||
|
PSID pSid;
|
||
|
DWORD cSids;
|
||
|
|
||
|
LPCWSTR pcwszAllow = m_pcwszResources[0];
|
||
|
LPCWSTR pcwszDeny = m_pcwszResources[1];
|
||
|
|
||
|
LPCWSTR pcwszPermissionType =
|
||
|
(ACCESS_ALLOWED_CALLBACK_ACE_TYPE==pAce->Header.AceType)?
|
||
|
pcwszAllow:pcwszDeny;
|
||
|
LPCWSTR pcwszSid; // no free
|
||
|
|
||
|
// asked for size and/or ace string
|
||
|
CSASSERT(pdwSize || pwszSD);
|
||
|
|
||
|
if(pAce->Header.AceType != ACCESS_ALLOWED_CALLBACK_ACE_TYPE &&
|
||
|
pAce->Header.AceType != ACCESS_DENIED_CALLBACK_ACE_TYPE)
|
||
|
{
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
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(pSid=(PSID)&pSidList->SidListStart, cSids=0; cSids<pSidList->dwSidCount;
|
||
|
cSids++, pSid = (PSID)(((BYTE*)pSid)+GetLengthSid(pSid)))
|
||
|
{
|
||
|
CSASSERT(IsValidSid(pSid));
|
||
|
|
||
|
CSid sidClient(pSid);
|
||
|
LPCWSTR pcwszSidClient;
|
||
|
|
||
|
pcwszSidClient = sidClient.GetName();
|
||
|
if(!pcwszSidClient)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
dwSize += wcslen(pcwszSidClient) + 2; // \tClientNameOrSid\n
|
||
|
|
||
|
if(pwszSD)
|
||
|
{
|
||
|
wcscat(pwszSD, L"\t");
|
||
|
wcscat(pwszSD, pcwszSidClient);
|
||
|
wcscat(pwszSD, L"\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwSize *= sizeof(WCHAR);
|
||
|
|
||
|
if(pdwSize)
|
||
|
{
|
||
|
*pdwSize = dwSize;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CertSrv::GetWellKnownSID(
|
||
|
PSID *ppSid,
|
||
|
SID_IDENTIFIER_AUTHORITY *pAuth,
|
||
|
BYTE SubauthorityCount,
|
||
|
DWORD SubAuthority1,
|
||
|
DWORD SubAuthority2,
|
||
|
DWORD SubAuthority3,
|
||
|
DWORD SubAuthority4,
|
||
|
DWORD SubAuthority5,
|
||
|
DWORD SubAuthority6,
|
||
|
DWORD SubAuthority7,
|
||
|
DWORD SubAuthority8)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
// build Everyone SID
|
||
|
if(!AllocateAndInitializeSid(
|
||
|
pAuth,
|
||
|
SubauthorityCount,
|
||
|
SubAuthority1,
|
||
|
SubAuthority2,
|
||
|
SubAuthority3,
|
||
|
SubAuthority4,
|
||
|
SubAuthority5,
|
||
|
SubAuthority6,
|
||
|
SubAuthority7,
|
||
|
SubAuthority8,
|
||
|
ppSid))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "AllocateAndInitializeSid");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// caller is responsible for LocalFree'ing PSID
|
||
|
HRESULT CertSrv::GetEveryoneSID(PSID *ppSid)
|
||
|
{
|
||
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_WORLD_SID_AUTHORITY;
|
||
|
return GetWellKnownSID(
|
||
|
ppSid,
|
||
|
&SIDAuth,
|
||
|
1,
|
||
|
SECURITY_WORLD_RID);
|
||
|
return S_OK;
|
||
|
}
|
||
|
// caller is responsible for LocalFree'ing PSID
|
||
|
HRESULT CertSrv::GetLocalSystemSID(PSID *ppSid)
|
||
|
{
|
||
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
|
||
|
return GetWellKnownSID(
|
||
|
ppSid,
|
||
|
&SIDAuth,
|
||
|
1,
|
||
|
SECURITY_LOCAL_SYSTEM_RID);
|
||
|
}
|
||
|
|
||
|
// caller is responsible for LocalFree'ing PSID
|
||
|
HRESULT CertSrv::GetBuiltinAdministratorsSID(PSID *ppSid)
|
||
|
{
|
||
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
|
||
|
return GetWellKnownSID(
|
||
|
ppSid,
|
||
|
&SIDAuth,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS);
|
||
|
}
|
||
|
|