425 lines
11 KiB
C++
425 lines
11 KiB
C++
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
//
|
||
|
// File: acl.cpp
|
||
|
//
|
||
|
// Contents: Access Control helpers for certsrv
|
||
|
//
|
||
|
// History: 11-16-98 petesk created
|
||
|
// 10/99 xtan, major changes
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cpp>
|
||
|
#pragma hdrstop
|
||
|
#include <ntdsapi.h>
|
||
|
#define SECURITY_WIN32
|
||
|
|
||
|
#include <security.h>
|
||
|
#include <sddl.h>
|
||
|
#include <aclapi.h>
|
||
|
|
||
|
#include "certca.h"
|
||
|
#include "cscsp.h"
|
||
|
#include "certacl.h"
|
||
|
#include "certsd.h"
|
||
|
|
||
|
// defines
|
||
|
|
||
|
const GUID GUID_APPRV_REQ = { /* 0e10c966-78fb-11d2-90d4-00c04f79dc55 */
|
||
|
0x0e10c966,
|
||
|
0x78fb,
|
||
|
0x11d2,
|
||
|
{0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55} };
|
||
|
|
||
|
const GUID GUID_REVOKE= { /* 0e10c967-78fb-11d2-90d4-00c04f79dc55 */
|
||
|
0x0e10c967,
|
||
|
0x78fb,
|
||
|
0x11d2,
|
||
|
{0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55} };
|
||
|
|
||
|
// Important, keep enroll GUID in sync with string define in certacl.h
|
||
|
const GUID GUID_ENROLL = { /* 0e10c968-78fb-11d2-90d4-00c04f79dc55 */
|
||
|
0x0e10c968,
|
||
|
0x78fb,
|
||
|
0x11d2,
|
||
|
{0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55} };
|
||
|
|
||
|
const GUID GUID_AUTOENROLL = { /* a05b8cc2-17bc-4802-a710-e7c15ab866a2 */
|
||
|
0xa05b8cc2,
|
||
|
0x17bc,
|
||
|
0x4802,
|
||
|
{0xa7, 0x10, 0xe7, 0xc1, 0x5a, 0xb8, 0x66, 0xa2} };
|
||
|
|
||
|
const GUID GUID_READ_DB = { /* 0e10c969-78fb-11d2-90d4-00c04f79dc55 */
|
||
|
0x0e10c969,
|
||
|
0x78fb,
|
||
|
0x11d2,
|
||
|
{0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55} };
|
||
|
|
||
|
HRESULT
|
||
|
myGetSDFromTemplate(
|
||
|
IN WCHAR const *pwszStringSD,
|
||
|
IN OPTIONAL WCHAR const *pwszReplace,
|
||
|
OUT PSECURITY_DESCRIPTOR *ppSD)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
WCHAR *pwszReplaceSD = NULL;
|
||
|
WCHAR const *pwszFinalSD = pwszStringSD;
|
||
|
|
||
|
CSASSERT(NULL != ppSD);
|
||
|
|
||
|
if (NULL == ppSD)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "null SD pointer");
|
||
|
}
|
||
|
|
||
|
if (NULL != pwszReplace)
|
||
|
{
|
||
|
// replace the token
|
||
|
|
||
|
CSASSERT(NULL != wcsstr(pwszStringSD, L"%ws"));
|
||
|
|
||
|
pwszReplaceSD = (WCHAR*)LocalAlloc(LMEM_FIXED,
|
||
|
(wcslen(pwszStringSD) +
|
||
|
wcslen(pwszReplace) + 1) * sizeof(WCHAR) );
|
||
|
if (NULL == pwszReplaceSD)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
wsprintf(pwszReplaceSD, pwszStringSD, pwszReplace);
|
||
|
pwszFinalSD = pwszReplaceSD;
|
||
|
}
|
||
|
|
||
|
// build the security descriptor including the local machine.
|
||
|
if (!myConvertStringSecurityDescriptorToSecurityDescriptor(
|
||
|
pwszFinalSD,
|
||
|
SDDL_REVISION,
|
||
|
ppSD,
|
||
|
NULL))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(
|
||
|
hr,
|
||
|
error,
|
||
|
"myConvertStringSecurityDescriptorToSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
DBGPRINT((DBG_SS_CERTLIBI, "security descriptor:%ws\n", pwszFinalSD));
|
||
|
|
||
|
hr = S_OK;
|
||
|
error:
|
||
|
if (NULL != pwszReplaceSD)
|
||
|
{
|
||
|
LocalFree(pwszReplaceSD);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
myGetSecurityDescriptorDacl(
|
||
|
IN PSECURITY_DESCRIPTOR pSD,
|
||
|
OUT PACL *ppDacl) // no free
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
PACL pDacl = NULL; //no free
|
||
|
BOOL bDaclPresent = FALSE;
|
||
|
BOOL bDaclDefaulted = FALSE;
|
||
|
|
||
|
CSASSERT(NULL != ppDacl);
|
||
|
|
||
|
//init
|
||
|
*ppDacl = NULL;
|
||
|
|
||
|
// get dacl pointers
|
||
|
if (!GetSecurityDescriptorDacl(pSD,
|
||
|
&bDaclPresent,
|
||
|
&pDacl,
|
||
|
&bDaclDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorDacl");
|
||
|
}
|
||
|
if(!bDaclPresent || (pDacl == NULL))
|
||
|
{
|
||
|
hr = E_UNEXPECTED;
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorDacl");
|
||
|
}
|
||
|
|
||
|
*ppDacl = pDacl;
|
||
|
|
||
|
hr = S_OK;
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
myGetSecurityDescriptorSacl(
|
||
|
IN PSECURITY_DESCRIPTOR pSD,
|
||
|
OUT PACL *ppSacl) // no free
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
PACL pSacl = NULL; //no free
|
||
|
BOOL bSaclPresent = FALSE;
|
||
|
BOOL bSaclDefaulted = FALSE;
|
||
|
|
||
|
CSASSERT(NULL != ppSacl);
|
||
|
|
||
|
//init
|
||
|
*ppSacl = NULL;
|
||
|
|
||
|
// get dacl pointers
|
||
|
if (!GetSecurityDescriptorSacl(pSD,
|
||
|
&bSaclPresent,
|
||
|
&pSacl,
|
||
|
&bSaclDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorDacl");
|
||
|
}
|
||
|
if(!bSaclPresent || (pSacl == NULL))
|
||
|
{
|
||
|
hr = E_UNEXPECTED;
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorDacl");
|
||
|
}
|
||
|
|
||
|
*ppSacl = pSacl;
|
||
|
|
||
|
hr = S_OK;
|
||
|
error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#define CERTSRV_DACL_CONTROL_MASK SE_DACL_AUTO_INHERIT_REQ | \
|
||
|
SE_DACL_AUTO_INHERITED | \
|
||
|
SE_DACL_PROTECTED
|
||
|
#define CERTSRV_SACL_CONTROL_MASK SE_SACL_AUTO_INHERIT_REQ | \
|
||
|
SE_SACL_AUTO_INHERITED | \
|
||
|
SE_SACL_PROTECTED
|
||
|
|
||
|
|
||
|
// Merge parts of a new SD with an old SD based on the SI flags:
|
||
|
// DACL_SECURITY_INFORMATION - use new SD DACL
|
||
|
// SACL_SECURITY_INFORMATION - use new SD SACL
|
||
|
// OWNER_SECURITY_INFORMATION - use new SD owner
|
||
|
// GROUP_SECURITY_INFORMATION - use new SD group
|
||
|
|
||
|
HRESULT
|
||
|
myMergeSD(
|
||
|
IN PSECURITY_DESCRIPTOR pSDOld,
|
||
|
IN PSECURITY_DESCRIPTOR pSDMerge,
|
||
|
IN SECURITY_INFORMATION si,
|
||
|
OUT PSECURITY_DESCRIPTOR *ppSDNew)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
PSECURITY_DESCRIPTOR pSDDaclSource =
|
||
|
si & DACL_SECURITY_INFORMATION ? pSDMerge : pSDOld;
|
||
|
PSECURITY_DESCRIPTOR pSDSaclSource =
|
||
|
si & SACL_SECURITY_INFORMATION ? pSDMerge : pSDOld;
|
||
|
PSECURITY_DESCRIPTOR pSDOwnerSource =
|
||
|
si & OWNER_SECURITY_INFORMATION ? pSDMerge : pSDOld;
|
||
|
PSECURITY_DESCRIPTOR pSDGroupSource =
|
||
|
si & GROUP_SECURITY_INFORMATION ? pSDMerge : pSDOld;
|
||
|
PSECURITY_DESCRIPTOR pSDNew = NULL;
|
||
|
PSECURITY_DESCRIPTOR pSDNewRelative = NULL;
|
||
|
SECURITY_DESCRIPTOR_CONTROL sdc;
|
||
|
PACL pDacl = NULL; //no free
|
||
|
PSID pGroupSid = NULL; //no free
|
||
|
BOOL fGroupDefaulted = FALSE;
|
||
|
PSID pOwnerSid = NULL; //no free
|
||
|
BOOL fOwnerDefaulted = FALSE;
|
||
|
DWORD dwSize;
|
||
|
BOOL fSaclPresent = FALSE;
|
||
|
BOOL fSaclDefaulted = FALSE;
|
||
|
PACL pSacl = NULL; //no free
|
||
|
DWORD dwRevision;
|
||
|
|
||
|
CSASSERT(NULL != pSDOld);
|
||
|
CSASSERT(NULL != pSDMerge);
|
||
|
CSASSERT(NULL != ppSDNew);
|
||
|
|
||
|
*ppSDNew = NULL;
|
||
|
|
||
|
pSDNew = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED,
|
||
|
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||
|
if (pSDNew == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(pSDNew, SECURITY_DESCRIPTOR_REVISION))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "InitializeSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
// set SD control
|
||
|
if (!GetSecurityDescriptorControl(pSDOld, &sdc, &dwRevision))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorControl");
|
||
|
}
|
||
|
|
||
|
if (!SetSecurityDescriptorControl(
|
||
|
pSDNew,
|
||
|
CERTSRV_DACL_CONTROL_MASK|
|
||
|
CERTSRV_SACL_CONTROL_MASK,
|
||
|
sdc &
|
||
|
(CERTSRV_DACL_CONTROL_MASK|
|
||
|
CERTSRV_SACL_CONTROL_MASK)))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorControl");
|
||
|
}
|
||
|
|
||
|
// get CA security acl info
|
||
|
hr = myGetSecurityDescriptorDacl(
|
||
|
pSDDaclSource,
|
||
|
&pDacl);
|
||
|
_JumpIfError(hr, error, "myGetDaclFromInfoSecurityDescriptor");
|
||
|
|
||
|
// set new SD dacl
|
||
|
if(!SetSecurityDescriptorDacl(pSDNew,
|
||
|
TRUE,
|
||
|
pDacl,
|
||
|
FALSE))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorDacl");
|
||
|
}
|
||
|
|
||
|
// set new SD group
|
||
|
if(!GetSecurityDescriptorGroup(pSDGroupSource, &pGroupSid, &fGroupDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorGroup");
|
||
|
}
|
||
|
if(!SetSecurityDescriptorGroup(pSDNew, pGroupSid, fGroupDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorGroup");
|
||
|
}
|
||
|
|
||
|
// set new SD owner
|
||
|
if(!GetSecurityDescriptorOwner(pSDOwnerSource, &pOwnerSid, &fOwnerDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorGroup");
|
||
|
}
|
||
|
if(!SetSecurityDescriptorOwner(pSDNew, pOwnerSid, fOwnerDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorGroup");
|
||
|
}
|
||
|
|
||
|
// set new SD sacl
|
||
|
if(!GetSecurityDescriptorSacl(pSDSaclSource, &fSaclPresent, &pSacl, &fSaclDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "GetSecurityDescriptorSacl");
|
||
|
}
|
||
|
if(!SetSecurityDescriptorSacl(pSDNew, fSaclPresent, pSacl, fSaclDefaulted))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "SetSecurityDescriptorSacl");
|
||
|
}
|
||
|
|
||
|
if (!IsValidSecurityDescriptor(pSDNew))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "IsValidSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
dwSize = GetSecurityDescriptorLength(pSDNew);
|
||
|
pSDNewRelative = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, dwSize);
|
||
|
if(pSDNewRelative == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if(!MakeSelfRelativeSD(pSDNew, pSDNewRelative, &dwSize))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
|
||
|
if (!IsValidSecurityDescriptor(pSDNewRelative))
|
||
|
{
|
||
|
hr = myHLastError();
|
||
|
_JumpError(hr, error, "IsValidSecurityDescriptor");
|
||
|
}
|
||
|
|
||
|
*ppSDNew = pSDNewRelative;
|
||
|
pSDNewRelative = NULL;
|
||
|
hr = S_OK;
|
||
|
error:
|
||
|
if(pSDNew)
|
||
|
{
|
||
|
LocalFree(pSDNew);
|
||
|
}
|
||
|
if(pSDNewRelative)
|
||
|
{
|
||
|
LocalFree(pSDNewRelative);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
UpdateServiceSacl(bool fTurnOnAuditing)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
PSECURITY_DESCRIPTOR pSaclSD = NULL;
|
||
|
PACL pSacl = NULL; // no free
|
||
|
bool fPrivilegeEnabled = false;
|
||
|
|
||
|
hr = myGetSDFromTemplate(
|
||
|
fTurnOnAuditing?
|
||
|
CERTSRV_SERVICE_SACL_ON:
|
||
|
CERTSRV_SERVICE_SACL_OFF,
|
||
|
NULL, // no insertion string
|
||
|
&pSaclSD);
|
||
|
_JumpIfError(hr, error, "myGetSDFromTemplate");
|
||
|
|
||
|
hr = myGetSecurityDescriptorSacl(
|
||
|
pSaclSD,
|
||
|
&pSacl);
|
||
|
_JumpIfError(hr, error, "myGet");
|
||
|
|
||
|
|
||
|
hr = myEnablePrivilege(SE_SECURITY_NAME, TRUE);
|
||
|
_JumpIfError(hr, error, "myEnablePrivilege");
|
||
|
|
||
|
fPrivilegeEnabled = true;
|
||
|
|
||
|
hr = SetNamedSecurityInfo(
|
||
|
wszSERVICE_NAME,
|
||
|
SE_SERVICE,
|
||
|
SACL_SECURITY_INFORMATION,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
pSacl);
|
||
|
if(ERROR_SUCCESS != hr)
|
||
|
{
|
||
|
hr = myHError(hr);
|
||
|
_JumpError(hr, error, "SetNamedSecurityInfo");
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
if(fPrivilegeEnabled)
|
||
|
{
|
||
|
myEnablePrivilege(SE_SECURITY_NAME, FALSE);
|
||
|
}
|
||
|
LOCAL_FREE(pSaclSD);
|
||
|
return hr;
|
||
|
}
|
||
|
|