#include "pch.h" #include "fundsrmp.h" // // The various SIDs, the easy way // DWORD BobGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00020001}; DWORD MarthaGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00020002}; DWORD JoeGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00020003}; DWORD VPGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010001}; DWORD ManagerGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010002}; DWORD EmployeeGuid[] = {0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010003}; DWORD EveryoneGuid[] = {0x101, 0x01000000, 0}; PSID BobSid = (PSID)BobGuid; PSID MarthaSid= (PSID)MarthaGuid; PSID JoeSid = (PSID)JoeGuid; PSID VPSid = (PSID)VPGuid; PSID ManagerSid = (PSID)ManagerGuid; PSID EmployeeSid = (PSID)EmployeeGuid; PSID EveryoneSid = (PSID)EveryoneGuid; // // Maximum spending approvals, in cents // DWORD MaxSpendingVP = 100000000; DWORD MaxSpendingManager = 1000000; DWORD MaxSpendingEmployee = 50000; // // The callback routines used with AuthZ // BOOL FundsAccessCheck( IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext, IN PACE_HEADER pAce, IN PVOID pArgs OPTIONAL, IN OUT PBOOL pbAceApplicable ) /*++ Routine Description This is the callback access check. It is registered with a resource manager. AuthzAccessCheck calls this function when it encounters a callback type ACE, one of: ACCESS_ALLOWED_CALLBACK_ACE_TYPE ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE This function determines if the given callback ACE applies to the client context (which has already had dynamic groups computed) and the optional arguments, in this case the request amount. The list of groups which apply to the user is traversed. If a group is found which allows the user the requested access, pbAceApplicable is set to true and the function returns. If the end of the group list is reached, pbAceApplicable is set to false and the function returns. Arguments hAuthzClientContext - handle to the AuthzClientContext. pAce - pointer to the Ace header. pArgs - optional arguments, in this case DWORD*, DWORD is the spending request amount in cents pbAceApplicable - returns true iff the ACE allows the client's request Return value Bool, true on success, false on error Error checking Sample code, no error checking --*/ { // // First, look up the user's SID from the context // DWORD dwTokenGroupsSize = 0; PVOID pvTokenGroupsBuf = NULL; DWORD i; PDWORD pAccessMask = NULL; // // The requested spending amount, in cents // DWORD dwRequestedSpending = ((PDWORD)pArgs)[0]; // // By default, the ACE does not apply to the request // *pbAceApplicable = FALSE; // // The object's access mask (right after the ACE_HEADER) // The access mask determines types of expenditures allowed // from this fund // pAccessMask = (PDWORD) (pAce + sizeof(ACE_HEADER)); // // Get needed buffer size // AuthzGetContextInformation(hAuthzClientContext, AuthzContextInfoGroupsSids, NULL, 0, &dwTokenGroupsSize ); pvTokenGroupsBuf = malloc(dwTokenGroupsSize); // // Get the actual TOKEN_GROUPS array // AuthzGetContextInformation(hAuthzClientContext, AuthzContextInfoGroupsSids, pvTokenGroupsBuf, dwTokenGroupsSize, &dwTokenGroupsSize ); // // Go through the groups until end is reached or a group applying to the // request is found // for( i = 0; i < ((PTOKEN_GROUPS)pvTokenGroupsBuf)->GroupCount && *pbAceApplicable != TRUE; i++ ) { // // Again, this is the business logic. // Each level of employee can approve different amounts. // // // VP // if( dwRequestedSpending <= MaxSpendingVP && EqualSid(VPSid, ((PTOKEN_GROUPS)pvTokenGroupsBuf)->Groups[i].Sid) ) { *pbAceApplicable = TRUE; } // // Manager // if( dwRequestedSpending <= MaxSpendingManager && EqualSid(ManagerSid, ((PTOKEN_GROUPS)pvTokenGroupsBuf)->Groups[i].Sid) ) { *pbAceApplicable = TRUE; } // // Employee // if( dwRequestedSpending <= MaxSpendingEmployee && EqualSid(EmployeeSid, ((PTOKEN_GROUPS)pvTokenGroupsBuf)->Groups[i].Sid) ) { *pbAceApplicable = TRUE; } } return TRUE; } BOOL FundsComputeDynamicGroups( IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext, IN PVOID Args, OUT PSID_AND_ATTRIBUTES *pSidAttrArray, OUT PDWORD pSidCount, OUT PSID_AND_ATTRIBUTES *pRestrictedSidAttrArray, OUT PDWORD pRestrictedSidCount ) /*++ Routine Description Resource manager callback to compute dynamic groups. This is used by the RM to decide if the specified client context should be included in any RM defined groups. In this example, the employees are hardcoded into their roles. However, this is the place you would normally retrieve data from an external source to determine the users' additional roles. Arguments hAuthzClientContext - handle to client context. Args - optional parameter to pass information for evaluating group membership. pSidAttrArray - computed group membership SIDs pSidCount - count of SIDs pRestrictedSidAttrArray - computed group membership restricted SIDs pRestrictedSidCount - count of restricted SIDs Return Value Bool, true for success, false on failure. Error checking Sample code, no error checking --*/ { // // First, look up the user's SID from the context // DWORD dwSidSize = 0; PVOID pvSidBuf = NULL; PSID psSidPtr = NULL; // // Get needed buffer size // AuthzGetContextInformation(hAuthzClientContext, AuthzContextInfoUserSid, NULL, 0, &dwSidSize ); pvSidBuf = malloc(dwSidSize); // // Get the actual SID (inside a TOKEN_USER structure) // AuthzGetContextInformation(hAuthzClientContext, AuthzContextInfoUserSid, pvSidBuf, dwSidSize, &dwSidSize ); psSidPtr = ((PTOKEN_USER)pvSidBuf)->User.Sid; // // Allocate the memory for the returns, which will be deallocated by FreeDynamicGroups // Only a single group will be returned, determining the employee type // *pSidCount = 1; *pSidAttrArray = (PSID_AND_ATTRIBUTES)malloc( sizeof(SID_AND_ATTRIBUTES) ); // // No restricted group sids // pRestrictedSidCount = 0; *pRestrictedSidAttrArray = NULL; (*pSidAttrArray)[0].Attributes = SE_GROUP_ENABLED; // // The hardcoded logic: // Bob is a VP // Martha is a Manager // Joe is an Employee // if( EqualSid(psSidPtr, BobSid) ) { (*pSidAttrArray)[0].Sid = VPSid; } else if( EqualSid(psSidPtr, MarthaSid) ) { (*pSidAttrArray)[0].Sid = ManagerSid; } else if( EqualSid(psSidPtr, JoeSid) ) { (*pSidAttrArray)[0].Sid = EmployeeSid; } free(pvSidBuf); return TRUE; } VOID FundsFreeDynamicGroups ( IN PSID_AND_ATTRIBUTES pSidAttrArray ) /*++ Routine Description Frees memory allocated for the dynamic group array. Arguments pSidAttrArray - array to free. Return Value None. --*/ { if (pSidAttrArray != NULL) { free(pSidAttrArray); } }