Source code of Windows XP (NT5)
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.

4748 lines
125 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. authz.c
  5. Abstract:
  6. This module implements the user mode authorization APIs exported to the
  7. external world.
  8. Author:
  9. Kedar Dubhashi - March 2000
  10. Environment:
  11. User mode only.
  12. Revision History:
  13. Created - March 2000
  14. --*/
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <authzp.h>
  18. #include <authzi.h>
  19. BOOL
  20. AuthzAccessCheck(
  21. IN DWORD Flags,
  22. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  23. IN PAUTHZ_ACCESS_REQUEST pRequest,
  24. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent OPTIONAL,
  25. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  26. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  27. IN DWORD OptionalSecurityDescriptorCount,
  28. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  29. OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults OPTIONAL
  30. )
  31. /*++
  32. Routine Description:
  33. This API decides what access bits may be granted to a client for a given set
  34. of security security descriptors. The pReply structure is used to return an
  35. array of granted access masks and error statuses. There is an option to
  36. cache the access masks that will always be granted. A handle to cached
  37. values is returned if the caller asks for caching.
  38. Arguments:
  39. Flags - AUTHZ_ACCESS_CHECK_NO_DEEP_COPY_SD - do not deep copy the SD information into the caching
  40. handle. Default behaviour is to perform a deep copy.
  41. hAuthzClientContext - Authz context representing the client.
  42. pRequest - Access request specifies the desired access mask, principal self
  43. sid, the object type list strucutre (if any).
  44. hAuditEvent - Object specific audit event will be passed in this handle.
  45. Non-null parameter is an automatic request for audit.
  46. pSecurityDescriptor - Primary security descriptor to be used for access
  47. checks. The owner sid for the object is picked from this one. A NULL
  48. DACL in this security descriptor represents a NULL DACL for the entire
  49. object. A NULL SACL in this security descriptor is treated the same way
  50. as an EMPTY SACL.
  51. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  52. of security descriptors. NULL ACLs in these security descriptors are
  53. treated as EMPTY ACLS and the ACL for the entire object is the logical
  54. concatenation of all the ACLs.
  55. OptionalSecurityDescriptorCount - Number of optional security descriptors
  56. This does not include the Primay security descriptor.
  57. pReply - Supplies a pointer to a reply structure used to return the results
  58. of access check as an array of (GrantedAccessMask, ErrorValue) pairs.
  59. The number of results to be returned in supplied by the caller in
  60. pResult->ResultListLength.
  61. Expected error values are:
  62. ERROR_SUCCESS - If all the access bits (not including MAXIMUM_ALLOWED)
  63. are granted and GrantedAccessMask is not zero.
  64. ERROR_PRIVILEGE_NOT_HELD - if the DesiredAccess includes
  65. ACCESS_SYSTEM_SECURITY and the client does not have SeSecurityPrivilege.
  66. ERROR_ACCESS_DENIED in each of the following cases -
  67. 1. any of the bits asked for is not granted.
  68. 2. MaximumAllowed bit it on and granted access is zero.
  69. 3. DesiredAccess is 0.
  70. phAccessCheckResults - Supplies a pointer to return a handle to the cached results
  71. of access check. Non-null phAccessCheckResults is an implicit request to cache
  72. results of this access check call and will result in a MAXIMUM_ALLOWED
  73. check.
  74. Return Value:
  75. A value of TRUE is returned if the API is successful. Otherwise,
  76. a value of FALSE is returned. In the failure case, error value may be
  77. retrieved using GetLastError().
  78. --*/
  79. {
  80. BOOL b = TRUE;
  81. DWORD LocalTypeListLength = 0;
  82. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  83. PIOBJECT_TYPE_LIST LocalCachingTypeList = NULL;
  84. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  85. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  86. IOBJECT_TYPE_LIST FixedTypeList = {0};
  87. IOBJECT_TYPE_LIST FixedCachingTypeList = {0};
  88. UNREFERENCED_PARAMETER(Flags);
  89. #ifdef AUTHZ_PARAM_CHECK
  90. //
  91. // Verify that the arguments passed are valid.
  92. // Also, initialize the output parameters to default.
  93. //
  94. b = AuthzpVerifyAccessCheckArguments(
  95. pCC,
  96. pRequest,
  97. pSecurityDescriptor,
  98. OptionalSecurityDescriptorArray,
  99. OptionalSecurityDescriptorCount,
  100. pReply,
  101. phAccessCheckResults
  102. );
  103. if (!b)
  104. {
  105. return FALSE;
  106. }
  107. #endif
  108. //
  109. // No client should be able to open an object by asking for zero access.
  110. // If desired access is 0 then return an error.
  111. //
  112. // Note: No audit is generated in this case.
  113. //
  114. if (0 == pRequest->DesiredAccess)
  115. {
  116. AuthzpFillReplyStructure(
  117. pReply,
  118. ERROR_ACCESS_DENIED,
  119. 0
  120. );
  121. return TRUE;
  122. }
  123. //
  124. // Generic bits should be mapped to specific ones by the resource manager.
  125. //
  126. if (FLAG_ON(pRequest->DesiredAccess, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)))
  127. {
  128. SetLastError(ERROR_GENERIC_NOT_MAPPED);
  129. return FALSE;
  130. }
  131. //
  132. // In the simple case, there is no object type list. Fake one of length = 1
  133. // to represent the entire object.
  134. //
  135. if (0 == pRequest->ObjectTypeListLength)
  136. {
  137. LocalTypeList = &FixedTypeList;
  138. FixedTypeList.ParentIndex = -1;
  139. LocalTypeListLength = 1;
  140. //
  141. // If the caller has asked for caching, fake an object type list that'd
  142. // be used for computing static "always granted" access.
  143. //
  144. if (ARGUMENT_PRESENT(phAccessCheckResults))
  145. {
  146. RtlCopyMemory(
  147. &FixedCachingTypeList,
  148. &FixedTypeList,
  149. sizeof(IOBJECT_TYPE_LIST)
  150. );
  151. LocalCachingTypeList = &FixedCachingTypeList;
  152. }
  153. }
  154. else
  155. {
  156. //
  157. // Capture the object type list into an internal structure.
  158. //
  159. b = AuthzpCaptureObjectTypeList(
  160. pRequest->ObjectTypeList,
  161. pRequest->ObjectTypeListLength,
  162. &LocalTypeList,
  163. ARGUMENT_PRESENT(phAccessCheckResults) ? &LocalCachingTypeList : NULL
  164. );
  165. if (!b)
  166. {
  167. return FALSE;
  168. }
  169. LocalTypeListLength = pRequest->ObjectTypeListLength;
  170. }
  171. //
  172. // There are three cases when we have to perform a MaximumAllowed access
  173. // check and traverse the whole acl:
  174. // 1. RM has requested for caching.
  175. // 2. DesiredAccessMask has MAXIMUM_ALLOWED turned on.
  176. // 3. ObjectTypeList is present and pReply->ResultList has a length > 1
  177. //
  178. if (ARGUMENT_PRESENT(phAccessCheckResults) ||
  179. FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED) ||
  180. (pReply->ResultListLength > 1))
  181. {
  182. b = AuthzpAccessCheckWithCaching(
  183. Flags,
  184. pCC,
  185. pRequest,
  186. pSecurityDescriptor,
  187. OptionalSecurityDescriptorArray,
  188. OptionalSecurityDescriptorCount,
  189. pReply,
  190. phAccessCheckResults,
  191. LocalTypeList,
  192. LocalCachingTypeList,
  193. LocalTypeListLength
  194. );
  195. }
  196. else
  197. {
  198. //
  199. // Perform a normal access check in the default case. Acl traversal may
  200. // be abandoned if any of the desired access bits are denied before they
  201. // are granted.
  202. //
  203. b = AuthzpNormalAccessCheckWithoutCaching(
  204. pCC,
  205. pRequest,
  206. pSecurityDescriptor,
  207. OptionalSecurityDescriptorArray,
  208. OptionalSecurityDescriptorCount,
  209. pReply,
  210. LocalTypeList,
  211. LocalTypeListLength
  212. );
  213. }
  214. if (!b)
  215. {
  216. goto Cleanup;
  217. }
  218. //
  219. // Check if an audit needs to be generated if the RM has requested audit
  220. // generation by passing a non-null AuditEvent structure.
  221. //
  222. if (ARGUMENT_PRESENT(pAuditEvent))
  223. {
  224. b = AuthzpGenerateAudit(
  225. pCC,
  226. pRequest,
  227. pAuditEvent,
  228. pSecurityDescriptor,
  229. OptionalSecurityDescriptorArray,
  230. OptionalSecurityDescriptorCount,
  231. pReply,
  232. LocalTypeList
  233. );
  234. if (!b)
  235. {
  236. goto Cleanup;
  237. }
  238. }
  239. Cleanup:
  240. //
  241. // Clean up allocated memory.
  242. //
  243. if ((&FixedTypeList != LocalTypeList) && (AUTHZ_NON_NULL_PTR(LocalTypeList)))
  244. {
  245. AuthzpFree(LocalTypeList);
  246. AuthzpFreeNonNull(LocalCachingTypeList);
  247. }
  248. return b;
  249. }
  250. BOOL
  251. AuthzCachedAccessCheck(
  252. IN DWORD Flags,
  253. IN AUTHZ_ACCESS_CHECK_RESULTS_HANDLE hAccessCheckResults,
  254. IN PAUTHZ_ACCESS_REQUEST pRequest,
  255. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent OPTIONAL,
  256. IN OUT PAUTHZ_ACCESS_REPLY pReply
  257. )
  258. /*++
  259. Routine Description:
  260. This API performs a fast access check based on a cached handle which holds
  261. the static granted bits evaluated at the time of a previously made
  262. AuthzAccessCheck call. The pReply structure is used to return an array of
  263. granted access masks and error statuses.
  264. Assumptions:
  265. The client context pointer is stored in the hAccessCheckResults. The structure of
  266. the client context must be exactly the same as it was at the time the
  267. hAccessCheckResults was created. This restriction is for the following fields:
  268. Sids, RestrictedSids, Privileges.
  269. Pointers to the primary security descriptor and the optional security
  270. descriptor array are stored in the hAccessCheckResults at the time of handle
  271. creation. These must still be valid.
  272. Arguments:
  273. Flags - TBD.
  274. hAccessCheckResults - Handle to the cached access check results.
  275. pRequest - Access request specifies the desired access mask, principal self
  276. sid, the object type list strucutre (if any).
  277. AuditEvent - Object specific audit info will be passed in this structure.
  278. Non-null parameter is an automatic request for audit.
  279. pReply - Supplies a pointer to a reply structure used to return the results
  280. of access check as an array of (GrantedAccessMask, ErrorValue) pairs.
  281. The number of results to be returned in supplied by the caller in
  282. pResult->ResultListLength.
  283. Expected error values are:
  284. ERROR_SUCCESS - If all the access bits (not including MAXIMUM_ALLOWED)
  285. are granted and GrantedAccessMask is not zero.
  286. ERROR_PRIVILEGE_NOT_HELD - if the DesiredAccess includes
  287. ACCESS_SYSTEM_SECURITY and the client does not have SeSecurityPrivilege.
  288. ERROR_ACCESS_DENIED in each of the following cases -
  289. 1. any of the bits asked for is not granted.
  290. 2. MaximumAllowed bit it on and granted access is zero.
  291. 3. DesiredAccess is 0.
  292. Return Value:
  293. A value of TRUE is returned if the API is successful. Otherwise,
  294. a value of FALSE is returned. In the failure case, error value may be
  295. retrieved using GetLastError().
  296. --*/
  297. {
  298. DWORD i = 0;
  299. DWORD LocalTypeListLength = 0;
  300. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  301. PAUTHZI_HANDLE pAH = (PAUTHZI_HANDLE) hAccessCheckResults;
  302. BOOL b = TRUE;
  303. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  304. IOBJECT_TYPE_LIST FixedTypeList = {0};
  305. UNREFERENCED_PARAMETER(Flags);
  306. #ifdef AUTHZ_PARAM_CHECK
  307. b = AuthzpVerifyCachedAccessCheckArguments(
  308. pAH,
  309. pRequest,
  310. pReply
  311. );
  312. if (!b)
  313. {
  314. return FALSE;
  315. }
  316. #endif
  317. //
  318. // No client should be able to open an object by asking for zero access.
  319. // If desired access is 0 then return an error.
  320. //
  321. // Note: No audit is generated in this case.
  322. //
  323. if (0 == pRequest->DesiredAccess)
  324. {
  325. AuthzpFillReplyStructure(
  326. pReply,
  327. ERROR_ACCESS_DENIED,
  328. 0
  329. );
  330. return TRUE;
  331. }
  332. //
  333. // Generic bits should be mapped to specific ones by the resource manager.
  334. //
  335. if (FLAG_ON(pRequest->DesiredAccess, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)))
  336. {
  337. SetLastError(ERROR_GENERIC_NOT_MAPPED);
  338. return FALSE;
  339. }
  340. //
  341. // Capture the object type list if one has been passed in or fake one with
  342. // just one element.
  343. //
  344. if (0 == pRequest->ObjectTypeListLength)
  345. {
  346. LocalTypeList = &FixedTypeList;
  347. LocalTypeListLength = 1;
  348. FixedTypeList.ParentIndex = -1;
  349. }
  350. else
  351. {
  352. b = AuthzpCaptureObjectTypeList(
  353. pRequest->ObjectTypeList,
  354. pRequest->ObjectTypeListLength,
  355. &LocalTypeList,
  356. NULL
  357. );
  358. if (!b)
  359. {
  360. return FALSE;
  361. }
  362. LocalTypeListLength = pRequest->ObjectTypeListLength;
  363. }
  364. //
  365. // If all the bits have already been granted then just copy the results and
  366. // skip access check.
  367. //
  368. if (!FLAG_ON(pRequest->DesiredAccess, ~pAH->GrantedAccessMask[i]))
  369. {
  370. AuthzpFillReplyStructure(
  371. pReply,
  372. ERROR_SUCCESS,
  373. pRequest->DesiredAccess
  374. );
  375. goto GenerateAudit;
  376. }
  377. //
  378. // The assumption is privileges can not be changed. Thus, if the client did
  379. // not have SecurityPrivilege previously then he does not have it now.
  380. //
  381. if (FLAG_ON(pRequest->DesiredAccess, ACCESS_SYSTEM_SECURITY))
  382. {
  383. AuthzpFillReplyStructure(
  384. pReply,
  385. ERROR_PRIVILEGE_NOT_HELD,
  386. 0
  387. );
  388. goto GenerateAudit;
  389. }
  390. //
  391. // If all aces are simple aces then there's nothing to do. All access bits
  392. // are static.
  393. //
  394. if ((!FLAG_ON(pAH->Flags, AUTHZ_DYNAMIC_EVALUATION_PRESENT)) &&
  395. (!FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED)))
  396. {
  397. AuthzpFillReplyStructureFromCachedGrantedAccessMask(
  398. pReply,
  399. pRequest->DesiredAccess,
  400. pAH->GrantedAccessMask
  401. );
  402. goto GenerateAudit;
  403. }
  404. //
  405. // Get the access bits from the last static access check.
  406. //
  407. for (i = 0; i < LocalTypeListLength; i++)
  408. {
  409. LocalTypeList[i].CurrentGranted = pAH->GrantedAccessMask[i];
  410. LocalTypeList[i].Remaining = pRequest->DesiredAccess & ~pAH->GrantedAccessMask[i];
  411. }
  412. //
  413. // If there are no deny aces, then perform a quick access check evaluating
  414. // only the allow aces that are dynamic or have principal self sid in them.
  415. //
  416. if (!FLAG_ON(pAH->Flags, (AUTHZ_DENY_ACE_PRESENT | AUTHZ_DYNAMIC_DENY_ACE_PRESENT)))
  417. {
  418. if (FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED) ||
  419. (pReply->ResultListLength > 1))
  420. {
  421. b = AuthzpQuickMaximumAllowedAccessCheck(
  422. pAH->pAuthzClientContext,
  423. pAH,
  424. pRequest,
  425. pReply,
  426. LocalTypeList,
  427. LocalTypeListLength
  428. );
  429. }
  430. else
  431. {
  432. b = AuthzpQuickNormalAccessCheck(
  433. pAH->pAuthzClientContext,
  434. pAH,
  435. pRequest,
  436. pReply,
  437. LocalTypeList,
  438. LocalTypeListLength
  439. );
  440. }
  441. }
  442. else if (0 != pRequest->ObjectTypeListLength)
  443. {
  444. //
  445. // Now we have to evaluate the entire acl since there are deny aces
  446. // and the caller has asked for a result list.
  447. //
  448. b = AuthzpAccessCheckWithCaching(
  449. Flags,
  450. pAH->pAuthzClientContext,
  451. pRequest,
  452. pAH->pSecurityDescriptor,
  453. pAH->OptionalSecurityDescriptorArray,
  454. pAH->OptionalSecurityDescriptorCount,
  455. pReply,
  456. NULL,
  457. LocalTypeList,
  458. NULL,
  459. LocalTypeListLength
  460. );
  461. }
  462. else
  463. {
  464. //
  465. // There are deny aces in the acl but the caller has not asked for
  466. // entire resultlist. Preform a normal access check.
  467. //
  468. b = AuthzpNormalAccessCheckWithoutCaching(
  469. pAH->pAuthzClientContext,
  470. pRequest,
  471. pAH->pSecurityDescriptor,
  472. pAH->OptionalSecurityDescriptorArray,
  473. pAH->OptionalSecurityDescriptorCount,
  474. pReply,
  475. LocalTypeList,
  476. LocalTypeListLength
  477. );
  478. }
  479. if (!b) goto Cleanup;
  480. AuthzpFillReplyFromParameters(
  481. pRequest,
  482. pReply,
  483. LocalTypeList
  484. );
  485. GenerateAudit:
  486. if (ARGUMENT_PRESENT(pAuditEvent))
  487. {
  488. b = AuthzpGenerateAudit(
  489. pAH->pAuthzClientContext,
  490. pRequest,
  491. pAuditEvent,
  492. pAH->pSecurityDescriptor,
  493. pAH->OptionalSecurityDescriptorArray,
  494. pAH->OptionalSecurityDescriptorCount,
  495. pReply,
  496. LocalTypeList
  497. );
  498. if (!b) goto Cleanup;
  499. }
  500. Cleanup:
  501. if ((&FixedTypeList != LocalTypeList) && (AUTHZ_NON_NULL_PTR(LocalTypeList)))
  502. {
  503. AuthzpFree(LocalTypeList);
  504. }
  505. return b;
  506. }
  507. BOOL
  508. AuthzOpenObjectAudit(
  509. IN DWORD Flags,
  510. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  511. IN PAUTHZ_ACCESS_REQUEST pRequest,
  512. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  513. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  514. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  515. IN DWORD OptionalSecurityDescriptorCount,
  516. IN PAUTHZ_ACCESS_REPLY pReply
  517. )
  518. /*++
  519. Routine Description
  520. This API examines the SACL in the passed security descriptor(s) and generates
  521. any appropriate audits.
  522. Arguments
  523. Flags - TBD.
  524. hAuthzClientContext - Client context to perform the SACL evaluation against.
  525. pRequest - pointer to request structure.
  526. hAuditEvent - Handle to the audit that may be generated.
  527. pSecurityDescriptor - Pointer to a security descriptor.
  528. OptionalSecurityDescriptorArray - Optional array of security descriptors.
  529. OptionalSecurityDescriptorCount - Size of optional security descriptor array.
  530. pReply - Pointer to the reply structure.
  531. Return Value
  532. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  533. --*/
  534. {
  535. BOOL b = TRUE;
  536. DWORD LocalTypeListLength = 0;
  537. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  538. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  539. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  540. IOBJECT_TYPE_LIST FixedTypeList = {0};
  541. UNREFERENCED_PARAMETER(Flags);
  542. //
  543. // Verify that the arguments passed are valid.
  544. //
  545. b = AuthzpVerifyOpenObjectArguments(
  546. pCC,
  547. pSecurityDescriptor,
  548. OptionalSecurityDescriptorArray,
  549. OptionalSecurityDescriptorCount,
  550. pAuditEvent
  551. );
  552. if (!b)
  553. {
  554. return FALSE;
  555. }
  556. //
  557. // In the simple case, there is no object type list. Fake one of length = 1
  558. // to represent the entire object.
  559. //
  560. if (0 == pRequest->ObjectTypeListLength)
  561. {
  562. LocalTypeList = &FixedTypeList;
  563. FixedTypeList.ParentIndex = -1;
  564. LocalTypeListLength = 1;
  565. }
  566. else
  567. {
  568. //
  569. // Capture the object type list into an internal structure.
  570. //
  571. b = AuthzpCaptureObjectTypeList(
  572. pRequest->ObjectTypeList,
  573. pRequest->ObjectTypeListLength,
  574. &LocalTypeList,
  575. NULL
  576. );
  577. if (!b)
  578. {
  579. goto Cleanup;
  580. }
  581. LocalTypeListLength = pRequest->ObjectTypeListLength;
  582. }
  583. b = AuthzpGenerateAudit(
  584. pCC,
  585. pRequest,
  586. pAuditEvent,
  587. pSecurityDescriptor,
  588. OptionalSecurityDescriptorArray,
  589. OptionalSecurityDescriptorCount,
  590. pReply,
  591. LocalTypeList
  592. );
  593. if (!b)
  594. {
  595. goto Cleanup;
  596. }
  597. Cleanup:
  598. //
  599. // Clean up allocated memory.
  600. //
  601. if (&FixedTypeList != LocalTypeList)
  602. {
  603. AuthzpFreeNonNull(LocalTypeList);
  604. }
  605. return b;
  606. }
  607. BOOL
  608. AuthzFreeHandle(
  609. IN OUT AUTHZ_ACCESS_CHECK_RESULTS_HANDLE hAccessCheckResults
  610. )
  611. /*++
  612. Routine Description:
  613. This API finds and deletes the input handle from the handle list.
  614. Arguments:
  615. hAcc - Handle to be freed.
  616. Return Value:
  617. A value of TRUE is returned if the API is successful. Otherwise,
  618. a value of FALSE is returned. In the failure case, error value may be
  619. retrieved using GetLastError().
  620. --*/
  621. {
  622. PAUTHZI_HANDLE pAH = (PAUTHZI_HANDLE) hAccessCheckResults;
  623. PAUTHZI_HANDLE pCurrent = NULL;
  624. PAUTHZI_HANDLE pPrev = NULL;
  625. BOOL b = TRUE;
  626. //
  627. // Validate parameters.
  628. //
  629. if (!ARGUMENT_PRESENT(pAH) ||
  630. !AUTHZ_NON_NULL_PTR(pAH->pAuthzClientContext) ||
  631. !AUTHZ_NON_NULL_PTR(pAH->pAuthzClientContext->AuthzHandleHead))
  632. {
  633. SetLastError(ERROR_INVALID_PARAMETER);
  634. return FALSE;
  635. }
  636. AuthzpAcquireClientCacheWriteLock(pAH->pAuthzClientContext);
  637. pCurrent = pAH->pAuthzClientContext->AuthzHandleHead;
  638. //
  639. // Check if the handle is at the beginning of the list.
  640. //
  641. if (pCurrent == pAH)
  642. {
  643. pAH->pAuthzClientContext->AuthzHandleHead = pAH->pAuthzClientContext->AuthzHandleHead->next;
  644. }
  645. else
  646. {
  647. //
  648. // The handle is not the head of the list. Loop thru the list to find
  649. // it.
  650. //
  651. pPrev = pCurrent;
  652. pCurrent = pCurrent->next;
  653. for (; AUTHZ_NON_NULL_PTR(pCurrent); pPrev = pCurrent, pCurrent = pCurrent->next)
  654. {
  655. if (pCurrent == pAH)
  656. {
  657. pPrev->next = pCurrent->next;
  658. break;
  659. }
  660. }
  661. //
  662. // The caller has sent us an invalid handle.
  663. //
  664. if (!AUTHZ_NON_NULL_PTR(pCurrent))
  665. {
  666. b = FALSE;
  667. SetLastError(ERROR_INVALID_PARAMETER);
  668. }
  669. }
  670. AuthzpReleaseClientCacheLock(pCC);
  671. //
  672. // Free the handle node.
  673. //
  674. if (b)
  675. {
  676. AuthzpFree(pAH);
  677. }
  678. return b;
  679. }
  680. BOOL
  681. AuthzInitializeResourceManager(
  682. IN DWORD Flags,
  683. IN PFN_AUTHZ_DYNAMIC_ACCESS_CHECK pfnDynamicAccessCheck OPTIONAL,
  684. IN PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS pfnComputeDynamicGroups OPTIONAL,
  685. IN PFN_AUTHZ_FREE_DYNAMIC_GROUPS pfnFreeDynamicGroups OPTIONAL,
  686. IN PCWSTR szResourceManagerName,
  687. OUT PAUTHZ_RESOURCE_MANAGER_HANDLE phAuthzResourceManager
  688. )
  689. /*++
  690. Routine Description:
  691. This API allocates and initializes a resource manager structure.
  692. Arguments:
  693. Flags - AUTHZ_RM_FLAG_NO_AUDIT - use if the RM will never generate an audit to
  694. save some cycles.
  695. pfnAccessCheck - Pointer to the RM supplied access check function to be
  696. called when a callback ace is encountered by the access check algorithm.
  697. pfnComputeDynamicGroups - Pointer to the RM supplied function to compute
  698. groups to be added to the client context at the time of its creation.
  699. pfnFreeDynamicGroups - Pointer to the function to free the memory allocated
  700. by the pfnComputeDynamicGroups function.
  701. szResourceManagerName - the name of the resource manager.
  702. pAuthzResourceManager - To return the resource manager handle. The returned
  703. handle must be freed using AuthzFreeResourceManager.
  704. Return Value:
  705. A value of TRUE is returned if the API is successful. Otherwise,
  706. a value of FALSE is returned. In the failure case, error value may be
  707. retrieved using GetLastError().
  708. --*/
  709. {
  710. PAUTHZI_RESOURCE_MANAGER pRM = NULL;
  711. BOOL b = TRUE;
  712. ULONG len = 0;
  713. if (!ARGUMENT_PRESENT(phAuthzResourceManager) ||
  714. (Flags & ~AUTHZ_VALID_RM_INIT_FLAGS))
  715. {
  716. SetLastError(ERROR_INVALID_PARAMETER);
  717. return FALSE;
  718. }
  719. *phAuthzResourceManager = NULL;
  720. if (AUTHZ_NON_NULL_PTR(szResourceManagerName))
  721. {
  722. len = (ULONG) wcslen(szResourceManagerName) + 1;
  723. }
  724. pRM = (PAUTHZI_RESOURCE_MANAGER)
  725. AuthzpAlloc(sizeof(AUTHZI_RESOURCE_MANAGER) + sizeof(WCHAR) * len);
  726. if (AUTHZ_ALLOCATION_FAILED(pRM))
  727. {
  728. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  729. return FALSE;
  730. }
  731. //
  732. // Use the default pessimistic function if none has been specified.
  733. //
  734. if (AUTHZ_NON_NULL_PTR(pfnDynamicAccessCheck))
  735. {
  736. pRM->pfnDynamicAccessCheck = pfnDynamicAccessCheck;
  737. }
  738. else
  739. {
  740. pRM->pfnDynamicAccessCheck = &AuthzpDefaultAccessCheck;
  741. }
  742. if (!FLAG_ON(Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  743. {
  744. //
  745. // Initialize the generic audit queue and generic audit events.
  746. //
  747. b = AuthziInitializeAuditQueue(
  748. AUTHZ_MONITOR_AUDIT_QUEUE_SIZE,
  749. 1000,
  750. 100,
  751. NULL,
  752. &pRM->hAuditQueue
  753. );
  754. if (!b)
  755. {
  756. goto Cleanup;
  757. }
  758. //
  759. // Initialize the generic audit event.
  760. //
  761. b = AuthziInitializeAuditEventType(
  762. AUTHZP_DEFAULT_RM_EVENTS | AUTHZP_INIT_GENERIC_AUDIT_EVENT,
  763. 0,
  764. 0,
  765. 0,
  766. &pRM->hAET
  767. );
  768. if (!b)
  769. {
  770. goto Cleanup;
  771. }
  772. b = AuthziInitializeAuditEventType(
  773. AUTHZP_DEFAULT_RM_EVENTS,
  774. SE_CATEGID_DS_ACCESS,
  775. SE_AUDITID_OBJECT_OPERATION,
  776. 9,
  777. &pRM->hAETDS
  778. );
  779. if (!b)
  780. {
  781. goto Cleanup;
  782. }
  783. }
  784. pRM->pfnComputeDynamicGroups = pfnComputeDynamicGroups;
  785. pRM->pfnFreeDynamicGroups = pfnFreeDynamicGroups;
  786. pRM->Flags = Flags;
  787. pRM->pUserSID = NULL;
  788. pRM->szResourceManagerName = (PWSTR)((PUCHAR)pRM + sizeof(AUTHZI_RESOURCE_MANAGER));
  789. b = AuthzpGetProcessTokenInfo(
  790. &pRM->pUserSID,
  791. &pRM->AuthID
  792. );
  793. if (!b)
  794. {
  795. goto Cleanup;
  796. }
  797. if (0 != len)
  798. {
  799. RtlCopyMemory(
  800. pRM->szResourceManagerName,
  801. szResourceManagerName,
  802. sizeof(WCHAR) * len
  803. );
  804. }
  805. else
  806. {
  807. pRM->szResourceManagerName = NULL;
  808. }
  809. *phAuthzResourceManager = (AUTHZ_RESOURCE_MANAGER_HANDLE) pRM;
  810. Cleanup:
  811. if (!b)
  812. {
  813. //
  814. // Copy LastError value, since the calls to AuthziFreeAuditEventType can succeed and
  815. // overwrite it with 0x103 (STATUS_PENDING).
  816. //
  817. DWORD dwError = GetLastError();
  818. if (NULL != pRM)
  819. {
  820. if (!FLAG_ON(Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  821. {
  822. AuthziFreeAuditQueue(pRM->hAuditQueue);
  823. AuthziFreeAuditEventType(pRM->hAET);
  824. AuthziFreeAuditEventType(pRM->hAETDS);
  825. }
  826. AuthzpFreeNonNull(pRM->pUserSID);
  827. AuthzpFree(pRM);
  828. }
  829. SetLastError(dwError);
  830. }
  831. return b;
  832. }
  833. BOOL
  834. AuthzFreeResourceManager(
  835. IN OUT AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager
  836. )
  837. /*++
  838. Routine Description:
  839. This API frees up a resource manager. If the default queue is in use, this call will wait for that
  840. queue to empty.
  841. Arguments:
  842. hAuthzResourceManager - Handle to the resource manager object to be freed.
  843. Return Value:
  844. A value of TRUE is returned if the API is successful. Otherwise,
  845. a value of FALSE is returned. In the failure case, error value may be
  846. retrieved using GetLastError().
  847. --*/
  848. {
  849. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  850. BOOL b = TRUE;
  851. if (!ARGUMENT_PRESENT(pRM))
  852. {
  853. SetLastError(ERROR_INVALID_PARAMETER);
  854. return FALSE;
  855. }
  856. if (!FLAG_ON(pRM->Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  857. {
  858. (VOID) AuthziFreeAuditQueue(pRM->hAuditQueue);
  859. b = AuthziFreeAuditEventType(pRM->hAET);
  860. ASSERT(b == TRUE && L"Freeing pAEI didn't work.\n");
  861. b = AuthziFreeAuditEventType(pRM->hAETDS);
  862. ASSERT(b == TRUE && L"Freeing pAEIDS didn't work.\n");
  863. }
  864. AuthzpFreeNonNull(pRM->pUserSID);
  865. AuthzpFree(pRM);
  866. return TRUE;
  867. }
  868. BOOL
  869. AuthzInitializeContextFromToken(
  870. IN DWORD Flags,
  871. IN HANDLE TokenHandle,
  872. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  873. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  874. IN LUID Identifier,
  875. IN PVOID DynamicGroupArgs,
  876. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext
  877. )
  878. /*++
  879. Routine Description:
  880. Initialize the authz context from the handle to the kernel token. The token
  881. must have been opened for TOKEN_QUERY.
  882. Arguments:
  883. Flags - None
  884. TokenHandle - Handle to the client token from which the authz context will
  885. be initialized. The token must have been opened with TOKEN_QUERY access.
  886. AuthzResourceManager - The resource manager handle creating this client
  887. context. This will be stored in the client context structure.
  888. pExpirationTime - To set for how long the returned context structure is
  889. valid. If no value is passed then the token never expires.
  890. Expiration time is not currently enforced in the system.
  891. Identifier - Resource manager manager specific identifier. This is never
  892. interpreted by Authz.
  893. DynamicGroupArgs - To be passed to the callback function that computes
  894. dynamic groups
  895. pAuthzClientContext - To return a handle to the AuthzClientContext
  896. Return Value:
  897. A value of TRUE is returned if the API is successful. Otherwise,
  898. a value of FALSE is returned. In the failure case, error value may be
  899. retrieved using GetLastError().
  900. --*/
  901. {
  902. UCHAR Buffer[AUTHZ_MAX_STACK_BUFFER_SIZE];
  903. NTSTATUS Status = STATUS_SUCCESS;
  904. PUCHAR pBuffer = (PVOID) Buffer;
  905. BOOL b = TRUE;
  906. BOOL bAllocatedSids = FALSE;
  907. BOOL bLockHeld = FALSE;
  908. PTOKEN_GROUPS_AND_PRIVILEGES pTokenInfo = NULL;
  909. PAUTHZI_RESOURCE_MANAGER pRM = NULL;
  910. PAUTHZI_CLIENT_CONTEXT pCC = NULL;
  911. DWORD Length = 0;
  912. LARGE_INTEGER ExpirationTime = {0, 0};
  913. UNREFERENCED_PARAMETER(Flags);
  914. if (!ARGUMENT_PRESENT(TokenHandle) ||
  915. !ARGUMENT_PRESENT(hAuthzResourceManager) ||
  916. !ARGUMENT_PRESENT(phAuthzClientContext))
  917. {
  918. SetLastError(ERROR_INVALID_PARAMETER);
  919. return FALSE;
  920. }
  921. *phAuthzClientContext = NULL;
  922. //
  923. // Query the token information into user mode buffer. A local stack buffer
  924. // is used in the first call hoping that it would be sufficient to hold
  925. // the return values.
  926. //
  927. Status = NtQueryInformationToken(
  928. TokenHandle,
  929. TokenGroupsAndPrivileges,
  930. pBuffer,
  931. AUTHZ_MAX_STACK_BUFFER_SIZE,
  932. &Length
  933. );
  934. if (STATUS_BUFFER_TOO_SMALL == Status)
  935. {
  936. pBuffer = (PVOID) AuthzpAlloc(Length);
  937. if (AUTHZ_ALLOCATION_FAILED(pBuffer))
  938. {
  939. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  940. return FALSE;
  941. }
  942. Status = NtQueryInformationToken(
  943. TokenHandle,
  944. TokenGroupsAndPrivileges,
  945. pBuffer,
  946. Length,
  947. &Length
  948. );
  949. }
  950. if (!NT_SUCCESS(Status))
  951. {
  952. #ifdef AUTHZ_DEBUG
  953. wprintf(L"\nNtQueryInformationToken failed with %d\n", Status);
  954. #endif
  955. SetLastError(RtlNtStatusToDosError(Status));
  956. b = FALSE;
  957. goto Cleanup;
  958. }
  959. pTokenInfo = (PTOKEN_GROUPS_AND_PRIVILEGES) pBuffer;
  960. pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  961. if (ARGUMENT_PRESENT(pExpirationTime))
  962. {
  963. ExpirationTime = *pExpirationTime;
  964. }
  965. //
  966. // Initialize the client context. The callee allocates memory for the client
  967. // context structure.
  968. //
  969. b = AuthzpAllocateAndInitializeClientContext(
  970. &pCC,
  971. NULL,
  972. AUTHZ_CURRENT_CONTEXT_REVISION,
  973. Identifier,
  974. ExpirationTime,
  975. 0,
  976. pTokenInfo->SidCount,
  977. pTokenInfo->SidLength,
  978. pTokenInfo->Sids,
  979. pTokenInfo->RestrictedSidCount,
  980. pTokenInfo->RestrictedSidLength,
  981. pTokenInfo->RestrictedSids,
  982. pTokenInfo->PrivilegeCount,
  983. pTokenInfo->PrivilegeLength,
  984. pTokenInfo->Privileges,
  985. pTokenInfo->AuthenticationId,
  986. NULL,
  987. pRM
  988. );
  989. if (!b)
  990. {
  991. goto Cleanup;
  992. }
  993. AuthzpAcquireClientContextReadLock(pCC);
  994. bLockHeld = TRUE;
  995. //
  996. // Add dynamic sids to the token.
  997. //
  998. b = AuthzpAddDynamicSidsToToken(
  999. pCC,
  1000. pRM,
  1001. DynamicGroupArgs,
  1002. pTokenInfo->Sids,
  1003. pTokenInfo->SidLength,
  1004. pTokenInfo->SidCount,
  1005. pTokenInfo->RestrictedSids,
  1006. pTokenInfo->RestrictedSidLength,
  1007. pTokenInfo->RestrictedSidCount,
  1008. pTokenInfo->Privileges,
  1009. pTokenInfo->PrivilegeLength,
  1010. pTokenInfo->PrivilegeCount,
  1011. FALSE
  1012. );
  1013. if (!b)
  1014. {
  1015. goto Cleanup;
  1016. }
  1017. bAllocatedSids = TRUE;
  1018. *phAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC;
  1019. AuthzPrintContext(pCC);
  1020. //
  1021. // initialize the sid hash for regular sids
  1022. //
  1023. AuthzpInitSidHash(
  1024. pCC->Sids,
  1025. pCC->SidCount,
  1026. pCC->SidHash
  1027. );
  1028. //
  1029. // initialize the sid hash for restricted sids
  1030. //
  1031. AuthzpInitSidHash(
  1032. pCC->RestrictedSids,
  1033. pCC->RestrictedSidCount,
  1034. pCC->RestrictedSidHash
  1035. );
  1036. Cleanup:
  1037. if ((PVOID) Buffer != pBuffer)
  1038. {
  1039. AuthzpFreeNonNull(pBuffer);
  1040. }
  1041. if (!b)
  1042. {
  1043. DWORD dwSavedError = GetLastError();
  1044. if (AUTHZ_NON_NULL_PTR(pCC))
  1045. {
  1046. if (bAllocatedSids)
  1047. {
  1048. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pCC);
  1049. SetLastError(dwSavedError);
  1050. }
  1051. else
  1052. {
  1053. AuthzpFree(pCC);
  1054. }
  1055. }
  1056. }
  1057. if (bLockHeld)
  1058. {
  1059. AuthzpReleaseClientContextLock(pCC);
  1060. }
  1061. return b;
  1062. }
  1063. BOOL
  1064. AuthzInitializeContextFromSid(
  1065. IN DWORD Flags,
  1066. IN PSID UserSid,
  1067. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  1068. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1069. IN LUID Identifier,
  1070. IN PVOID DynamicGroupArgs,
  1071. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext
  1072. )
  1073. /*++
  1074. Routine Description:
  1075. This API takes a user sid and creates a user mode client context from it.
  1076. It fetches the TokenGroups attributes from the AD in case of domain sids.
  1077. The machine local groups are computed on the ServerName specified. The
  1078. resource manager may dynamic groups using callback mechanism.
  1079. Arguments:
  1080. Flags -
  1081. AUTHZ_SKIP_TOKEN_GROUPS - Do not token groups if this is on.
  1082. UserSid - The sid of the user for whom a client context will be created.
  1083. ServerName - The machine on which local groups should be computed. A NULL
  1084. server name defaults to the local machine.
  1085. AuthzResourceManager - The resource manager handle creating this client
  1086. context. This will be stored in the client context structure.
  1087. pExpirationTime - To set for how long the returned context structure is
  1088. valid. If no value is passed then the token never expires.
  1089. Expiration time is not currently enforced in the system.
  1090. Identifier - Resource manager manager specific identifier. This is never
  1091. interpreted by Authz.
  1092. DynamicGroupArgs - To be passed to the callback function that computes
  1093. dynamic groups
  1094. pAuthzClientContext - To return a handle to the AuthzClientContext
  1095. structure. The returned handle must be freed using AuthzFreeContext.
  1096. Return Value:
  1097. A value of TRUE is returned if the API is successful. Otherwise,
  1098. a value of FALSE is returned. In the failure case, error value may be
  1099. retrieved using GetLastError().
  1100. --*/
  1101. {
  1102. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  1103. PAUTHZI_CLIENT_CONTEXT pCC = NULL;
  1104. BOOL b = FALSE;
  1105. DWORD SidCount = 0;
  1106. DWORD SidLength = 0;
  1107. LARGE_INTEGER ExpirationTime = {0, 0};
  1108. LUID NullLuid = {0, 0};
  1109. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  1110. if (!ARGUMENT_PRESENT(UserSid) ||
  1111. !ARGUMENT_PRESENT(hAuthzResourceManager) ||
  1112. !ARGUMENT_PRESENT(phAuthzClientContext))
  1113. {
  1114. SetLastError(ERROR_INVALID_PARAMETER);
  1115. return FALSE;
  1116. }
  1117. *phAuthzClientContext = NULL;
  1118. //
  1119. // Compute the token groups and the machine local groups. These will be
  1120. // returned in memory allocated by the callee.
  1121. //
  1122. b = AuthzpGetAllGroupsBySid(
  1123. UserSid,
  1124. Flags,
  1125. &pSidAttr,
  1126. &SidCount,
  1127. &SidLength
  1128. );
  1129. if (!b)
  1130. {
  1131. goto Cleanup;
  1132. }
  1133. if (ARGUMENT_PRESENT(pExpirationTime))
  1134. {
  1135. ExpirationTime = *pExpirationTime;
  1136. }
  1137. //
  1138. // Initialize the client context. The callee allocates memory for the client
  1139. // context structure.
  1140. //
  1141. b = AuthzpAllocateAndInitializeClientContext(
  1142. &pCC,
  1143. NULL,
  1144. AUTHZ_CURRENT_CONTEXT_REVISION,
  1145. Identifier,
  1146. ExpirationTime,
  1147. 0,
  1148. SidCount,
  1149. SidLength,
  1150. pSidAttr,
  1151. 0,
  1152. 0,
  1153. NULL,
  1154. 0,
  1155. 0,
  1156. NULL,
  1157. NullLuid,
  1158. NULL,
  1159. pRM
  1160. );
  1161. if (!b) goto Cleanup;
  1162. //
  1163. // Add dynamic sids to the token.
  1164. //
  1165. b = AuthzpAddDynamicSidsToToken(
  1166. pCC,
  1167. pRM,
  1168. DynamicGroupArgs,
  1169. pSidAttr,
  1170. SidLength,
  1171. SidCount,
  1172. NULL,
  1173. 0,
  1174. 0,
  1175. NULL,
  1176. 0,
  1177. 0,
  1178. TRUE
  1179. );
  1180. if (!b) goto Cleanup;
  1181. *phAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC;
  1182. AuthzPrintContext(pCC);
  1183. //
  1184. // initialize the sid hash for regular sids
  1185. //
  1186. AuthzpInitSidHash(
  1187. pCC->Sids,
  1188. pCC->SidCount,
  1189. pCC->SidHash
  1190. );
  1191. //
  1192. // initialize the sid hash for restricted sids
  1193. //
  1194. AuthzpInitSidHash(
  1195. pCC->RestrictedSids,
  1196. pCC->RestrictedSidCount,
  1197. pCC->RestrictedSidHash
  1198. );
  1199. Cleanup:
  1200. if (!b)
  1201. {
  1202. AuthzpFreeNonNull(pSidAttr);
  1203. if (AUTHZ_NON_NULL_PTR(pCC))
  1204. {
  1205. if (pSidAttr != pCC->Sids)
  1206. {
  1207. AuthzpFreeNonNull(pCC->Sids);
  1208. }
  1209. AuthzpFreeNonNull(pCC->RestrictedSids);
  1210. AuthzpFree(pCC);
  1211. }
  1212. }
  1213. else
  1214. {
  1215. if (pSidAttr != pCC->Sids)
  1216. {
  1217. AuthzpFree(pSidAttr);
  1218. }
  1219. }
  1220. return b;
  1221. }
  1222. BOOL
  1223. AuthzInitializeContextFromAuthzContext(
  1224. IN DWORD Flags,
  1225. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1226. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1227. IN LUID Identifier,
  1228. IN PVOID DynamicGroupArgs,
  1229. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phNewAuthzClientContext
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. This API creates an AUTHZ_CLIENT_CONTEXT based on another AUTHZ_CLIENT_CONTEXT.
  1234. Arguments:
  1235. Flags - TBD
  1236. hAuthzClientContext - Client context to duplicate
  1237. pExpirationTime - To set for how long the returned context structure is
  1238. valid. If no value is passed then the token never expires.
  1239. Expiration time is not currently enforced in the system.
  1240. Identifier - Resource manager manager specific identifier.
  1241. DynamicGroupArgs - To be passed to the callback function that computes
  1242. dynamic groups. If NULL then callback not called.
  1243. phNewAuthzClientContext - Duplicate of context. Must be freed using AuthzFreeContext.
  1244. Return Value:
  1245. A value of TRUE is returned if the API is successful. Otherwise,
  1246. a value of FALSE is returned. In the failure case, error value may be
  1247. retrieved using GetLastError().
  1248. --*/
  1249. {
  1250. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1251. PAUTHZI_CLIENT_CONTEXT pNewCC = NULL;
  1252. PAUTHZI_CLIENT_CONTEXT pServer = NULL;
  1253. BOOL b = FALSE;
  1254. BOOL bAllocatedSids = FALSE;
  1255. LARGE_INTEGER ExpirationTime = {0, 0};
  1256. if (!ARGUMENT_PRESENT(phNewAuthzClientContext) ||
  1257. !ARGUMENT_PRESENT(hAuthzClientContext))
  1258. {
  1259. SetLastError(ERROR_INVALID_PARAMETER);
  1260. return FALSE;
  1261. }
  1262. *phNewAuthzClientContext = NULL;
  1263. //
  1264. // Determine the ExpirationTime of the new context.
  1265. //
  1266. if (ARGUMENT_PRESENT(pExpirationTime))
  1267. {
  1268. ExpirationTime = *pExpirationTime;
  1269. }
  1270. AuthzpAcquireClientContextReadLock(pCC);
  1271. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  1272. {
  1273. b = AuthzInitializeContextFromAuthzContext(
  1274. 0,
  1275. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server,
  1276. NULL,
  1277. pCC->Server->Identifier,
  1278. NULL,
  1279. (PAUTHZ_CLIENT_CONTEXT_HANDLE) &pServer
  1280. );
  1281. if (!b)
  1282. {
  1283. goto Cleanup;
  1284. }
  1285. }
  1286. //
  1287. // Now initialize the new context.
  1288. //
  1289. b = AuthzpAllocateAndInitializeClientContext(
  1290. &pNewCC,
  1291. pServer,
  1292. pCC->Revision,
  1293. Identifier,
  1294. ExpirationTime,
  1295. Flags,
  1296. pCC->SidCount,
  1297. pCC->SidLength,
  1298. pCC->Sids,
  1299. pCC->RestrictedSidCount,
  1300. pCC->RestrictedSidLength,
  1301. pCC->RestrictedSids,
  1302. pCC->PrivilegeCount,
  1303. pCC->PrivilegeLength,
  1304. pCC->Privileges,
  1305. pCC->AuthenticationId,
  1306. NULL,
  1307. pCC->pResourceManager
  1308. );
  1309. if (!b)
  1310. {
  1311. goto Cleanup;
  1312. }
  1313. b = AuthzpAddDynamicSidsToToken(
  1314. pNewCC,
  1315. pNewCC->pResourceManager,
  1316. DynamicGroupArgs,
  1317. pNewCC->Sids,
  1318. pNewCC->SidLength,
  1319. pNewCC->SidCount,
  1320. pNewCC->RestrictedSids,
  1321. pNewCC->RestrictedSidLength,
  1322. pNewCC->RestrictedSidCount,
  1323. pNewCC->Privileges,
  1324. pNewCC->PrivilegeLength,
  1325. pNewCC->PrivilegeCount,
  1326. FALSE
  1327. );
  1328. if (!b)
  1329. {
  1330. goto Cleanup;
  1331. }
  1332. bAllocatedSids = TRUE;
  1333. *phNewAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pNewCC;
  1334. #ifdef AUTHZ_DEBUG
  1335. wprintf(L"ContextFromAuthzContext: Original Context:\n");
  1336. AuthzPrintContext(pCC);
  1337. wprintf(L"ContextFromAuthzContext: New Context:\n");
  1338. AuthzPrintContext(pNewCC);
  1339. #endif
  1340. //
  1341. // initialize the sid hash for regular sids
  1342. //
  1343. AuthzpInitSidHash(
  1344. pNewCC->Sids,
  1345. pNewCC->SidCount,
  1346. pNewCC->SidHash
  1347. );
  1348. //
  1349. // initialize the sid hash for restricted sids
  1350. //
  1351. AuthzpInitSidHash(
  1352. pNewCC->RestrictedSids,
  1353. pNewCC->RestrictedSidCount,
  1354. pNewCC->RestrictedSidHash
  1355. );
  1356. Cleanup:
  1357. if (!b)
  1358. {
  1359. DWORD dwSavedError = GetLastError();
  1360. if (AUTHZ_NON_NULL_PTR(pNewCC))
  1361. {
  1362. if (bAllocatedSids)
  1363. {
  1364. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pNewCC);
  1365. }
  1366. else
  1367. {
  1368. AuthzpFree(pNewCC);
  1369. }
  1370. }
  1371. else
  1372. {
  1373. if (AUTHZ_NON_NULL_PTR(pServer))
  1374. {
  1375. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pServer);
  1376. }
  1377. }
  1378. SetLastError(dwSavedError);
  1379. }
  1380. AuthzpReleaseClientContextLock(pCC);
  1381. return b;
  1382. }
  1383. BOOL
  1384. AuthzAddSidsToContext(
  1385. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1386. IN PSID_AND_ATTRIBUTES Sids OPTIONAL,
  1387. IN DWORD SidCount,
  1388. IN PSID_AND_ATTRIBUTES RestrictedSids OPTIONAL,
  1389. IN DWORD RestrictedSidCount,
  1390. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phNewAuthzClientContext
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This API creates a new context given a set of sids as well as restricted sids
  1395. and an already existing context. The original is unchanged.
  1396. Arguments:
  1397. hAuthzClientContext - Client context to which the given sids will be added
  1398. Sids - Sids and attributes to be added to the normal part of the client
  1399. context
  1400. SidCount - Number of sids to be added
  1401. RestrictedSids - Sids and attributes to be added to the restricted part of
  1402. the client context
  1403. RestrictedSidCount - Number of restricted sids to be added
  1404. phNewAuthzClientContext - The new context with the additional sids.
  1405. Return Value:
  1406. A value of TRUE is returned if the API is successful. Otherwise,
  1407. a value of FALSE is returned. In the failure case, error value may be
  1408. retrieved using GetLastError().
  1409. --*/
  1410. {
  1411. DWORD i = 0;
  1412. DWORD SidLength = 0;
  1413. DWORD RestrictedSidLength = 0;
  1414. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  1415. PSID_AND_ATTRIBUTES pRestrictedSidAttr = NULL;
  1416. BOOL b = TRUE;
  1417. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1418. PAUTHZI_CLIENT_CONTEXT pNewCC = NULL;
  1419. PAUTHZI_CLIENT_CONTEXT pServer = NULL;
  1420. PLUID_AND_ATTRIBUTES pPrivileges = NULL;
  1421. if ((!ARGUMENT_PRESENT(phNewAuthzClientContext)) ||
  1422. (!ARGUMENT_PRESENT(hAuthzClientContext)) ||
  1423. (0 != SidCount && !ARGUMENT_PRESENT(Sids)) ||
  1424. (0 != RestrictedSidCount && !ARGUMENT_PRESENT(RestrictedSids)))
  1425. {
  1426. SetLastError(ERROR_INVALID_PARAMETER);
  1427. return FALSE;
  1428. }
  1429. *phNewAuthzClientContext = NULL;
  1430. AuthzpAcquireClientContextReadLock(pCC);
  1431. //
  1432. // Recursively duplicate the server
  1433. //
  1434. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  1435. {
  1436. b = AuthzInitializeContextFromAuthzContext(
  1437. 0,
  1438. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server,
  1439. NULL,
  1440. pCC->Server->Identifier,
  1441. NULL,
  1442. (PAUTHZ_CLIENT_CONTEXT_HANDLE) &pServer
  1443. );
  1444. if (!b)
  1445. {
  1446. goto Cleanup;
  1447. }
  1448. }
  1449. //
  1450. // Duplicate the context, and do all further work on the duplicate.
  1451. //
  1452. b = AuthzpAllocateAndInitializeClientContext(
  1453. &pNewCC,
  1454. pServer,
  1455. pCC->Revision,
  1456. pCC->Identifier,
  1457. pCC->ExpirationTime,
  1458. pCC->Flags,
  1459. 0,
  1460. 0,
  1461. NULL,
  1462. 0,
  1463. 0,
  1464. NULL,
  1465. 0,
  1466. 0,
  1467. NULL,
  1468. pCC->AuthenticationId,
  1469. NULL,
  1470. pCC->pResourceManager
  1471. );
  1472. if (!b)
  1473. {
  1474. goto Cleanup;
  1475. }
  1476. SidLength = sizeof(SID_AND_ATTRIBUTES) * SidCount;
  1477. //
  1478. // Compute the length required to hold the new sids.
  1479. //
  1480. for (i = 0; i < SidCount; i++)
  1481. {
  1482. #ifdef AUTHZ_PARAM_CHECK
  1483. if (FLAG_ON(Sids[i].Attributes, ~AUTHZ_VALID_SID_ATTRIBUTES) ||
  1484. !FLAG_ON(Sids[i].Attributes, AUTHZ_VALID_SID_ATTRIBUTES))
  1485. {
  1486. SetLastError(ERROR_INVALID_PARAMETER);
  1487. b = FALSE;
  1488. goto Cleanup;
  1489. }
  1490. if (!RtlValidSid(Sids[i].Sid))
  1491. {
  1492. SetLastError(ERROR_INVALID_PARAMETER);
  1493. b = FALSE;
  1494. goto Cleanup;
  1495. }
  1496. #endif
  1497. SidLength += RtlLengthSid(Sids[i].Sid);
  1498. }
  1499. RestrictedSidLength = sizeof(SID_AND_ATTRIBUTES) * RestrictedSidCount;
  1500. //
  1501. // Compute the length required to hold the new restricted sids.
  1502. //
  1503. for (i = 0; i < RestrictedSidCount; i++)
  1504. {
  1505. #ifdef AUTHZ_PARAM_CHECK
  1506. if (FLAG_ON(RestrictedSids[i].Attributes, ~AUTHZ_VALID_SID_ATTRIBUTES) ||
  1507. !FLAG_ON(RestrictedSids[i].Attributes, AUTHZ_VALID_SID_ATTRIBUTES))
  1508. {
  1509. SetLastError(ERROR_INVALID_PARAMETER);
  1510. b = FALSE;
  1511. goto Cleanup;
  1512. }
  1513. if (!RtlValidSid(RestrictedSids[i].Sid))
  1514. {
  1515. SetLastError(ERROR_INVALID_PARAMETER);
  1516. b = FALSE;
  1517. goto Cleanup;
  1518. }
  1519. #endif
  1520. RestrictedSidLength += RtlLengthSid(RestrictedSids[i].Sid);
  1521. }
  1522. //
  1523. // Copy the existing sids and the new ones into the allocated memory.
  1524. //
  1525. SidLength += pCC->SidLength;
  1526. if (0 != SidLength)
  1527. {
  1528. pSidAttr = (PSID_AND_ATTRIBUTES) AuthzpAlloc(SidLength);
  1529. if (AUTHZ_ALLOCATION_FAILED(pSidAttr))
  1530. {
  1531. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1532. b = FALSE;
  1533. goto Cleanup;
  1534. }
  1535. b = AuthzpCopySidsAndAttributes(
  1536. pSidAttr,
  1537. pCC->Sids,
  1538. pCC->SidCount,
  1539. Sids,
  1540. SidCount
  1541. );
  1542. if (!b)
  1543. {
  1544. goto Cleanup;
  1545. }
  1546. }
  1547. //
  1548. // Copy the existing restricted sids and the new ones into the allocated
  1549. // memory.
  1550. //
  1551. RestrictedSidLength += pCC->RestrictedSidLength;
  1552. if (0 != RestrictedSidLength)
  1553. {
  1554. pRestrictedSidAttr = (PSID_AND_ATTRIBUTES) AuthzpAlloc(RestrictedSidLength);
  1555. if (AUTHZ_ALLOCATION_FAILED(pRestrictedSidAttr))
  1556. {
  1557. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1558. b = FALSE;
  1559. goto Cleanup;
  1560. }
  1561. b = AuthzpCopySidsAndAttributes(
  1562. pRestrictedSidAttr,
  1563. pCC->RestrictedSids,
  1564. pCC->RestrictedSidCount,
  1565. RestrictedSids,
  1566. RestrictedSidCount
  1567. );
  1568. if (!b)
  1569. {
  1570. goto Cleanup;
  1571. }
  1572. }
  1573. //
  1574. // Copy the existing privileges into the allocated memory.
  1575. //
  1576. pPrivileges = (PLUID_AND_ATTRIBUTES) AuthzpAlloc(pCC->PrivilegeLength);
  1577. if (AUTHZ_ALLOCATION_FAILED(pPrivileges))
  1578. {
  1579. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1580. b = FALSE;
  1581. goto Cleanup;
  1582. }
  1583. AuthzpCopyLuidAndAttributes(
  1584. pNewCC,
  1585. pCC->Privileges,
  1586. pCC->PrivilegeCount,
  1587. pPrivileges
  1588. );
  1589. //
  1590. // Update fields in the client context.
  1591. //
  1592. pNewCC->Sids = pSidAttr;
  1593. pNewCC->SidLength = SidLength;
  1594. pNewCC->SidCount = SidCount + pCC->SidCount;
  1595. pSidAttr = NULL;
  1596. pNewCC->RestrictedSids = pRestrictedSidAttr;
  1597. pNewCC->RestrictedSidLength = RestrictedSidLength;
  1598. pNewCC->RestrictedSidCount = RestrictedSidCount + pCC->RestrictedSidCount;
  1599. pRestrictedSidAttr = NULL;
  1600. pNewCC->Privileges = pPrivileges;
  1601. pNewCC->PrivilegeCount = pCC->PrivilegeCount;
  1602. pNewCC->PrivilegeLength = pCC->PrivilegeLength;
  1603. pPrivileges = NULL;
  1604. *phNewAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pNewCC;
  1605. #ifdef AUTHZ_DEBUG
  1606. wprintf(L"AddSids: Original Context:\n");
  1607. AuthzPrintContext(pCC);
  1608. wprintf(L"AddSids: New Context:\n");
  1609. AuthzPrintContext(pNewCC);
  1610. #endif
  1611. //
  1612. // initialize the sid hash for regular sids
  1613. //
  1614. AuthzpInitSidHash(
  1615. pNewCC->Sids,
  1616. pNewCC->SidCount,
  1617. pNewCC->SidHash
  1618. );
  1619. //
  1620. // initialize the sid hash for restricted sids
  1621. //
  1622. AuthzpInitSidHash(
  1623. pNewCC->RestrictedSids,
  1624. pNewCC->RestrictedSidCount,
  1625. pNewCC->RestrictedSidHash
  1626. );
  1627. Cleanup:
  1628. AuthzpReleaseClientContextLock(pCC);
  1629. //
  1630. // These statements are relevant in the failure case.
  1631. // In the success case, the pointers are set to NULL.
  1632. //
  1633. if (!b)
  1634. {
  1635. DWORD dwSavedError = GetLastError();
  1636. AuthzpFreeNonNull(pSidAttr);
  1637. AuthzpFreeNonNull(pRestrictedSidAttr);
  1638. AuthzpFreeNonNull(pPrivileges);
  1639. if (AUTHZ_NON_NULL_PTR(pNewCC))
  1640. {
  1641. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pNewCC);
  1642. }
  1643. SetLastError(dwSavedError);
  1644. }
  1645. return b;
  1646. }
  1647. BOOL
  1648. AuthzGetInformationFromContext(
  1649. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1650. IN AUTHZ_CONTEXT_INFORMATION_CLASS InfoClass,
  1651. IN DWORD BufferSize,
  1652. OUT PDWORD pSizeRequired,
  1653. OUT PVOID Buffer
  1654. )
  1655. /*++
  1656. Routine Description:
  1657. This API returns information about the client context in a buffer supplied
  1658. by the caller. It also returns the size of the buffer required to hold the
  1659. requested information.
  1660. Arguments:
  1661. AuthzClientContext - Authz client context from which requested information
  1662. will be read.
  1663. InfoClass - Type of information to be returned. The caller can ask for
  1664. a. privileges
  1665. TOKEN_PRIVILEGES
  1666. b. sids and their attributes
  1667. TOKEN_GROUPS
  1668. c. restricted sids and their attributes
  1669. TOKEN_GROUPS
  1670. d. authz context persistent structure which can be saved to and
  1671. read from the disk.
  1672. PVOID
  1673. e. User sid
  1674. TOKEN_USER
  1675. f. Server Context one level higher
  1676. PAUTHZ_CLIENT_CONTEXT
  1677. g. Expiration time
  1678. LARGE_INTEGER
  1679. h. Identifier
  1680. LUID
  1681. BufferSize - Size of the supplied buffer.
  1682. pSizeRequired - To return the size of the structure needed to hold the results.
  1683. Buffer - To hold the information requested. The structure returned will
  1684. depend on the information class requested.
  1685. Return Value:
  1686. A value of TRUE is returned if the API is successful. Otherwise,
  1687. a value of FALSE is returned. In the failure case, error value may be
  1688. retrieved using GetLastError().
  1689. --*/
  1690. {
  1691. DWORD LocalSize = 0;
  1692. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1693. if (!ARGUMENT_PRESENT(hAuthzClientContext) ||
  1694. (!ARGUMENT_PRESENT(Buffer) && BufferSize != 0) ||
  1695. !ARGUMENT_PRESENT(pSizeRequired))
  1696. {
  1697. SetLastError(ERROR_INVALID_PARAMETER);
  1698. return FALSE;
  1699. }
  1700. *pSizeRequired = 0;
  1701. switch(InfoClass)
  1702. {
  1703. case AuthzContextInfoUserSid:
  1704. LocalSize = RtlLengthSid(pCC->Sids[0].Sid) + sizeof(TOKEN_USER);
  1705. *pSizeRequired = LocalSize;
  1706. if (LocalSize > BufferSize)
  1707. {
  1708. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1709. return FALSE;
  1710. }
  1711. //
  1712. // xor SE_GROUP_ENABLED from the User attributes. Authz sets this because it simplifies
  1713. // access check logic.
  1714. //
  1715. ((PTOKEN_USER)Buffer)->User.Attributes = pCC->Sids[0].Attributes ^ SE_GROUP_ENABLED;
  1716. ((PTOKEN_USER)Buffer)->User.Sid = ((PUCHAR) Buffer) + sizeof(TOKEN_USER);
  1717. RtlCopyMemory(
  1718. ((PTOKEN_USER)Buffer)->User.Sid,
  1719. pCC->Sids[0].Sid,
  1720. RtlLengthSid(pCC->Sids[0].Sid)
  1721. );
  1722. return TRUE;
  1723. case AuthzContextInfoGroupsSids:
  1724. LocalSize = pCC->SidLength +
  1725. sizeof(TOKEN_GROUPS) -
  1726. RtlLengthSid(pCC->Sids[0].Sid) -
  1727. 2 * sizeof(SID_AND_ATTRIBUTES);
  1728. *pSizeRequired = LocalSize;
  1729. if (LocalSize > BufferSize)
  1730. {
  1731. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1732. return FALSE;
  1733. }
  1734. ((PTOKEN_GROUPS) Buffer)->GroupCount = pCC->SidCount - 1;
  1735. return AuthzpCopySidsAndAttributes(
  1736. ((PTOKEN_GROUPS) Buffer)->Groups,
  1737. pCC->Sids + 1,
  1738. pCC->SidCount - 1,
  1739. NULL,
  1740. 0
  1741. );
  1742. case AuthzContextInfoRestrictedSids:
  1743. LocalSize = pCC->RestrictedSidLength +
  1744. sizeof(TOKEN_GROUPS) -
  1745. sizeof(SID_AND_ATTRIBUTES);
  1746. *pSizeRequired = LocalSize;
  1747. if (LocalSize > BufferSize)
  1748. {
  1749. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1750. return FALSE;
  1751. }
  1752. ((PTOKEN_GROUPS) Buffer)->GroupCount = pCC->RestrictedSidCount;
  1753. return AuthzpCopySidsAndAttributes(
  1754. ((PTOKEN_GROUPS) Buffer)->Groups,
  1755. pCC->RestrictedSids,
  1756. pCC->RestrictedSidCount,
  1757. NULL,
  1758. 0
  1759. );
  1760. case AuthzContextInfoPrivileges:
  1761. LocalSize = pCC->PrivilegeLength +
  1762. sizeof(TOKEN_PRIVILEGES) -
  1763. sizeof(LUID_AND_ATTRIBUTES);
  1764. *pSizeRequired = LocalSize;
  1765. if (LocalSize > BufferSize)
  1766. {
  1767. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1768. return FALSE;
  1769. }
  1770. ((PTOKEN_PRIVILEGES) Buffer)->PrivilegeCount = pCC->PrivilegeCount;
  1771. memcpy(
  1772. ((PTOKEN_PRIVILEGES) Buffer)->Privileges,
  1773. pCC->Privileges,
  1774. pCC->PrivilegeLength
  1775. );
  1776. return TRUE;
  1777. case AuthzContextInfoExpirationTime:
  1778. LocalSize = sizeof(LARGE_INTEGER);
  1779. *pSizeRequired = LocalSize;
  1780. if (LocalSize > BufferSize)
  1781. {
  1782. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1783. return FALSE;
  1784. }
  1785. *((PLARGE_INTEGER) Buffer) = pCC->ExpirationTime;
  1786. return TRUE;
  1787. case AuthzContextInfoIdentifier:
  1788. LocalSize = sizeof(LUID);
  1789. *pSizeRequired = LocalSize;
  1790. if (LocalSize > BufferSize)
  1791. {
  1792. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1793. return FALSE;
  1794. }
  1795. *((PLUID) Buffer) = pCC->Identifier;
  1796. return TRUE;
  1797. case AuthzContextInfoServerContext:
  1798. LocalSize = sizeof(AUTHZ_CLIENT_CONTEXT_HANDLE);
  1799. *pSizeRequired = LocalSize;
  1800. if (LocalSize > BufferSize)
  1801. {
  1802. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1803. return FALSE;
  1804. }
  1805. *((PAUTHZ_CLIENT_CONTEXT_HANDLE) Buffer) = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server;
  1806. return TRUE;
  1807. default:
  1808. SetLastError(ERROR_INVALID_PARAMETER);
  1809. return FALSE;
  1810. }
  1811. }
  1812. BOOL
  1813. AuthzFreeContext(
  1814. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. This API frees up all the structures/memory accociated with the client
  1819. context. Note that the list of handles for this client will be freed in
  1820. this call.
  1821. Arguments:
  1822. AuthzClientContext - Context to be freed.
  1823. Return Value:
  1824. A value of TRUE is returned if the API is successful. Otherwise,
  1825. a value of FALSE is returned. In the failure case, error value may be
  1826. retrieved using GetLastError().
  1827. --*/
  1828. {
  1829. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1830. BOOL b = TRUE;
  1831. PAUTHZI_HANDLE pCurrent = NULL;
  1832. PAUTHZI_HANDLE pPrev = NULL;
  1833. if (!ARGUMENT_PRESENT(pCC))
  1834. {
  1835. SetLastError(ERROR_INVALID_PARAMETER);
  1836. return FALSE;
  1837. }
  1838. AuthzpAcquireClientContextWriteLock(pCC);
  1839. AuthzpFreeNonNull(pCC->Privileges);
  1840. AuthzpFreeNonNull(pCC->Sids);
  1841. AuthzpFreeNonNull(pCC->RestrictedSids);
  1842. pCurrent = pCC->AuthzHandleHead;
  1843. //
  1844. // Loop thru all the handles and free them up.
  1845. //
  1846. while (AUTHZ_NON_NULL_PTR(pCurrent))
  1847. {
  1848. pPrev = pCurrent;
  1849. pCurrent = pCurrent->next;
  1850. AuthzpFree(pPrev);
  1851. }
  1852. //
  1853. // Free up the server context. The context is a recursive structure.
  1854. //
  1855. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  1856. {
  1857. b = AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server);
  1858. }
  1859. AuthzpFree(pCC);
  1860. return b;
  1861. }
  1862. AUTHZAPI
  1863. BOOL
  1864. WINAPI
  1865. AuthzInitializeObjectAccessAuditEvent(
  1866. IN DWORD Flags,
  1867. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType,
  1868. IN PWSTR szOperationType,
  1869. IN PWSTR szObjectType,
  1870. IN PWSTR szObjectName,
  1871. IN PWSTR szAdditionalInfo,
  1872. OUT PAUTHZ_AUDIT_EVENT_HANDLE phAuditEvent,
  1873. IN DWORD dwAdditionalParameterCount,
  1874. ...
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Allocates and initializes an AUTHZ_AUDIT_EVENT_HANDLE for use with AuthzAccessCheck.
  1879. The handle is used for storing information for audit generation.
  1880. Arguments:
  1881. Flags - Audit flags. Currently defined bits are:
  1882. AUTHZ_NO_SUCCESS_AUDIT - disables generation of success audits
  1883. AUTHZ_NO_FAILURE_AUDIT - disables generation of failure audits
  1884. AUTHZ_NO_ALLOC_STRINGS - storage space is not allocated for the 4 wide character strings. Rather,
  1885. the handle will only hold pointers to resource manager memory.
  1886. hAuditEventType - for future use. Should be NULL.
  1887. szOperationType - Resource manager defined string that indicates the operation being
  1888. performed that is to be audited.
  1889. szObjectType - Resource manager defined string that indicates the type of object being
  1890. accessed.
  1891. szObjectName - the name of the specific object being accessed.
  1892. szAdditionalInfo - Resource Manager defined string for additional audit information.
  1893. phAuditEvent - pointer to AUTHZ_AUDIT_EVENT_HANDLE. Space for this is allocated in the function.
  1894. dwAdditionalParameterCount - Must be zero.
  1895. Return Value:
  1896. Returns TRUE if successful, FALSE if unsuccessful.
  1897. Extended information available with GetLastError().
  1898. --*/
  1899. {
  1900. PAUTHZI_AUDIT_EVENT pAuditEvent = NULL;
  1901. BOOL b = TRUE;
  1902. DWORD dwStringSize = 0;
  1903. DWORD dwObjectTypeLength = 0;
  1904. DWORD dwObjectNameLength = 0;
  1905. DWORD dwOperationTypeLength = 0;
  1906. DWORD dwAdditionalInfoLength = 0;
  1907. if ((!ARGUMENT_PRESENT(phAuditEvent)) ||
  1908. (NULL != hAuditEventType) ||
  1909. (0 != dwAdditionalParameterCount) ||
  1910. (!ARGUMENT_PRESENT(szOperationType)) ||
  1911. (!ARGUMENT_PRESENT(szObjectType)) ||
  1912. (!ARGUMENT_PRESENT(szObjectName)) ||
  1913. (!ARGUMENT_PRESENT(szAdditionalInfo)) ||
  1914. (Flags & (~(AUTHZ_VALID_OBJECT_ACCESS_AUDIT_FLAGS | AUTHZ_DS_CATEGORY_FLAG))))
  1915. {
  1916. SetLastError(ERROR_INVALID_PARAMETER);
  1917. return FALSE;
  1918. }
  1919. *phAuditEvent = NULL;
  1920. //
  1921. // Allocate and initialize a new AUTHZI_AUDIT_EVENT. Include for the string in the contiguous memory, if
  1922. // needed.
  1923. //
  1924. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  1925. {
  1926. dwStringSize = 0;
  1927. }
  1928. else
  1929. {
  1930. dwOperationTypeLength = (DWORD) wcslen(szOperationType) + 1;
  1931. dwObjectTypeLength = (DWORD) wcslen(szObjectType) + 1;
  1932. dwObjectNameLength = (DWORD) wcslen(szObjectName) + 1;
  1933. dwAdditionalInfoLength = (DWORD) wcslen(szAdditionalInfo) + 1;
  1934. dwStringSize = sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength + dwAdditionalInfoLength);
  1935. }
  1936. pAuditEvent = (PAUTHZI_AUDIT_EVENT) AuthzpAlloc(sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize);
  1937. if (AUTHZ_ALLOCATION_FAILED(pAuditEvent))
  1938. {
  1939. b = FALSE;
  1940. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1941. goto Cleanup;
  1942. }
  1943. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  1944. {
  1945. pAuditEvent->szOperationType = szOperationType;
  1946. pAuditEvent->szObjectType = szObjectType;
  1947. pAuditEvent->szObjectName = szObjectName;
  1948. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  1949. }
  1950. else
  1951. {
  1952. //
  1953. // Set the string pointers into the contiguous memory.
  1954. //
  1955. pAuditEvent->szOperationType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT));
  1956. RtlCopyMemory(
  1957. pAuditEvent->szOperationType,
  1958. szOperationType,
  1959. sizeof(WCHAR) * dwOperationTypeLength
  1960. );
  1961. pAuditEvent->szObjectType = (PWSTR)((PUCHAR)pAuditEvent->szOperationType + (sizeof(WCHAR) * dwOperationTypeLength));
  1962. RtlCopyMemory(
  1963. pAuditEvent->szObjectType,
  1964. szObjectType,
  1965. sizeof(WCHAR) * dwObjectTypeLength
  1966. );
  1967. pAuditEvent->szObjectName = (PWSTR)((PUCHAR)pAuditEvent->szObjectType + (sizeof(WCHAR) * dwObjectTypeLength));
  1968. RtlCopyMemory(
  1969. pAuditEvent->szObjectName,
  1970. szObjectName,
  1971. sizeof(WCHAR) * dwObjectNameLength
  1972. );
  1973. pAuditEvent->szAdditionalInfo = (PWSTR)((PUCHAR)pAuditEvent->szObjectName + (sizeof(WCHAR) * dwObjectNameLength));
  1974. RtlCopyMemory(
  1975. pAuditEvent->szAdditionalInfo,
  1976. szAdditionalInfo,
  1977. sizeof(WCHAR) * dwAdditionalInfoLength
  1978. );
  1979. }
  1980. //
  1981. // AEI and Queue will be filled in from RM in AuthzpCreateAndLogAudit
  1982. //
  1983. pAuditEvent->hAET = NULL;
  1984. pAuditEvent->hAuditQueue = NULL;
  1985. pAuditEvent->pAuditParams = NULL;
  1986. pAuditEvent->Flags = Flags;
  1987. pAuditEvent->dwTimeOut = INFINITE;
  1988. pAuditEvent->dwSize = sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize;
  1989. Cleanup:
  1990. if (!b)
  1991. {
  1992. AuthzpFreeNonNull(pAuditEvent);
  1993. }
  1994. else
  1995. {
  1996. *phAuditEvent = (AUTHZ_AUDIT_EVENT_HANDLE) pAuditEvent;
  1997. }
  1998. return b;
  1999. }
  2000. BOOL
  2001. AuthzGetInformationFromAuditEvent(
  2002. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  2003. IN AUTHZ_AUDIT_EVENT_INFORMATION_CLASS InfoClass,
  2004. IN DWORD BufferSize,
  2005. OUT PDWORD pSizeRequired,
  2006. OUT PVOID Buffer
  2007. )
  2008. /*++
  2009. Routine Description
  2010. Queries information in the AUTHZ_AUDIT_EVENT_HANDLE.
  2011. Arguments
  2012. hAuditEvent - the AUTHZ_AUDIT_EVENT_HANDLE to query.
  2013. InfoClass - The class of information to query. Valid values are:
  2014. a. AuthzAuditEventInfoFlags - returns the flags set for the handle. Type is DWORD.
  2015. e. AuthzAuditEventInfoOperationType - returns the operation type. Type is PCWSTR.
  2016. e. AuthzAuditEventInfoObjectType - returns the object type. Type is PCWSTR.
  2017. f. AuthzAuditEventInfoObjectName - returns the object name. Type is PCWSTR.
  2018. g. AuthzAuditEventInfoAdditionalInfo - returns the additional info field. Type is PCWSTR.
  2019. BufferSize - Size of the supplied buffer.
  2020. pSizeRequired - To return the size of the structure needed to hold the results.
  2021. Buffer - To hold the information requested. The structure returned will
  2022. depend on the information class requested.
  2023. Return Value
  2024. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2025. --*/
  2026. {
  2027. DWORD LocalSize = 0;
  2028. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  2029. if ((!ARGUMENT_PRESENT(hAuditEvent)) ||
  2030. (!ARGUMENT_PRESENT(pSizeRequired)) ||
  2031. (!ARGUMENT_PRESENT(Buffer) && BufferSize > 0))
  2032. {
  2033. SetLastError(ERROR_INVALID_PARAMETER);
  2034. return FALSE;
  2035. }
  2036. *pSizeRequired = 0;
  2037. switch(InfoClass)
  2038. {
  2039. case AuthzAuditEventInfoFlags:
  2040. LocalSize = sizeof(DWORD);
  2041. *pSizeRequired = LocalSize;
  2042. if (LocalSize > BufferSize)
  2043. {
  2044. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2045. return FALSE;
  2046. }
  2047. *((PDWORD)Buffer) = pAuditEvent->Flags;
  2048. return TRUE;
  2049. case AuthzAuditEventInfoOperationType:
  2050. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szOperationType) + 1));
  2051. *pSizeRequired = LocalSize;
  2052. if (LocalSize > BufferSize)
  2053. {
  2054. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2055. return FALSE;
  2056. }
  2057. RtlCopyMemory(
  2058. Buffer,
  2059. pAuditEvent->szOperationType,
  2060. LocalSize
  2061. );
  2062. return TRUE;
  2063. case AuthzAuditEventInfoObjectType:
  2064. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szObjectType) + 1));
  2065. *pSizeRequired = LocalSize;
  2066. if (LocalSize > BufferSize)
  2067. {
  2068. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2069. return FALSE;
  2070. }
  2071. RtlCopyMemory(
  2072. Buffer,
  2073. pAuditEvent->szObjectType,
  2074. LocalSize
  2075. );
  2076. return TRUE;
  2077. case AuthzAuditEventInfoObjectName:
  2078. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szObjectName) + 1));
  2079. *pSizeRequired = LocalSize;
  2080. if (LocalSize > BufferSize)
  2081. {
  2082. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2083. return FALSE;
  2084. }
  2085. RtlCopyMemory(
  2086. Buffer,
  2087. pAuditEvent->szObjectName,
  2088. LocalSize
  2089. );
  2090. return TRUE;
  2091. case AuthzAuditEventInfoAdditionalInfo:
  2092. if (NULL == pAuditEvent->szAdditionalInfo)
  2093. {
  2094. SetLastError(ERROR_INVALID_PARAMETER);
  2095. return FALSE;
  2096. }
  2097. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szAdditionalInfo) + 1));
  2098. *pSizeRequired = LocalSize;
  2099. if (LocalSize > BufferSize)
  2100. {
  2101. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2102. return FALSE;
  2103. }
  2104. RtlCopyMemory(
  2105. Buffer,
  2106. pAuditEvent->szAdditionalInfo,
  2107. LocalSize
  2108. );
  2109. return TRUE;
  2110. default:
  2111. SetLastError(ERROR_INVALID_PARAMETER);
  2112. return FALSE;
  2113. }
  2114. }
  2115. BOOL
  2116. AuthzFreeAuditEvent(
  2117. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent
  2118. )
  2119. /*++
  2120. Routine Description:
  2121. Frees hAuditEvent and notifies the appropriate queue to unregister the audit context in LSA.
  2122. Arguments:
  2123. hAuditEvent - AUTHZ_AUDIT_EVENT_HANDLE. Must have initially been created
  2124. with AuthzRMInitializeObjectAccessAuditEvent or AuthzInitializeAuditEvent().
  2125. Return Value:
  2126. Boolean: TRUE if successful; FALSE if failure.
  2127. Extended information available with GetLastError().
  2128. --*/
  2129. {
  2130. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  2131. if (!ARGUMENT_PRESENT(hAuditEvent))
  2132. {
  2133. SetLastError(ERROR_INVALID_PARAMETER);
  2134. return FALSE;
  2135. }
  2136. //
  2137. // If the RM specified the AuditEvent, then we should deref the context. If the AuditEvent
  2138. // has not been used, or was a default event type, then this field will be NULL.
  2139. //
  2140. if (AUTHZ_NON_NULL_PTR(pAuditEvent->hAET))
  2141. {
  2142. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  2143. }
  2144. AuthzpFree(pAuditEvent);
  2145. return TRUE;
  2146. }
  2147. //
  2148. // Routines for internal callers.
  2149. //
  2150. BOOL
  2151. AuthziInitializeAuditEventType(
  2152. IN DWORD Flags,
  2153. IN USHORT CategoryID,
  2154. IN USHORT AuditID,
  2155. IN USHORT ParameterCount,
  2156. OUT PAUTHZ_AUDIT_EVENT_TYPE_HANDLE phAuditEventType
  2157. )
  2158. /*++
  2159. Routine Description
  2160. Initializes an AUTHZ_AUDIT_EVENT_TYPE_HANDLE for use in AuthzInitializeAuditEvent().
  2161. Arguments
  2162. phAuditEventType - pointer to pointer to receive memory allocated for AUTHZ_AUDIT_EVENT_TYPE_HANDLE.
  2163. dwFlags - Flags that control behavior of function.
  2164. AUTHZ_INIT_GENERIC_AUDIT_EVENT - initialize the AUTHZ_AUDIT_EVENT_TYPE for generic object
  2165. access audits. When this flag is specified, none of the optional parameters need to
  2166. be passed. This is equivalent to calling:
  2167. AuthzInitializeAuditEvent(
  2168. &hAEI,
  2169. 0,
  2170. SE_CATEGID_OBJECT_ACCESS,
  2171. SE_AUDITID_OBJECT_OPERATION,
  2172. 9
  2173. );
  2174. CategoryID - The category id of the audit.
  2175. AuditID - The ID of the audit in msaudite.
  2176. ParameterCount - The number of fields in the audit.
  2177. Return Value
  2178. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2179. --*/
  2180. {
  2181. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAET = NULL;
  2182. BOOL b = TRUE;
  2183. AUDIT_HANDLE hAudit = NULL;
  2184. if (!ARGUMENT_PRESENT(phAuditEventType))
  2185. {
  2186. SetLastError(ERROR_INVALID_PARAMETER);
  2187. return FALSE;
  2188. }
  2189. *phAuditEventType = NULL;
  2190. pAET = AuthzpAlloc(sizeof(AUTHZ_AUDIT_EVENT_TYPE_OLD));
  2191. if (AUTHZ_ALLOCATION_FAILED(pAET))
  2192. {
  2193. b = FALSE;
  2194. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2195. goto Cleanup;
  2196. }
  2197. if (FLAG_ON(Flags, AUTHZP_INIT_GENERIC_AUDIT_EVENT))
  2198. {
  2199. pAET->Version = AUDIT_TYPE_LEGACY;
  2200. pAET->u.Legacy.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  2201. pAET->u.Legacy.AuditId = SE_AUDITID_OBJECT_OPERATION;
  2202. pAET->u.Legacy.ParameterCount = 11;
  2203. }
  2204. else
  2205. {
  2206. pAET->Version = AUDIT_TYPE_LEGACY;
  2207. pAET->u.Legacy.CategoryId = CategoryID;
  2208. pAET->u.Legacy.AuditId = AuditID;
  2209. //
  2210. // ParameterCount gets increased by 2 because the LSA expects the first two
  2211. // parameters to be the user sid and subsystem name.
  2212. //
  2213. pAET->u.Legacy.ParameterCount = ParameterCount + 2;
  2214. }
  2215. b = AuthzpRegisterAuditEvent(
  2216. pAET,
  2217. &hAudit
  2218. );
  2219. if (!b)
  2220. {
  2221. goto Cleanup;
  2222. }
  2223. pAET->hAudit = (ULONG_PTR) hAudit;
  2224. pAET->dwFlags = Flags & ~AUTHZP_INIT_GENERIC_AUDIT_EVENT;
  2225. Cleanup:
  2226. if (!b)
  2227. {
  2228. AuthzpFreeNonNull(pAET);
  2229. }
  2230. else
  2231. {
  2232. AuthzpReferenceAuditEventType((AUTHZ_AUDIT_EVENT_TYPE_HANDLE)pAET);
  2233. *phAuditEventType = (AUTHZ_AUDIT_EVENT_TYPE_HANDLE)pAET;
  2234. }
  2235. return b;
  2236. }
  2237. BOOL
  2238. AuthziModifyAuditEventType(
  2239. IN DWORD Flags,
  2240. IN USHORT CategoryID,
  2241. IN USHORT AuditID,
  2242. IN USHORT ParameterCount,
  2243. IN OUT AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType
  2244. )
  2245. /*++
  2246. Routine Description
  2247. Modifies an existing AuditEventType.
  2248. Arguments
  2249. Flags - AUTHZ_AUDIT_EVENT_TYPE_AUDITID
  2250. Return Value
  2251. --*/
  2252. {
  2253. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD) hAuditEventType;
  2254. BOOL b = TRUE;
  2255. if (!ARGUMENT_PRESENT(hAuditEventType))
  2256. {
  2257. SetLastError(ERROR_INVALID_PARAMETER);
  2258. return FALSE;
  2259. }
  2260. UNREFERENCED_PARAMETER(CategoryID);
  2261. UNREFERENCED_PARAMETER(ParameterCount);
  2262. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_AUDITID))
  2263. {
  2264. pAAETO->u.Legacy.AuditId = AuditID;
  2265. }
  2266. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_CATEGID))
  2267. {
  2268. SetLastError(ERROR_INVALID_PARAMETER);
  2269. b = FALSE;
  2270. goto Cleanup;
  2271. }
  2272. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_PARAM))
  2273. {
  2274. SetLastError(ERROR_INVALID_PARAMETER);
  2275. b = FALSE;
  2276. goto Cleanup;
  2277. }
  2278. Cleanup:
  2279. return b;
  2280. }
  2281. BOOL
  2282. AuthziFreeAuditEventType(
  2283. AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType
  2284. )
  2285. /*++
  2286. Routine Description
  2287. Frees the PAUDIT_EVENT_TYPE allocated by AuthzInitializeAuditEventType().
  2288. Arguments
  2289. pAuditEventType - pointer to memory to free.
  2290. Return Value
  2291. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2292. --*/
  2293. {
  2294. BOOL b = TRUE;
  2295. if (!ARGUMENT_PRESENT(hAuditEventType))
  2296. {
  2297. SetLastError(ERROR_INVALID_PARAMETER);
  2298. return FALSE;
  2299. }
  2300. b = AuthzpDereferenceAuditEventType(
  2301. hAuditEventType
  2302. );
  2303. return b;
  2304. }
  2305. AUTHZAPI
  2306. BOOL
  2307. WINAPI
  2308. AuthziInitializeAuditQueue(
  2309. IN DWORD Flags,
  2310. IN DWORD dwAuditQueueHigh,
  2311. IN DWORD dwAuditQueueLow,
  2312. IN PVOID Reserved,
  2313. OUT PAUTHZ_AUDIT_QUEUE_HANDLE phAuditQueue
  2314. )
  2315. /*++
  2316. Routine Description
  2317. Creates an audit queue.
  2318. Arguments
  2319. phAuditQueue - pointer to handle for the audit queue.
  2320. Flags -
  2321. AUTHZ_MONITOR_AUDIT_QUEUE_SIZE - notifies Authz that it should not let the size of the
  2322. audit queue grow unchecked.
  2323. dwAuditQueueHigh - high water mark for the audit queue.
  2324. dwAuditQueueLow - low water mark for the audit queue.
  2325. Reserved - for future expansion.
  2326. Return Value
  2327. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2328. --*/
  2329. {
  2330. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2331. BOOL b = TRUE;
  2332. NTSTATUS Status = STATUS_SUCCESS;
  2333. UNREFERENCED_PARAMETER(Reserved);
  2334. if (!ARGUMENT_PRESENT(phAuditQueue))
  2335. {
  2336. SetLastError(ERROR_INVALID_PARAMETER);
  2337. return FALSE;
  2338. }
  2339. *phAuditQueue = NULL;
  2340. pQueue = AuthzpAlloc(sizeof(AUTHZI_AUDIT_QUEUE));
  2341. if (AUTHZ_ALLOCATION_FAILED(pQueue))
  2342. {
  2343. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2344. b = FALSE;
  2345. goto Cleanup;
  2346. }
  2347. pQueue->dwAuditQueueHigh = dwAuditQueueHigh;
  2348. pQueue->dwAuditQueueLow = dwAuditQueueLow;
  2349. pQueue->bWorker = TRUE;
  2350. pQueue->Flags = Flags;
  2351. //
  2352. // This event is set whenever an audit is queued with AuthziLogAuditEvent(). It
  2353. // notifies the dequeueing thread that there is work to do.
  2354. //
  2355. pQueue->hAuthzAuditAddedEvent = CreateEvent(
  2356. NULL,
  2357. TRUE,
  2358. FALSE, // Initially not signaled, since no audit has been added yet.
  2359. NULL
  2360. );
  2361. if (NULL == pQueue->hAuthzAuditAddedEvent)
  2362. {
  2363. b = FALSE;
  2364. goto Cleanup;
  2365. }
  2366. //
  2367. // This event is set when the audit queue is empty.
  2368. //
  2369. pQueue->hAuthzAuditQueueEmptyEvent = CreateEvent(
  2370. NULL,
  2371. TRUE,
  2372. TRUE, // Initially signaled.
  2373. NULL
  2374. );
  2375. if (NULL == pQueue->hAuthzAuditQueueEmptyEvent)
  2376. {
  2377. b = FALSE;
  2378. goto Cleanup;
  2379. }
  2380. //
  2381. // This event is set when the audit queue is below the low water mark.
  2382. //
  2383. pQueue->hAuthzAuditQueueLowEvent = CreateEvent(
  2384. NULL,
  2385. FALSE,// The system only schedules one thread waiting on this event (auto reset event).
  2386. TRUE, // Initially set.
  2387. NULL
  2388. );
  2389. if (NULL == pQueue->hAuthzAuditQueueLowEvent)
  2390. {
  2391. b = FALSE;
  2392. goto Cleanup;
  2393. }
  2394. //
  2395. // This boolean is true only when the high water mark has been reached
  2396. //
  2397. pQueue->bAuthzAuditQueueHighEvent = FALSE;
  2398. //
  2399. // This lock is taken whenever audits are being added or removed from the queue, or events / boolean being set.
  2400. //
  2401. Status = RtlInitializeCriticalSection(&pQueue->AuthzAuditQueueLock);
  2402. if (!NT_SUCCESS(Status))
  2403. {
  2404. SetLastError(RtlNtStatusToDosError(Status));
  2405. b = FALSE;
  2406. goto Cleanup;
  2407. }
  2408. //
  2409. // Initialize the list
  2410. //
  2411. InitializeListHead(&pQueue->AuthzAuditQueue);
  2412. //
  2413. // Create the worker thread that sends audits to LSA.
  2414. //
  2415. pQueue->hAuthzAuditThread = CreateThread(
  2416. NULL,
  2417. 0,
  2418. AuthzpDeQueueThreadWorker,
  2419. pQueue,
  2420. 0,
  2421. NULL
  2422. );
  2423. if (NULL == pQueue->hAuthzAuditThread)
  2424. {
  2425. b = FALSE;
  2426. goto Cleanup;
  2427. }
  2428. Cleanup:
  2429. if (!b)
  2430. {
  2431. if (AUTHZ_NON_NULL_PTR(pQueue))
  2432. {
  2433. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditQueueLowEvent);
  2434. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditAddedEvent);
  2435. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditQueueEmptyEvent);
  2436. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditThread);
  2437. AuthzpFree(pQueue);
  2438. }
  2439. }
  2440. else
  2441. {
  2442. *phAuditQueue = (AUTHZ_AUDIT_QUEUE_HANDLE)pQueue;
  2443. }
  2444. return b;
  2445. }
  2446. AUTHZAPI
  2447. BOOL
  2448. WINAPI
  2449. AuthziModifyAuditQueue(
  2450. IN OUT AUTHZ_AUDIT_QUEUE_HANDLE hQueue OPTIONAL,
  2451. IN DWORD Flags,
  2452. IN DWORD dwQueueFlags OPTIONAL,
  2453. IN DWORD dwAuditQueueSizeHigh OPTIONAL,
  2454. IN DWORD dwAuditQueueSizeLow OPTIONAL,
  2455. IN DWORD dwThreadPriority OPTIONAL
  2456. )
  2457. /*++
  2458. Routine Description
  2459. Allows the Resource Manager to modify audit queue information.
  2460. Arguments
  2461. Flags - Flags specifying which fields are to be reinitialized. Valid flags are:
  2462. AUTHZ_AUDIT_QUEUE_HIGH
  2463. AUTHZ_AUDIT_QUEUE_LOW
  2464. AUTHZ_AUDIT_QUEUE_THREAD_PRIORITY
  2465. AUTHZ_AUDIT_QUEUE_FLAGS
  2466. Specifying one of the above flags in the Flags field causes the appropriate field of
  2467. the resource manager to be modified to the correct value below:
  2468. dwQueueFlags - set the flags for the audit queue.
  2469. dwAuditQueueSizeHigh - High water mark for the audit queue.
  2470. dwAuditQueueSizeLow - Low water mark for the audit queue.
  2471. dwThreadPriority - Changes the priority of the audit dequeue thread. Valid values are described
  2472. in the SetThreadPriority API. A RM may wish to change the priority of the thread if, for example,
  2473. the high water mark is being reached too frequently and the RM does not want to allow the queue to
  2474. grow beyond its current size.
  2475. Return Value
  2476. Boolean: TRUE on success; FALSE on failure.
  2477. Extended information available with GetLastError().
  2478. --*/
  2479. {
  2480. BOOL b = TRUE;
  2481. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2482. if (!ARGUMENT_PRESENT(hQueue))
  2483. {
  2484. SetLastError(ERROR_INVALID_PARAMETER);
  2485. return FALSE;
  2486. }
  2487. pQueue = (PAUTHZI_AUDIT_QUEUE)hQueue;
  2488. //
  2489. // Set the fields that the caller has asked us to initialize.
  2490. //
  2491. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_FLAGS))
  2492. {
  2493. pQueue->Flags = dwQueueFlags;
  2494. }
  2495. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_HIGH))
  2496. {
  2497. pQueue->dwAuditQueueHigh = dwAuditQueueSizeHigh;
  2498. }
  2499. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_LOW))
  2500. {
  2501. pQueue->dwAuditQueueLow = dwAuditQueueSizeLow;
  2502. }
  2503. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_THREAD_PRIORITY))
  2504. {
  2505. b = SetThreadPriority(pQueue->hAuthzAuditThread, dwThreadPriority);
  2506. if (!b)
  2507. {
  2508. goto Cleanup;
  2509. }
  2510. }
  2511. Cleanup:
  2512. return b;
  2513. }
  2514. AUTHZAPI
  2515. BOOL
  2516. WINAPI
  2517. AuthziFreeAuditQueue(
  2518. IN AUTHZ_AUDIT_QUEUE_HANDLE hQueue OPTIONAL
  2519. )
  2520. /*++
  2521. Routine Description
  2522. This API flushes and frees a queue. The actual freeing of queue memory occurs in the dequeueing thread,
  2523. after all audits have been flushed.
  2524. Arguments
  2525. hQueue - handle to the queue object to free.
  2526. Return Value
  2527. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2528. --*/
  2529. {
  2530. PAUTHZI_AUDIT_QUEUE pQueue = (PAUTHZI_AUDIT_QUEUE) hQueue;
  2531. DWORD dwError = ERROR_SUCCESS;
  2532. BOOL b = TRUE;
  2533. if (!ARGUMENT_PRESENT(hQueue))
  2534. {
  2535. SetLastError(ERROR_INVALID_PARAMETER);
  2536. return FALSE;
  2537. }
  2538. dwError = WaitForSingleObject(
  2539. pQueue->hAuthzAuditQueueEmptyEvent,
  2540. INFINITE
  2541. );
  2542. if (WAIT_OBJECT_0 != dwError)
  2543. {
  2544. ASSERT(L"WaitForSingleObject on hAuthzAuditQueueEmptyEvent failed." && FALSE);
  2545. SetLastError(dwError);
  2546. b = FALSE;
  2547. goto Cleanup;
  2548. }
  2549. //
  2550. // Set this BOOL to FALSE so that the dequeueing thread knows it can terminate. Set the
  2551. // AddedEvent so that the thread can be scheduled.
  2552. //
  2553. pQueue->bWorker = FALSE;
  2554. b = SetEvent(
  2555. pQueue->hAuthzAuditAddedEvent
  2556. );
  2557. if (!b)
  2558. {
  2559. goto Cleanup;
  2560. }
  2561. //
  2562. // Wait for the thread to terminate.
  2563. //
  2564. dwError = WaitForSingleObject(
  2565. pQueue->hAuthzAuditThread,
  2566. INFINITE
  2567. );
  2568. //
  2569. // The wait should succeed since we have told the thread to finish working.
  2570. //
  2571. if (WAIT_OBJECT_0 != dwError)
  2572. {
  2573. ASSERT(L"WaitForSingleObject on hAuthzAuditThread failed." && FALSE);
  2574. SetLastError(dwError);
  2575. b = FALSE;
  2576. goto Cleanup;
  2577. }
  2578. RtlDeleteCriticalSection(&pQueue->AuthzAuditQueueLock);
  2579. AuthzpCloseHandle(pQueue->hAuthzAuditAddedEvent);
  2580. AuthzpCloseHandle(pQueue->hAuthzAuditQueueLowEvent);
  2581. AuthzpCloseHandle(pQueue->hAuthzAuditQueueEmptyEvent);
  2582. AuthzpCloseHandle(pQueue->hAuthzAuditThread);
  2583. AuthzpFree(pQueue);
  2584. Cleanup:
  2585. return b;
  2586. }
  2587. BOOL
  2588. AuthziLogAuditEvent(
  2589. IN DWORD Flags,
  2590. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  2591. IN PVOID pReserved
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. This API manages the logging of Audit Records. The function constructs an
  2596. Audit Record from the information provided and appends it to the Audit
  2597. Record Queue, a doubly-linked list of Audit Records awaiting output to the
  2598. Audit Log. A dedicated thread reads this queue, sending the Audit Records
  2599. to the LSA and removing them from the Audit Queue.
  2600. This call is not guaranteed to return without latency. If the queue is at
  2601. or above the high water mark for size, then the calling thread will be
  2602. suspended until such time that the queue reaches the low water mark. Be
  2603. aware of this latency when fashioning your calls to AuthziLogAuditEvent.
  2604. If such latency is not allowable for the audit that is being generated,
  2605. then specify the correct flag when initializing the
  2606. AUTHZ_AUDIT_EVENT_HANDLE (in AuthzInitAuditEventHandle()). Flags are listed
  2607. in that routines description.
  2608. Arguments:
  2609. hAuditEvent - handle previously obtained by calling AuthzInitAuditEventHandle
  2610. Flags - TBD
  2611. pReserved - reserved for future enhancements
  2612. Return Value:
  2613. Boolean: TRUE on success, FALSE on failure.
  2614. Extended information available with GetLastError().
  2615. --*/
  2616. {
  2617. NTSTATUS Status = STATUS_SUCCESS;
  2618. BOOL b = TRUE;
  2619. BOOL bRef = FALSE;
  2620. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2621. PAUDIT_PARAMS pMarshalledAuditParams = NULL;
  2622. PAUTHZ_AUDIT_QUEUE_ENTRY pAuthzAuditEntry = NULL;
  2623. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT)hAuditEvent;
  2624. //
  2625. // Verify what the caller has passed in.
  2626. //
  2627. if (!ARGUMENT_PRESENT(hAuditEvent))
  2628. {
  2629. SetLastError(ERROR_INVALID_PARAMETER);
  2630. return FALSE;
  2631. }
  2632. //
  2633. // Make a self relative copy of the pAuditEvent->pAuditParams.
  2634. //
  2635. b = AuthzpMarshallAuditParams(
  2636. &pMarshalledAuditParams,
  2637. pAuditEvent->pAuditParams
  2638. );
  2639. if (!b)
  2640. {
  2641. goto Cleanup;
  2642. }
  2643. pQueue = (PAUTHZI_AUDIT_QUEUE)pAuditEvent->hAuditQueue;
  2644. if (NULL == pQueue)
  2645. {
  2646. b = AuthzpSendAuditToLsa(
  2647. (AUDIT_HANDLE)((PAUTHZ_AUDIT_EVENT_TYPE_OLD)pAuditEvent->hAET)->hAudit,
  2648. 0,
  2649. pMarshalledAuditParams,
  2650. NULL
  2651. );
  2652. goto Cleanup;
  2653. }
  2654. else
  2655. {
  2656. //
  2657. // Create the audit queue entry.
  2658. //
  2659. pAuthzAuditEntry = AuthzpAlloc(sizeof(AUTHZ_AUDIT_QUEUE_ENTRY));
  2660. if (AUTHZ_ALLOCATION_FAILED(pAuthzAuditEntry))
  2661. {
  2662. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2663. b = FALSE;
  2664. goto Cleanup;
  2665. }
  2666. pAuthzAuditEntry->pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD)pAuditEvent->hAET;
  2667. pAuthzAuditEntry->Flags = Flags;
  2668. pAuthzAuditEntry->pReserved = pReserved;
  2669. pAuthzAuditEntry->pAuditParams = pMarshalledAuditParams;
  2670. AuthzpReferenceAuditEventType(pAuditEvent->hAET);
  2671. bRef = TRUE;
  2672. if (FLAG_ON(pQueue->Flags, AUTHZ_MONITOR_AUDIT_QUEUE_SIZE))
  2673. {
  2674. //
  2675. // Monitor queue size if specified by the Resource Manager.
  2676. //
  2677. //
  2678. // If we are closing in on the high water mark then wait for the queue
  2679. // to be below the low water mark.
  2680. //
  2681. #define AUTHZ_QUEUE_WAIT_HEURISTIC .75
  2682. if (pQueue->AuthzAuditQueueLength > pQueue->dwAuditQueueHigh * AUTHZ_QUEUE_WAIT_HEURISTIC)
  2683. {
  2684. Status = WaitForSingleObject(
  2685. pQueue->hAuthzAuditQueueLowEvent,
  2686. pAuditEvent->dwTimeOut
  2687. );
  2688. if (WAIT_FAILED == Status)
  2689. {
  2690. ASSERT(L"WaitForSingleObject on hAuthzAuditQueueLowEvent failed." && FALSE);
  2691. }
  2692. if (WAIT_TIMEOUT == Status)
  2693. {
  2694. b = FALSE;
  2695. SetLastError(RtlNtStatusToDosError(Status));
  2696. goto Cleanup;
  2697. }
  2698. }
  2699. //
  2700. // Queue the event and modify appropriate events.
  2701. //
  2702. b = AuthzpEnQueueAuditEventMonitor(
  2703. pQueue,
  2704. pAuthzAuditEntry
  2705. );
  2706. goto Cleanup;
  2707. }
  2708. else
  2709. {
  2710. //
  2711. // If we are not to monitor the audit queue then simply queue the entry.
  2712. //
  2713. b = AuthzpEnQueueAuditEvent(
  2714. pQueue,
  2715. pAuthzAuditEntry
  2716. );
  2717. goto Cleanup;
  2718. }
  2719. }
  2720. Cleanup:
  2721. if (pQueue)
  2722. {
  2723. if (FALSE == b)
  2724. {
  2725. if (bRef)
  2726. {
  2727. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  2728. }
  2729. AuthzpFreeNonNull(pAuthzAuditEntry);
  2730. AuthzpFreeNonNull(pMarshalledAuditParams);
  2731. }
  2732. //
  2733. // hAuthzAuditQueueLowEvent is an auto reset event. Only one waiting thread is released when it is signalled, and then
  2734. // event is automatically switched to a nonsignalled state. This is appropriate here because it keeps many threads from
  2735. // running and overflowing the high water mark. However, I must always resignal the event myself if the conditions
  2736. // for signaling are true.
  2737. //
  2738. RtlEnterCriticalSection(&pQueue->AuthzAuditQueueLock);
  2739. if (!pQueue->bAuthzAuditQueueHighEvent)
  2740. {
  2741. if (pQueue->AuthzAuditQueueLength <= pQueue->dwAuditQueueHigh)
  2742. {
  2743. BOOL bSet;
  2744. bSet = SetEvent(pQueue->hAuthzAuditQueueLowEvent);
  2745. if (!bSet)
  2746. {
  2747. ASSERT(L"SetEvent on hAuthzAuditQueueLowEvent failed" && FALSE);
  2748. }
  2749. }
  2750. }
  2751. RtlLeaveCriticalSection(&pQueue->AuthzAuditQueueLock);
  2752. }
  2753. else
  2754. {
  2755. AuthzpFreeNonNull(pMarshalledAuditParams);
  2756. }
  2757. return b;
  2758. }
  2759. BOOL
  2760. AuthziAllocateAuditParams(
  2761. OUT PAUDIT_PARAMS * ppParams,
  2762. IN USHORT NumParams
  2763. )
  2764. /*++
  2765. Routine Description:
  2766. Allocate the AUDIT_PARAMS structure for the correct number of parameters.
  2767. Arguments:
  2768. ppParams - pointer to PAUDIT_PARAMS structure to be initialized.
  2769. NumParams - number of parameters passed in the var-arg section.
  2770. This must be SE_MAX_AUDIT_PARAMETERS or less.
  2771. Return Value:
  2772. Boolean: TRUE on success, FALSE on failure. Extended information available with GetLastError().
  2773. --*/
  2774. {
  2775. BOOL b = TRUE;
  2776. PAUDIT_PARAMS pAuditParams = NULL;
  2777. if (!ARGUMENT_PRESENT(ppParams))
  2778. {
  2779. SetLastError(ERROR_INVALID_PARAMETER);
  2780. return FALSE;
  2781. }
  2782. *ppParams = NULL;
  2783. //
  2784. // the first two params are always fixed. thus the total number
  2785. // is 2 + the passed number.
  2786. //
  2787. if ((NumParams + 2) > SE_MAX_AUDIT_PARAMETERS)
  2788. {
  2789. SetLastError(ERROR_INVALID_PARAMETER);
  2790. b = FALSE;
  2791. goto Cleanup;
  2792. }
  2793. pAuditParams = AuthzpAlloc(sizeof(AUDIT_PARAMS) + (sizeof(AUDIT_PARAM) * (NumParams + 2)));
  2794. if (AUTHZ_ALLOCATION_FAILED(pAuditParams))
  2795. {
  2796. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2797. b = FALSE;
  2798. goto Cleanup;
  2799. }
  2800. pAuditParams->Parameters = (PAUDIT_PARAM)((PUCHAR)pAuditParams + sizeof(AUDIT_PARAMS));
  2801. Cleanup:
  2802. if (!b)
  2803. {
  2804. AuthzpFreeNonNull(pAuditParams);
  2805. }
  2806. else
  2807. {
  2808. *ppParams = pAuditParams;
  2809. }
  2810. return b;
  2811. }
  2812. BOOL
  2813. AuthziInitializeAuditParamsWithRM(
  2814. IN DWORD Flags,
  2815. IN AUTHZ_RESOURCE_MANAGER_HANDLE hResourceManager,
  2816. IN USHORT NumParams,
  2817. OUT PAUDIT_PARAMS pParams,
  2818. ...
  2819. )
  2820. /*++
  2821. Routine Description:
  2822. Initialize the AUDIT_PARAMS structure based on the passed
  2823. data. This is the recommended way to init AUDIT_PARAMS. It is
  2824. faster than AuthzInitializeAuditParams and works with an
  2825. impersonating caller.
  2826. The caller passes in type ~ value pairs in the vararg section.
  2827. This function will initialize the corresponding array elements
  2828. based on each such pair. In case of certain types, there may
  2829. be more than one value argument required. This requirement
  2830. is documented next to each param-type.
  2831. Arguments:
  2832. pParams - pointer to AUDIT_PARAMS structure to be initialized
  2833. the size of pParams->Parameters member must be big enough
  2834. to hold NumParams elements. The caller must allocate
  2835. memory for this structure and its members.
  2836. hResourceManager - Handle to the Resource manager that is creating the audit.
  2837. Flags - control flags. one or more of the following:
  2838. APF_AuditSuccess
  2839. NumParams - number of parameters passed in the var-arg section.
  2840. This must be SE_MAX_AUDIT_PARAMETERS or less.
  2841. ... - The format of the variable arg portion is as follows:
  2842. <one of APT_ * flags> <zero or more values>
  2843. APT_String <pointer to null terminated string>
  2844. Flags:
  2845. AP_Filespec : treats the string as a filename
  2846. APT_Ulong <ulong value> [<object-type-index>]
  2847. Flags:
  2848. AP_FormatHex : number appears in hex
  2849. in eventlog
  2850. AP_AccessMask: number is treated as
  2851. an access-mask
  2852. Index to object type must follow
  2853. APT_Pointer <pointer/handle>
  2854. 32 bit on 32 bit systems and
  2855. 64 bit on 64 bit systems
  2856. APT_Sid <pointer to sid>
  2857. APT_LogonId [<logon-id>]
  2858. Flags:
  2859. AP_PrimaryLogonId : logon-id is captured
  2860. from the process token.
  2861. No need to specify one.
  2862. AP_ClientLogonId : logon-id is captured
  2863. from the thread token.
  2864. No need to specify one.
  2865. no flags : need to supply a logon-id
  2866. APT_ObjectTypeList <ptr to obj type list> <obj-type-index>
  2867. Index to object type must be specified
  2868. Return Value:
  2869. TRUE on success
  2870. FALSE otherwise
  2871. call GetLastError() to retrieve the errorcode,
  2872. which will be one of the following:
  2873. ERROR_INVALID_PARAMETER if one of the params is incorrect
  2874. Notes:
  2875. --*/
  2876. {
  2877. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hResourceManager;
  2878. DWORD dwError = NO_ERROR;
  2879. BOOL b = TRUE;
  2880. BOOL bImpersonating = TRUE;
  2881. USHORT i;
  2882. AUDIT_PARAM_TYPE ParamType = APT_None;
  2883. PAUDIT_PARAM pParam = NULL;
  2884. LUID Luid = { 0 };
  2885. LUID AuthIdThread = { 0 };
  2886. PSID pThreadSID = NULL;
  2887. ULONG TypeFlags;
  2888. ULONG ParamFlags;
  2889. ULONG ObjectTypeIndex;
  2890. va_list(arglist);
  2891. //
  2892. // the first two params are always fixed. thus the total number
  2893. // is 2 + the passed number.
  2894. //
  2895. if (!ARGUMENT_PRESENT(hResourceManager) ||
  2896. !ARGUMENT_PRESENT(pParams) ||
  2897. (NumParams + 2) > SE_MAX_AUDIT_PARAMETERS)
  2898. {
  2899. dwError = ERROR_INVALID_PARAMETER;
  2900. goto Cleanup;
  2901. }
  2902. b = AuthzpGetThreadTokenInfo(
  2903. &pThreadSID,
  2904. &AuthIdThread
  2905. );
  2906. if (!b)
  2907. {
  2908. dwError = GetLastError();
  2909. if (dwError == ERROR_NO_TOKEN)
  2910. {
  2911. bImpersonating = FALSE;
  2912. dwError = NO_ERROR;
  2913. b = TRUE;
  2914. }
  2915. else
  2916. {
  2917. goto Cleanup;
  2918. }
  2919. }
  2920. va_start (arglist, pParams);
  2921. pParams->Length = 0;
  2922. pParams->Flags = Flags;
  2923. pParams->Count = NumParams+2;
  2924. pParam = pParams->Parameters;
  2925. //
  2926. // the first param is always the sid of the user in thread token
  2927. // if thread is not impersonating, sid in the primary token is used.
  2928. //
  2929. pParam->Type = APT_Sid;
  2930. if (bImpersonating)
  2931. {
  2932. pParam->Data0 = (ULONG_PTR) pThreadSID;
  2933. }
  2934. else
  2935. {
  2936. pParam->Data0 = (ULONG_PTR) pRM->pUserSID;
  2937. }
  2938. pParam++;
  2939. //
  2940. // the second param is always the sub-system name
  2941. //
  2942. pParam->Type = APT_String;
  2943. pParam->Data0 = (ULONG_PTR) pRM->szResourceManagerName;
  2944. pParam++;
  2945. //
  2946. // now initialize the rest using the var-arg portion
  2947. //
  2948. for (i = 0; i < NumParams; i++, pParam++)
  2949. {
  2950. TypeFlags = va_arg(arglist, ULONG);
  2951. ParamType = ApExtractType(TypeFlags);
  2952. ParamFlags = ApExtractFlags(TypeFlags);
  2953. pParam->Type = ParamType;
  2954. switch(ParamType)
  2955. {
  2956. default:
  2957. dwError = ERROR_INVALID_PARAMETER;
  2958. break;
  2959. case APT_Pointer:
  2960. case APT_String:
  2961. case APT_Sid:
  2962. pParam->Data0 = (ULONG_PTR) va_arg(arglist, PVOID);
  2963. break;
  2964. case APT_Ulong:
  2965. pParam->Data0 = va_arg(arglist, ULONG);
  2966. //
  2967. // in case of an access-mask, store the object-type index
  2968. // This is because, the meaning of the access-mask bits
  2969. // cannot be determined without knowing the object type.
  2970. //
  2971. if (ParamFlags & AP_AccessMask)
  2972. {
  2973. ObjectTypeIndex = va_arg(arglist, ULONG);
  2974. //
  2975. // The object-type-index:
  2976. // - must have been specified earlier
  2977. // - must be specified as a string.
  2978. //
  2979. if ( ( ObjectTypeIndex >= i ) ||
  2980. ( pParams->Parameters[ObjectTypeIndex].Type !=
  2981. APT_String ) )
  2982. {
  2983. dwError = ERROR_INVALID_PARAMETER;
  2984. }
  2985. else
  2986. {
  2987. pParam->Data1 = ObjectTypeIndex;
  2988. }
  2989. }
  2990. pParam->Flags = ParamFlags;
  2991. break;
  2992. case APT_LogonId:
  2993. if (ParamFlags & AP_PrimaryLogonId)
  2994. {
  2995. //
  2996. // use the captured process token info
  2997. //
  2998. pParam->Data0 = pRM->AuthID.LowPart;
  2999. pParam->Data1 = pRM->AuthID.HighPart;
  3000. }
  3001. else if (ParamFlags & AP_ClientLogonId)
  3002. {
  3003. //ASSERT( bImpersonating && L"AuthziInitializeAuditParamsWithRM: AP_ClientLogonId specified while not impersonating" );
  3004. //
  3005. // use the captured thread token info
  3006. //
  3007. pParam->Data0 = AuthIdThread.LowPart;
  3008. pParam->Data1 = AuthIdThread.HighPart;
  3009. }
  3010. else
  3011. {
  3012. //
  3013. // no flag is specified, use the supplied logon-id
  3014. //
  3015. Luid = va_arg(arglist, LUID);
  3016. pParam->Data0 = Luid.LowPart;
  3017. pParam->Data1 = Luid.HighPart;
  3018. }
  3019. break;
  3020. case APT_ObjectTypeList:
  3021. pParam->Data0 = (ULONG_PTR) va_arg(
  3022. arglist,
  3023. PAUDIT_OBJECT_TYPES
  3024. );
  3025. pParam->Data1 = va_arg(arglist, ULONG);
  3026. break;
  3027. }
  3028. if (dwError != NO_ERROR)
  3029. {
  3030. break;
  3031. }
  3032. }
  3033. Cleanup:
  3034. if ( dwError != NO_ERROR )
  3035. {
  3036. SetLastError( dwError );
  3037. b = FALSE;
  3038. if ( pThreadSID != NULL )
  3039. {
  3040. LocalFree( pThreadSID );
  3041. }
  3042. }
  3043. va_end (arglist);
  3044. return b;
  3045. }
  3046. BOOL
  3047. AuthziInitializeAuditParamsFromArray(
  3048. IN DWORD Flags,
  3049. IN AUTHZ_RESOURCE_MANAGER_HANDLE hResourceManager,
  3050. IN USHORT NumParams,
  3051. IN PAUDIT_PARAM pParamArray,
  3052. OUT PAUDIT_PARAMS pParams
  3053. )
  3054. /*++
  3055. Routine Description:
  3056. Initialize the AUDIT_PARAMS structure based on the passed
  3057. data.
  3058. Arguments:
  3059. pParams - pointer to AUDIT_PARAMS structure to be initialized
  3060. the size of pParams->Parameters member must be big enough
  3061. to hold NumParams elements. The caller must allocate
  3062. memory for this structure and its members.
  3063. hResourceManager - Handle to the Resource manager that is creating the audit.
  3064. Flags - control flags. one or more of the following:
  3065. APF_AuditSuccess
  3066. pParamArray - an array of type AUDIT_PARAM
  3067. Return Value:
  3068. TRUE on success
  3069. FALSE otherwise
  3070. call GetLastError() to retrieve the errorcode,
  3071. which will be one of the following:
  3072. ERROR_INVALID_PARAMETER if one of the params is incorrect
  3073. Notes:
  3074. --*/
  3075. {
  3076. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hResourceManager;
  3077. DWORD dwError = NO_ERROR;
  3078. BOOL b = TRUE;
  3079. BOOL bImpersonating = TRUE;
  3080. PAUDIT_PARAM pParam = NULL;
  3081. LUID AuthIdThread;
  3082. PSID pThreadSID = NULL;
  3083. //
  3084. // the first two params are always fixed. thus the total number
  3085. // is 2 + the passed number.
  3086. //
  3087. if (!ARGUMENT_PRESENT(hResourceManager) ||
  3088. !ARGUMENT_PRESENT(pParams) ||
  3089. !ARGUMENT_PRESENT(pParamArray) ||
  3090. (NumParams + 2) > SE_MAX_AUDIT_PARAMETERS)
  3091. {
  3092. dwError = ERROR_INVALID_PARAMETER;
  3093. goto Cleanup;
  3094. }
  3095. b = AuthzpGetThreadTokenInfo(
  3096. &pThreadSID,
  3097. &AuthIdThread
  3098. );
  3099. if (!b)
  3100. {
  3101. dwError = GetLastError();
  3102. if (dwError == ERROR_NO_TOKEN)
  3103. {
  3104. bImpersonating = FALSE;
  3105. dwError = NO_ERROR;
  3106. b = TRUE;
  3107. }
  3108. else
  3109. {
  3110. goto Cleanup;
  3111. }
  3112. }
  3113. pParams->Length = 0;
  3114. pParams->Flags = Flags;
  3115. pParams->Count = NumParams+2;
  3116. pParam = pParams->Parameters;
  3117. //
  3118. // the first param is always the sid of the user in thread token
  3119. // if thread is not impersonating, sid in the primary token is used.
  3120. //
  3121. pParam->Type = APT_Sid;
  3122. if (bImpersonating)
  3123. {
  3124. pParam->Data0 = (ULONG_PTR) pThreadSID;
  3125. }
  3126. else
  3127. {
  3128. pParam->Data0 = (ULONG_PTR) pRM->pUserSID;
  3129. }
  3130. pParam++;
  3131. //
  3132. // the second param is always the sub-system name
  3133. //
  3134. pParam->Type = APT_String;
  3135. pParam->Data0 = (ULONG_PTR) pRM->szResourceManagerName;
  3136. pParam++;
  3137. //
  3138. // now initialize the rest using the array.
  3139. //
  3140. RtlCopyMemory(
  3141. pParam,
  3142. pParamArray,
  3143. sizeof(AUDIT_PARAM) * NumParams
  3144. );
  3145. Cleanup:
  3146. if ( dwError != NO_ERROR )
  3147. {
  3148. SetLastError( dwError );
  3149. b = FALSE;
  3150. if ( pThreadSID != NULL )
  3151. {
  3152. LocalFree( pThreadSID );
  3153. }
  3154. }
  3155. return b;
  3156. }
  3157. BOOL
  3158. AuthziInitializeAuditParams(
  3159. IN DWORD dwFlags,
  3160. OUT PAUDIT_PARAMS pParams,
  3161. OUT PSID* ppUserSid,
  3162. IN PCWSTR SubsystemName,
  3163. IN USHORT NumParams,
  3164. ...
  3165. )
  3166. /*++
  3167. Routine Description:
  3168. Initialize the AUDIT_PARAMS structure based on the passed
  3169. data.
  3170. The caller passes in type ~ value pairs in the vararg section.
  3171. This function will initialize the corresponding array elements
  3172. based on each such pair. In case of certain types, there may
  3173. be more than one value argument required. This requirement
  3174. is documented next to each param-type.
  3175. Arguments:
  3176. pParams - pointer to AUDIT_PARAMS structure to be initialized
  3177. the size of pParams->Parameters member must be big enough
  3178. to hold NumParams elements. The caller must allocate
  3179. memory for this structure and its members.
  3180. ppUserSid - pointer to user sid allocated. This sid is referenced
  3181. by the first parameter (index 0) in AUDIT_PARAMS structure.
  3182. The caller should free this by calling LocalFree
  3183. *after* freeing the AUDIT_PARAMS structure.
  3184. SubsystemName - name of Subsystem that is generating audit
  3185. dwFlags - control flags. one or more of the following:
  3186. APF_AuditSuccess
  3187. NumParams - number of parameters passed in the var-arg section.
  3188. This must be SE_MAX_AUDIT_PARAMETERS or less.
  3189. ... - The format of the variable arg portion is as follows:
  3190. <one of APT_ * flags> <zero or more values>
  3191. APT_String <pointer to null terminated string>
  3192. Flags:
  3193. AP_Filespec : treats the string as a filename
  3194. APT_Ulong <ulong value> [<object-type-index>]
  3195. Flags:
  3196. AP_FormatHex : number appears in hex
  3197. in eventlog
  3198. AP_AccessMask: number is treated as
  3199. an access-mask
  3200. Index to object type must follow
  3201. APT_Pointer <pointer/handle>
  3202. 32 bit on 32 bit systems and
  3203. 64 bit on 64 bit systems
  3204. APT_Sid <pointer to sid>
  3205. APT_LogonId [<logon-id>]
  3206. Flags:
  3207. AP_PrimaryLogonId : logon-id is captured
  3208. from the process token.
  3209. No need to specify one.
  3210. AP_ClientLogonId : logon-id is captured
  3211. from the thread token.
  3212. No need to specify one.
  3213. no flags : need to supply a logon-id
  3214. APT_ObjectTypeList <ptr to obj type list> <obj-type-index>
  3215. Index to object type must be specified
  3216. Return Value:
  3217. TRUE on success
  3218. FALSE otherwise
  3219. call GetLastError() to retrieve the errorcode,
  3220. which will be one of the following:
  3221. ERROR_INVALID_PARAMETER if one of the params is incorrect
  3222. Notes:
  3223. --*/
  3224. {
  3225. DWORD dwError = NO_ERROR;
  3226. BOOL fResult = TRUE;
  3227. USHORT i;
  3228. AUDIT_PARAM_TYPE ParamType;
  3229. AUDIT_PARAM* pParam;
  3230. LUID Luid;
  3231. LUID AuthIdThread, AuthIdProcess;
  3232. BOOL fImpersonating=TRUE;
  3233. ULONG TypeFlags;
  3234. ULONG ParamFlags;
  3235. ULONG ObjectTypeIndex;
  3236. va_list(arglist);
  3237. *ppUserSid = NULL;
  3238. //
  3239. // the first two params are always fixed. thus the total number
  3240. // is 2 + the passed number.
  3241. //
  3242. if (( (NumParams+2) > SE_MAX_AUDIT_PARAMETERS ) ||
  3243. ( pParams == NULL ) ||
  3244. ( ppUserSid == NULL ) ||
  3245. ( SubsystemName == NULL ) ||
  3246. ( dwFlags & ~APF_ValidFlags )
  3247. )
  3248. {
  3249. dwError = ERROR_INVALID_PARAMETER;
  3250. goto Cleanup;
  3251. }
  3252. if (!AuthzpGetThreadTokenInfo( ppUserSid, &AuthIdThread ))
  3253. {
  3254. dwError = GetLastError();
  3255. if (dwError == ERROR_NO_TOKEN)
  3256. {
  3257. fImpersonating = FALSE;
  3258. dwError = NO_ERROR;
  3259. }
  3260. else
  3261. {
  3262. goto Cleanup;
  3263. }
  3264. }
  3265. if (!AuthzpGetProcessTokenInfo( fImpersonating ? NULL : ppUserSid,
  3266. &AuthIdProcess ))
  3267. {
  3268. dwError = GetLastError();
  3269. goto Cleanup;
  3270. }
  3271. va_start (arglist, NumParams);
  3272. pParams->Length = 0;
  3273. pParams->Flags = dwFlags;
  3274. pParams->Count = NumParams+2;
  3275. pParam = pParams->Parameters;
  3276. //
  3277. // the first param is always the sid of the user in thread token
  3278. // if thread is not impersonating, sid in the primary token is used.
  3279. //
  3280. pParam->Type = APT_Sid;
  3281. pParam->Data0 = (ULONG_PTR) *ppUserSid;
  3282. pParam++;
  3283. //
  3284. // the second param is always the sub-system name
  3285. //
  3286. pParam->Type = APT_String;
  3287. pParam->Data0 = (ULONG_PTR) SubsystemName;
  3288. pParam++;
  3289. //
  3290. // now initialize the rest using the var-arg portion
  3291. //
  3292. for ( i=0; i<NumParams; i++, pParam++ )
  3293. {
  3294. TypeFlags = va_arg(arglist, ULONG);
  3295. ParamType = ApExtractType(TypeFlags);
  3296. ParamFlags = ApExtractFlags(TypeFlags);
  3297. pParam->Type = ParamType;
  3298. switch( ParamType )
  3299. {
  3300. default:
  3301. dwError = ERROR_INVALID_PARAMETER;
  3302. break;
  3303. case APT_Pointer:
  3304. case APT_String:
  3305. case APT_Sid:
  3306. pParam->Data0 = (ULONG_PTR) va_arg(arglist, PVOID);
  3307. break;
  3308. case APT_Ulong:
  3309. pParam->Data0 = va_arg(arglist, ULONG);
  3310. //
  3311. // in case of an access-mask, store the object-type index
  3312. // This is because, the meaning of the access-mask bits
  3313. // cannot be determined without knowing the object type.
  3314. //
  3315. if (ParamFlags & AP_AccessMask)
  3316. {
  3317. ObjectTypeIndex = va_arg(arglist, ULONG);
  3318. //
  3319. // The object-type-index:
  3320. // - must have been specified earlier
  3321. // - must be specified as a string.
  3322. //
  3323. if ( ( ObjectTypeIndex >= i ) ||
  3324. ( pParams->Parameters[ObjectTypeIndex].Type !=
  3325. APT_String ) )
  3326. {
  3327. dwError = ERROR_INVALID_PARAMETER;
  3328. }
  3329. else
  3330. {
  3331. pParam->Data1 = ObjectTypeIndex;
  3332. }
  3333. }
  3334. pParam->Flags = ParamFlags;
  3335. break;
  3336. case APT_LogonId:
  3337. if (ParamFlags & AP_PrimaryLogonId)
  3338. {
  3339. //
  3340. // use the captured process token info
  3341. //
  3342. pParam->Data0 = AuthIdProcess.LowPart;
  3343. pParam->Data1 = AuthIdProcess.HighPart;
  3344. }
  3345. else if (ParamFlags & AP_ClientLogonId)
  3346. {
  3347. //
  3348. // use the captured thread token info
  3349. //
  3350. pParam->Data0 = AuthIdThread.LowPart;
  3351. pParam->Data1 = AuthIdThread.HighPart;
  3352. }
  3353. else
  3354. {
  3355. //
  3356. // no flag is specified, use the supplied logon-id
  3357. //
  3358. Luid = va_arg(arglist, LUID);
  3359. pParam->Data0 = Luid.LowPart;
  3360. pParam->Data1 = Luid.HighPart;
  3361. }
  3362. break;
  3363. case APT_ObjectTypeList:
  3364. pParam->Data0 = (ULONG_PTR) va_arg(arglist,
  3365. AUDIT_OBJECT_TYPES*);
  3366. pParam->Data1 = va_arg(arglist, ULONG);
  3367. break;
  3368. }
  3369. if (dwError != NO_ERROR)
  3370. {
  3371. break;
  3372. }
  3373. }
  3374. Cleanup:
  3375. if ( dwError != NO_ERROR )
  3376. {
  3377. SetLastError( dwError );
  3378. fResult = FALSE;
  3379. if ( *ppUserSid != NULL )
  3380. {
  3381. LocalFree( *ppUserSid );
  3382. *ppUserSid = NULL;
  3383. }
  3384. }
  3385. va_end (arglist);
  3386. return fResult;
  3387. }
  3388. BOOL
  3389. AuthziFreeAuditParams(
  3390. PAUDIT_PARAMS pParams
  3391. )
  3392. /*++
  3393. Routine Description
  3394. Frees the AUDIT_PARAMS created by AuthzAllocateInitializeAuditParamsWithRM.
  3395. Arguments
  3396. pParams - pointer to AUDIT_PARAMS.
  3397. Return Value
  3398. Boolean: TRUE on success, FALSE on failure.
  3399. --*/
  3400. {
  3401. if (!ARGUMENT_PRESENT(pParams))
  3402. {
  3403. SetLastError(ERROR_INVALID_PARAMETER);
  3404. return FALSE;
  3405. }
  3406. AuthzpFree(pParams);
  3407. return TRUE;
  3408. }
  3409. BOOL
  3410. AuthziInitializeAuditEvent(
  3411. IN DWORD Flags,
  3412. IN AUTHZ_RESOURCE_MANAGER_HANDLE hRM,
  3413. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAET OPTIONAL,
  3414. IN PAUDIT_PARAMS pAuditParams OPTIONAL,
  3415. IN AUTHZ_AUDIT_QUEUE_HANDLE hAuditQueue OPTIONAL,
  3416. IN DWORD dwTimeOut,
  3417. IN PWSTR szOperationType,
  3418. IN PWSTR szObjectType,
  3419. IN PWSTR szObjectName,
  3420. IN PWSTR szAdditionalInfo OPTIONAL,
  3421. OUT PAUTHZ_AUDIT_EVENT_HANDLE phAuditEvent
  3422. )
  3423. /*++
  3424. Routine Description:
  3425. Allocates and initializes an AUTHZ_AUDIT_EVENT_HANDLE. The handle is used for storing information
  3426. for audit generation per AuthzAccessCheck().
  3427. Arguments:
  3428. phAuditEvent - pointer to AUTHZ_AUDIT_EVENT_HANDLE. Space for this is allocated in the function.
  3429. Flags - Audit flags. Currently defined bits are:
  3430. AUTHZ_NO_SUCCESS_AUDIT - disables generation of success audits
  3431. AUTHZ_NO_FAILURE_AUDIT - disables generation of failure audits
  3432. AUTHZ_DS_CATEGORY_FLAG - swithces the default audit category from OBJECT_ACCESS to DS_ACCESS.
  3433. AUTHZ_NO_ALLOC_STRINGS - storage space is not allocated for the 4 wide character strings. Rather,
  3434. the handle will only hold pointers to resource manager memory.
  3435. hRM - handle to a Resource Manager.
  3436. hAET - pointer to an AUTHZ_AUDIT_EVENT_TYPE structure. This is needed if the resource manager
  3437. is creating its own audit types. This is not needed for generic object operation audits.
  3438. pAuditParams - If this is specified, then pAuditParams will be used to
  3439. create the audit. If NULL is passed, then a generic AUDIT_PARAMS will
  3440. be constructed that is suitable for the generic object access audit.
  3441. hAuditQueue - queue object created with AuthzInitializeAuditQueue. If none is specified, the
  3442. default RM queue will be used.
  3443. dwTimeOut - milliseconds that a thread attempting to generate an audit with this
  3444. AUTHZ_AUDIT_EVENT_HANDLE should wait for access to the queue. Use INFINITE to
  3445. specify an unlimited timeout.
  3446. szOperationType - Resource manager defined string that indicates the operation being
  3447. performed that is to be audited.
  3448. szObjectType - Resource manager defined string that indicates the type of object being
  3449. accessed.
  3450. szObjectName - the name of the specific object being accessed.
  3451. szAdditionalInfo - Resource Manager defined string for additional audit information.
  3452. Return Value:
  3453. Returns TRUE if successful, FALSE if unsuccessful.
  3454. Extended information available with GetLastError().
  3455. --*/
  3456. {
  3457. PAUTHZI_AUDIT_EVENT pAuditEvent = NULL;
  3458. BOOL b = TRUE;
  3459. BOOL bRef = FALSE;
  3460. DWORD dwStringSize = 0;
  3461. DWORD dwObjectTypeLength = 0;
  3462. DWORD dwObjectNameLength = 0;
  3463. DWORD dwOperationTypeLength = 0;
  3464. DWORD dwAdditionalInfoLength = 0;
  3465. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hRM;
  3466. if (!ARGUMENT_PRESENT(phAuditEvent) ||
  3467. (!ARGUMENT_PRESENT(hAET) && !ARGUMENT_PRESENT(hRM)) ||
  3468. !ARGUMENT_PRESENT(szOperationType) ||
  3469. !ARGUMENT_PRESENT(szObjectType) ||
  3470. !ARGUMENT_PRESENT(szObjectName) ||
  3471. !ARGUMENT_PRESENT(szAdditionalInfo))
  3472. {
  3473. SetLastError(ERROR_INVALID_PARAMETER);
  3474. return FALSE;
  3475. }
  3476. *phAuditEvent = NULL;
  3477. //
  3478. // Allocate and initialize a new AUTHZI_AUDIT_EVENT.
  3479. //
  3480. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  3481. {
  3482. dwStringSize = 0;
  3483. }
  3484. else
  3485. {
  3486. dwOperationTypeLength = (DWORD) wcslen(szOperationType) + 1;
  3487. dwObjectTypeLength = (DWORD) wcslen(szObjectType) + 1;
  3488. dwObjectNameLength = (DWORD) wcslen(szObjectName) + 1;
  3489. dwAdditionalInfoLength = (DWORD) wcslen(szAdditionalInfo) + 1;
  3490. dwStringSize = sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength + dwAdditionalInfoLength);
  3491. }
  3492. pAuditEvent = (PAUTHZI_AUDIT_EVENT) AuthzpAlloc(sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize);
  3493. if (AUTHZ_ALLOCATION_FAILED(pAuditEvent))
  3494. {
  3495. b = FALSE;
  3496. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3497. goto Cleanup;
  3498. }
  3499. RtlZeroMemory(
  3500. pAuditEvent,
  3501. sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize
  3502. );
  3503. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  3504. {
  3505. pAuditEvent->szOperationType = szOperationType;
  3506. pAuditEvent->szObjectType = szObjectType;
  3507. pAuditEvent->szObjectName = szObjectName;
  3508. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  3509. }
  3510. else
  3511. {
  3512. //
  3513. // Set the string pointers into the contiguous memory.
  3514. //
  3515. pAuditEvent->szOperationType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT));
  3516. pAuditEvent->szObjectType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3517. + (sizeof(WCHAR) * dwOperationTypeLength));
  3518. pAuditEvent->szObjectName = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3519. + (sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength)));
  3520. pAuditEvent->szAdditionalInfo = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3521. + (sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength)));
  3522. RtlCopyMemory(
  3523. pAuditEvent->szOperationType,
  3524. szOperationType,
  3525. sizeof(WCHAR) * dwOperationTypeLength
  3526. );
  3527. RtlCopyMemory(
  3528. pAuditEvent->szObjectType,
  3529. szObjectType,
  3530. sizeof(WCHAR) * dwObjectTypeLength
  3531. );
  3532. RtlCopyMemory(
  3533. pAuditEvent->szObjectName,
  3534. szObjectName,
  3535. sizeof(WCHAR) * dwObjectNameLength
  3536. );
  3537. RtlCopyMemory(
  3538. pAuditEvent->szAdditionalInfo,
  3539. szAdditionalInfo,
  3540. sizeof(WCHAR) * dwAdditionalInfoLength
  3541. );
  3542. }
  3543. //
  3544. // Use the passed audit event type if present, otherwise use the RM's generic Audit Event.
  3545. //
  3546. if (ARGUMENT_PRESENT(hAET))
  3547. {
  3548. pAuditEvent->hAET = hAET;
  3549. }
  3550. else
  3551. {
  3552. if (FLAG_ON(Flags, AUTHZ_DS_CATEGORY_FLAG))
  3553. {
  3554. pAuditEvent->hAET = pRM->hAETDS;
  3555. }
  3556. else
  3557. {
  3558. pAuditEvent->hAET = pRM->hAET;
  3559. }
  3560. }
  3561. AuthzpReferenceAuditEventType(pAuditEvent->hAET);
  3562. bRef = TRUE;
  3563. //
  3564. // Use the specified queue, if it exists. Else use the RM queue.
  3565. //
  3566. if (ARGUMENT_PRESENT(hAuditQueue))
  3567. {
  3568. pAuditEvent->hAuditQueue = hAuditQueue;
  3569. }
  3570. else if (ARGUMENT_PRESENT(hRM))
  3571. {
  3572. pAuditEvent->hAuditQueue = pRM->hAuditQueue;
  3573. }
  3574. pAuditEvent->pAuditParams = pAuditParams;
  3575. pAuditEvent->Flags = Flags;
  3576. pAuditEvent->dwTimeOut = dwTimeOut;
  3577. pAuditEvent->dwSize = sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize;
  3578. Cleanup:
  3579. if (!b)
  3580. {
  3581. if (bRef)
  3582. {
  3583. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  3584. }
  3585. AuthzpFreeNonNull(pAuditEvent);
  3586. }
  3587. else
  3588. {
  3589. *phAuditEvent = (AUTHZ_AUDIT_EVENT_HANDLE) pAuditEvent;
  3590. }
  3591. return b;
  3592. }
  3593. BOOL
  3594. AuthziModifyAuditEvent(
  3595. IN DWORD Flags,
  3596. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  3597. IN DWORD NewFlags,
  3598. IN PWSTR szOperationType,
  3599. IN PWSTR szObjectType,
  3600. IN PWSTR szObjectName,
  3601. IN PWSTR szAdditionalInfo
  3602. )
  3603. /*++
  3604. Routine Description
  3605. Arguments
  3606. Flags - flags to specify which field of the hAuditEvent to modify. Valid flags are:
  3607. AUTHZ_AUDIT_EVENT_FLAGS
  3608. AUTHZ_AUDIT_EVENT_OPERATION_TYPE
  3609. AUTHZ_AUDIT_EVENT_OBJECT_TYPE
  3610. AUTHZ_AUDIT_EVENT_OBJECT_NAME
  3611. AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO
  3612. hAuditEvent - handle to modify. Must be created with AUTHZ_NO_ALLOC_STRINGS flag.
  3613. NewFlags - replacement flags for hAuditEvent.
  3614. szOperationType - replacement string for hAuditEvent.
  3615. szObjectType - replacement string for hAuditEvent.
  3616. szObjectName - replacement string for hAuditEvent.
  3617. szAdditionalInfo - replacement string for hAuditEvent.
  3618. Return Value
  3619. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  3620. --*/
  3621. {
  3622. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  3623. if ((!ARGUMENT_PRESENT(hAuditEvent)) ||
  3624. (Flags & ~AUTHZ_VALID_MODIFY_AUDIT_EVENT_FLAGS) ||
  3625. (!FLAG_ON(pAuditEvent->Flags, AUTHZ_NO_ALLOC_STRINGS)))
  3626. {
  3627. SetLastError(ERROR_INVALID_PARAMETER);
  3628. return FALSE;
  3629. }
  3630. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_FLAGS))
  3631. {
  3632. pAuditEvent->Flags = NewFlags;
  3633. }
  3634. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OPERATION_TYPE))
  3635. {
  3636. pAuditEvent->szOperationType = szOperationType;
  3637. }
  3638. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OBJECT_TYPE))
  3639. {
  3640. pAuditEvent->szObjectType = szObjectType;
  3641. }
  3642. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OBJECT_NAME))
  3643. {
  3644. pAuditEvent->szOperationType = szObjectName;
  3645. }
  3646. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO))
  3647. {
  3648. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  3649. }
  3650. return TRUE;
  3651. }