Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

290 lines
6.4 KiB

  1. #include "fundsrm.h"
  2. #include "fundsrmp.h"
  3. #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))
  4. FundsRM::FundsRM(DWORD dwFundsAvailable) {
  5. /*++
  6. Routine Description
  7. The constructor for the Funds resource manager.
  8. It initializes an instance of an Authz Resource Manager, providing it
  9. with the appropriate callback functions.
  10. It also creates a security descriptor for the fund, allowing only
  11. corporate and transfer expenditures, not personal. Additional logic
  12. could be added to allow VPs to override these restrictions, etc.
  13. Arguments
  14. DWORD dwFundsAvailable - The amount of money in the fund managed by this
  15. resource manager
  16. Return Value
  17. None.
  18. --*/
  19. //
  20. // The amount of money in the fund
  21. //
  22. _dwFundsAvailable = dwFundsAvailable;
  23. //
  24. // Initialize the fund's resource manager
  25. //
  26. AuthzInitializeResourceManager(
  27. FundsAccessCheck,
  28. FundsComputeDynamicGroups,
  29. FundsFreeDynamicGroups,
  30. NULL, // no auditing
  31. 0, // no flags
  32. &_hRM
  33. );
  34. //
  35. // Create the fund's security descriptor
  36. //
  37. InitializeSecurityDescriptor(&_SD, SECURITY_DESCRIPTOR_REVISION);
  38. SetSecurityDescriptorGroup(&_SD, NULL, FALSE);
  39. SetSecurityDescriptorSacl(&_SD, FALSE, NULL, FALSE);
  40. SetSecurityDescriptorOwner(&_SD, NULL, FALSE);
  41. //
  42. // Initialize the DACL for the fund
  43. //
  44. PACL pDaclFund = (PACL)malloc(1024);
  45. InitializeAcl(pDaclFund, 1024, ACL_REVISION_DS);
  46. //
  47. // Add an access-allowed ACE for Everyone
  48. // Only company spending and transfers are allowed for this fund
  49. //
  50. AddAccessAllowedAce(pDaclFund,
  51. ACL_REVISION_DS,
  52. ACCESS_FUND_CORPORATE | ACCESS_FUND_TRANSFER,
  53. EveryoneSid);
  54. //
  55. // Now set that ACE to a callback ACE
  56. //
  57. ((PACE_HEADER)FirstAce(pDaclFund))->AceType =
  58. ACCESS_ALLOWED_CALLBACK_ACE_TYPE;
  59. //
  60. // Add that ACL as the security descriptor's DACL
  61. //
  62. SetSecurityDescriptorDacl(&_SD, TRUE, pDaclFund, FALSE);
  63. }
  64. FundsRM::~FundsRM() {
  65. /*++
  66. Routine Description
  67. The destructor for the Funds resource manager.
  68. Frees any dynamically allocated memory used.
  69. Arguments
  70. None.
  71. Return Value
  72. None.
  73. --*/
  74. //
  75. // Deallocate the DACL in the security descriptor
  76. //
  77. PACL pDaclFund = NULL;
  78. BOOL fDaclPresent;
  79. BOOL fDaclDefaulted;
  80. GetSecurityDescriptorDacl(&_SD,
  81. &fDaclPresent,
  82. &pDaclFund,
  83. &fDaclDefaulted);
  84. if( pDaclFund != NULL )
  85. {
  86. free(pDaclFund);
  87. }
  88. //
  89. // Deallocate the resource manager
  90. //
  91. AuthzFreeResourceManager(_hRM);
  92. }
  93. BOOL FundsRM::Authorize(LPTSTR szwUsername,
  94. DWORD dwRequestAmount,
  95. DWORD dwSpendingType) {
  96. /*++
  97. Routine Description
  98. This function is called by a user who needs approval of a given amount
  99. of spending in a given spending type. Internally, this uses the
  100. AuthzAccessCheck function to determine whether the given user
  101. should be allowed the requested spending.
  102. If the spending is approved, it is deducted from the fund's total.
  103. Arguments
  104. LPTSTR szwUsername - The name of the user, currently limited to
  105. Bob, Martha, or Joe
  106. DWORD dwRequestAmount - The amount of spending requested, in cents
  107. DWORD dwSpendingType - The type of spending, ACCESS_FUND_PERSONAL,
  108. ACCESS_FUND_TRANSFER, or ACCESS_FUND_CORPORATE
  109. Return Value
  110. BOOL - True if the spending was approved, FALSE otherwise
  111. --*/
  112. //
  113. // No need to check access if not enough money in fund
  114. //
  115. if( dwRequestAmount > _dwFundsAvailable )
  116. {
  117. return FALSE;
  118. }
  119. //
  120. // This would normally impersonate the RPC user and create the
  121. // client context from the token. However, we can just use strings for now.
  122. //
  123. PSID pUserSid = NULL;
  124. if( wcscmp(szwUsername, L"Bob") == 0 )
  125. {
  126. pUserSid = BobSid;
  127. }
  128. else if( wcscmp(szwUsername, L"Martha") == 0 )
  129. {
  130. pUserSid = MarthaSid;
  131. }
  132. else if( wcscmp(szwUsername, L"Joe") == 0 )
  133. {
  134. pUserSid = JoeSid;
  135. }
  136. //
  137. // Only the above usernames are supported
  138. //
  139. if( pUserSid == NULL ) {
  140. return FALSE;
  141. }
  142. //
  143. // Now we create a client context from the SID
  144. //
  145. AUTHZ_CLIENT_CONTEXT_HANDLE hCC = NULL;
  146. LUID ZeroLuid = { 0, 0};
  147. AuthzInitializeContextFromSid(pUserSid,
  148. NULL, // this is local, no need for server
  149. _hRM, // Using the Fund resource manager
  150. NULL, // no expiration
  151. ZeroLuid, // no need for unique luid
  152. 0, // no flags,
  153. NULL, // no args for ComputeDynamicGroups
  154. &hCC);
  155. //
  156. // Initialize the access check result structure
  157. //
  158. DWORD dwGrantedAccessMask = 0;
  159. DWORD dwErr = ERROR_ACCESS_DENIED; // default to deny
  160. AUTHZ_ACCESS_REPLY AccessReply = {0};
  161. AccessReply.ResultListLength = 1;
  162. AccessReply.GrantedAccessMask = &dwGrantedAccessMask;
  163. AccessReply.Error = &dwErr;
  164. //
  165. // Initialize the access check request
  166. //
  167. AUTHZ_ACCESS_REQUEST AccessRequest = {0};
  168. AccessRequest.DesiredAccess = dwSpendingType;
  169. AccessRequest.PrincipalSelfSid = NULL;
  170. AccessRequest.ObjectTypeList = NULL;
  171. AccessRequest.ObjectTypeListLength = 0;
  172. AccessRequest.OptionalArguments = &dwRequestAmount;
  173. AuthzAccessCheck(hCC, // Bob is requesting the transfer
  174. &AccessRequest,
  175. NULL, // no auditing
  176. &_SD,
  177. NULL, // only one SD and one object
  178. 0, // no additional SDs
  179. &AccessReply,
  180. NULL // no need to cache the access check
  181. );
  182. //
  183. // Now free the client context
  184. //
  185. AuthzFreeContext(hCC);
  186. //
  187. // AuthzAccessCheck sets ERROR_SUCCESS if all acces bits are granted
  188. //
  189. if( dwErr == ERROR_SUCCESS )
  190. {
  191. _dwFundsAvailable -= dwRequestAmount;
  192. return TRUE;
  193. }
  194. else
  195. {
  196. return FALSE;
  197. }
  198. }
  199. DWORD FundsRM::FundsAvailable() {
  200. /*++
  201. Routine Description
  202. Accessor for the funds available
  203. Arguments
  204. None.
  205. Return Value
  206. DWORD - The amount of money available in the fund
  207. --*/
  208. return _dwFundsAvailable;
  209. }