windows-nt/Source/XPSP1/NT/ds/security/authz/test/fundsrm/fundsrmp.c
2020-09-26 16:20:57 +08:00

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);
}
}