330 lines
7.6 KiB
C
330 lines
7.6 KiB
C
|
#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);
|
||
|
}
|
||
|
}
|