Directory Services

Example Code for Checking a Control Access Right in an Object's ACL

The following code example can be used to verify that the currently logged-on user has permissions for a control access right on the specified object.

// Define the Generic Mapping structure.
// Generic read
#define GENERIC_READ_MAPPING	 ((STANDARD_RIGHTS_READ)	 | \
								(ADS_RIGHT_ACTRL_DS_LIST)   | \
								(ADS_RIGHT_DS_READ_PROP)   | \
								(ADS_RIGHT_DS_LIST_OBJECT))
// Generic execute
#define GENERIC_EXECUTE_MAPPING  ((STANDARD_RIGHTS_EXECUTE)  | \
								(ADS_RIGHT_ACTRL_DS_LIST))
// Generic right
#define GENERIC_WRITE_MAPPING	((STANDARD_RIGHTS_WRITE)	| \
								(ADS_RIGHT_DS_SELF)	| \
				(ADS_RIGHT_DS_WRITE_PROP))
// Generic all
#define GENERIC_ALL_MAPPING	((STANDARD_RIGHTS_REQUIRED) | \
								(ADS_RIGHT_DS_CREATE_CHILD)	| \
								(ADS_RIGHT_DS_DELETE_CHILD)	| \
								(ADS_RIGHT_DS_DELETE_TREE)	 | \
								(ADS_RIGHT_DS_READ_PROP)   | \
								(ADS_RIGHT_DS_WRITE_PROP)  | \
								(ADS_RIGHT_ACTRL_DS_LIST)   | \
								(ADS_RIGHT_DS_LIST_OBJECT)	 | \
								(ADS_RIGHT_DS_CONTROL_ACCESS)  | \
								(ADS_RIGHT_DS_SELF))
// Standard DS generic access rights mapping
#define DS_GENERIC_MAPPING {GENERIC_READ_MAPPING, \
				GENERIC_WRITE_MAPPING,   \
				GENERIC_EXECUTE_MAPPING, \
				GENERIC_ALL_MAPPING}
 
HRESULT CheckExtendedRight(
							HANDLE hToken,
							IDirectoryObject *pObject,
							CLSID pclsid,
							DWORD *dwAccess
							)
 
