1173 lines
35 KiB
C++
1173 lines
35 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1999.
|
||
|
//
|
||
|
// File: EffRight.cpp
|
||
|
//
|
||
|
// Contents: Effective Rights Diagnosis and support methods
|
||
|
//
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
#include "stdafx.h"
|
||
|
#include "adutils.h"
|
||
|
#include "EffRight.h"
|
||
|
#include "AccessCk.h"
|
||
|
#include "SecDesc.h"
|
||
|
|
||
|
// Classes
|
||
|
#pragma warning (disable : 4127)
|
||
|
|
||
|
class CResultObject
|
||
|
{
|
||
|
public:
|
||
|
CResultObject (
|
||
|
ACCESS_MASK accessBit,
|
||
|
const wstring& strResult,
|
||
|
GUID_TYPE guidType,
|
||
|
USHORT level);
|
||
|
~CResultObject () {}
|
||
|
|
||
|
bool operator== (CResultObject& rResultObject)
|
||
|
{
|
||
|
if ( m_accessBit == rResultObject.m_accessBit )
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
bool operator< (CResultObject& rResultObject)
|
||
|
{
|
||
|
if ( 0 == m_level )
|
||
|
return true;
|
||
|
|
||
|
if ( m_accessBit < rResultObject.m_accessBit )
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const CResultObject& operator= (const CResultObject& obj)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER (obj);
|
||
|
ASSERT (0);
|
||
|
}
|
||
|
|
||
|
void PrintResult ()
|
||
|
{
|
||
|
MyWprintf (m_strResult.c_str ());
|
||
|
}
|
||
|
|
||
|
ACCESS_MASK GetRight () const
|
||
|
{
|
||
|
return m_accessBit;
|
||
|
}
|
||
|
|
||
|
bool IsValid () const
|
||
|
{
|
||
|
return m_bIsValid;
|
||
|
}
|
||
|
|
||
|
USHORT GetLevel () const
|
||
|
{
|
||
|
return m_level;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
const wstring m_strResult;
|
||
|
const ACCESS_MASK m_accessBit;
|
||
|
const GUID_TYPE m_guidType;
|
||
|
bool m_bIsValid;
|
||
|
const USHORT m_level;
|
||
|
};
|
||
|
|
||
|
CResultObject::CResultObject (
|
||
|
ACCESS_MASK accessBit,
|
||
|
const wstring& strResult,
|
||
|
GUID_TYPE guidType,
|
||
|
USHORT level) :
|
||
|
m_accessBit (accessBit),
|
||
|
m_strResult (strResult),
|
||
|
m_guidType (guidType),
|
||
|
m_bIsValid (true),
|
||
|
m_level (level)
|
||
|
{
|
||
|
|
||
|
// case ACTRL_DS_LIST:
|
||
|
// case ACTRL_DELETE:
|
||
|
// case ACTRL_CHANGE_ACCESS:
|
||
|
// case ACTRL_CHANGE_OWNER:
|
||
|
// case ACTRL_DS_LIST_OBJECT:
|
||
|
// case ACTRL_DS_SELF:
|
||
|
|
||
|
switch (guidType)
|
||
|
{
|
||
|
case GUID_TYPE_CLASS:
|
||
|
ASSERT (0 == m_level);
|
||
|
switch (accessBit)
|
||
|
{
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
case ACTRL_DS_READ_PROP: // all
|
||
|
case ACTRL_DS_WRITE_PROP: // all
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_CONTROL_ACCESS: // all
|
||
|
case ACTRL_DS_SELF:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
m_bIsValid = false;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_ATTRIBUTE:
|
||
|
ASSERT (0 != m_level);
|
||
|
switch (accessBit)
|
||
|
{
|
||
|
case ACTRL_DS_READ_PROP:
|
||
|
case ACTRL_DS_WRITE_PROP:
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
case ACTRL_DS_CONTROL_ACCESS:
|
||
|
m_bIsValid = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
m_bIsValid = false;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_CONTROL:
|
||
|
ASSERT (0 != m_level);
|
||
|
switch (accessBit)
|
||
|
{
|
||
|
case ACTRL_DS_CONTROL_ACCESS:
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
m_bIsValid = false;
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_READ_PROP:
|
||
|
case ACTRL_DS_WRITE_PROP:
|
||
|
case ACTRL_READ_CONTROL:
|
||
|
default:
|
||
|
m_bIsValid = false;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT (FALSE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
typedef CResultObject* PCResultObject;
|
||
|
|
||
|
bool compare_resultObject (PCResultObject& obj1, PCResultObject& obj2)
|
||
|
{
|
||
|
return (*obj1) < (*obj2);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Function Prototypes
|
||
|
//
|
||
|
|
||
|
HRESULT GetFQDN (
|
||
|
PSID_FQDN* pPsidFQDN,
|
||
|
wstring& strFQDN);
|
||
|
HRESULT GetDownlevelName (
|
||
|
PSID_FQDN* pPsidFQDN,
|
||
|
wstring& strDownlevelName);
|
||
|
HRESULT ProcessObject (
|
||
|
const wstring& strObjectDN,
|
||
|
POBJECT_TYPE_LIST pObjectTypeList,
|
||
|
size_t objectTypeListLength,
|
||
|
PSID principalSelfSid,
|
||
|
const wstring& strDownlevelName);
|
||
|
HRESULT GetTokenGroups (
|
||
|
const wstring& strObjectDN,
|
||
|
list<PSID>& psidList);
|
||
|
HRESULT EnumerateEffectivePermissions (
|
||
|
const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const P_TYPE ptype,
|
||
|
vector<PCResultObject>& resultList);
|
||
|
HRESULT DisplayEffectivePermission (
|
||
|
const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const P_TYPE ptype,
|
||
|
const int strIDAll,
|
||
|
const int strIDParam,
|
||
|
const int strIDCDO,
|
||
|
vector<PCResultObject>& resultList);
|
||
|
HRESULT DisplayEffectivePermission (
|
||
|
const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const P_TYPE ptype,
|
||
|
const int strID,
|
||
|
vector<PCResultObject>& resultList);
|
||
|
void PrintGroupProvenance (
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const P_TYPE ptype,
|
||
|
wstring& strProvenance);
|
||
|
void PrintEffectiveRightsHeader (
|
||
|
ACCESS_MASK lastRight,
|
||
|
USHORT level);
|
||
|
|
||
|
HRESULT EffectiveRightsDiagnosis ()
|
||
|
{
|
||
|
_TRACE (1, L"Entering EffectiveRightsDiagnosis\n");
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
wstring str;
|
||
|
|
||
|
if ( !_Module.DoTabDelimitedOutput () )
|
||
|
{
|
||
|
LoadFromResource (str, IDS_EFFECTIVE_RIGHTS_DIAGNOSIS);
|
||
|
|
||
|
MyWprintf (str.c_str ());
|
||
|
}
|
||
|
|
||
|
POBJECT_TYPE_LIST pObjectTypeList = 0;
|
||
|
size_t objectTypeListLength = 0;
|
||
|
|
||
|
hr = _Module.m_adsiObject.BuildObjectTypeList (&pObjectTypeList, objectTypeListLength);
|
||
|
|
||
|
if ( SUCCEEDED (hr) && SUCCEEDED (SepInit ()) )
|
||
|
{
|
||
|
PSID principalSelfSid = 0;
|
||
|
hr = _Module.m_adsiObject.GetPrincipalSelfSid (principalSelfSid);
|
||
|
if ( !wcscmp (_Module.GetEffectiveRightsPrincipal ().c_str (), L"*") )
|
||
|
{
|
||
|
for (PSID_FQDN_LIST::iterator itr = _Module.m_PSIDList.begin ();
|
||
|
itr != _Module.m_PSIDList.end ();// && SUCCEEDED (hr);
|
||
|
itr++)
|
||
|
{
|
||
|
wstring strDownlevelName;
|
||
|
wstring strFQDN;
|
||
|
|
||
|
hr = GetFQDN (*itr, strFQDN);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = GetDownlevelName (*itr, strDownlevelName);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = ProcessObject (strFQDN, pObjectTypeList,
|
||
|
objectTypeListLength, principalSelfSid,
|
||
|
strDownlevelName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = ProcessObject (_Module.GetEffectiveRightsPrincipal (),
|
||
|
pObjectTypeList, objectTypeListLength, principalSelfSid,
|
||
|
_Module.GetEffectiveRightsPrincipal ());
|
||
|
}
|
||
|
|
||
|
// Free memory allocated for Sid
|
||
|
if ( principalSelfSid )
|
||
|
CoTaskMemFree (principalSelfSid);
|
||
|
|
||
|
// Free object type list array
|
||
|
for (DWORD idx = 0; idx < objectTypeListLength; idx++)
|
||
|
{
|
||
|
CoTaskMemFree (pObjectTypeList[idx].ObjectType);
|
||
|
}
|
||
|
CoTaskMemFree (pObjectTypeList);
|
||
|
|
||
|
SepCleanup ();
|
||
|
}
|
||
|
|
||
|
_TRACE (-1, L"Leaving EffectiveRightsDiagnosis: 0x%x\n", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT GetDownlevelName (PSID_FQDN* pPsidFQDN, wstring& strDownlevelName)
|
||
|
{
|
||
|
_TRACE (1, L"Entering GetDownlevelName\n");
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if ( pPsidFQDN )
|
||
|
{
|
||
|
switch (pPsidFQDN->m_sne)
|
||
|
{
|
||
|
case SidTypeUser: // Indicates a user SID.
|
||
|
case SidTypeGroup: // Indicates a group SID.
|
||
|
case SidTypeAlias: // Indicates an alias SID.
|
||
|
case SidTypeWellKnownGroup: // Indicates an SID for a well-known group.
|
||
|
case SidTypeDomain: // Indicates a domain SID.
|
||
|
case SidTypeDeletedAccount: // Indicates an SID for a deleted account.
|
||
|
strDownlevelName = pPsidFQDN->m_strDownLevelName;
|
||
|
break;
|
||
|
|
||
|
case SidTypeInvalid: // Indicates an invalid SID.
|
||
|
case SidTypeUnknown: // Indicates an unknown SID type.
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = E_UNEXPECTED;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = E_POINTER;
|
||
|
|
||
|
_TRACE (-1, L"Leaving GetDownlevelName: 0x%x\n", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT GetFQDN (PSID_FQDN* pPsidFQDN, wstring& strFQDN)
|
||
|
{
|
||
|
_TRACE (1, L"Entering GetFQDN\n");
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if ( pPsidFQDN )
|
||
|
{
|
||
|
switch (pPsidFQDN->m_sne)
|
||
|
{
|
||
|
case SidTypeUser: // Indicates a user SID.
|
||
|
case SidTypeGroup: // Indicates a group SID.
|
||
|
case SidTypeAlias: // Indicates an alias SID.
|
||
|
case SidTypeWellKnownGroup: // Indicates an SID for a well-known group.
|
||
|
strFQDN = pPsidFQDN->m_strFQDN;
|
||
|
break;
|
||
|
|
||
|
case SidTypeDomain: // Indicates a domain SID.
|
||
|
case SidTypeDeletedAccount: // Indicates an SID for a deleted account.
|
||
|
case SidTypeInvalid: // Indicates an invalid SID.
|
||
|
case SidTypeUnknown: // Indicates an unknown SID type.
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = E_UNEXPECTED;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = E_POINTER;
|
||
|
|
||
|
_TRACE (-1, L"Leaving GetFQDN: 0x%x\n", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT GetTokenGroups (const wstring& strObjectDN, list<PSID>& psidList)
|
||
|
{
|
||
|
_TRACE (1, L"Entering GetTokenGroups\n");
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
|
||
|
CComPtr<IADsPathname> spPathname;
|
||
|
//
|
||
|
// Constructing the directory paths
|
||
|
//
|
||
|
hr = CoCreateInstance(
|
||
|
CLSID_Pathname,
|
||
|
NULL,
|
||
|
CLSCTX_ALL,
|
||
|
IID_PPV_ARG (IADsPathname, &spPathname));
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
ASSERT (!!spPathname);
|
||
|
hr = spPathname->put_EscapedMode (ADS_ESCAPEDMODE_OFF_EX );
|
||
|
|
||
|
hr = spPathname->Set (const_cast <PWSTR> (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = spPathname->Set (
|
||
|
const_cast <PWSTR> (strObjectDN.c_str ()),
|
||
|
ADS_SETTYPE_DN);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
BSTR bstrFullPath = 0;
|
||
|
hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
CComPtr<IDirectoryObject> spDirObj;
|
||
|
|
||
|
|
||
|
hr = ADsGetObject (
|
||
|
bstrFullPath,
|
||
|
IID_PPV_ARG (IDirectoryObject, &spDirObj));
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
{
|
||
|
//
|
||
|
// Get "objectSid" attribute
|
||
|
//
|
||
|
const PWSTR wzAllowedAttributes = L"objectSid";
|
||
|
PADS_ATTR_INFO pAttrs = 0;
|
||
|
DWORD cAttrs = 0;
|
||
|
LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
|
||
|
|
||
|
hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
|
||
|
{
|
||
|
for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
|
||
|
{
|
||
|
PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
|
||
|
if ( pSid && IsValidSid (pSid) )
|
||
|
{
|
||
|
DWORD dwSidLen = GetLengthSid (pSid);
|
||
|
PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
|
||
|
|
||
|
if ( pSidCopy )
|
||
|
{
|
||
|
if ( CopySid (dwSidLen, pSidCopy, pSid) )
|
||
|
{
|
||
|
ASSERT (IsValidSid (pSidCopy));
|
||
|
psidList.push_back (pSidCopy);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CoTaskMemFree (pSidCopy);
|
||
|
hr = GetLastError ();
|
||
|
_TRACE (0, L"CopySid () failed: 0x%x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( pAttrs )
|
||
|
FreeADsMem (pAttrs);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
//
|
||
|
// Get "tokenGroups" attribute
|
||
|
//
|
||
|
const PWSTR wzAllowedAttributes = L"tokenGroups";
|
||
|
PADS_ATTR_INFO pAttrs = 0;
|
||
|
DWORD cAttrs = 0;
|
||
|
LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
|
||
|
|
||
|
hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
|
||
|
{
|
||
|
for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
|
||
|
{
|
||
|
PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
|
||
|
if ( pSid && IsValidSid (pSid) )
|
||
|
{
|
||
|
DWORD dwSidLen = GetLengthSid (pSid);
|
||
|
PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
|
||
|
|
||
|
if ( pSidCopy )
|
||
|
{
|
||
|
if ( CopySid (dwSidLen, pSidCopy, pSid) )
|
||
|
{
|
||
|
ASSERT (IsValidSid (pSidCopy));
|
||
|
psidList.push_back (pSidCopy);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CoTaskMemFree (pSidCopy);
|
||
|
hr = GetLastError ();
|
||
|
_TRACE (0, L"CopySid () failed: 0x%x\n", hr);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( pAttrs )
|
||
|
FreeADsMem (pAttrs);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"ADsGetObject (%s) failed: 0x%x\n", bstrFullPath);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"IADsPathname->Retrieve () failed: 0x%x\n", hr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n",
|
||
|
strObjectDN.c_str (), hr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n", ACLDIAG_LDAP, hr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_TRACE (0, L"CoCreateInstance(CLSID_Pathname) failed: 0x%x\n", hr);
|
||
|
}
|
||
|
|
||
|
_TRACE (-1, L"Leaving GetTokenGroups: 0x%x\n", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT ProcessObject (
|
||
|
const wstring& strObjectDN, // object having permissions on the
|
||
|
// target object
|
||
|
POBJECT_TYPE_LIST pObjectTypeList, // class, property and property set
|
||
|
// GUIDs of target object
|
||
|
size_t objectTypeListLength,// number of elements in pObjectTypeList
|
||
|
PSID principalSelfSid,
|
||
|
const wstring& strDownlevelName)
|
||
|
{
|
||
|
_TRACE (1, L"Entering ProcessObject\n");
|
||
|
HRESULT hr = S_OK;
|
||
|
list<PSID> psidList; // sid of strObjectDN and all groups of which it is a member
|
||
|
|
||
|
|
||
|
hr = GetTokenGroups (strObjectDN, psidList);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
PACL pDacl = 0;
|
||
|
BOOL bDaclPresent = FALSE;
|
||
|
BOOL bDaclDefaulted = FALSE;
|
||
|
|
||
|
if ( GetSecurityDescriptorDacl (_Module.m_pSecurityDescriptor,
|
||
|
&bDaclPresent, &pDacl, &bDaclDefaulted) )
|
||
|
{
|
||
|
PIOBJECT_TYPE_LIST LocalTypeList = 0;
|
||
|
//
|
||
|
// Capture any Object type list
|
||
|
//
|
||
|
|
||
|
NTSTATUS Status = SeCaptureObjectTypeList( pObjectTypeList,
|
||
|
objectTypeListLength,
|
||
|
&LocalTypeList);
|
||
|
|
||
|
if ( NT_SUCCESS(Status) )
|
||
|
{
|
||
|
hr = SepMaximumAccessCheck (psidList,
|
||
|
pDacl,
|
||
|
principalSelfSid,
|
||
|
objectTypeListLength,
|
||
|
LocalTypeList,
|
||
|
objectTypeListLength);
|
||
|
|
||
|
if ( !_Module.DoTabDelimitedOutput () )
|
||
|
{
|
||
|
wstring str;
|
||
|
|
||
|
FormatMessage (str, L"\n%1:\n\n", strDownlevelName.c_str ());
|
||
|
MyWprintf (str.c_str ());
|
||
|
}
|
||
|
|
||
|
vector<PCResultObject> resultList;
|
||
|
|
||
|
for (DWORD idx = 0; idx < objectTypeListLength; idx++)
|
||
|
{
|
||
|
EnumerateEffectivePermissions (strDownlevelName,
|
||
|
LocalTypeList[idx], P_ALLOW, resultList);
|
||
|
EnumerateEffectivePermissions (strDownlevelName,
|
||
|
LocalTypeList[idx], P_DENY, resultList);
|
||
|
}
|
||
|
|
||
|
// Sort LocalTypeList
|
||
|
// 1. Object Level Rights
|
||
|
// 2. Property Level Rights
|
||
|
// a. Create
|
||
|
// b. Delete
|
||
|
// c. Read
|
||
|
// d. Write
|
||
|
// 3. Control Rights
|
||
|
sort (resultList.begin (), resultList.end (), compare_resultObject);
|
||
|
ACCESS_MASK lastRight = 0;
|
||
|
|
||
|
for (vector<PCResultObject>::iterator itr = resultList.begin ();
|
||
|
itr != resultList.end (); itr++)
|
||
|
{
|
||
|
PCResultObject pResultObject = *itr;
|
||
|
|
||
|
if ( lastRight != pResultObject->GetRight () )
|
||
|
{
|
||
|
lastRight = pResultObject->GetRight ();
|
||
|
if ( !_Module.DoTabDelimitedOutput () )
|
||
|
PrintEffectiveRightsHeader (lastRight, pResultObject->GetLevel ());
|
||
|
}
|
||
|
pResultObject->PrintResult ();
|
||
|
delete pResultObject;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( LocalTypeList )
|
||
|
delete [] LocalTypeList;
|
||
|
}
|
||
|
|
||
|
// Free memory pointed to by psidList members
|
||
|
for (list<PSID>::iterator itr = psidList.begin ();
|
||
|
itr != psidList.end ();
|
||
|
itr++)
|
||
|
{
|
||
|
CoTaskMemFree (*itr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_TRACE (-1, L"Leaving ProcessObject: 0x%x\n", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Method: EnumerateEffectivePermissions ()
|
||
|
//
|
||
|
// Purpose: Print all the permissions contained on the passed in ACE
|
||
|
//
|
||
|
// Inputs: otl - structure containing the ACE whose permissions we wish
|
||
|
// to print
|
||
|
//
|
||
|
// ptype - allow, deny, succes, failure, success and failure
|
||
|
//
|
||
|
HRESULT EnumerateEffectivePermissions (
|
||
|
const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const P_TYPE ptype,
|
||
|
vector<PCResultObject>& resultList)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_CREATE_CHILD,
|
||
|
ptype,
|
||
|
IDS_CREATE_ALL_SUBOBJECTS_ER,
|
||
|
IDS_CREATE_CLASS_OBJECTS_ER,
|
||
|
IDS_CREATE_CLASS_OBJECTS,
|
||
|
resultList);
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_DELETE_CHILD,
|
||
|
ptype,
|
||
|
IDS_DELETE_ALL_SUBOBJECTS_ER,
|
||
|
IDS_DELETE_CLASS_OBJECTS_ER,
|
||
|
IDS_DELETE_CLASS_OBJECTS,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_READ_PROP,
|
||
|
ptype,
|
||
|
IDS_READ_ALL_PROPERTIES_ER,
|
||
|
IDS_READ_PROPERTY_PROPERTY_ER,
|
||
|
IDS_READ_PROPERTY_PROPERTY,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_WRITE_PROP,
|
||
|
ptype,
|
||
|
IDS_WRITE_ALL_PROPERTIES_ER,
|
||
|
IDS_WRITE_PROPERTY_PROPERTY_ER,
|
||
|
IDS_WRITE_PROPERTY_PROPERTY,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_LIST,
|
||
|
ptype,
|
||
|
IDS_LIST_CONTENTS_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_LIST_OBJECT,
|
||
|
ptype,
|
||
|
IDS_LIST_OBJECT_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
if ( otl.CurrentGranted & ACTRL_DS_CONTROL_ACCESS )
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_CONTROL_ACCESS,
|
||
|
ptype,
|
||
|
IDS_ALL_CONTROL_ACCESSES_ER,
|
||
|
IDS_CONTROL_ACCESS_DISPLAY_NAME,
|
||
|
IDS_CONTROL_ACCESS_DISPLAY_NAME,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DELETE,
|
||
|
ptype,
|
||
|
IDS_DELETE_THIS_OBJECT_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_READ_CONTROL,
|
||
|
ptype,
|
||
|
IDS_READ_PERMISSIONS_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_CHANGE_ACCESS,
|
||
|
ptype,
|
||
|
IDS_MODIFY_PERMISSIONS_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_CHANGE_OWNER,
|
||
|
ptype,
|
||
|
IDS_TAKE_CHANGE_OWNERSHIP_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
if ( SUCCEEDED (hr) )
|
||
|
{
|
||
|
hr = DisplayEffectivePermission (strObjectDN,
|
||
|
otl,
|
||
|
ACTRL_DS_SELF,
|
||
|
ptype,
|
||
|
IDS_MODIFY_MEMBERSHIP_ER,
|
||
|
resultList);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Method: DisplayEffectivePermission ()
|
||
|
//
|
||
|
// Purpose: Print an OBJECT_ACE_TYPE permission
|
||
|
//
|
||
|
// Inputs: otl - structure containing the ACE whose permission we wish
|
||
|
// to print
|
||
|
//
|
||
|
// accessMask - the specific permission we're looking to print
|
||
|
//
|
||
|
// bAllow - whether the permission is allowed or denied
|
||
|
//
|
||
|
// strIDAll - string to print if permission applies to all object
|
||
|
// classes
|
||
|
//
|
||
|
// strIDParam - string print if permission applies to a specific
|
||
|
// object class
|
||
|
//
|
||
|
HRESULT DisplayEffectivePermission (const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const P_TYPE ptype,
|
||
|
const int strIDAll,
|
||
|
const int strIDParam,
|
||
|
const int strIDCDO,
|
||
|
vector<PCResultObject>& resultList)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
wstring str;
|
||
|
wstring strPermission;
|
||
|
|
||
|
|
||
|
if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
|
||
|
((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
|
||
|
{
|
||
|
wstring strGuidResult;
|
||
|
GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
|
||
|
|
||
|
_Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
|
||
|
|
||
|
switch (guidType)
|
||
|
{
|
||
|
case GUID_TYPE_CLASS:
|
||
|
FormatMessage (strPermission, strIDAll, strGuidResult.c_str ());
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_ATTRIBUTE:
|
||
|
switch (accessMask)
|
||
|
{
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_SELF:
|
||
|
// case ACTRL_DS_CONTROL_ACCESS:
|
||
|
return S_OK;
|
||
|
|
||
|
default:
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
FormatMessage (strPermission, strIDCDO, strGuidResult.c_str ());
|
||
|
else
|
||
|
FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_CONTROL:
|
||
|
switch (accessMask)
|
||
|
{
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_SELF:
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
case ACTRL_DELETE:
|
||
|
case ACTRL_CHANGE_ACCESS:
|
||
|
case ACTRL_CHANGE_OWNER:
|
||
|
case ACTRL_DS_CONTROL_ACCESS:
|
||
|
return S_OK;
|
||
|
|
||
|
case ACTRL_DS_READ_PROP:
|
||
|
case ACTRL_DS_WRITE_PROP:
|
||
|
case ACTRL_READ_CONTROL:
|
||
|
default:
|
||
|
FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_UNKNOWN:
|
||
|
default:
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
|
||
|
int strid = 0;
|
||
|
|
||
|
switch (ptype)
|
||
|
{
|
||
|
case P_ALLOW:
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
strid = IDS_CAN_CDO;
|
||
|
else
|
||
|
strid = IDS_CAN_ER;
|
||
|
break;
|
||
|
|
||
|
case P_DENY:
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
strid = IDS_CANNOT_CDO;
|
||
|
else
|
||
|
strid = IDS_CANNOT_EF;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
{
|
||
|
FormatMessage (str, strid,
|
||
|
strObjectDN.c_str (),
|
||
|
strPermission.c_str ());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FormatMessage (str, strid,
|
||
|
strPermission.c_str ());
|
||
|
}
|
||
|
|
||
|
wstring strProvenance;
|
||
|
|
||
|
PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
|
||
|
str += strProvenance;
|
||
|
|
||
|
PCResultObject pResultObject = new CResultObject (accessMask, str,
|
||
|
guidType, otl.Level);
|
||
|
if ( pResultObject )
|
||
|
{
|
||
|
if ( pResultObject->IsValid () )
|
||
|
resultList.push_back (pResultObject);
|
||
|
else
|
||
|
delete pResultObject;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Method: DisplayEffectivePermission ()
|
||
|
//
|
||
|
// Purpose: Print a non-OBJECT_ACE_TYPE permission
|
||
|
//
|
||
|
// Inputs: otl - structure containing the ACE whose permission we wish
|
||
|
// to print
|
||
|
//
|
||
|
// accessMask - the specific permission we're looking to print
|
||
|
//
|
||
|
// bAllow - whether the permission is allowed or denied
|
||
|
//
|
||
|
// strID - string to print
|
||
|
//
|
||
|
HRESULT DisplayEffectivePermission (
|
||
|
const wstring& strObjectDN,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const P_TYPE ptype,
|
||
|
const int strID,
|
||
|
vector<PCResultObject>& resultList)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
wstring str;
|
||
|
wstring strPermission;
|
||
|
|
||
|
|
||
|
if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
|
||
|
((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
|
||
|
{
|
||
|
wstring strGuidResult;
|
||
|
GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
|
||
|
wstring strType;
|
||
|
|
||
|
_Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
|
||
|
|
||
|
switch (guidType)
|
||
|
{
|
||
|
case GUID_TYPE_CLASS:
|
||
|
LoadFromResource (strType, IDS_CLASS);
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_ATTRIBUTE:
|
||
|
switch (accessMask)
|
||
|
{
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_SELF:
|
||
|
return S_OK;
|
||
|
|
||
|
default:
|
||
|
LoadFromResource (strType, IDS_PROPERTY);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_CONTROL:
|
||
|
switch (accessMask)
|
||
|
{
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_SELF:
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
case ACTRL_DELETE:
|
||
|
case ACTRL_CHANGE_ACCESS:
|
||
|
case ACTRL_CHANGE_OWNER:
|
||
|
case ACTRL_DS_CONTROL_ACCESS:
|
||
|
return S_OK;
|
||
|
|
||
|
case ACTRL_DS_READ_PROP:
|
||
|
case ACTRL_DS_WRITE_PROP:
|
||
|
case ACTRL_READ_CONTROL:
|
||
|
default:
|
||
|
LoadFromResource (strType, IDS_CONTROL);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GUID_TYPE_UNKNOWN:
|
||
|
default:
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
LoadFromResource (strPermission, strID);
|
||
|
|
||
|
int id = 0;
|
||
|
switch (ptype)
|
||
|
{
|
||
|
case P_ALLOW:
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
id = IDS_CAN_CDO;
|
||
|
else
|
||
|
id = IDS_CAN;
|
||
|
break;
|
||
|
|
||
|
case P_DENY:
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
id = IDS_CANNOT_CDO;
|
||
|
else
|
||
|
id = IDS_CANNOT_EF;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
{
|
||
|
FormatMessage (str, id,
|
||
|
strObjectDN.c_str (),
|
||
|
strPermission.c_str ());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FormatMessage (str, id, strPermission.c_str ());
|
||
|
}
|
||
|
|
||
|
wstring strProvenance;
|
||
|
|
||
|
PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
|
||
|
str += strProvenance;
|
||
|
|
||
|
PCResultObject pResultObject = new CResultObject (accessMask, str,
|
||
|
guidType, otl.Level);
|
||
|
if ( pResultObject )
|
||
|
{
|
||
|
if ( pResultObject->IsValid () )
|
||
|
resultList.push_back (pResultObject);
|
||
|
else
|
||
|
delete pResultObject;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
void PrintGroupProvenance (
|
||
|
const ACCESS_MASK accessMask,
|
||
|
const IOBJECT_TYPE_LIST& otl,
|
||
|
const P_TYPE ptype,
|
||
|
wstring& strProvenance)
|
||
|
{
|
||
|
UINT nSid = 0;
|
||
|
|
||
|
for (ULONG nBit = 0x1; nBit; nBit <<= 1, nSid++)
|
||
|
{
|
||
|
if ( accessMask & nBit )
|
||
|
{
|
||
|
wstring strGroup;
|
||
|
PSID psid = 0;
|
||
|
SID_NAME_USE sne = SidTypeUnknown;
|
||
|
|
||
|
if ( P_ALLOW == ptype )
|
||
|
psid = otl.grantingSid[nSid];
|
||
|
else
|
||
|
psid = otl.denyingSid[nSid];
|
||
|
|
||
|
if ( IsValidSid (psid) )
|
||
|
{
|
||
|
GetNameFromSid (psid, strGroup, 0, sne);
|
||
|
if ( SidTypeGroup == sne )
|
||
|
{
|
||
|
if ( _Module.DoTabDelimitedOutput () )
|
||
|
FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP_CDO, strGroup.c_str ());
|
||
|
else
|
||
|
FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP, strGroup.c_str ());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
strProvenance += L"\n";
|
||
|
}
|
||
|
|
||
|
|
||
|
void PrintEffectiveRightsHeader (ACCESS_MASK lastRight, USHORT level)
|
||
|
{
|
||
|
wstring str;
|
||
|
|
||
|
|
||
|
if ( 0 == level ) // Object level rights
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch (lastRight)
|
||
|
{
|
||
|
case ACTRL_DS_LIST:
|
||
|
case ACTRL_DELETE:
|
||
|
case ACTRL_READ_CONTROL:
|
||
|
case ACTRL_CHANGE_ACCESS:
|
||
|
case ACTRL_CHANGE_OWNER:
|
||
|
str = L"\n\n";
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_CREATE_CHILD:
|
||
|
LoadFromResource (str, IDS_CAN_CREATE_FOLLOWING_CHILD_OBJECTS);
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_DELETE_CHILD:
|
||
|
LoadFromResource (str, IDS_CAN_DELETE_FOLLOWING_CHILD_OBJECTS);
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_READ_PROP:
|
||
|
LoadFromResource (str, IDS_CAN_READ_FOLLOWING_PROPERTIES);
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_WRITE_PROP:
|
||
|
LoadFromResource (str, IDS_CAN_WRITE_FOLLOWING_PROPERTIES);
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_CONTROL_ACCESS:
|
||
|
LoadFromResource (str, IDS_CAN_DO_FOLLOWING_CONTROL_OPERATIONS);
|
||
|
break;
|
||
|
|
||
|
case ACTRL_DS_LIST_OBJECT:
|
||
|
case ACTRL_DS_SELF:
|
||
|
default:
|
||
|
str = L"\n\n";
|
||
|
break;;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MyWprintf (str.c_str ());
|
||
|
}
|