312 lines
7.9 KiB
C++
312 lines
7.9 KiB
C++
//+--------------------------------------------------------------------------
|
|
// File: prvlg.cpp
|
|
// Contents: privilege manager implementation
|
|
//---------------------------------------------------------------------------
|
|
#include <pch.cpp>
|
|
#include "prvlg.h"
|
|
|
|
using namespace CertSrv;
|
|
|
|
LSA_UNICODE_STRING CPrivilegeManager::m_lsaSecurityPrivilege[] =
|
|
{
|
|
sizeof(SE_SECURITY_NAME)-2,
|
|
sizeof(SE_SECURITY_NAME),
|
|
SE_SECURITY_NAME
|
|
};
|
|
|
|
LSA_UNICODE_STRING CPrivilegeManager::m_lsaBackupRestorePrivilege[] =
|
|
{
|
|
{
|
|
sizeof(SE_BACKUP_NAME)-2,
|
|
sizeof(SE_BACKUP_NAME),
|
|
SE_BACKUP_NAME
|
|
},
|
|
{
|
|
sizeof(SE_RESTORE_NAME)-2,
|
|
sizeof(SE_RESTORE_NAME),
|
|
SE_RESTORE_NAME
|
|
}
|
|
};
|
|
|
|
|
|
HRESULT CPrivilegeManager::OpenPolicy()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS NTStatus;
|
|
|
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
|
|
|
NTStatus = LsaOpenPolicy(
|
|
NULL,
|
|
&ObjectAttributes,
|
|
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
|
&m_lsah);
|
|
if(STATUS_SUCCESS!=NTStatus)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(LsaNtStatusToWinError(NTStatus));
|
|
_JumpError(hr, error, "LsaOpenPolicy");
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::ClosePolicy()
|
|
{
|
|
if(m_lsah)
|
|
LsaClose(m_lsah);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CPrivilegeManager::GetPrivilegeString(
|
|
DWORD dwRole,
|
|
PLSA_UNICODE_STRING &plsastr,
|
|
ULONG &cstr)
|
|
{
|
|
switch(dwRole)
|
|
{
|
|
case CA_ACCESS_AUDITOR:
|
|
plsastr = m_lsaSecurityPrivilege;
|
|
cstr = ARRAYSIZE(m_lsaSecurityPrivilege);
|
|
break;
|
|
case CA_ACCESS_OPERATOR:
|
|
plsastr = m_lsaBackupRestorePrivilege;
|
|
cstr = ARRAYSIZE(m_lsaBackupRestorePrivilege);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::AddPrivilege(
|
|
const PSID pSid,
|
|
DWORD dwRole)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
NTSTATUS NTStatus;
|
|
PLSA_UNICODE_STRING plsastr = NULL;
|
|
ULONG cstr = 0;
|
|
|
|
GetPrivilegeString(
|
|
dwRole,
|
|
plsastr,
|
|
cstr);
|
|
|
|
NTStatus = LsaAddAccountRights(
|
|
m_lsah,
|
|
pSid,
|
|
plsastr,
|
|
cstr);
|
|
if(STATUS_SUCCESS!=NTStatus)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(LsaNtStatusToWinError(NTStatus));
|
|
_JumpError(hr, error, "LsaAddAcountRights");
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::RemovePrivilege(
|
|
const PSID pSid,
|
|
DWORD dwRole)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
NTSTATUS NTStatus;
|
|
PLSA_UNICODE_STRING plsastr = NULL;
|
|
ULONG cstr = 0;
|
|
|
|
GetPrivilegeString(
|
|
dwRole,
|
|
plsastr,
|
|
cstr);
|
|
|
|
NTStatus = LsaRemoveAccountRights(
|
|
m_lsah,
|
|
pSid,
|
|
FALSE,
|
|
plsastr,
|
|
cstr);
|
|
if(STATUS_SUCCESS!=NTStatus && STATUS_OBJECT_NAME_NOT_FOUND!=NTStatus)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(LsaNtStatusToWinError(NTStatus));
|
|
_JumpError(hr, error, "LsaRemoveAcountRights");
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::InitBuffer(
|
|
PACCESS_ALLOWED_ACE **buffer,
|
|
DWORD cAce)
|
|
{
|
|
*buffer = (PACCESS_ALLOWED_ACE *)LocalAlloc(LMEM_FIXED,
|
|
cAce*sizeof(PACCESS_ALLOWED_ACE));
|
|
if(!*buffer)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
ZeroMemory(*buffer, cAce*sizeof(PACCESS_ALLOWED_ACE));
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::ComputePrivilegeChanges(
|
|
const PSECURITY_DESCRIPTOR pOldSD,
|
|
const PSECURITY_DESCRIPTOR pNewSD)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PACCESS_ALLOWED_ACE pOldAce, pNewAce;
|
|
DWORD cOldAce, cNewAce;
|
|
PACL pOldAcl, pNewAcl; // no free
|
|
|
|
hr = myGetSecurityDescriptorDacl(
|
|
pOldSD,
|
|
&pOldAcl);
|
|
_JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
|
|
|
|
hr = myGetSecurityDescriptorDacl(
|
|
pNewSD,
|
|
&pNewAcl);
|
|
_JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
|
|
|
|
m_cOldAce = pOldAcl->AceCount;
|
|
m_cNewAce = pNewAcl->AceCount;
|
|
|
|
hr = InitBuffer(
|
|
&m_pAddPrivilegeAudit,
|
|
m_cNewAce);
|
|
_JumpIfError(hr, error, "InitBuffer");
|
|
|
|
hr = InitBuffer(
|
|
&m_pAddPrivilegeBackup,
|
|
m_cNewAce);
|
|
_JumpIfError(hr, error, "InitBuffer");
|
|
|
|
hr = InitBuffer(
|
|
&m_pRemovePrivilegeAudit,
|
|
m_cOldAce);
|
|
_JumpIfError(hr, error, "InitBuffer");
|
|
|
|
hr = InitBuffer(
|
|
&m_pRemovePrivilegeBackup,
|
|
m_cOldAce);
|
|
_JumpIfError(hr, error, "InitBuffer");
|
|
|
|
for(cNewAce=0; cNewAce<m_cNewAce; cNewAce++)
|
|
{
|
|
if(!GetAce(pNewAcl, cNewAce, (PVOID*)&pNewAce))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "GetAce");
|
|
}
|
|
|
|
if(pNewAce->Mask&CA_ACCESS_AUDITOR)
|
|
m_pAddPrivilegeAudit[cNewAce] = pNewAce;
|
|
if(pNewAce->Mask&CA_ACCESS_OPERATOR)
|
|
m_pAddPrivilegeBackup[cNewAce] = pNewAce;
|
|
}
|
|
|
|
for(cOldAce=0; cOldAce<m_cOldAce; cOldAce++)
|
|
{
|
|
|
|
if(!GetAce(pOldAcl, cOldAce, (PVOID*)&pOldAce))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "GetAce");
|
|
}
|
|
|
|
if(pOldAce->Mask&CA_ACCESS_AUDITOR)
|
|
m_pRemovePrivilegeAudit[cOldAce] = pOldAce;
|
|
if(pOldAce->Mask&CA_ACCESS_OPERATOR)
|
|
m_pRemovePrivilegeBackup[cOldAce] = pOldAce;
|
|
|
|
for(cNewAce=0; cNewAce<m_cNewAce; cNewAce++)
|
|
{
|
|
if(!GetAce(pNewAcl, cNewAce, (PVOID*)&pNewAce))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "GetAce");
|
|
}
|
|
|
|
if(EqualSid((PSID)&pOldAce->SidStart,
|
|
(PSID)&pNewAce->SidStart))
|
|
{
|
|
if((pOldAce->Mask&CA_ACCESS_AUDITOR)&&
|
|
(pNewAce->Mask&CA_ACCESS_AUDITOR))
|
|
{
|
|
m_pRemovePrivilegeAudit[cOldAce] = NULL;
|
|
}
|
|
if((pOldAce->Mask&CA_ACCESS_OPERATOR)&&
|
|
(pNewAce->Mask&CA_ACCESS_OPERATOR))
|
|
{
|
|
m_pRemovePrivilegeBackup[cOldAce] = NULL;
|
|
}
|
|
if((pOldAce->Mask&CA_ACCESS_AUDITOR)&&
|
|
(pNewAce->Mask&CA_ACCESS_AUDITOR))
|
|
{
|
|
m_pAddPrivilegeAudit[cNewAce] = NULL;
|
|
}
|
|
if((pOldAce->Mask&CA_ACCESS_OPERATOR)&&
|
|
(pNewAce->Mask&CA_ACCESS_OPERATOR))
|
|
{
|
|
m_pAddPrivilegeBackup[cNewAce] = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPrivilegeManager::UpdatePrivileges()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cOldAce, cNewAce;
|
|
|
|
hr = OpenPolicy();
|
|
_JumpIfError(hr, error, "CPrivilegeManager::OpenPolicy");
|
|
|
|
for(cOldAce=0; cOldAce<m_cOldAce; cOldAce++)
|
|
{
|
|
if(m_pRemovePrivilegeBackup[cOldAce])
|
|
{
|
|
hr = RemovePrivilege(
|
|
(PSID)&(m_pRemovePrivilegeBackup[cOldAce]->SidStart),
|
|
CA_ACCESS_OPERATOR);
|
|
_JumpIfError(hr, error, "CPrivilegeManager::RemovePrivilege");
|
|
}
|
|
if(m_pRemovePrivilegeAudit[cOldAce])
|
|
{
|
|
hr = RemovePrivilege(
|
|
(PSID)&(m_pRemovePrivilegeAudit[cOldAce]->SidStart),
|
|
CA_ACCESS_AUDITOR);
|
|
_JumpIfError(hr, error, "CPrivilegeManager::RemovePrivilege");
|
|
}
|
|
}
|
|
|
|
for(cNewAce=0; cNewAce<m_cNewAce; cNewAce++)
|
|
{
|
|
if(m_pAddPrivilegeBackup[cNewAce])
|
|
{
|
|
hr = AddPrivilege(
|
|
(PSID)&(m_pAddPrivilegeBackup[cNewAce]->SidStart),
|
|
CA_ACCESS_OPERATOR);
|
|
_JumpIfError(hr, error, "CPrivilegeManager::AddPrivilege");
|
|
}
|
|
if(m_pAddPrivilegeAudit[cNewAce])
|
|
{
|
|
hr = AddPrivilege(
|
|
(PSID)&(m_pAddPrivilegeAudit[cNewAce]->SidStart),
|
|
CA_ACCESS_AUDITOR);
|
|
_JumpIfError(hr, error, "CPrivilegeManager::AddPrivilege");
|
|
}
|
|
}
|
|
error:
|
|
|
|
ClosePolicy();
|
|
|
|
return hr;
|
|
} |