{
HRESULT hr = E_FAIL;
*dwAccess = FALSE;
BOOL bSuccess = FALSE;
PADS_ATTR_INFO pAttrInfo = NULL;
DWORD   dwReturn= 0;
LPWSTR   pAttrNames[]= {L"nTSecurityDescriptor",L"objectSid"};
PSECURITY_DESCRIPTOR pSD = NULL;
DWORD   SDSize;
VOID	*pAbsoluteSD = NULL; 
DWORD   AbsoluteSDSize = 0;
VOID	*pDacl = NULL;
DWORD   DaclSize = 0;
VOID	*pSacl = NULL;
DWORD   SaclSize = 0;
VOID	*pOwner = NULL;
DWORD   OwnerSize = 0;
VOID	*pGroup = NULL;
DWORD   GroupSize = 0;
PSID pSID = NULL;
UINT nGUIDLength = 0;

// Get attributes for security descriptor and SID.
hr = pObject->GetObjectAttributes( pAttrNames, 
								2, 
								&pAttrInfo, 
								&dwReturn );
if ( (SUCCEEDED(hr)) && (dwReturn>0) )
{
	for(DWORD idx=0; idx < dwReturn;idx++, pAttrInfo++ )
	{
		// Verify the attribute name.
		if ( _wcsicmp(pAttrInfo->pszAttrName,L"nTSecurityDescriptor") == 0 )
		{
			// Check the attribute type.
			if (pAttrInfo->dwADsType==ADSTYPE_NT_SECURITY_DESCRIPTOR)
			{
				pSD = (PSECURITY_DESCRIPTOR)(pAttrInfo->pADsValues->SecurityDescriptor.lpValue);
				SDSize = (pAttrInfo->pADsValues->SecurityDescriptor.dwLength);
		}
	}
		if ( _wcsicmp(pAttrInfo->pszAttrName,L"objectSID") == 0 )
		{
			// Verify the attribute type.
			if (pAttrInfo->dwADsType==ADSTYPE_OCTET_STRING)
			{
				pSID = (PSID)(pAttrInfo->pADsValues->OctetString.lpValue);
		}
	}
}
	OBJECT_TYPE_LIST sObjectList;
	sObjectList.Level = ACCESS_OBJECT_GUID;
	sObjectList.Sbz = 0;

	sObjectList.ObjectType = (GUID*)&pclsid;

	CHAR PrivilegeSetBuffer[256];
	PRIVILEGE_SET *PrivilegeSet = (PRIVILEGE_SET *)PrivilegeSetBuffer;
	DWORD dwPrivSetSize = sizeof( PrivilegeSetBuffer );
	DWORD GrantedAccess = 0;
	ZeroMemory(PrivilegeSetBuffer, 256);
	DWORD DesiredAccess = ADS_RIGHT_DS_CONTROL_ACCESS;
	// Use the GENERIC_MAPPING structure to convert any 
	// generic access rights to object-specific access rights.
	GENERIC_MAPPING GenericMapping = DS_GENERIC_MAPPING;
	// Before calling AccessCheck, a convert must be performed
	// security descriptor into Absolute form.
	if( ! MakeAbsoluteSD(
					pSD,
					(PSECURITY_DESCRIPTOR)pAbsoluteSD,
					&AbsoluteSDSize,
					(PACL)pDacl,
					&DaclSize,
					(PACL)pSacl,
					&SaclSize,
					(PSID)pOwner,
					&OwnerSize,
					(PSID)pGroup,
					&GroupSize
					))
	{
		pAbsoluteSD = (PSECURITY_DESCRIPTOR)LocalAlloc(0,AbsoluteSDSize);
		if(!pAbsoluteSD)
		{
			// TODO: handle this.
	}
		pDacl = (PACL)LocalAlloc(0,DaclSize);
		if(!pDacl)
		{
			// TODO: handle this.
	}
		pSacl = (PACL)LocalAlloc(0,SaclSize);
		if(!pSacl)
		{
			// TODO: handle this.
	}
		pOwner = (PSID)LocalAlloc(0,OwnerSize);
		if(!pOwner)
		{
			// TODO: handle this.
	}
		pGroup = (PSID)LocalAlloc(0,GroupSize);
		if(!pGroup)
		{
			// TODO: handle this.
	}
		if( ! MakeAbsoluteSD(
						pSD,
						(PSECURITY_DESCRIPTOR)pAbsoluteSD,
						&AbsoluteSDSize,
						(PACL)pDacl,
						&DaclSize,
						(PACL)pSacl,
						&SaclSize,
						(PSID)pOwner,
						&OwnerSize,
						(PSID)pGroup,
						&GroupSize
				))
		{
			//
			// TODO: handle this.
			//
			// Cleanup and return.
			if (pAttrInfo)
				FreeADsMem( pAttrInfo ); 
			return E_FAIL;
 
	}
}
 
	bSuccess = AccessCheckByTypeResultList(
			 pSD,   // Security descriptor
			 pSID, 		// SID of the verified object
			 hToken, 		 // Handle to client access token
			 DesiredAccess, 		// Requested access rights 
			 &sObjectList, // An array of object types
			 1,  // Number of object type elements
			 &GenericMapping,  // Map generic to specific rights
			 PrivilegeSet, // Receives privileges used
			 &dwPrivSetSize,  // Size of privilege-set buffer
			 &GrantedAccess,  // Retrieves mask of granted rights
			 dwAccess		// Retrieves results of access verification
			 );
	// Verify that access check function call succeeded.
	if(bSuccess)
	{
		hr = S_OK;
}
	else
		hr = E_FAIL;
}
// Use FreeADsMem for all memory obtained from ADSI call.
if (pAttrInfo)
		FreeADsMem( pAttrInfo ); 
 
return hr;
}