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

6936 lines
183 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. #include <sddl.h>
  20. #include <overflow.h>
  21. GUID AuthzpNullGuid = { 0 };
  22. DWORD
  23. DeleteKeyRecursivelyW(
  24. IN HKEY hkey,
  25. IN LPCWSTR pwszSubKey
  26. );
  27. BOOL
  28. AuthzAccessCheck(
  29. IN DWORD Flags,
  30. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  31. IN PAUTHZ_ACCESS_REQUEST pRequest,
  32. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent OPTIONAL,
  33. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  34. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  35. IN DWORD OptionalSecurityDescriptorCount,
  36. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  37. OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults OPTIONAL
  38. )
  39. /*++
  40. Routine Description:
  41. This API decides what access bits may be granted to a client for a given set
  42. of security security descriptors. The pReply structure is used to return an
  43. array of granted access masks and error statuses. There is an option to
  44. cache the access masks that will always be granted. A handle to cached
  45. values is returned if the caller asks for caching.
  46. Arguments:
  47. Flags - AUTHZ_ACCESS_CHECK_NO_DEEP_COPY_SD - do not deep copy the SD information into the caching
  48. handle. Default behaviour is to perform a deep copy.
  49. hAuthzClientContext - Authz context representing the client.
  50. pRequest - Access request specifies the desired access mask, principal self
  51. sid, the object type list strucutre (if any).
  52. hAuditEvent - Object specific audit event will be passed in this handle.
  53. Non-null parameter is an automatic request for audit.
  54. pSecurityDescriptor - Primary security descriptor to be used for access
  55. checks. The owner sid for the object is picked from this one. A NULL
  56. DACL in this security descriptor represents a NULL DACL for the entire
  57. object. A NULL SACL in this security descriptor is treated the same way
  58. as an EMPTY SACL.
  59. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  60. of security descriptors. NULL ACLs in these security descriptors are
  61. treated as EMPTY ACLS and the ACL for the entire object is the logical
  62. concatenation of all the ACLs.
  63. OptionalSecurityDescriptorCount - Number of optional security descriptors
  64. This does not include the Primay security descriptor.
  65. pReply - Supplies a pointer to a reply structure used to return the results
  66. of access check as an array of (GrantedAccessMask, ErrorValue) pairs.
  67. The number of results to be returned in supplied by the caller in
  68. pResult->ResultListLength.
  69. Expected error values are:
  70. ERROR_SUCCESS - If all the access bits (not including MAXIMUM_ALLOWED)
  71. are granted and GrantedAccessMask is not zero.
  72. ERROR_PRIVILEGE_NOT_HELD - if the DesiredAccess includes
  73. ACCESS_SYSTEM_SECURITY and the client does not have SeSecurityPrivilege.
  74. ERROR_ACCESS_DENIED in each of the following cases -
  75. 1. any of the bits asked for is not granted.
  76. 2. MaximumAllowed bit it on and granted access is zero.
  77. 3. DesiredAccess is 0.
  78. phAccessCheckResults - Supplies a pointer to return a handle to the cached results
  79. of access check. Non-null phAccessCheckResults is an implicit request to cache
  80. results of this access check call and will result in a MAXIMUM_ALLOWED
  81. check.
  82. Return Value:
  83. A value of TRUE is returned if the API is successful. Otherwise,
  84. a value of FALSE is returned. In the failure case, error value may be
  85. retrieved using GetLastError().
  86. --*/
  87. {
  88. BOOL b = TRUE;
  89. DWORD LocalTypeListLength = 0;
  90. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  91. PIOBJECT_TYPE_LIST LocalCachingTypeList = NULL;
  92. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  93. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  94. IOBJECT_TYPE_LIST FixedTypeList = {0};
  95. IOBJECT_TYPE_LIST FixedCachingTypeList = {0};
  96. UNREFERENCED_PARAMETER(Flags);
  97. #ifdef AUTHZ_PARAM_CHECK
  98. //
  99. // Verify that the arguments passed are valid.
  100. // Also, initialize the output parameters to default.
  101. //
  102. b = AuthzpVerifyAccessCheckArguments(
  103. pCC,
  104. pRequest,
  105. pSecurityDescriptor,
  106. OptionalSecurityDescriptorArray,
  107. OptionalSecurityDescriptorCount,
  108. pReply,
  109. phAccessCheckResults
  110. );
  111. if (!b)
  112. {
  113. return FALSE;
  114. }
  115. #endif
  116. //
  117. // No client should be able to open an object by asking for zero access.
  118. // If desired access is 0 then return an error.
  119. //
  120. // Note: No audit is generated in this case.
  121. //
  122. if (0 == pRequest->DesiredAccess)
  123. {
  124. AuthzpFillReplyStructure(
  125. pReply,
  126. ERROR_ACCESS_DENIED,
  127. 0
  128. );
  129. return TRUE;
  130. }
  131. //
  132. // Generic bits should be mapped to specific ones by the resource manager.
  133. //
  134. if (FLAG_ON(pRequest->DesiredAccess, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)))
  135. {
  136. SetLastError(ERROR_GENERIC_NOT_MAPPED);
  137. return FALSE;
  138. }
  139. //
  140. // In the simple case, there is no object type list. Fake one of length = 1
  141. // to represent the entire object.
  142. //
  143. if (0 == pRequest->ObjectTypeListLength)
  144. {
  145. LocalTypeList = &FixedTypeList;
  146. FixedTypeList.ParentIndex = -1;
  147. LocalTypeListLength = 1;
  148. //
  149. // If the caller has asked for caching, fake an object type list that'd
  150. // be used for computing static "always granted" access.
  151. //
  152. if (ARGUMENT_PRESENT(phAccessCheckResults))
  153. {
  154. RtlCopyMemory(
  155. &FixedCachingTypeList,
  156. &FixedTypeList,
  157. sizeof(IOBJECT_TYPE_LIST)
  158. );
  159. LocalCachingTypeList = &FixedCachingTypeList;
  160. }
  161. }
  162. else
  163. {
  164. DWORD Size = sizeof(IOBJECT_TYPE_LIST) * pRequest->ObjectTypeListLength;
  165. //
  166. // Allocate size for capturing object type list into local structure.
  167. //
  168. if (ARGUMENT_PRESENT(phAccessCheckResults))
  169. {
  170. //
  171. // We need twice the size in case of caching.
  172. //
  173. SafeAllocaAllocate(LocalTypeList, (2 * Size));
  174. if (AUTHZ_ALLOCATION_FAILED(LocalTypeList))
  175. {
  176. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  177. return FALSE;
  178. }
  179. LocalCachingTypeList = (PIOBJECT_TYPE_LIST) (((PUCHAR) LocalTypeList) + Size);
  180. }
  181. else
  182. {
  183. SafeAllocaAllocate(LocalTypeList, Size);
  184. if (AUTHZ_ALLOCATION_FAILED(LocalTypeList))
  185. {
  186. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  187. return FALSE;
  188. }
  189. }
  190. //
  191. // Capture the object type list into an internal structure.
  192. //
  193. b = AuthzpCaptureObjectTypeList(
  194. pRequest->ObjectTypeList,
  195. pRequest->ObjectTypeListLength,
  196. LocalTypeList,
  197. LocalCachingTypeList
  198. );
  199. if (!b)
  200. {
  201. goto Cleanup;
  202. }
  203. LocalTypeListLength = pRequest->ObjectTypeListLength;
  204. }
  205. //
  206. // There are three cases when we have to perform a MaximumAllowed access
  207. // check and traverse the whole acl:
  208. // 1. RM has requested for caching.
  209. // 2. DesiredAccessMask has MAXIMUM_ALLOWED turned on.
  210. // 3. ObjectTypeList is present and pReply->ResultList has a length > 1
  211. //
  212. if (ARGUMENT_PRESENT(phAccessCheckResults) ||
  213. FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED) ||
  214. (pReply->ResultListLength > 1))
  215. {
  216. b = AuthzpAccessCheckWithCaching(
  217. Flags,
  218. pCC,
  219. pRequest,
  220. pSecurityDescriptor,
  221. OptionalSecurityDescriptorArray,
  222. OptionalSecurityDescriptorCount,
  223. pReply,
  224. phAccessCheckResults,
  225. LocalTypeList,
  226. LocalCachingTypeList,
  227. LocalTypeListLength
  228. );
  229. }
  230. else
  231. {
  232. //
  233. // Perform a normal access check in the default case. Acl traversal may
  234. // be abandoned if any of the desired access bits are denied before they
  235. // are granted.
  236. //
  237. b = AuthzpNormalAccessCheckWithoutCaching(
  238. pCC,
  239. pRequest,
  240. pSecurityDescriptor,
  241. OptionalSecurityDescriptorArray,
  242. OptionalSecurityDescriptorCount,
  243. pReply,
  244. LocalTypeList,
  245. LocalTypeListLength
  246. );
  247. }
  248. if (!b)
  249. {
  250. goto Cleanup;
  251. }
  252. //
  253. // Check if an audit needs to be generated if the RM has requested audit
  254. // generation by passing a non-null AuditEvent structure.
  255. //
  256. if (ARGUMENT_PRESENT(pAuditEvent))
  257. {
  258. b = AuthzpGenerateAudit(
  259. pCC,
  260. pRequest,
  261. pAuditEvent,
  262. pSecurityDescriptor,
  263. OptionalSecurityDescriptorArray,
  264. OptionalSecurityDescriptorCount,
  265. pReply,
  266. LocalTypeList
  267. );
  268. if (!b)
  269. {
  270. goto Cleanup;
  271. }
  272. }
  273. Cleanup:
  274. //
  275. // Clean up allocated memory.
  276. //
  277. if ((&FixedTypeList != LocalTypeList) && (AUTHZ_NON_NULL_PTR(LocalTypeList)))
  278. {
  279. SafeAllocaFree(LocalTypeList);
  280. }
  281. return b;
  282. }
  283. BOOL
  284. AuthzCachedAccessCheck(
  285. IN DWORD Flags,
  286. IN AUTHZ_ACCESS_CHECK_RESULTS_HANDLE hAccessCheckResults,
  287. IN PAUTHZ_ACCESS_REQUEST pRequest,
  288. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent OPTIONAL,
  289. IN OUT PAUTHZ_ACCESS_REPLY pReply
  290. )
  291. /*++
  292. Routine Description:
  293. This API performs a fast access check based on a cached handle which holds
  294. the static granted bits evaluated at the time of a previously made
  295. AuthzAccessCheck call. The pReply structure is used to return an array of
  296. granted access masks and error statuses.
  297. Assumptions:
  298. The client context pointer is stored in the hAccessCheckResults. The structure of
  299. the client context must be exactly the same as it was at the time the
  300. hAccessCheckResults was created. This restriction is for the following fields:
  301. Sids, RestrictedSids, Privileges.
  302. Pointers to the primary security descriptor and the optional security
  303. descriptor array are stored in the hAccessCheckResults at the time of handle
  304. creation. These must still be valid.
  305. Arguments:
  306. Flags - TBD.
  307. hAccessCheckResults - Handle to the cached access check results.
  308. pRequest - Access request specifies the desired access mask, principal self
  309. sid, the object type list strucutre (if any).
  310. AuditEvent - Object specific audit info will be passed in this structure.
  311. Non-null parameter is an automatic request for audit.
  312. pReply - Supplies a pointer to a reply structure used to return the results
  313. of access check as an array of (GrantedAccessMask, ErrorValue) pairs.
  314. The number of results to be returned in supplied by the caller in
  315. pResult->ResultListLength.
  316. Expected error values are:
  317. ERROR_SUCCESS - If all the access bits (not including MAXIMUM_ALLOWED)
  318. are granted and GrantedAccessMask is not zero.
  319. ERROR_PRIVILEGE_NOT_HELD - if the DesiredAccess includes
  320. ACCESS_SYSTEM_SECURITY and the client does not have SeSecurityPrivilege.
  321. ERROR_ACCESS_DENIED in each of the following cases -
  322. 1. any of the bits asked for is not granted.
  323. 2. MaximumAllowed bit it on and granted access is zero.
  324. 3. DesiredAccess is 0.
  325. Return Value:
  326. A value of TRUE is returned if the API is successful. Otherwise,
  327. a value of FALSE is returned. In the failure case, error value may be
  328. retrieved using GetLastError().
  329. --*/
  330. {
  331. DWORD i = 0;
  332. DWORD LocalTypeListLength = 0;
  333. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  334. PACL pAcl = NULL;
  335. PAUTHZI_HANDLE pAH = (PAUTHZI_HANDLE) hAccessCheckResults;
  336. BOOL b = TRUE;
  337. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  338. IOBJECT_TYPE_LIST FixedTypeList = {0};
  339. UNREFERENCED_PARAMETER(Flags);
  340. #ifdef AUTHZ_PARAM_CHECK
  341. b = AuthzpVerifyCachedAccessCheckArguments(
  342. pAH,
  343. pRequest,
  344. pReply
  345. );
  346. if (!b)
  347. {
  348. return FALSE;
  349. }
  350. #endif
  351. //
  352. // No client should be able to open an object by asking for zero access.
  353. // If desired access is 0 then return an error.
  354. //
  355. // Note: No audit is generated in this case.
  356. //
  357. if (0 == pRequest->DesiredAccess)
  358. {
  359. AuthzpFillReplyStructure(
  360. pReply,
  361. ERROR_ACCESS_DENIED,
  362. 0
  363. );
  364. return TRUE;
  365. }
  366. //
  367. // Generic bits should be mapped to specific ones by the resource manager.
  368. //
  369. if (FLAG_ON(pRequest->DesiredAccess, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)))
  370. {
  371. SetLastError(ERROR_GENERIC_NOT_MAPPED);
  372. return FALSE;
  373. }
  374. //
  375. // Capture the object type list if one has been passed in or fake one with
  376. // just one element.
  377. //
  378. if (0 == pRequest->ObjectTypeListLength)
  379. {
  380. LocalTypeList = &FixedTypeList;
  381. LocalTypeListLength = 1;
  382. FixedTypeList.ParentIndex = -1;
  383. }
  384. else
  385. {
  386. DWORD Size = sizeof(IOBJECT_TYPE_LIST) * pRequest->ObjectTypeListLength;
  387. SafeAllocaAllocate(LocalTypeList, Size);
  388. if (AUTHZ_ALLOCATION_FAILED(LocalTypeList))
  389. {
  390. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  391. return FALSE;
  392. }
  393. b = AuthzpCaptureObjectTypeList(
  394. pRequest->ObjectTypeList,
  395. pRequest->ObjectTypeListLength,
  396. LocalTypeList,
  397. NULL
  398. );
  399. if (!b)
  400. {
  401. goto Cleanup;
  402. }
  403. LocalTypeListLength = pRequest->ObjectTypeListLength;
  404. }
  405. //
  406. // If all the bits have already been granted then just copy the results and
  407. // skip access check.
  408. //
  409. if (!FLAG_ON(pRequest->DesiredAccess, ~pAH->GrantedAccessMask[i]))
  410. {
  411. AuthzpFillReplyStructure(
  412. pReply,
  413. ERROR_SUCCESS,
  414. pRequest->DesiredAccess
  415. );
  416. goto GenerateAudit;
  417. }
  418. //
  419. // The assumption is privileges can not be changed. Thus, if the client did
  420. // not have SecurityPrivilege previously then he does not have it now.
  421. //
  422. if (FLAG_ON(pRequest->DesiredAccess, ACCESS_SYSTEM_SECURITY))
  423. {
  424. AuthzpFillReplyStructure(
  425. pReply,
  426. ERROR_PRIVILEGE_NOT_HELD,
  427. 0
  428. );
  429. goto GenerateAudit;
  430. }
  431. //
  432. // If all aces are simple aces then there's nothing to do. All access bits
  433. // are static.
  434. //
  435. if ((!FLAG_ON(pAH->Flags, AUTHZ_DYNAMIC_EVALUATION_PRESENT)) &&
  436. (!FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED)))
  437. {
  438. AuthzpFillReplyStructureFromCachedGrantedAccessMask(
  439. pReply,
  440. pRequest->DesiredAccess,
  441. pAH->GrantedAccessMask
  442. );
  443. goto GenerateAudit;
  444. }
  445. //
  446. // Get the access bits from the last static access check.
  447. //
  448. for (i = 0; i < LocalTypeListLength; i++)
  449. {
  450. LocalTypeList[i].CurrentGranted = pAH->GrantedAccessMask[i];
  451. LocalTypeList[i].Remaining = pRequest->DesiredAccess & ~pAH->GrantedAccessMask[i];
  452. }
  453. //
  454. // NULL Dacl is synonymous with Full Control.
  455. //
  456. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pAH->pSecurityDescriptor);
  457. if (!AUTHZ_NON_NULL_PTR(pAcl))
  458. {
  459. for (i = 0; i < LocalTypeListLength; i++)
  460. {
  461. LocalTypeList[i].CurrentGranted |= (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL);
  462. }
  463. }
  464. else
  465. {
  466. //
  467. // If there are no deny aces, then perform a quick access check evaluating
  468. // only the allow aces that are dynamic or have principal self sid in them.
  469. //
  470. if (!FLAG_ON(pAH->Flags, (AUTHZ_DENY_ACE_PRESENT | AUTHZ_DYNAMIC_DENY_ACE_PRESENT)))
  471. {
  472. if (FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED) ||
  473. (pReply->ResultListLength > 1))
  474. {
  475. b = AuthzpQuickMaximumAllowedAccessCheck(
  476. pAH->pAuthzClientContext,
  477. pAH,
  478. pRequest,
  479. pReply,
  480. LocalTypeList,
  481. LocalTypeListLength
  482. );
  483. }
  484. else
  485. {
  486. b = AuthzpQuickNormalAccessCheck(
  487. pAH->pAuthzClientContext,
  488. pAH,
  489. pRequest,
  490. pReply,
  491. LocalTypeList,
  492. LocalTypeListLength
  493. );
  494. }
  495. }
  496. else if ((0 != pRequest->ObjectTypeListLength) || (FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED)))
  497. {
  498. //
  499. // Now we have to evaluate the entire acl since there are deny aces
  500. // and the caller has asked for a result list.
  501. //
  502. b = AuthzpAccessCheckWithCaching(
  503. Flags,
  504. pAH->pAuthzClientContext,
  505. pRequest,
  506. pAH->pSecurityDescriptor,
  507. pAH->OptionalSecurityDescriptorArray,
  508. pAH->OptionalSecurityDescriptorCount,
  509. pReply,
  510. NULL,
  511. LocalTypeList,
  512. NULL,
  513. LocalTypeListLength
  514. );
  515. }
  516. else
  517. {
  518. //
  519. // There are deny aces in the acl but the caller has not asked for
  520. // entire resultlist. Preform a normal access check.
  521. //
  522. b = AuthzpNormalAccessCheckWithoutCaching(
  523. pAH->pAuthzClientContext,
  524. pRequest,
  525. pAH->pSecurityDescriptor,
  526. pAH->OptionalSecurityDescriptorArray,
  527. pAH->OptionalSecurityDescriptorCount,
  528. pReply,
  529. LocalTypeList,
  530. LocalTypeListLength
  531. );
  532. }
  533. if (!b)
  534. {
  535. goto Cleanup;
  536. }
  537. }
  538. AuthzpFillReplyFromParameters(
  539. pRequest,
  540. pReply,
  541. LocalTypeList
  542. );
  543. GenerateAudit:
  544. if (ARGUMENT_PRESENT(pAuditEvent))
  545. {
  546. b = AuthzpGenerateAudit(
  547. pAH->pAuthzClientContext,
  548. pRequest,
  549. pAuditEvent,
  550. pAH->pSecurityDescriptor,
  551. pAH->OptionalSecurityDescriptorArray,
  552. pAH->OptionalSecurityDescriptorCount,
  553. pReply,
  554. LocalTypeList
  555. );
  556. if (!b) goto Cleanup;
  557. }
  558. Cleanup:
  559. if ((&FixedTypeList != LocalTypeList) && (AUTHZ_NON_NULL_PTR(LocalTypeList)))
  560. {
  561. SafeAllocaFree(LocalTypeList);
  562. }
  563. return b;
  564. }
  565. BOOL
  566. AuthzOpenObjectAudit(
  567. IN DWORD Flags,
  568. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  569. IN PAUTHZ_ACCESS_REQUEST pRequest,
  570. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  571. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  572. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  573. IN DWORD OptionalSecurityDescriptorCount,
  574. IN PAUTHZ_ACCESS_REPLY pReply
  575. )
  576. /*++
  577. Routine Description
  578. This API examines the SACL in the passed security descriptor(s) and generates
  579. any appropriate audits.
  580. Arguments
  581. Flags - TBD.
  582. hAuthzClientContext - Client context to perform the SACL evaluation against.
  583. pRequest - pointer to request structure.
  584. hAuditEvent - Handle to the audit that may be generated.
  585. pSecurityDescriptor - Pointer to a security descriptor.
  586. OptionalSecurityDescriptorArray - Optional array of security descriptors.
  587. OptionalSecurityDescriptorCount - Size of optional security descriptor array.
  588. pReply - Pointer to the reply structure.
  589. Return Value
  590. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  591. --*/
  592. {
  593. BOOL b = TRUE;
  594. DWORD LocalTypeListLength = 0;
  595. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  596. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  597. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  598. IOBJECT_TYPE_LIST FixedTypeList = {0};
  599. UNREFERENCED_PARAMETER(Flags);
  600. //
  601. // Verify that the arguments passed are valid.
  602. //
  603. b = AuthzpVerifyOpenObjectArguments(
  604. pCC,
  605. pSecurityDescriptor,
  606. OptionalSecurityDescriptorArray,
  607. OptionalSecurityDescriptorCount,
  608. pAuditEvent
  609. );
  610. if (!b)
  611. {
  612. return FALSE;
  613. }
  614. //
  615. // In the simple case, there is no object type list. Fake one of length = 1
  616. // to represent the entire object.
  617. //
  618. if (0 == pRequest->ObjectTypeListLength)
  619. {
  620. LocalTypeList = &FixedTypeList;
  621. FixedTypeList.ParentIndex = -1;
  622. LocalTypeListLength = 1;
  623. }
  624. else
  625. {
  626. DWORD Size = sizeof(IOBJECT_TYPE_LIST) * pRequest->ObjectTypeListLength;
  627. SafeAllocaAllocate(LocalTypeList, Size);
  628. if (AUTHZ_ALLOCATION_FAILED(LocalTypeList))
  629. {
  630. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  631. return FALSE;
  632. }
  633. //
  634. // Capture the object type list into an internal structure.
  635. //
  636. b = AuthzpCaptureObjectTypeList(
  637. pRequest->ObjectTypeList,
  638. pRequest->ObjectTypeListLength,
  639. LocalTypeList,
  640. NULL
  641. );
  642. if (!b)
  643. {
  644. goto Cleanup;
  645. }
  646. LocalTypeListLength = pRequest->ObjectTypeListLength;
  647. }
  648. b = AuthzpGenerateAudit(
  649. pCC,
  650. pRequest,
  651. pAuditEvent,
  652. pSecurityDescriptor,
  653. OptionalSecurityDescriptorArray,
  654. OptionalSecurityDescriptorCount,
  655. pReply,
  656. LocalTypeList
  657. );
  658. if (!b)
  659. {
  660. goto Cleanup;
  661. }
  662. Cleanup:
  663. //
  664. // Clean up allocated memory.
  665. //
  666. if (&FixedTypeList != LocalTypeList)
  667. {
  668. SafeAllocaFree(LocalTypeList);
  669. }
  670. return b;
  671. }
  672. BOOL
  673. AuthzFreeHandle(
  674. IN OUT AUTHZ_ACCESS_CHECK_RESULTS_HANDLE hAccessCheckResults
  675. )
  676. /*++
  677. Routine Description:
  678. This API finds and deletes the input handle from the handle list.
  679. Arguments:
  680. hAcc - Handle to be freed.
  681. Return Value:
  682. A value of TRUE is returned if the API is successful. Otherwise,
  683. a value of FALSE is returned. In the failure case, error value may be
  684. retrieved using GetLastError().
  685. --*/
  686. {
  687. PAUTHZI_HANDLE pAH = (PAUTHZI_HANDLE) hAccessCheckResults;
  688. PAUTHZI_HANDLE pCurrent = NULL;
  689. PAUTHZI_HANDLE pPrev = NULL;
  690. BOOL b = TRUE;
  691. //
  692. // Validate parameters.
  693. //
  694. if (!ARGUMENT_PRESENT(pAH) ||
  695. !AUTHZ_NON_NULL_PTR(pAH->pAuthzClientContext) ||
  696. !AUTHZ_NON_NULL_PTR(pAH->pAuthzClientContext->AuthzHandleHead))
  697. {
  698. SetLastError(ERROR_INVALID_PARAMETER);
  699. return FALSE;
  700. }
  701. AuthzpAcquireClientCacheWriteLock(pAH->pAuthzClientContext);
  702. pCurrent = pAH->pAuthzClientContext->AuthzHandleHead;
  703. //
  704. // Check if the handle is at the beginning of the list.
  705. //
  706. if (pCurrent == pAH)
  707. {
  708. pAH->pAuthzClientContext->AuthzHandleHead = pAH->pAuthzClientContext->AuthzHandleHead->next;
  709. }
  710. else
  711. {
  712. //
  713. // The handle is not the head of the list. Loop thru the list to find
  714. // it.
  715. //
  716. pPrev = pCurrent;
  717. pCurrent = pCurrent->next;
  718. for (; AUTHZ_NON_NULL_PTR(pCurrent); pPrev = pCurrent, pCurrent = pCurrent->next)
  719. {
  720. if (pCurrent == pAH)
  721. {
  722. pPrev->next = pCurrent->next;
  723. break;
  724. }
  725. }
  726. //
  727. // The caller has sent us an invalid handle.
  728. //
  729. if (!AUTHZ_NON_NULL_PTR(pCurrent))
  730. {
  731. b = FALSE;
  732. SetLastError(ERROR_INVALID_PARAMETER);
  733. }
  734. }
  735. AuthzpReleaseClientCacheLock(pCC);
  736. //
  737. // Free the handle node.
  738. //
  739. if (b)
  740. {
  741. AuthzpFree(pAH);
  742. }
  743. return b;
  744. }
  745. BOOL
  746. AuthzInitializeResourceManager(
  747. IN DWORD Flags,
  748. IN PFN_AUTHZ_DYNAMIC_ACCESS_CHECK pfnDynamicAccessCheck OPTIONAL,
  749. IN PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS pfnComputeDynamicGroups OPTIONAL,
  750. IN PFN_AUTHZ_FREE_DYNAMIC_GROUPS pfnFreeDynamicGroups OPTIONAL,
  751. IN PCWSTR szResourceManagerName,
  752. OUT PAUTHZ_RESOURCE_MANAGER_HANDLE phAuthzResourceManager
  753. )
  754. /*++
  755. Routine Description:
  756. This API allocates and initializes a resource manager structure.
  757. Arguments:
  758. Flags - AUTHZ_RM_FLAG_NO_AUDIT - use if the RM will never generate an audit to
  759. save some cycles.
  760. - AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION - if the current thread is
  761. impersonating then use the impersonation token as the identity of the
  762. resource manager.
  763. pfnAccessCheck - Pointer to the RM supplied access check function to be
  764. called when a callback ace is encountered by the access check algorithm.
  765. pfnComputeDynamicGroups - Pointer to the RM supplied function to compute
  766. groups to be added to the client context at the time of its creation.
  767. pfnFreeDynamicGroups - Pointer to the function to free the memory allocated
  768. by the pfnComputeDynamicGroups function.
  769. szResourceManagerName - the name of the resource manager.
  770. pAuthzResourceManager - To return the resource manager handle. The returned
  771. handle must be freed using AuthzFreeResourceManager.
  772. Return Value:
  773. A value of TRUE is returned if the API is successful. Otherwise,
  774. a value of FALSE is returned. In the failure case, error value may be
  775. retrieved using GetLastError().
  776. --*/
  777. {
  778. PAUTHZI_RESOURCE_MANAGER pRM = NULL;
  779. BOOL b = TRUE;
  780. ULONG len = 0;
  781. if (!ARGUMENT_PRESENT(phAuthzResourceManager) ||
  782. (Flags & ~AUTHZ_VALID_RM_INIT_FLAGS))
  783. {
  784. SetLastError(ERROR_INVALID_PARAMETER);
  785. return FALSE;
  786. }
  787. *phAuthzResourceManager = NULL;
  788. if (AUTHZ_NON_NULL_PTR(szResourceManagerName))
  789. {
  790. len = (ULONG) wcslen(szResourceManagerName) + 1;
  791. }
  792. pRM = (PAUTHZI_RESOURCE_MANAGER)
  793. AuthzpAlloc(sizeof(AUTHZI_RESOURCE_MANAGER) + sizeof(WCHAR) * len);
  794. if (AUTHZ_ALLOCATION_FAILED(pRM))
  795. {
  796. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  797. return FALSE;
  798. }
  799. //
  800. // Use the default pessimistic function if none has been specified.
  801. //
  802. if (AUTHZ_NON_NULL_PTR(pfnDynamicAccessCheck))
  803. {
  804. pRM->pfnDynamicAccessCheck = pfnDynamicAccessCheck;
  805. }
  806. else
  807. {
  808. pRM->pfnDynamicAccessCheck = &AuthzpDefaultAccessCheck;
  809. }
  810. if (!FLAG_ON(Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  811. {
  812. //
  813. // Initialize the generic audit queue and generic audit events.
  814. //
  815. b = AuthziInitializeAuditQueue(
  816. AUTHZ_MONITOR_AUDIT_QUEUE_SIZE,
  817. 1000,
  818. 100,
  819. NULL,
  820. &pRM->hAuditQueue
  821. );
  822. if (!b)
  823. {
  824. goto Cleanup;
  825. }
  826. //
  827. // Initialize the generic audit event.
  828. //
  829. b = AuthziInitializeAuditEventType(
  830. AUTHZP_DEFAULT_RM_EVENTS | AUTHZP_INIT_GENERIC_AUDIT_EVENT,
  831. 0,
  832. 0,
  833. 0,
  834. &pRM->hAET
  835. );
  836. if (!b)
  837. {
  838. goto Cleanup;
  839. }
  840. b = AuthziInitializeAuditEventType(
  841. AUTHZP_DEFAULT_RM_EVENTS,
  842. SE_CATEGID_DS_ACCESS,
  843. SE_AUDITID_OBJECT_OPERATION,
  844. AUTHZP_NUM_PARAMS_FOR_SE_AUDITID_OBJECT_OPERATION,
  845. &pRM->hAETDS
  846. );
  847. if (!b)
  848. {
  849. goto Cleanup;
  850. }
  851. }
  852. pRM->pfnComputeDynamicGroups = pfnComputeDynamicGroups;
  853. pRM->pfnFreeDynamicGroups = pfnFreeDynamicGroups;
  854. pRM->Flags = Flags;
  855. pRM->pUserSID = NULL;
  856. pRM->szResourceManagerName = (PWSTR)((PUCHAR)pRM + sizeof(AUTHZI_RESOURCE_MANAGER));
  857. if (FLAG_ON(Flags, AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION))
  858. {
  859. b = AuthzpGetThreadTokenInfo(
  860. &pRM->pUserSID,
  861. &pRM->AuthID
  862. );
  863. if (!b)
  864. {
  865. goto Cleanup;
  866. }
  867. }
  868. else
  869. {
  870. b = AuthzpGetProcessTokenInfo(
  871. &pRM->pUserSID,
  872. &pRM->AuthID
  873. );
  874. if (!b)
  875. {
  876. goto Cleanup;
  877. }
  878. }
  879. if (0 != len)
  880. {
  881. RtlCopyMemory(
  882. pRM->szResourceManagerName,
  883. szResourceManagerName,
  884. sizeof(WCHAR) * len
  885. );
  886. }
  887. else
  888. {
  889. pRM->szResourceManagerName = NULL;
  890. }
  891. *phAuthzResourceManager = (AUTHZ_RESOURCE_MANAGER_HANDLE) pRM;
  892. Cleanup:
  893. if (!b)
  894. {
  895. //
  896. // Copy LastError value, since the calls to AuthziFreeAuditEventType can succeed and
  897. // overwrite it with 0x103 (STATUS_PENDING).
  898. //
  899. DWORD dwError = GetLastError();
  900. if (NULL != pRM)
  901. {
  902. if (!FLAG_ON(Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  903. {
  904. AuthziFreeAuditQueue(pRM->hAuditQueue);
  905. AuthziFreeAuditEventType(pRM->hAET);
  906. AuthziFreeAuditEventType(pRM->hAETDS);
  907. }
  908. AuthzpFreeNonNull(pRM->pUserSID);
  909. AuthzpFree(pRM);
  910. }
  911. SetLastError(dwError);
  912. }
  913. return b;
  914. }
  915. BOOL
  916. AuthzFreeResourceManager(
  917. IN OUT AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager
  918. )
  919. /*++
  920. Routine Description:
  921. This API frees up a resource manager. If the default queue is in use, this call will wait for that
  922. queue to empty.
  923. Arguments:
  924. hAuthzResourceManager - Handle to the resource manager object to be freed.
  925. Return Value:
  926. A value of TRUE is returned if the API is successful. Otherwise,
  927. a value of FALSE is returned. In the failure case, error value may be
  928. retrieved using GetLastError().
  929. --*/
  930. {
  931. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  932. if (!ARGUMENT_PRESENT(pRM))
  933. {
  934. SetLastError(ERROR_INVALID_PARAMETER);
  935. return FALSE;
  936. }
  937. if (!FLAG_ON(pRM->Flags, AUTHZ_RM_FLAG_NO_AUDIT))
  938. {
  939. (VOID) AuthziFreeAuditQueue(pRM->hAuditQueue);
  940. (VOID) AuthziFreeAuditEventType(pRM->hAET);
  941. (VOID) AuthziFreeAuditEventType(pRM->hAETDS);
  942. }
  943. AuthzpFreeNonNull(pRM->pUserSID);
  944. AuthzpFree(pRM);
  945. return TRUE;
  946. }
  947. BOOL
  948. AuthzInitializeContextFromToken(
  949. IN DWORD Flags,
  950. IN HANDLE TokenHandle,
  951. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  952. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  953. IN LUID Identifier,
  954. IN PVOID DynamicGroupArgs,
  955. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext
  956. )
  957. /*++
  958. Routine Description:
  959. Initialize the authz context from the handle to the kernel token. The token
  960. must have been opened for TOKEN_QUERY.
  961. Arguments:
  962. Flags - None
  963. TokenHandle - Handle to the client token from which the authz context will
  964. be initialized. The token must have been opened with TOKEN_QUERY access.
  965. AuthzResourceManager - The resource manager handle creating this client
  966. context. This will be stored in the client context structure.
  967. pExpirationTime - To set for how long the returned context structure is
  968. valid. If no value is passed then the token never expires.
  969. Expiration time is not currently enforced in the system.
  970. Identifier - Resource manager manager specific identifier. This is never
  971. interpreted by Authz.
  972. DynamicGroupArgs - To be passed to the callback function that computes
  973. dynamic groups
  974. pAuthzClientContext - To return a handle to the AuthzClientContext
  975. Return Value:
  976. A value of TRUE is returned if the API is successful. Otherwise,
  977. a value of FALSE is returned. In the failure case, error value may be
  978. retrieved using GetLastError().
  979. --*/
  980. {
  981. UCHAR Buffer[AUTHZ_MAX_STACK_BUFFER_SIZE];
  982. NTSTATUS Status = STATUS_SUCCESS;
  983. PUCHAR pBuffer = (PVOID) Buffer;
  984. BOOL b = TRUE;
  985. BOOL bAllocatedSids = FALSE;
  986. BOOL bLockHeld = FALSE;
  987. PTOKEN_GROUPS_AND_PRIVILEGES pTokenInfo = NULL;
  988. PAUTHZI_RESOURCE_MANAGER pRM = NULL;
  989. PAUTHZI_CLIENT_CONTEXT pCC = NULL;
  990. DWORD Length = 0;
  991. LARGE_INTEGER ExpirationTime = {0, 0};
  992. UNREFERENCED_PARAMETER(Flags);
  993. if (!ARGUMENT_PRESENT(TokenHandle) ||
  994. !ARGUMENT_PRESENT(hAuthzResourceManager) ||
  995. !ARGUMENT_PRESENT(phAuthzClientContext))
  996. {
  997. SetLastError(ERROR_INVALID_PARAMETER);
  998. return FALSE;
  999. }
  1000. *phAuthzClientContext = NULL;
  1001. //
  1002. // Query the token information into user mode buffer. A local stack buffer
  1003. // is used in the first call hoping that it would be sufficient to hold
  1004. // the return values.
  1005. //
  1006. Status = NtQueryInformationToken(
  1007. TokenHandle,
  1008. TokenGroupsAndPrivileges,
  1009. pBuffer,
  1010. AUTHZ_MAX_STACK_BUFFER_SIZE,
  1011. &Length
  1012. );
  1013. if (STATUS_BUFFER_TOO_SMALL == Status)
  1014. {
  1015. pBuffer = (PVOID) AuthzpAlloc(Length);
  1016. if (AUTHZ_ALLOCATION_FAILED(pBuffer))
  1017. {
  1018. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1019. return FALSE;
  1020. }
  1021. Status = NtQueryInformationToken(
  1022. TokenHandle,
  1023. TokenGroupsAndPrivileges,
  1024. pBuffer,
  1025. Length,
  1026. &Length
  1027. );
  1028. }
  1029. if (!NT_SUCCESS(Status))
  1030. {
  1031. #ifdef AUTHZ_DEBUG
  1032. wprintf(L"\nNtQueryInformationToken failed with %d\n", Status);
  1033. #endif
  1034. SetLastError(RtlNtStatusToDosError(Status));
  1035. b = FALSE;
  1036. goto Cleanup;
  1037. }
  1038. pTokenInfo = (PTOKEN_GROUPS_AND_PRIVILEGES) pBuffer;
  1039. pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  1040. if (ARGUMENT_PRESENT(pExpirationTime))
  1041. {
  1042. ExpirationTime = *pExpirationTime;
  1043. }
  1044. //
  1045. // Initialize the client context. The callee allocates memory for the client
  1046. // context structure.
  1047. //
  1048. b = AuthzpAllocateAndInitializeClientContext(
  1049. &pCC,
  1050. NULL,
  1051. AUTHZ_CURRENT_CONTEXT_REVISION,
  1052. Identifier,
  1053. ExpirationTime,
  1054. 0,
  1055. pTokenInfo->SidCount,
  1056. pTokenInfo->SidLength,
  1057. pTokenInfo->Sids,
  1058. pTokenInfo->RestrictedSidCount,
  1059. pTokenInfo->RestrictedSidLength,
  1060. pTokenInfo->RestrictedSids,
  1061. pTokenInfo->PrivilegeCount,
  1062. pTokenInfo->PrivilegeLength,
  1063. pTokenInfo->Privileges,
  1064. pTokenInfo->AuthenticationId,
  1065. NULL,
  1066. pRM
  1067. );
  1068. if (!b)
  1069. {
  1070. goto Cleanup;
  1071. }
  1072. AuthzpAcquireClientContextReadLock(pCC);
  1073. bLockHeld = TRUE;
  1074. //
  1075. // Add dynamic sids to the token.
  1076. //
  1077. b = AuthzpAddDynamicSidsToToken(
  1078. pCC,
  1079. pRM,
  1080. DynamicGroupArgs,
  1081. pTokenInfo->Sids,
  1082. pTokenInfo->SidLength,
  1083. pTokenInfo->SidCount,
  1084. pTokenInfo->RestrictedSids,
  1085. pTokenInfo->RestrictedSidLength,
  1086. pTokenInfo->RestrictedSidCount,
  1087. pTokenInfo->Privileges,
  1088. pTokenInfo->PrivilegeLength,
  1089. pTokenInfo->PrivilegeCount,
  1090. FALSE
  1091. );
  1092. if (!b)
  1093. {
  1094. goto Cleanup;
  1095. }
  1096. bAllocatedSids = TRUE;
  1097. *phAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC;
  1098. AuthzPrintContext(pCC);
  1099. //
  1100. // initialize the sid hash for regular sids
  1101. //
  1102. AuthzpInitSidHash(
  1103. pCC->Sids,
  1104. pCC->SidCount,
  1105. pCC->SidHash
  1106. );
  1107. //
  1108. // initialize the sid hash for restricted sids
  1109. //
  1110. AuthzpInitSidHash(
  1111. pCC->RestrictedSids,
  1112. pCC->RestrictedSidCount,
  1113. pCC->RestrictedSidHash
  1114. );
  1115. Cleanup:
  1116. if ((PVOID) Buffer != pBuffer)
  1117. {
  1118. AuthzpFreeNonNull(pBuffer);
  1119. }
  1120. if (!b)
  1121. {
  1122. DWORD dwSavedError = GetLastError();
  1123. if (AUTHZ_NON_NULL_PTR(pCC))
  1124. {
  1125. if (bAllocatedSids)
  1126. {
  1127. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pCC);
  1128. SetLastError(dwSavedError);
  1129. }
  1130. else
  1131. {
  1132. AuthzpFree(pCC);
  1133. }
  1134. }
  1135. }
  1136. if (bLockHeld)
  1137. {
  1138. AuthzpReleaseClientContextLock(pCC);
  1139. }
  1140. return b;
  1141. }
  1142. BOOL
  1143. AuthzpInitializeContextFromSid(
  1144. IN DWORD Flags,
  1145. IN PSID UserSid,
  1146. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  1147. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1148. IN LUID Identifier,
  1149. IN PVOID DynamicGroupArgs,
  1150. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext,
  1151. IN BOOL bIsInternalRoutine
  1152. )
  1153. /*++
  1154. Routine Description:
  1155. This API takes a user sid and creates a user mode client context from it.
  1156. It fetches the TokenGroups attributes from the AD in case of domain sids.
  1157. The machine local groups are computed on the ServerName specified. The
  1158. resource manager may dynamic groups using callback mechanism.
  1159. Arguments:
  1160. Flags -
  1161. AUTHZ_SKIP_TOKEN_GROUPS - Do not token groups if this is on.
  1162. UserSid - The sid of the user for whom a client context will be created.
  1163. ServerName - The machine on which local groups should be computed. A NULL
  1164. server name defaults to the local machine.
  1165. AuthzResourceManager - The resource manager handle creating this client
  1166. context. This will be stored in the client context structure.
  1167. pExpirationTime - To set for how long the returned context structure is
  1168. valid. If no value is passed then the token never expires.
  1169. Expiration time is not currently enforced in the system.
  1170. Identifier - Resource manager manager specific identifier. This is never
  1171. interpreted by Authz.
  1172. DynamicGroupArgs - To be passed to the callback function that computes
  1173. dynamic groups
  1174. pAuthzClientContext - To return a handle to the AuthzClientContext
  1175. structure. The returned handle must be freed using AuthzFreeContext.
  1176. bIsInternalRoutine - When this is on, Group context is built recursively.
  1177. Return Value:
  1178. A value of TRUE is returned if the API is successful. Otherwise,
  1179. a value of FALSE is returned. In the failure case, error value may be
  1180. retrieved using GetLastError().
  1181. --*/
  1182. {
  1183. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  1184. PAUTHZI_CLIENT_CONTEXT pCC = NULL;
  1185. BOOL b = FALSE;
  1186. DWORD SidCount = 0;
  1187. DWORD SidLength = 0;
  1188. LARGE_INTEGER ExpirationTime = {0, 0};
  1189. LUID NullLuid = {0, 0};
  1190. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hAuthzResourceManager;
  1191. if (!ARGUMENT_PRESENT(UserSid) ||
  1192. !ARGUMENT_PRESENT(hAuthzResourceManager) ||
  1193. !ARGUMENT_PRESENT(phAuthzClientContext))
  1194. {
  1195. SetLastError(ERROR_INVALID_PARAMETER);
  1196. return FALSE;
  1197. }
  1198. *phAuthzClientContext = NULL;
  1199. if ((0 == (Flags & AUTHZ_SKIP_TOKEN_GROUPS)) && (FALSE == bIsInternalRoutine))
  1200. {
  1201. DWORD LocalFlags = 0;
  1202. //
  1203. // If the caller did not supply AUTHZ_SKIP_TOKEN_GROUPS, check whether
  1204. // we should add it ourselves. This should be done for WellKnown and
  1205. // Builtins.
  1206. //
  1207. b = AuthzpComputeSkipFlagsForWellKnownSid(UserSid, &LocalFlags);
  1208. if (!b)
  1209. {
  1210. return FALSE;
  1211. }
  1212. Flags |= LocalFlags;
  1213. }
  1214. //
  1215. // Compute the token groups and the machine local groups. These will be
  1216. // returned in memory allocated by the callee.
  1217. //
  1218. b = AuthzpGetAllGroupsBySid(
  1219. UserSid,
  1220. Flags,
  1221. &pSidAttr,
  1222. &SidCount,
  1223. &SidLength
  1224. );
  1225. if (!b)
  1226. {
  1227. goto Cleanup;
  1228. }
  1229. if (ARGUMENT_PRESENT(pExpirationTime))
  1230. {
  1231. ExpirationTime = *pExpirationTime;
  1232. }
  1233. //
  1234. // Initialize the client context. The callee allocates memory for the client
  1235. // context structure.
  1236. //
  1237. b = AuthzpAllocateAndInitializeClientContext(
  1238. &pCC,
  1239. NULL,
  1240. AUTHZ_CURRENT_CONTEXT_REVISION,
  1241. Identifier,
  1242. ExpirationTime,
  1243. 0,
  1244. SidCount,
  1245. SidLength,
  1246. pSidAttr,
  1247. 0,
  1248. 0,
  1249. NULL,
  1250. 0,
  1251. 0,
  1252. NULL,
  1253. NullLuid,
  1254. NULL,
  1255. pRM
  1256. );
  1257. if (!b) goto Cleanup;
  1258. //
  1259. // Add dynamic sids to the token.
  1260. //
  1261. b = AuthzpAddDynamicSidsToToken(
  1262. pCC,
  1263. pRM,
  1264. DynamicGroupArgs,
  1265. pSidAttr,
  1266. SidLength,
  1267. SidCount,
  1268. NULL,
  1269. 0,
  1270. 0,
  1271. NULL,
  1272. 0,
  1273. 0,
  1274. TRUE
  1275. );
  1276. if (!b) goto Cleanup;
  1277. *phAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC;
  1278. AuthzPrintContext(pCC);
  1279. //
  1280. // initialize the sid hash for regular sids
  1281. //
  1282. AuthzpInitSidHash(
  1283. pCC->Sids,
  1284. pCC->SidCount,
  1285. pCC->SidHash
  1286. );
  1287. //
  1288. // initialize the sid hash for restricted sids
  1289. //
  1290. AuthzpInitSidHash(
  1291. pCC->RestrictedSids,
  1292. pCC->RestrictedSidCount,
  1293. pCC->RestrictedSidHash
  1294. );
  1295. Cleanup:
  1296. if (!b)
  1297. {
  1298. AuthzpFreeNonNull(pSidAttr);
  1299. if (AUTHZ_NON_NULL_PTR(pCC))
  1300. {
  1301. if (pSidAttr != pCC->Sids)
  1302. {
  1303. AuthzpFreeNonNull(pCC->Sids);
  1304. }
  1305. AuthzpFreeNonNull(pCC->RestrictedSids);
  1306. AuthzpFree(pCC);
  1307. }
  1308. }
  1309. else
  1310. {
  1311. if (pSidAttr != pCC->Sids)
  1312. {
  1313. AuthzpFree(pSidAttr);
  1314. }
  1315. }
  1316. return b;
  1317. }
  1318. BOOL
  1319. AuthzInitializeContextFromSid(
  1320. IN DWORD Flags,
  1321. IN PSID UserSid,
  1322. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  1323. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1324. IN LUID Identifier,
  1325. IN PVOID DynamicGroupArgs,
  1326. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. This API takes a user sid and creates a user mode client context from it.
  1331. It fetches the TokenGroups attributes from the AD in case of domain sids.
  1332. The machine local groups are computed on the ServerName specified. The
  1333. resource manager may dynamic groups using callback mechanism.
  1334. Arguments:
  1335. Flags -
  1336. AUTHZ_SKIP_TOKEN_GROUPS - Do not evaluate token groups if this is on.
  1337. UserSid - The sid of the user for whom a client context will be created.
  1338. ServerName - The machine on which local groups should be computed. A NULL
  1339. server name defaults to the local machine.
  1340. AuthzResourceManager - The resource manager handle creating this client
  1341. context. This will be stored in the client context structure.
  1342. pExpirationTime - To set for how long the returned context structure is
  1343. valid. If no value is passed then the token never expires.
  1344. Expiration time is not currently enforced in the system.
  1345. Identifier - Resource manager manager specific identifier. This is never
  1346. interpreted by Authz.
  1347. DynamicGroupArgs - To be passed to the callback function that computes
  1348. dynamic groups
  1349. pAuthzClientContext - To return a handle to the AuthzClientContext
  1350. structure. The returned handle must be freed using AuthzFreeContext.
  1351. Return Value:
  1352. A value of TRUE is returned if the API is successful. Otherwise,
  1353. a value of FALSE is returned. In the failure case, error value may be
  1354. retrieved using GetLastError().
  1355. --*/
  1356. {
  1357. return AuthzpInitializeContextFromSid(
  1358. Flags,
  1359. UserSid,
  1360. hAuthzResourceManager,
  1361. pExpirationTime,
  1362. Identifier,
  1363. DynamicGroupArgs,
  1364. phAuthzClientContext,
  1365. FALSE // This is not the internal routine.
  1366. );
  1367. }
  1368. BOOL
  1369. AuthziInitializeContextFromSid(
  1370. IN DWORD Flags,
  1371. IN PSID UserSid,
  1372. IN AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager,
  1373. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1374. IN LUID Identifier,
  1375. IN PVOID DynamicGroupArgs,
  1376. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phAuthzClientContext
  1377. )
  1378. /*++
  1379. Routine Description:
  1380. This API takes a user sid and creates a user mode client context from it.
  1381. It fetches the TokenGroups attributes from the AD in case of domain sids.
  1382. The machine local groups are computed on the ServerName specified. The
  1383. resource manager may dynamic groups using callback mechanism.
  1384. Arguments:
  1385. Flags -
  1386. AUTHZ_SKIP_TOKEN_GROUPS - Do not evaluate token groups if this is on.
  1387. UserSid - The sid of the user for whom a client context will be created.
  1388. ServerName - The machine on which local groups should be computed. A NULL
  1389. server name defaults to the local machine.
  1390. AuthzResourceManager - The resource manager handle creating this client
  1391. context. This will be stored in the client context structure.
  1392. pExpirationTime - To set for how long the returned context structure is
  1393. valid. If no value is passed then the token never expires.
  1394. Expiration time is not currently enforced in the system.
  1395. Identifier - Resource manager manager specific identifier. This is never
  1396. interpreted by Authz.
  1397. DynamicGroupArgs - To be passed to the callback function that computes
  1398. dynamic groups
  1399. pAuthzClientContext - To return a handle to the AuthzClientContext
  1400. structure. The returned handle must be freed using AuthzFreeContext.
  1401. Return Value:
  1402. A value of TRUE is returned if the API is successful. Otherwise,
  1403. a value of FALSE is returned. In the failure case, error value may be
  1404. retrieved using GetLastError().
  1405. --*/
  1406. {
  1407. return AuthzpInitializeContextFromSid(
  1408. Flags,
  1409. UserSid,
  1410. hAuthzResourceManager,
  1411. pExpirationTime,
  1412. Identifier,
  1413. DynamicGroupArgs,
  1414. phAuthzClientContext,
  1415. TRUE // This is the internal routine.
  1416. );
  1417. }
  1418. BOOL
  1419. AuthzInitializeContextFromAuthzContext(
  1420. IN DWORD Flags,
  1421. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1422. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1423. IN LUID Identifier,
  1424. IN PVOID DynamicGroupArgs,
  1425. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phNewAuthzClientContext
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. This API creates an AUTHZ_CLIENT_CONTEXT based on another AUTHZ_CLIENT_CONTEXT.
  1430. Arguments:
  1431. Flags - TBD
  1432. hAuthzClientContext - Client context to duplicate
  1433. pExpirationTime - To set for how long the returned context structure is
  1434. valid. If no value is passed then the token never expires.
  1435. Expiration time is not currently enforced in the system.
  1436. Identifier - Resource manager manager specific identifier.
  1437. DynamicGroupArgs - To be passed to the callback function that computes
  1438. dynamic groups. If NULL then callback not called.
  1439. phNewAuthzClientContext - Duplicate of context. Must be freed using AuthzFreeContext.
  1440. Return Value:
  1441. A value of TRUE is returned if the API is successful. Otherwise,
  1442. a value of FALSE is returned. In the failure case, error value may be
  1443. retrieved using GetLastError().
  1444. --*/
  1445. {
  1446. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1447. PAUTHZI_CLIENT_CONTEXT pNewCC = NULL;
  1448. PAUTHZI_CLIENT_CONTEXT pServer = NULL;
  1449. BOOL b = FALSE;
  1450. BOOL bAllocatedSids = FALSE;
  1451. LARGE_INTEGER ExpirationTime = {0, 0};
  1452. if (!ARGUMENT_PRESENT(phNewAuthzClientContext) ||
  1453. !ARGUMENT_PRESENT(hAuthzClientContext))
  1454. {
  1455. SetLastError(ERROR_INVALID_PARAMETER);
  1456. return FALSE;
  1457. }
  1458. *phNewAuthzClientContext = NULL;
  1459. //
  1460. // Determine the ExpirationTime of the new context.
  1461. //
  1462. if (ARGUMENT_PRESENT(pExpirationTime))
  1463. {
  1464. ExpirationTime = *pExpirationTime;
  1465. }
  1466. AuthzpAcquireClientContextReadLock(pCC);
  1467. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  1468. {
  1469. b = AuthzInitializeContextFromAuthzContext(
  1470. 0,
  1471. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server,
  1472. NULL,
  1473. pCC->Server->Identifier,
  1474. NULL,
  1475. (PAUTHZ_CLIENT_CONTEXT_HANDLE) &pServer
  1476. );
  1477. if (!b)
  1478. {
  1479. goto Cleanup;
  1480. }
  1481. }
  1482. //
  1483. // Now initialize the new context.
  1484. //
  1485. b = AuthzpAllocateAndInitializeClientContext(
  1486. &pNewCC,
  1487. pServer,
  1488. pCC->Revision,
  1489. Identifier,
  1490. ExpirationTime,
  1491. Flags,
  1492. pCC->SidCount,
  1493. pCC->SidLength,
  1494. pCC->Sids,
  1495. pCC->RestrictedSidCount,
  1496. pCC->RestrictedSidLength,
  1497. pCC->RestrictedSids,
  1498. pCC->PrivilegeCount,
  1499. pCC->PrivilegeLength,
  1500. pCC->Privileges,
  1501. pCC->AuthenticationId,
  1502. NULL,
  1503. pCC->pResourceManager
  1504. );
  1505. if (!b)
  1506. {
  1507. goto Cleanup;
  1508. }
  1509. b = AuthzpAddDynamicSidsToToken(
  1510. pNewCC,
  1511. pNewCC->pResourceManager,
  1512. DynamicGroupArgs,
  1513. pNewCC->Sids,
  1514. pNewCC->SidLength,
  1515. pNewCC->SidCount,
  1516. pNewCC->RestrictedSids,
  1517. pNewCC->RestrictedSidLength,
  1518. pNewCC->RestrictedSidCount,
  1519. pNewCC->Privileges,
  1520. pNewCC->PrivilegeLength,
  1521. pNewCC->PrivilegeCount,
  1522. FALSE
  1523. );
  1524. if (!b)
  1525. {
  1526. goto Cleanup;
  1527. }
  1528. bAllocatedSids = TRUE;
  1529. *phNewAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pNewCC;
  1530. #ifdef AUTHZ_DEBUG
  1531. wprintf(L"ContextFromAuthzContext: Original Context:\n");
  1532. AuthzPrintContext(pCC);
  1533. wprintf(L"ContextFromAuthzContext: New Context:\n");
  1534. AuthzPrintContext(pNewCC);
  1535. #endif
  1536. //
  1537. // initialize the sid hash for regular sids
  1538. //
  1539. AuthzpInitSidHash(
  1540. pNewCC->Sids,
  1541. pNewCC->SidCount,
  1542. pNewCC->SidHash
  1543. );
  1544. //
  1545. // initialize the sid hash for restricted sids
  1546. //
  1547. AuthzpInitSidHash(
  1548. pNewCC->RestrictedSids,
  1549. pNewCC->RestrictedSidCount,
  1550. pNewCC->RestrictedSidHash
  1551. );
  1552. Cleanup:
  1553. if (!b)
  1554. {
  1555. DWORD dwSavedError = GetLastError();
  1556. if (AUTHZ_NON_NULL_PTR(pNewCC))
  1557. {
  1558. if (bAllocatedSids)
  1559. {
  1560. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pNewCC);
  1561. }
  1562. else
  1563. {
  1564. AuthzpFree(pNewCC);
  1565. }
  1566. }
  1567. else
  1568. {
  1569. if (AUTHZ_NON_NULL_PTR(pServer))
  1570. {
  1571. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pServer);
  1572. }
  1573. }
  1574. SetLastError(dwSavedError);
  1575. }
  1576. AuthzpReleaseClientContextLock(pCC);
  1577. return b;
  1578. }
  1579. BOOL
  1580. AuthzAddSidsToContext(
  1581. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1582. IN PSID_AND_ATTRIBUTES Sids OPTIONAL,
  1583. IN DWORD SidCount,
  1584. IN PSID_AND_ATTRIBUTES RestrictedSids OPTIONAL,
  1585. IN DWORD RestrictedSidCount,
  1586. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE phNewAuthzClientContext
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. This API creates a new context given a set of sids as well as restricted sids
  1591. and an already existing context. The original is unchanged.
  1592. Arguments:
  1593. hAuthzClientContext - Client context to which the given sids will be added
  1594. Sids - Sids and attributes to be added to the normal part of the client
  1595. context
  1596. SidCount - Number of sids to be added
  1597. RestrictedSids - Sids and attributes to be added to the restricted part of
  1598. the client context
  1599. RestrictedSidCount - Number of restricted sids to be added
  1600. phNewAuthzClientContext - The new context with the additional sids.
  1601. Return Value:
  1602. A value of TRUE is returned if the API is successful. Otherwise,
  1603. a value of FALSE is returned. In the failure case, error value may be
  1604. retrieved using GetLastError().
  1605. --*/
  1606. {
  1607. DWORD i = 0;
  1608. DWORD SidLength = 0;
  1609. DWORD RestrictedSidLength = 0;
  1610. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  1611. PSID_AND_ATTRIBUTES pRestrictedSidAttr = NULL;
  1612. BOOL b = TRUE;
  1613. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1614. PAUTHZI_CLIENT_CONTEXT pNewCC = NULL;
  1615. PAUTHZI_CLIENT_CONTEXT pServer = NULL;
  1616. PLUID_AND_ATTRIBUTES pPrivileges = NULL;
  1617. if ((!ARGUMENT_PRESENT(phNewAuthzClientContext)) ||
  1618. (!ARGUMENT_PRESENT(hAuthzClientContext)) ||
  1619. (0 != SidCount && !ARGUMENT_PRESENT(Sids)) ||
  1620. (0 != RestrictedSidCount && !ARGUMENT_PRESENT(RestrictedSids)))
  1621. {
  1622. SetLastError(ERROR_INVALID_PARAMETER);
  1623. return FALSE;
  1624. }
  1625. *phNewAuthzClientContext = NULL;
  1626. AuthzpAcquireClientContextReadLock(pCC);
  1627. //
  1628. // Recursively duplicate the server
  1629. //
  1630. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  1631. {
  1632. b = AuthzInitializeContextFromAuthzContext(
  1633. 0,
  1634. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server,
  1635. NULL,
  1636. pCC->Server->Identifier,
  1637. NULL,
  1638. (PAUTHZ_CLIENT_CONTEXT_HANDLE) &pServer
  1639. );
  1640. if (!b)
  1641. {
  1642. goto Cleanup;
  1643. }
  1644. }
  1645. //
  1646. // Duplicate the context, and do all further work on the duplicate.
  1647. //
  1648. b = AuthzpAllocateAndInitializeClientContext(
  1649. &pNewCC,
  1650. pServer,
  1651. pCC->Revision,
  1652. pCC->Identifier,
  1653. pCC->ExpirationTime,
  1654. pCC->Flags,
  1655. 0,
  1656. 0,
  1657. NULL,
  1658. 0,
  1659. 0,
  1660. NULL,
  1661. 0,
  1662. 0,
  1663. NULL,
  1664. pCC->AuthenticationId,
  1665. NULL,
  1666. pCC->pResourceManager
  1667. );
  1668. if (!b)
  1669. {
  1670. goto Cleanup;
  1671. }
  1672. SidLength = sizeof(SID_AND_ATTRIBUTES) * SidCount;
  1673. //
  1674. // Compute the length required to hold the new sids.
  1675. //
  1676. for (i = 0; i < SidCount; i++)
  1677. {
  1678. #ifdef AUTHZ_PARAM_CHECK
  1679. if (FLAG_ON(Sids[i].Attributes, ~AUTHZ_VALID_SID_ATTRIBUTES) ||
  1680. !FLAG_ON(Sids[i].Attributes, AUTHZ_VALID_SID_ATTRIBUTES))
  1681. {
  1682. SetLastError(ERROR_INVALID_PARAMETER);
  1683. b = FALSE;
  1684. goto Cleanup;
  1685. }
  1686. if (!RtlValidSid(Sids[i].Sid))
  1687. {
  1688. SetLastError(ERROR_INVALID_PARAMETER);
  1689. b = FALSE;
  1690. goto Cleanup;
  1691. }
  1692. #endif
  1693. SidLength += RtlLengthSid(Sids[i].Sid);
  1694. }
  1695. RestrictedSidLength = sizeof(SID_AND_ATTRIBUTES) * RestrictedSidCount;
  1696. //
  1697. // Compute the length required to hold the new restricted sids.
  1698. //
  1699. for (i = 0; i < RestrictedSidCount; i++)
  1700. {
  1701. #ifdef AUTHZ_PARAM_CHECK
  1702. if (FLAG_ON(RestrictedSids[i].Attributes, ~AUTHZ_VALID_SID_ATTRIBUTES) ||
  1703. !FLAG_ON(RestrictedSids[i].Attributes, AUTHZ_VALID_SID_ATTRIBUTES))
  1704. {
  1705. SetLastError(ERROR_INVALID_PARAMETER);
  1706. b = FALSE;
  1707. goto Cleanup;
  1708. }
  1709. if (!RtlValidSid(RestrictedSids[i].Sid))
  1710. {
  1711. SetLastError(ERROR_INVALID_PARAMETER);
  1712. b = FALSE;
  1713. goto Cleanup;
  1714. }
  1715. #endif
  1716. RestrictedSidLength += RtlLengthSid(RestrictedSids[i].Sid);
  1717. }
  1718. //
  1719. // Copy the existing sids and the new ones into the allocated memory.
  1720. //
  1721. SidLength += pCC->SidLength;
  1722. if (0 != SidLength)
  1723. {
  1724. pSidAttr = (PSID_AND_ATTRIBUTES) AuthzpAlloc(SidLength);
  1725. if (AUTHZ_ALLOCATION_FAILED(pSidAttr))
  1726. {
  1727. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1728. b = FALSE;
  1729. goto Cleanup;
  1730. }
  1731. b = AuthzpCopySidsAndAttributes(
  1732. pSidAttr,
  1733. pCC->Sids,
  1734. pCC->SidCount,
  1735. Sids,
  1736. SidCount
  1737. );
  1738. if (!b)
  1739. {
  1740. goto Cleanup;
  1741. }
  1742. }
  1743. //
  1744. // Copy the existing restricted sids and the new ones into the allocated
  1745. // memory.
  1746. //
  1747. RestrictedSidLength += pCC->RestrictedSidLength;
  1748. if (0 != RestrictedSidLength)
  1749. {
  1750. pRestrictedSidAttr = (PSID_AND_ATTRIBUTES) AuthzpAlloc(RestrictedSidLength);
  1751. if (AUTHZ_ALLOCATION_FAILED(pRestrictedSidAttr))
  1752. {
  1753. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1754. b = FALSE;
  1755. goto Cleanup;
  1756. }
  1757. b = AuthzpCopySidsAndAttributes(
  1758. pRestrictedSidAttr,
  1759. pCC->RestrictedSids,
  1760. pCC->RestrictedSidCount,
  1761. RestrictedSids,
  1762. RestrictedSidCount
  1763. );
  1764. if (!b)
  1765. {
  1766. goto Cleanup;
  1767. }
  1768. }
  1769. //
  1770. // Copy the existing privileges into the allocated memory.
  1771. //
  1772. pPrivileges = (PLUID_AND_ATTRIBUTES) AuthzpAlloc(pCC->PrivilegeLength);
  1773. if (AUTHZ_ALLOCATION_FAILED(pPrivileges))
  1774. {
  1775. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1776. b = FALSE;
  1777. goto Cleanup;
  1778. }
  1779. AuthzpCopyLuidAndAttributes(
  1780. pNewCC,
  1781. pCC->Privileges,
  1782. pCC->PrivilegeCount,
  1783. pPrivileges
  1784. );
  1785. //
  1786. // Update fields in the client context.
  1787. //
  1788. pNewCC->Sids = pSidAttr;
  1789. pNewCC->SidLength = SidLength;
  1790. pNewCC->SidCount = SidCount + pCC->SidCount;
  1791. pSidAttr = NULL;
  1792. pNewCC->RestrictedSids = pRestrictedSidAttr;
  1793. pNewCC->RestrictedSidLength = RestrictedSidLength;
  1794. pNewCC->RestrictedSidCount = RestrictedSidCount + pCC->RestrictedSidCount;
  1795. pRestrictedSidAttr = NULL;
  1796. pNewCC->Privileges = pPrivileges;
  1797. pNewCC->PrivilegeCount = pCC->PrivilegeCount;
  1798. pNewCC->PrivilegeLength = pCC->PrivilegeLength;
  1799. pPrivileges = NULL;
  1800. *phNewAuthzClientContext = (AUTHZ_CLIENT_CONTEXT_HANDLE) pNewCC;
  1801. #ifdef AUTHZ_DEBUG
  1802. wprintf(L"AddSids: Original Context:\n");
  1803. AuthzPrintContext(pCC);
  1804. wprintf(L"AddSids: New Context:\n");
  1805. AuthzPrintContext(pNewCC);
  1806. #endif
  1807. //
  1808. // initialize the sid hash for regular sids
  1809. //
  1810. AuthzpInitSidHash(
  1811. pNewCC->Sids,
  1812. pNewCC->SidCount,
  1813. pNewCC->SidHash
  1814. );
  1815. //
  1816. // initialize the sid hash for restricted sids
  1817. //
  1818. AuthzpInitSidHash(
  1819. pNewCC->RestrictedSids,
  1820. pNewCC->RestrictedSidCount,
  1821. pNewCC->RestrictedSidHash
  1822. );
  1823. Cleanup:
  1824. AuthzpReleaseClientContextLock(pCC);
  1825. //
  1826. // These statements are relevant in the failure case.
  1827. // In the success case, the pointers are set to NULL.
  1828. //
  1829. if (!b)
  1830. {
  1831. DWORD dwSavedError = GetLastError();
  1832. AuthzpFreeNonNull(pSidAttr);
  1833. AuthzpFreeNonNull(pRestrictedSidAttr);
  1834. AuthzpFreeNonNull(pPrivileges);
  1835. if (AUTHZ_NON_NULL_PTR(pNewCC))
  1836. {
  1837. AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE)pNewCC);
  1838. }
  1839. SetLastError(dwSavedError);
  1840. }
  1841. return b;
  1842. }
  1843. BOOL
  1844. AuthzGetInformationFromContext(
  1845. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  1846. IN AUTHZ_CONTEXT_INFORMATION_CLASS InfoClass,
  1847. IN DWORD BufferSize,
  1848. OUT PDWORD pSizeRequired,
  1849. OUT PVOID Buffer
  1850. )
  1851. /*++
  1852. Routine Description:
  1853. This API returns information about the client context in a buffer supplied
  1854. by the caller. It also returns the size of the buffer required to hold the
  1855. requested information.
  1856. Arguments:
  1857. AuthzClientContext - Authz client context from which requested information
  1858. will be read.
  1859. InfoClass - Type of information to be returned. The caller can ask for
  1860. a. privileges
  1861. TOKEN_PRIVILEGES
  1862. b. sids and their attributes
  1863. TOKEN_GROUPS
  1864. c. restricted sids and their attributes
  1865. TOKEN_GROUPS
  1866. d. authz context persistent structure which can be saved to and
  1867. read from the disk.
  1868. PVOID
  1869. e. User sid
  1870. TOKEN_USER
  1871. f. Server Context one level higher
  1872. PAUTHZ_CLIENT_CONTEXT
  1873. g. Expiration time
  1874. LARGE_INTEGER
  1875. h. Identifier
  1876. LUID
  1877. BufferSize - Size of the supplied buffer.
  1878. pSizeRequired - To return the size of the structure needed to hold the results.
  1879. Buffer - To hold the information requested. The structure returned will
  1880. depend on the information class requested.
  1881. Return Value:
  1882. A value of TRUE is returned if the API is successful. Otherwise,
  1883. a value of FALSE is returned. In the failure case, error value may be
  1884. retrieved using GetLastError().
  1885. --*/
  1886. {
  1887. DWORD LocalSize = 0;
  1888. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  1889. if (!ARGUMENT_PRESENT(hAuthzClientContext) ||
  1890. (!ARGUMENT_PRESENT(Buffer) && BufferSize != 0) ||
  1891. !ARGUMENT_PRESENT(pSizeRequired))
  1892. {
  1893. SetLastError(ERROR_INVALID_PARAMETER);
  1894. return FALSE;
  1895. }
  1896. *pSizeRequired = 0;
  1897. switch(InfoClass)
  1898. {
  1899. case AuthzContextInfoUserSid:
  1900. LocalSize = RtlLengthSid(pCC->Sids[0].Sid) + sizeof(TOKEN_USER);
  1901. *pSizeRequired = LocalSize;
  1902. if (LocalSize > BufferSize)
  1903. {
  1904. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1905. return FALSE;
  1906. }
  1907. //
  1908. // xor SE_GROUP_ENABLED from the User attributes. Authz sets this because it simplifies
  1909. // access check logic.
  1910. //
  1911. ((PTOKEN_USER)Buffer)->User.Attributes = pCC->Sids[0].Attributes ^ SE_GROUP_ENABLED;
  1912. ((PTOKEN_USER)Buffer)->User.Sid = ((PUCHAR) Buffer) + sizeof(TOKEN_USER);
  1913. RtlCopyMemory(
  1914. ((PTOKEN_USER)Buffer)->User.Sid,
  1915. pCC->Sids[0].Sid,
  1916. RtlLengthSid(pCC->Sids[0].Sid)
  1917. );
  1918. return TRUE;
  1919. case AuthzContextInfoGroupsSids:
  1920. LocalSize = pCC->SidLength +
  1921. sizeof(TOKEN_GROUPS) -
  1922. RtlLengthSid(pCC->Sids[0].Sid) -
  1923. 2 * sizeof(SID_AND_ATTRIBUTES);
  1924. *pSizeRequired = LocalSize;
  1925. if (LocalSize > BufferSize)
  1926. {
  1927. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1928. return FALSE;
  1929. }
  1930. ((PTOKEN_GROUPS) Buffer)->GroupCount = pCC->SidCount - 1;
  1931. return AuthzpCopySidsAndAttributes(
  1932. ((PTOKEN_GROUPS) Buffer)->Groups,
  1933. pCC->Sids + 1,
  1934. pCC->SidCount - 1,
  1935. NULL,
  1936. 0
  1937. );
  1938. case AuthzContextInfoRestrictedSids:
  1939. LocalSize = pCC->RestrictedSidLength +
  1940. sizeof(TOKEN_GROUPS) -
  1941. sizeof(SID_AND_ATTRIBUTES);
  1942. *pSizeRequired = LocalSize;
  1943. if (LocalSize > BufferSize)
  1944. {
  1945. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1946. return FALSE;
  1947. }
  1948. ((PTOKEN_GROUPS) Buffer)->GroupCount = pCC->RestrictedSidCount;
  1949. return AuthzpCopySidsAndAttributes(
  1950. ((PTOKEN_GROUPS) Buffer)->Groups,
  1951. pCC->RestrictedSids,
  1952. pCC->RestrictedSidCount,
  1953. NULL,
  1954. 0
  1955. );
  1956. case AuthzContextInfoPrivileges:
  1957. LocalSize = pCC->PrivilegeLength +
  1958. sizeof(TOKEN_PRIVILEGES) -
  1959. sizeof(LUID_AND_ATTRIBUTES);
  1960. *pSizeRequired = LocalSize;
  1961. if (LocalSize > BufferSize)
  1962. {
  1963. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1964. return FALSE;
  1965. }
  1966. ((PTOKEN_PRIVILEGES) Buffer)->PrivilegeCount = pCC->PrivilegeCount;
  1967. memcpy(
  1968. ((PTOKEN_PRIVILEGES) Buffer)->Privileges,
  1969. pCC->Privileges,
  1970. pCC->PrivilegeLength
  1971. );
  1972. return TRUE;
  1973. case AuthzContextInfoExpirationTime:
  1974. LocalSize = sizeof(LARGE_INTEGER);
  1975. *pSizeRequired = LocalSize;
  1976. if (LocalSize > BufferSize)
  1977. {
  1978. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1979. return FALSE;
  1980. }
  1981. *((PLARGE_INTEGER) Buffer) = pCC->ExpirationTime;
  1982. return TRUE;
  1983. case AuthzContextInfoIdentifier:
  1984. LocalSize = sizeof(LUID);
  1985. *pSizeRequired = LocalSize;
  1986. if (LocalSize > BufferSize)
  1987. {
  1988. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1989. return FALSE;
  1990. }
  1991. *((PLUID) Buffer) = pCC->Identifier;
  1992. return TRUE;
  1993. case AuthzContextInfoAuthenticationId:
  1994. LocalSize = sizeof(LUID);
  1995. *pSizeRequired = LocalSize;
  1996. if (LocalSize > BufferSize)
  1997. {
  1998. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1999. return FALSE;
  2000. }
  2001. *((PLUID) Buffer) = pCC->AuthenticationId;
  2002. return TRUE;
  2003. case AuthzContextInfoServerContext:
  2004. LocalSize = sizeof(AUTHZ_CLIENT_CONTEXT_HANDLE);
  2005. *pSizeRequired = LocalSize;
  2006. if (LocalSize > BufferSize)
  2007. {
  2008. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2009. return FALSE;
  2010. }
  2011. *((PAUTHZ_CLIENT_CONTEXT_HANDLE) Buffer) = (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server;
  2012. return TRUE;
  2013. default:
  2014. SetLastError(ERROR_INVALID_PARAMETER);
  2015. return FALSE;
  2016. }
  2017. }
  2018. BOOL
  2019. AuthzFreeContext(
  2020. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext
  2021. )
  2022. /*++
  2023. Routine Description:
  2024. This API frees up all the structures/memory accociated with the client
  2025. context. Note that the list of handles for this client will be freed in
  2026. this call.
  2027. Arguments:
  2028. AuthzClientContext - Context to be freed.
  2029. Return Value:
  2030. A value of TRUE is returned if the API is successful. Otherwise,
  2031. a value of FALSE is returned. In the failure case, error value may be
  2032. retrieved using GetLastError().
  2033. --*/
  2034. {
  2035. PAUTHZI_CLIENT_CONTEXT pCC = (PAUTHZI_CLIENT_CONTEXT) hAuthzClientContext;
  2036. BOOL b = TRUE;
  2037. PAUTHZI_HANDLE pCurrent = NULL;
  2038. PAUTHZI_HANDLE pPrev = NULL;
  2039. if (!ARGUMENT_PRESENT(pCC))
  2040. {
  2041. SetLastError(ERROR_INVALID_PARAMETER);
  2042. return FALSE;
  2043. }
  2044. AuthzpAcquireClientContextWriteLock(pCC);
  2045. AuthzpFreeNonNull(pCC->Privileges);
  2046. AuthzpFreeNonNull(pCC->Sids);
  2047. AuthzpFreeNonNull(pCC->RestrictedSids);
  2048. pCurrent = pCC->AuthzHandleHead;
  2049. //
  2050. // Loop thru all the handles and free them up.
  2051. //
  2052. while (AUTHZ_NON_NULL_PTR(pCurrent))
  2053. {
  2054. pPrev = pCurrent;
  2055. pCurrent = pCurrent->next;
  2056. AuthzpFree(pPrev);
  2057. }
  2058. //
  2059. // Free up the server context. The context is a recursive structure.
  2060. //
  2061. if (AUTHZ_NON_NULL_PTR(pCC->Server))
  2062. {
  2063. b = AuthzFreeContext((AUTHZ_CLIENT_CONTEXT_HANDLE) pCC->Server);
  2064. }
  2065. AuthzpFree(pCC);
  2066. return b;
  2067. }
  2068. AUTHZAPI
  2069. BOOL
  2070. WINAPI
  2071. AuthzInitializeObjectAccessAuditEvent(
  2072. IN DWORD Flags,
  2073. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType,
  2074. IN PWSTR szOperationType,
  2075. IN PWSTR szObjectType,
  2076. IN PWSTR szObjectName,
  2077. IN PWSTR szAdditionalInfo,
  2078. OUT PAUTHZ_AUDIT_EVENT_HANDLE phAuditEvent,
  2079. IN DWORD dwAdditionalParameterCount,
  2080. ...
  2081. )
  2082. /*++
  2083. Routine Description:
  2084. Allocates and initializes an AUTHZ_AUDIT_EVENT_HANDLE for use with AuthzAccessCheck.
  2085. The handle is used for storing information for audit generation.
  2086. Arguments:
  2087. Flags - Audit flags. Currently defined bits are:
  2088. AUTHZ_NO_SUCCESS_AUDIT - disables generation of success audits
  2089. AUTHZ_NO_FAILURE_AUDIT - disables generation of failure audits
  2090. AUTHZ_NO_ALLOC_STRINGS - storage space is not allocated for the 4 wide character strings. Rather,
  2091. the handle will only hold pointers to resource manager memory.
  2092. hAuditEventType - for future use. Should be NULL.
  2093. szOperationType - Resource manager defined string that indicates the operation being
  2094. performed that is to be audited.
  2095. szObjectType - Resource manager defined string that indicates the type of object being
  2096. accessed.
  2097. szObjectName - the name of the specific object being accessed.
  2098. szAdditionalInfo - Resource Manager defined string for additional audit information.
  2099. phAuditEvent - pointer to AUTHZ_AUDIT_EVENT_HANDLE. Space for this is allocated in the function.
  2100. dwAdditionalParameterCount - Must be zero.
  2101. Return Value:
  2102. Returns TRUE if successful, FALSE if unsuccessful.
  2103. Extended information available with GetLastError().
  2104. --*/
  2105. {
  2106. UNREFERENCED_PARAMETER(dwAdditionalParameterCount);
  2107. return AuthzInitializeObjectAccessAuditEvent2(
  2108. Flags,
  2109. hAuditEventType,
  2110. szOperationType,
  2111. szObjectType,
  2112. szObjectName,
  2113. szAdditionalInfo,
  2114. L"\0",
  2115. phAuditEvent,
  2116. 0
  2117. );
  2118. }
  2119. AUTHZAPI
  2120. BOOL
  2121. WINAPI
  2122. AuthzInitializeObjectAccessAuditEvent2(
  2123. IN DWORD Flags,
  2124. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType,
  2125. IN PWSTR szOperationType,
  2126. IN PWSTR szObjectType,
  2127. IN PWSTR szObjectName,
  2128. IN PWSTR szAdditionalInfo,
  2129. IN PWSTR szAdditionalInfo2,
  2130. OUT PAUTHZ_AUDIT_EVENT_HANDLE phAuditEvent,
  2131. IN DWORD dwAdditionalParameterCount,
  2132. ...
  2133. )
  2134. /*++
  2135. Routine Description:
  2136. Allocates and initializes an AUTHZ_AUDIT_EVENT_HANDLE for use with AuthzAccessCheck.
  2137. The handle is used for storing information for audit generation.
  2138. Arguments:
  2139. Flags - Audit flags. Currently defined bits are:
  2140. AUTHZ_NO_SUCCESS_AUDIT - disables generation of success audits
  2141. AUTHZ_NO_FAILURE_AUDIT - disables generation of failure audits
  2142. AUTHZ_NO_ALLOC_STRINGS - storage space is not allocated for the 4 wide character strings. Rather,
  2143. the handle will only hold pointers to resource manager memory.
  2144. hAuditEventType - for future use. Should be NULL.
  2145. szOperationType - Resource manager defined string that indicates the operation being
  2146. performed that is to be audited.
  2147. szObjectType - Resource manager defined string that indicates the type of object being
  2148. accessed.
  2149. szObjectName - the name of the specific object being accessed.
  2150. szAdditionalInfo - Resource Manager defined string for additional audit information.
  2151. szAdditionalInfo2 - Resource Manager defined string for additional audit information.
  2152. phAuditEvent - pointer to AUTHZ_AUDIT_EVENT_HANDLE. Space for this is allocated in the function.
  2153. dwAdditionalParameterCount - Must be zero.
  2154. Return Value:
  2155. Returns TRUE if successful, FALSE if unsuccessful.
  2156. Extended information available with GetLastError().
  2157. --*/
  2158. {
  2159. PAUTHZI_AUDIT_EVENT pAuditEvent = NULL;
  2160. BOOL b = TRUE;
  2161. DWORD dwStringSize = 0;
  2162. DWORD dwObjectTypeLength = 0;
  2163. DWORD dwObjectNameLength = 0;
  2164. DWORD dwOperationTypeLength = 0;
  2165. DWORD dwAdditionalInfoLength = 0;
  2166. DWORD dwAdditionalInfo2Length = 0;
  2167. if ((!ARGUMENT_PRESENT(phAuditEvent)) ||
  2168. (NULL != hAuditEventType) ||
  2169. (0 != dwAdditionalParameterCount) ||
  2170. (!ARGUMENT_PRESENT(szOperationType)) ||
  2171. (!ARGUMENT_PRESENT(szObjectType)) ||
  2172. (!ARGUMENT_PRESENT(szObjectName)) ||
  2173. (!ARGUMENT_PRESENT(szAdditionalInfo)) ||
  2174. (!ARGUMENT_PRESENT(szAdditionalInfo2)) ||
  2175. (Flags & (~(AUTHZ_VALID_OBJECT_ACCESS_AUDIT_FLAGS | AUTHZ_DS_CATEGORY_FLAG))))
  2176. {
  2177. SetLastError(ERROR_INVALID_PARAMETER);
  2178. return FALSE;
  2179. }
  2180. *phAuditEvent = NULL;
  2181. //
  2182. // Allocate and initialize a new AUTHZI_AUDIT_EVENT. Include for the string in the contiguous memory, if
  2183. // needed.
  2184. //
  2185. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  2186. {
  2187. dwStringSize = 0;
  2188. }
  2189. else
  2190. {
  2191. dwOperationTypeLength = (DWORD) wcslen(szOperationType) + 1;
  2192. dwObjectTypeLength = (DWORD) wcslen(szObjectType) + 1;
  2193. dwObjectNameLength = (DWORD) wcslen(szObjectName) + 1;
  2194. dwAdditionalInfoLength = (DWORD) wcslen(szAdditionalInfo) + 1;
  2195. dwAdditionalInfo2Length = (DWORD) wcslen(szAdditionalInfo2) + 1;
  2196. dwStringSize = sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength + dwAdditionalInfoLength + dwAdditionalInfo2Length);
  2197. }
  2198. pAuditEvent = (PAUTHZI_AUDIT_EVENT) AuthzpAlloc(sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize);
  2199. if (AUTHZ_ALLOCATION_FAILED(pAuditEvent))
  2200. {
  2201. b = FALSE;
  2202. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2203. goto Cleanup;
  2204. }
  2205. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  2206. {
  2207. pAuditEvent->szOperationType = szOperationType;
  2208. pAuditEvent->szObjectType = szObjectType;
  2209. pAuditEvent->szObjectName = szObjectName;
  2210. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  2211. pAuditEvent->szAdditionalInfo2 = szAdditionalInfo2;
  2212. }
  2213. else
  2214. {
  2215. //
  2216. // Set the string pointers into the contiguous memory.
  2217. //
  2218. pAuditEvent->szOperationType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT));
  2219. RtlCopyMemory(
  2220. pAuditEvent->szOperationType,
  2221. szOperationType,
  2222. sizeof(WCHAR) * dwOperationTypeLength
  2223. );
  2224. pAuditEvent->szObjectType = (PWSTR)((PUCHAR)pAuditEvent->szOperationType + (sizeof(WCHAR) * dwOperationTypeLength));
  2225. RtlCopyMemory(
  2226. pAuditEvent->szObjectType,
  2227. szObjectType,
  2228. sizeof(WCHAR) * dwObjectTypeLength
  2229. );
  2230. pAuditEvent->szObjectName = (PWSTR)((PUCHAR)pAuditEvent->szObjectType + (sizeof(WCHAR) * dwObjectTypeLength));
  2231. RtlCopyMemory(
  2232. pAuditEvent->szObjectName,
  2233. szObjectName,
  2234. sizeof(WCHAR) * dwObjectNameLength
  2235. );
  2236. pAuditEvent->szAdditionalInfo = (PWSTR)((PUCHAR)pAuditEvent->szObjectName + (sizeof(WCHAR) * dwObjectNameLength));
  2237. RtlCopyMemory(
  2238. pAuditEvent->szAdditionalInfo,
  2239. szAdditionalInfo,
  2240. sizeof(WCHAR) * dwAdditionalInfoLength
  2241. );
  2242. pAuditEvent->szAdditionalInfo2 = (PWSTR)((PUCHAR)pAuditEvent->szAdditionalInfo + (sizeof(WCHAR) * dwAdditionalInfoLength));
  2243. RtlCopyMemory(
  2244. pAuditEvent->szAdditionalInfo2,
  2245. szAdditionalInfo2,
  2246. sizeof(WCHAR) * dwAdditionalInfo2Length
  2247. );
  2248. }
  2249. //
  2250. // AEI and Queue will be filled in from RM in AuthzpCreateAndLogAudit
  2251. //
  2252. pAuditEvent->hAET = NULL;
  2253. pAuditEvent->hAuditQueue = NULL;
  2254. pAuditEvent->pAuditParams = NULL;
  2255. pAuditEvent->Flags = Flags;
  2256. pAuditEvent->dwTimeOut = INFINITE;
  2257. pAuditEvent->dwSize = sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize;
  2258. Cleanup:
  2259. if (!b)
  2260. {
  2261. AuthzpFreeNonNull(pAuditEvent);
  2262. }
  2263. else
  2264. {
  2265. *phAuditEvent = (AUTHZ_AUDIT_EVENT_HANDLE) pAuditEvent;
  2266. }
  2267. return b;
  2268. }
  2269. BOOL
  2270. AuthzGetInformationFromAuditEvent(
  2271. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  2272. IN AUTHZ_AUDIT_EVENT_INFORMATION_CLASS InfoClass,
  2273. IN DWORD BufferSize,
  2274. OUT PDWORD pSizeRequired,
  2275. OUT PVOID Buffer
  2276. )
  2277. /*++
  2278. Routine Description
  2279. Queries information in the AUTHZ_AUDIT_EVENT_HANDLE.
  2280. Arguments
  2281. hAuditEvent - the AUTHZ_AUDIT_EVENT_HANDLE to query.
  2282. InfoClass - The class of information to query. Valid values are:
  2283. a. AuthzAuditEventInfoFlags - returns the flags set for the handle. Type is DWORD.
  2284. e. AuthzAuditEventInfoOperationType - returns the operation type. Type is PCWSTR.
  2285. e. AuthzAuditEventInfoObjectType - returns the object type. Type is PCWSTR.
  2286. f. AuthzAuditEventInfoObjectName - returns the object name. Type is PCWSTR.
  2287. g. AuthzAuditEventInfoAdditionalInfo - returns the additional info field. Type is PCWSTR.
  2288. BufferSize - Size of the supplied buffer.
  2289. pSizeRequired - To return the size of the structure needed to hold the results.
  2290. Buffer - To hold the information requested. The structure returned will
  2291. depend on the information class requested.
  2292. Return Value
  2293. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2294. --*/
  2295. {
  2296. DWORD LocalSize = 0;
  2297. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  2298. if ((!ARGUMENT_PRESENT(hAuditEvent)) ||
  2299. (!ARGUMENT_PRESENT(pSizeRequired)) ||
  2300. (!ARGUMENT_PRESENT(Buffer) && BufferSize > 0))
  2301. {
  2302. SetLastError(ERROR_INVALID_PARAMETER);
  2303. return FALSE;
  2304. }
  2305. *pSizeRequired = 0;
  2306. switch(InfoClass)
  2307. {
  2308. case AuthzAuditEventInfoFlags:
  2309. LocalSize = sizeof(DWORD);
  2310. *pSizeRequired = LocalSize;
  2311. if (LocalSize > BufferSize)
  2312. {
  2313. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2314. return FALSE;
  2315. }
  2316. *((PDWORD)Buffer) = pAuditEvent->Flags;
  2317. return TRUE;
  2318. case AuthzAuditEventInfoOperationType:
  2319. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szOperationType) + 1));
  2320. *pSizeRequired = LocalSize;
  2321. if (LocalSize > BufferSize)
  2322. {
  2323. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2324. return FALSE;
  2325. }
  2326. RtlCopyMemory(
  2327. Buffer,
  2328. pAuditEvent->szOperationType,
  2329. LocalSize
  2330. );
  2331. return TRUE;
  2332. case AuthzAuditEventInfoObjectType:
  2333. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szObjectType) + 1));
  2334. *pSizeRequired = LocalSize;
  2335. if (LocalSize > BufferSize)
  2336. {
  2337. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2338. return FALSE;
  2339. }
  2340. RtlCopyMemory(
  2341. Buffer,
  2342. pAuditEvent->szObjectType,
  2343. LocalSize
  2344. );
  2345. return TRUE;
  2346. case AuthzAuditEventInfoObjectName:
  2347. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szObjectName) + 1));
  2348. *pSizeRequired = LocalSize;
  2349. if (LocalSize > BufferSize)
  2350. {
  2351. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2352. return FALSE;
  2353. }
  2354. RtlCopyMemory(
  2355. Buffer,
  2356. pAuditEvent->szObjectName,
  2357. LocalSize
  2358. );
  2359. return TRUE;
  2360. case AuthzAuditEventInfoAdditionalInfo:
  2361. if (NULL == pAuditEvent->szAdditionalInfo)
  2362. {
  2363. SetLastError(ERROR_INVALID_PARAMETER);
  2364. return FALSE;
  2365. }
  2366. LocalSize = (DWORD)(sizeof(WCHAR) * (wcslen(pAuditEvent->szAdditionalInfo) + 1));
  2367. *pSizeRequired = LocalSize;
  2368. if (LocalSize > BufferSize)
  2369. {
  2370. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2371. return FALSE;
  2372. }
  2373. RtlCopyMemory(
  2374. Buffer,
  2375. pAuditEvent->szAdditionalInfo,
  2376. LocalSize
  2377. );
  2378. return TRUE;
  2379. default:
  2380. SetLastError(ERROR_INVALID_PARAMETER);
  2381. return FALSE;
  2382. }
  2383. }
  2384. BOOL
  2385. AuthzFreeAuditEvent(
  2386. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent
  2387. )
  2388. /*++
  2389. Routine Description:
  2390. Frees hAuditEvent and notifies the appropriate queue to unregister the audit context in LSA.
  2391. Arguments:
  2392. hAuditEvent - AUTHZ_AUDIT_EVENT_HANDLE. Must have initially been created
  2393. with AuthzRMInitializeObjectAccessAuditEvent or AuthzInitializeAuditEvent().
  2394. Return Value:
  2395. Boolean: TRUE if successful; FALSE if failure.
  2396. Extended information available with GetLastError().
  2397. --*/
  2398. {
  2399. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  2400. if (!ARGUMENT_PRESENT(hAuditEvent))
  2401. {
  2402. SetLastError(ERROR_INVALID_PARAMETER);
  2403. return FALSE;
  2404. }
  2405. //
  2406. // If the RM specified the AuditEvent, then we should deref the context. If the AuditEvent
  2407. // has not been used, or was a default event type, then this field will be NULL.
  2408. //
  2409. if (AUTHZ_NON_NULL_PTR(pAuditEvent->hAET))
  2410. {
  2411. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  2412. }
  2413. AuthzpFree(pAuditEvent);
  2414. return TRUE;
  2415. }
  2416. //
  2417. // Routines for internal callers.
  2418. //
  2419. BOOL
  2420. AuthziInitializeAuditEventType(
  2421. IN DWORD Flags,
  2422. IN USHORT CategoryID,
  2423. IN USHORT AuditID,
  2424. IN USHORT ParameterCount,
  2425. OUT PAUTHZ_AUDIT_EVENT_TYPE_HANDLE phAuditEventType
  2426. )
  2427. /*++
  2428. Routine Description
  2429. Initializes an AUTHZ_AUDIT_EVENT_TYPE_HANDLE for use in AuthzInitializeAuditEvent().
  2430. Arguments
  2431. phAuditEventType - pointer to pointer to receive memory allocated for AUTHZ_AUDIT_EVENT_TYPE_HANDLE.
  2432. dwFlags - Flags that control behavior of function.
  2433. AUTHZ_INIT_GENERIC_AUDIT_EVENT - initialize the AUTHZ_AUDIT_EVENT_TYPE for generic object
  2434. access audits. When this flag is specified, none of the optional parameters need to
  2435. be passed. This is equivalent to calling:
  2436. AuthzInitializeAuditEvent(
  2437. &hAEI,
  2438. 0,
  2439. SE_CATEGID_OBJECT_ACCESS,
  2440. SE_AUDITID_OBJECT_OPERATION,
  2441. AUTHZP_NUM_PARAMS_FOR_SE_AUDITID_OBJECT_OPERATION
  2442. );
  2443. CategoryID - The category id of the audit.
  2444. AuditID - The ID of the audit in msaudite.
  2445. ParameterCount - The number of fields in the audit.
  2446. Return Value
  2447. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2448. --*/
  2449. {
  2450. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAET = NULL;
  2451. BOOL b = TRUE;
  2452. AUDIT_HANDLE hAudit = NULL;
  2453. if (!ARGUMENT_PRESENT(phAuditEventType))
  2454. {
  2455. SetLastError(ERROR_INVALID_PARAMETER);
  2456. return FALSE;
  2457. }
  2458. *phAuditEventType = NULL;
  2459. pAET = AuthzpAlloc(sizeof(AUTHZ_AUDIT_EVENT_TYPE_OLD));
  2460. if (AUTHZ_ALLOCATION_FAILED(pAET))
  2461. {
  2462. b = FALSE;
  2463. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2464. goto Cleanup;
  2465. }
  2466. if (FLAG_ON(Flags, AUTHZP_INIT_GENERIC_AUDIT_EVENT))
  2467. {
  2468. pAET->Version = AUDIT_TYPE_LEGACY;
  2469. pAET->u.Legacy.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  2470. pAET->u.Legacy.AuditId = SE_AUDITID_OBJECT_OPERATION;
  2471. pAET->u.Legacy.ParameterCount = AUTHZP_NUM_PARAMS_FOR_SE_AUDITID_OBJECT_OPERATION + AUTHZP_NUM_FIXED_HEADER_PARAMS;
  2472. }
  2473. else
  2474. {
  2475. pAET->Version = AUDIT_TYPE_LEGACY;
  2476. pAET->u.Legacy.CategoryId = CategoryID;
  2477. pAET->u.Legacy.AuditId = AuditID;
  2478. //
  2479. // ParameterCount gets increased by 2 because the LSA expects the first two
  2480. // parameters to be the user sid and subsystem name.
  2481. //
  2482. pAET->u.Legacy.ParameterCount = ParameterCount + AUTHZP_NUM_FIXED_HEADER_PARAMS;
  2483. }
  2484. b = AuthzpRegisterAuditEvent(
  2485. pAET,
  2486. &hAudit
  2487. );
  2488. if (!b)
  2489. {
  2490. goto Cleanup;
  2491. }
  2492. pAET->hAudit = (ULONG_PTR) hAudit;
  2493. pAET->dwFlags = Flags & ~AUTHZP_INIT_GENERIC_AUDIT_EVENT;
  2494. Cleanup:
  2495. if (!b)
  2496. {
  2497. AuthzpFreeNonNull(pAET);
  2498. }
  2499. else
  2500. {
  2501. AuthzpReferenceAuditEventType((AUTHZ_AUDIT_EVENT_TYPE_HANDLE)pAET);
  2502. *phAuditEventType = (AUTHZ_AUDIT_EVENT_TYPE_HANDLE)pAET;
  2503. }
  2504. return b;
  2505. }
  2506. BOOL
  2507. AuthziModifyAuditEventType(
  2508. IN DWORD Flags,
  2509. IN USHORT CategoryID,
  2510. IN USHORT AuditID,
  2511. IN USHORT ParameterCount,
  2512. IN OUT AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType
  2513. )
  2514. /*++
  2515. Routine Description
  2516. Modifies an existing AuditEventType.
  2517. Arguments
  2518. Flags - AUTHZ_AUDIT_EVENT_TYPE_AUDITID
  2519. Return Value
  2520. --*/
  2521. {
  2522. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD) hAuditEventType;
  2523. BOOL b = TRUE;
  2524. if (!ARGUMENT_PRESENT(hAuditEventType))
  2525. {
  2526. SetLastError(ERROR_INVALID_PARAMETER);
  2527. return FALSE;
  2528. }
  2529. UNREFERENCED_PARAMETER(CategoryID);
  2530. UNREFERENCED_PARAMETER(ParameterCount);
  2531. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_AUDITID))
  2532. {
  2533. pAAETO->u.Legacy.AuditId = AuditID;
  2534. }
  2535. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_CATEGID))
  2536. {
  2537. SetLastError(ERROR_INVALID_PARAMETER);
  2538. b = FALSE;
  2539. goto Cleanup;
  2540. }
  2541. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_TYPE_PARAM))
  2542. {
  2543. SetLastError(ERROR_INVALID_PARAMETER);
  2544. b = FALSE;
  2545. goto Cleanup;
  2546. }
  2547. Cleanup:
  2548. return b;
  2549. }
  2550. BOOL
  2551. AuthziFreeAuditEventType(
  2552. AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAuditEventType
  2553. )
  2554. /*++
  2555. Routine Description
  2556. Frees the PAUDIT_EVENT_TYPE allocated by AuthzInitializeAuditEventType().
  2557. Arguments
  2558. pAuditEventType - pointer to memory to free.
  2559. Return Value
  2560. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2561. --*/
  2562. {
  2563. BOOL b = TRUE;
  2564. if (!ARGUMENT_PRESENT(hAuditEventType))
  2565. {
  2566. SetLastError(ERROR_INVALID_PARAMETER);
  2567. return FALSE;
  2568. }
  2569. b = AuthzpDereferenceAuditEventType(
  2570. hAuditEventType
  2571. );
  2572. return b;
  2573. }
  2574. AUTHZAPI
  2575. BOOL
  2576. WINAPI
  2577. AuthziInitializeAuditQueue(
  2578. IN DWORD Flags,
  2579. IN DWORD dwAuditQueueHigh,
  2580. IN DWORD dwAuditQueueLow,
  2581. IN PVOID Reserved,
  2582. OUT PAUTHZ_AUDIT_QUEUE_HANDLE phAuditQueue
  2583. )
  2584. /*++
  2585. Routine Description
  2586. Creates an audit queue.
  2587. Arguments
  2588. phAuditQueue - pointer to handle for the audit queue.
  2589. Flags -
  2590. AUTHZ_MONITOR_AUDIT_QUEUE_SIZE - notifies Authz that it should not let the size of the
  2591. audit queue grow unchecked.
  2592. dwAuditQueueHigh - high water mark for the audit queue.
  2593. dwAuditQueueLow - low water mark for the audit queue.
  2594. Reserved - for future expansion.
  2595. Return Value
  2596. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2597. --*/
  2598. {
  2599. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2600. BOOL b = TRUE;
  2601. BOOL bCrit = FALSE;
  2602. NTSTATUS Status = STATUS_SUCCESS;
  2603. UNREFERENCED_PARAMETER(Reserved);
  2604. if (!ARGUMENT_PRESENT(phAuditQueue))
  2605. {
  2606. SetLastError(ERROR_INVALID_PARAMETER);
  2607. return FALSE;
  2608. }
  2609. *phAuditQueue = NULL;
  2610. pQueue = AuthzpAlloc(sizeof(AUTHZI_AUDIT_QUEUE));
  2611. if (AUTHZ_ALLOCATION_FAILED(pQueue))
  2612. {
  2613. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2614. b = FALSE;
  2615. goto Cleanup;
  2616. }
  2617. pQueue->dwAuditQueueHigh = dwAuditQueueHigh;
  2618. pQueue->dwAuditQueueLow = dwAuditQueueLow;
  2619. pQueue->bWorker = TRUE;
  2620. pQueue->Flags = Flags;
  2621. //
  2622. // This event is set whenever an audit is queued with AuthziLogAuditEvent(). It
  2623. // notifies the dequeueing thread that there is work to do.
  2624. //
  2625. pQueue->hAuthzAuditAddedEvent = CreateEvent(
  2626. NULL,
  2627. TRUE,
  2628. FALSE, // Initially not signaled, since no audit has been added yet.
  2629. NULL
  2630. );
  2631. if (NULL == pQueue->hAuthzAuditAddedEvent)
  2632. {
  2633. b = FALSE;
  2634. goto Cleanup;
  2635. }
  2636. //
  2637. // This event is set when the audit queue is empty.
  2638. //
  2639. pQueue->hAuthzAuditQueueEmptyEvent = CreateEvent(
  2640. NULL,
  2641. TRUE,
  2642. TRUE, // Initially signaled.
  2643. NULL
  2644. );
  2645. if (NULL == pQueue->hAuthzAuditQueueEmptyEvent)
  2646. {
  2647. b = FALSE;
  2648. goto Cleanup;
  2649. }
  2650. //
  2651. // This event is set when the audit queue is below the low water mark.
  2652. //
  2653. pQueue->hAuthzAuditQueueLowEvent = CreateEvent(
  2654. NULL,
  2655. FALSE,// The system only schedules one thread waiting on this event (auto reset event).
  2656. TRUE, // Initially set.
  2657. NULL
  2658. );
  2659. if (NULL == pQueue->hAuthzAuditQueueLowEvent)
  2660. {
  2661. b = FALSE;
  2662. goto Cleanup;
  2663. }
  2664. //
  2665. // This boolean is true only when the high water mark has been reached
  2666. //
  2667. pQueue->bAuthzAuditQueueHighEvent = FALSE;
  2668. //
  2669. // This lock is taken whenever audits are being added or removed from the queue, or events / boolean being set.
  2670. //
  2671. Status = RtlInitializeCriticalSection(&pQueue->AuthzAuditQueueLock);
  2672. if (!NT_SUCCESS(Status))
  2673. {
  2674. SetLastError(RtlNtStatusToDosError(Status));
  2675. b = FALSE;
  2676. goto Cleanup;
  2677. }
  2678. bCrit = TRUE;
  2679. //
  2680. // Initialize the list
  2681. //
  2682. InitializeListHead(&pQueue->AuthzAuditQueue);
  2683. //
  2684. // Create the worker thread that sends audits to LSA.
  2685. //
  2686. pQueue->hAuthzAuditThread = CreateThread(
  2687. NULL,
  2688. 0,
  2689. AuthzpDeQueueThreadWorker,
  2690. pQueue,
  2691. 0,
  2692. NULL
  2693. );
  2694. if (NULL == pQueue->hAuthzAuditThread)
  2695. {
  2696. b = FALSE;
  2697. goto Cleanup;
  2698. }
  2699. Cleanup:
  2700. if (!b)
  2701. {
  2702. if (AUTHZ_NON_NULL_PTR(pQueue))
  2703. {
  2704. if (bCrit)
  2705. {
  2706. RtlDeleteCriticalSection(&pQueue->AuthzAuditQueueLock);
  2707. }
  2708. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditQueueLowEvent);
  2709. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditAddedEvent);
  2710. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditQueueEmptyEvent);
  2711. AuthzpCloseHandleNonNull(pQueue->hAuthzAuditThread);
  2712. AuthzpFree(pQueue);
  2713. }
  2714. }
  2715. else
  2716. {
  2717. *phAuditQueue = (AUTHZ_AUDIT_QUEUE_HANDLE)pQueue;
  2718. }
  2719. return b;
  2720. }
  2721. AUTHZAPI
  2722. BOOL
  2723. WINAPI
  2724. AuthziModifyAuditQueue(
  2725. IN OUT AUTHZ_AUDIT_QUEUE_HANDLE hQueue OPTIONAL,
  2726. IN DWORD Flags,
  2727. IN DWORD dwQueueFlags OPTIONAL,
  2728. IN DWORD dwAuditQueueSizeHigh OPTIONAL,
  2729. IN DWORD dwAuditQueueSizeLow OPTIONAL,
  2730. IN DWORD dwThreadPriority OPTIONAL
  2731. )
  2732. /*++
  2733. Routine Description
  2734. Allows the Resource Manager to modify audit queue information.
  2735. Arguments
  2736. Flags - Flags specifying which fields are to be reinitialized. Valid flags are:
  2737. AUTHZ_AUDIT_QUEUE_HIGH
  2738. AUTHZ_AUDIT_QUEUE_LOW
  2739. AUTHZ_AUDIT_QUEUE_THREAD_PRIORITY
  2740. AUTHZ_AUDIT_QUEUE_FLAGS
  2741. Specifying one of the above flags in the Flags field causes the appropriate field of
  2742. the resource manager to be modified to the correct value below:
  2743. dwQueueFlags - set the flags for the audit queue.
  2744. dwAuditQueueSizeHigh - High water mark for the audit queue.
  2745. dwAuditQueueSizeLow - Low water mark for the audit queue.
  2746. dwThreadPriority - Changes the priority of the audit dequeue thread. Valid values are described
  2747. in the SetThreadPriority API. A RM may wish to change the priority of the thread if, for example,
  2748. the high water mark is being reached too frequently and the RM does not want to allow the queue to
  2749. grow beyond its current size.
  2750. Return Value
  2751. Boolean: TRUE on success; FALSE on failure.
  2752. Extended information available with GetLastError().
  2753. --*/
  2754. {
  2755. BOOL b = TRUE;
  2756. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2757. if (!ARGUMENT_PRESENT(hQueue))
  2758. {
  2759. SetLastError(ERROR_INVALID_PARAMETER);
  2760. return FALSE;
  2761. }
  2762. pQueue = (PAUTHZI_AUDIT_QUEUE)hQueue;
  2763. //
  2764. // Set the fields that the caller has asked us to initialize.
  2765. //
  2766. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_FLAGS))
  2767. {
  2768. pQueue->Flags = dwQueueFlags;
  2769. }
  2770. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_HIGH))
  2771. {
  2772. pQueue->dwAuditQueueHigh = dwAuditQueueSizeHigh;
  2773. }
  2774. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_LOW))
  2775. {
  2776. pQueue->dwAuditQueueLow = dwAuditQueueSizeLow;
  2777. }
  2778. if (FLAG_ON(Flags, AUTHZ_AUDIT_QUEUE_THREAD_PRIORITY))
  2779. {
  2780. b = SetThreadPriority(pQueue->hAuthzAuditThread, dwThreadPriority);
  2781. if (!b)
  2782. {
  2783. goto Cleanup;
  2784. }
  2785. }
  2786. Cleanup:
  2787. return b;
  2788. }
  2789. AUTHZAPI
  2790. BOOL
  2791. WINAPI
  2792. AuthziFreeAuditQueue(
  2793. IN AUTHZ_AUDIT_QUEUE_HANDLE hQueue OPTIONAL
  2794. )
  2795. /*++
  2796. Routine Description
  2797. This API flushes and frees a queue. The actual freeing of queue memory occurs in the dequeueing thread,
  2798. after all audits have been flushed.
  2799. Arguments
  2800. hQueue - handle to the queue object to free.
  2801. Return Value
  2802. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  2803. --*/
  2804. {
  2805. PAUTHZI_AUDIT_QUEUE pQueue = (PAUTHZI_AUDIT_QUEUE) hQueue;
  2806. DWORD dwError = ERROR_SUCCESS;
  2807. BOOL b = TRUE;
  2808. if (!ARGUMENT_PRESENT(hQueue))
  2809. {
  2810. SetLastError(ERROR_INVALID_PARAMETER);
  2811. return FALSE;
  2812. }
  2813. dwError = WaitForSingleObject(
  2814. pQueue->hAuthzAuditQueueEmptyEvent,
  2815. INFINITE
  2816. );
  2817. if (WAIT_OBJECT_0 != dwError)
  2818. {
  2819. ASSERT(L"WaitForSingleObject on hAuthzAuditQueueEmptyEvent failed." && FALSE);
  2820. SetLastError(dwError);
  2821. b = FALSE;
  2822. goto Cleanup;
  2823. }
  2824. //
  2825. // Set this BOOL to FALSE so that the dequeueing thread knows it can terminate. Set the
  2826. // AddedEvent so that the thread can be scheduled.
  2827. //
  2828. pQueue->bWorker = FALSE;
  2829. b = SetEvent(
  2830. pQueue->hAuthzAuditAddedEvent
  2831. );
  2832. if (!b)
  2833. {
  2834. goto Cleanup;
  2835. }
  2836. //
  2837. // Wait for the thread to terminate.
  2838. //
  2839. dwError = WaitForSingleObject(
  2840. pQueue->hAuthzAuditThread,
  2841. INFINITE
  2842. );
  2843. //
  2844. // The wait should succeed since we have told the thread to finish working.
  2845. //
  2846. if (WAIT_OBJECT_0 != dwError)
  2847. {
  2848. ASSERT(L"WaitForSingleObject on hAuthzAuditThread failed." && FALSE);
  2849. SetLastError(dwError);
  2850. b = FALSE;
  2851. goto Cleanup;
  2852. }
  2853. RtlDeleteCriticalSection(&pQueue->AuthzAuditQueueLock);
  2854. AuthzpCloseHandle(pQueue->hAuthzAuditAddedEvent);
  2855. AuthzpCloseHandle(pQueue->hAuthzAuditQueueLowEvent);
  2856. AuthzpCloseHandle(pQueue->hAuthzAuditQueueEmptyEvent);
  2857. AuthzpCloseHandle(pQueue->hAuthzAuditThread);
  2858. AuthzpFree(pQueue);
  2859. Cleanup:
  2860. return b;
  2861. }
  2862. BOOL
  2863. AuthziLogAuditEvent(
  2864. IN DWORD Flags,
  2865. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  2866. IN PVOID pReserved
  2867. )
  2868. /*++
  2869. Routine Description:
  2870. This API manages the logging of Audit Records. The function constructs an
  2871. Audit Record from the information provided and appends it to the Audit
  2872. Record Queue, a doubly-linked list of Audit Records awaiting output to the
  2873. Audit Log. A dedicated thread reads this queue, sending the Audit Records
  2874. to the LSA and removing them from the Audit Queue.
  2875. This call is not guaranteed to return without latency. If the queue is at
  2876. or above the high water mark for size, then the calling thread will be
  2877. suspended until such time that the queue reaches the low water mark. Be
  2878. aware of this latency when fashioning your calls to AuthziLogAuditEvent.
  2879. If such latency is not allowable for the audit that is being generated,
  2880. then specify the correct flag when initializing the
  2881. AUTHZ_AUDIT_EVENT_HANDLE (in AuthzInitAuditEventHandle()). Flags are listed
  2882. in that routines description.
  2883. Arguments:
  2884. hAuditEvent - handle previously obtained by calling AuthzInitAuditEventHandle
  2885. Flags - TBD
  2886. pReserved - reserved for future enhancements
  2887. Return Value:
  2888. Boolean: TRUE on success, FALSE on failure.
  2889. Extended information available with GetLastError().
  2890. --*/
  2891. {
  2892. DWORD dwError = ERROR_SUCCESS;
  2893. BOOL b = TRUE;
  2894. BOOL bRef = FALSE;
  2895. PAUTHZI_AUDIT_QUEUE pQueue = NULL;
  2896. PAUDIT_PARAMS pMarshalledAuditParams = NULL;
  2897. PAUTHZ_AUDIT_QUEUE_ENTRY pAuthzAuditEntry = NULL;
  2898. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT)hAuditEvent;
  2899. //
  2900. // Verify what the caller has passed in.
  2901. //
  2902. if (!ARGUMENT_PRESENT(hAuditEvent))
  2903. {
  2904. SetLastError(ERROR_INVALID_PARAMETER);
  2905. return FALSE;
  2906. }
  2907. //
  2908. // Make a self relative copy of the pAuditEvent->pAuditParams.
  2909. //
  2910. b = AuthzpMarshallAuditParams(
  2911. &pMarshalledAuditParams,
  2912. pAuditEvent->pAuditParams
  2913. );
  2914. if (!b)
  2915. {
  2916. goto Cleanup;
  2917. }
  2918. pQueue = (PAUTHZI_AUDIT_QUEUE)pAuditEvent->hAuditQueue;
  2919. if (NULL == pQueue)
  2920. {
  2921. b = AuthzpSendAuditToLsa(
  2922. (AUDIT_HANDLE)((PAUTHZ_AUDIT_EVENT_TYPE_OLD)pAuditEvent->hAET)->hAudit,
  2923. 0,
  2924. pMarshalledAuditParams,
  2925. NULL
  2926. );
  2927. goto Cleanup;
  2928. }
  2929. else
  2930. {
  2931. //
  2932. // Create the audit queue entry.
  2933. //
  2934. pAuthzAuditEntry = AuthzpAlloc(sizeof(AUTHZ_AUDIT_QUEUE_ENTRY));
  2935. if (AUTHZ_ALLOCATION_FAILED(pAuthzAuditEntry))
  2936. {
  2937. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2938. b = FALSE;
  2939. goto Cleanup;
  2940. }
  2941. pAuthzAuditEntry->pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD)pAuditEvent->hAET;
  2942. pAuthzAuditEntry->Flags = Flags;
  2943. pAuthzAuditEntry->pReserved = pReserved;
  2944. pAuthzAuditEntry->pAuditParams = pMarshalledAuditParams;
  2945. AuthzpReferenceAuditEventType(pAuditEvent->hAET);
  2946. bRef = TRUE;
  2947. if (FLAG_ON(pQueue->Flags, AUTHZ_MONITOR_AUDIT_QUEUE_SIZE))
  2948. {
  2949. //
  2950. // Monitor queue size if specified by the Resource Manager.
  2951. //
  2952. //
  2953. // If we are closing in on the high water mark then wait for the queue
  2954. // to be below the low water mark.
  2955. //
  2956. #define AUTHZ_QUEUE_WAIT_HEURISTIC .75
  2957. if (pQueue->AuthzAuditQueueLength > pQueue->dwAuditQueueHigh * AUTHZ_QUEUE_WAIT_HEURISTIC)
  2958. {
  2959. dwError = WaitForSingleObject(
  2960. pQueue->hAuthzAuditQueueLowEvent,
  2961. pAuditEvent->dwTimeOut
  2962. );
  2963. if (WAIT_FAILED == dwError)
  2964. {
  2965. ASSERT(L"WaitForSingleObject on hAuthzAuditQueueLowEvent failed." && FALSE);
  2966. }
  2967. if (WAIT_OBJECT_0 != dwError)
  2968. {
  2969. b = FALSE;
  2970. //
  2971. // Don't set last error if WAIT_FAILED, because it is already set.
  2972. //
  2973. if (WAIT_FAILED != dwError)
  2974. {
  2975. SetLastError(dwError);
  2976. }
  2977. goto Cleanup;
  2978. }
  2979. }
  2980. //
  2981. // Queue the event and modify appropriate events.
  2982. //
  2983. b = AuthzpEnQueueAuditEventMonitor(
  2984. pQueue,
  2985. pAuthzAuditEntry
  2986. );
  2987. goto Cleanup;
  2988. }
  2989. else
  2990. {
  2991. //
  2992. // If we are not to monitor the audit queue then simply queue the entry.
  2993. //
  2994. b = AuthzpEnQueueAuditEvent(
  2995. pQueue,
  2996. pAuthzAuditEntry
  2997. );
  2998. goto Cleanup;
  2999. }
  3000. }
  3001. Cleanup:
  3002. if (pQueue)
  3003. {
  3004. if (FALSE == b)
  3005. {
  3006. if (bRef)
  3007. {
  3008. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  3009. }
  3010. AuthzpFreeNonNull(pAuthzAuditEntry);
  3011. AuthzpFreeNonNull(pMarshalledAuditParams);
  3012. }
  3013. //
  3014. // hAuthzAuditQueueLowEvent is an auto reset event. Only one waiting thread is released when it is signalled, and then
  3015. // event is automatically switched to a nonsignalled state. This is appropriate here because it keeps many threads from
  3016. // running and overflowing the high water mark. However, I must always resignal the event myself if the conditions
  3017. // for signaling are true.
  3018. //
  3019. RtlEnterCriticalSection(&pQueue->AuthzAuditQueueLock);
  3020. if (!pQueue->bAuthzAuditQueueHighEvent)
  3021. {
  3022. if (pQueue->AuthzAuditQueueLength <= pQueue->dwAuditQueueHigh)
  3023. {
  3024. BOOL bSet;
  3025. bSet = SetEvent(pQueue->hAuthzAuditQueueLowEvent);
  3026. if (!bSet)
  3027. {
  3028. ASSERT(L"SetEvent on hAuthzAuditQueueLowEvent failed" && FALSE);
  3029. }
  3030. }
  3031. }
  3032. RtlLeaveCriticalSection(&pQueue->AuthzAuditQueueLock);
  3033. }
  3034. else
  3035. {
  3036. AuthzpFreeNonNull(pMarshalledAuditParams);
  3037. }
  3038. return b;
  3039. }
  3040. BOOL
  3041. AuthziAllocateAuditParams(
  3042. OUT PAUDIT_PARAMS * ppParams,
  3043. IN USHORT NumParams
  3044. )
  3045. /*++
  3046. Routine Description:
  3047. Allocate the AUDIT_PARAMS structure for the correct number of parameters.
  3048. Arguments:
  3049. ppParams - pointer to PAUDIT_PARAMS structure to be initialized.
  3050. NumParams - number of parameters passed in the var-arg section.
  3051. This must be SE_MAX_AUDIT_PARAMETERS or less.
  3052. Return Value:
  3053. Boolean: TRUE on success, FALSE on failure. Extended information available with GetLastError().
  3054. --*/
  3055. {
  3056. BOOL b = TRUE;
  3057. PAUDIT_PARAMS pAuditParams = NULL;
  3058. if (!ARGUMENT_PRESENT(ppParams))
  3059. {
  3060. SetLastError(ERROR_INVALID_PARAMETER);
  3061. return FALSE;
  3062. }
  3063. *ppParams = NULL;
  3064. //
  3065. // the first two params are always fixed. thus the total number
  3066. // is 2 + the passed number.
  3067. //
  3068. if ((NumParams + 2) > SE_MAX_AUDIT_PARAMETERS)
  3069. {
  3070. SetLastError(ERROR_INVALID_PARAMETER);
  3071. b = FALSE;
  3072. goto Cleanup;
  3073. }
  3074. pAuditParams = AuthzpAlloc(sizeof(AUDIT_PARAMS) + (sizeof(AUDIT_PARAM) * (NumParams + 2)));
  3075. if (AUTHZ_ALLOCATION_FAILED(pAuditParams))
  3076. {
  3077. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3078. b = FALSE;
  3079. goto Cleanup;
  3080. }
  3081. pAuditParams->Parameters = (PAUDIT_PARAM)((PUCHAR)pAuditParams + sizeof(AUDIT_PARAMS));
  3082. Cleanup:
  3083. if (!b)
  3084. {
  3085. AuthzpFreeNonNull(pAuditParams);
  3086. }
  3087. else
  3088. {
  3089. *ppParams = pAuditParams;
  3090. }
  3091. return b;
  3092. }
  3093. BOOL
  3094. AuthziInitializeAuditParamsWithRM(
  3095. IN DWORD Flags,
  3096. IN AUTHZ_RESOURCE_MANAGER_HANDLE hResourceManager,
  3097. IN USHORT NumParams,
  3098. OUT PAUDIT_PARAMS pParams,
  3099. ...
  3100. )
  3101. /*++
  3102. Routine Description:
  3103. Initialize the AUDIT_PARAMS structure based on the passed
  3104. data. This is the recommended way to init AUDIT_PARAMS. It is
  3105. faster than AuthzInitializeAuditParams and works with an
  3106. impersonating caller.
  3107. The caller passes in type ~ value pairs in the vararg section.
  3108. This function will initialize the corresponding array elements
  3109. based on each such pair. In case of certain types, there may
  3110. be more than one value argument required. This requirement
  3111. is documented next to each param-type.
  3112. Arguments:
  3113. pParams - pointer to AUDIT_PARAMS structure to be initialized
  3114. the size of pParams->Parameters member must be big enough
  3115. to hold NumParams elements. The caller must allocate
  3116. memory for this structure and its members.
  3117. hResourceManager - Handle to the Resource manager that is creating the audit.
  3118. Flags - control flags. one or more of the following:
  3119. APF_AuditSuccess
  3120. NumParams - number of parameters passed in the var-arg section.
  3121. This must be SE_MAX_AUDIT_PARAMETERS or less.
  3122. ... - The format of the variable arg portion is as follows:
  3123. <one of APT_ * flags> <zero or more values>
  3124. APT_String <pointer to null terminated string>
  3125. Flags:
  3126. AP_Filespec : treats the string as a filename
  3127. APT_Ulong <ulong value> [<object-type-index>]
  3128. Flags:
  3129. AP_FormatHex : number appears in hex
  3130. in eventlog
  3131. AP_AccessMask: number is treated as
  3132. an access-mask
  3133. Index to object type must follow
  3134. APT_Pointer <pointer/handle>
  3135. 32 bit on 32 bit systems and
  3136. 64 bit on 64 bit systems
  3137. APT_Sid <pointer to sid>
  3138. APT_Luid <Luid>
  3139. APT_Guid <pointer to guid>
  3140. APT_LogonId [<logon-id>]
  3141. Flags:
  3142. AP_PrimaryLogonId : logon-id is captured
  3143. from the process token.
  3144. No need to specify one.
  3145. AP_ClientLogonId : logon-id is captured
  3146. from the thread token.
  3147. No need to specify one.
  3148. no flags : need to supply a logon-id
  3149. APT_ObjectTypeList <ptr to obj type list> <obj-type-index>
  3150. Index to object type must be specified
  3151. APT_Time <filetime>
  3152. APT_Int64 <ULONGLONG or LARGE_INTEGER>
  3153. Return Value:
  3154. TRUE on success
  3155. FALSE otherwise
  3156. call GetLastError() to retrieve the errorcode,
  3157. which will be one of the following:
  3158. ERROR_INVALID_PARAMETER if one of the params is incorrect
  3159. Notes:
  3160. --*/
  3161. {
  3162. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hResourceManager;
  3163. PSID pUserSid = NULL;
  3164. DWORD dwError = NO_ERROR;
  3165. BOOL b = TRUE;
  3166. LUID AuthIdThread = {0};
  3167. va_list(arglist);
  3168. if (!ARGUMENT_PRESENT(hResourceManager) ||
  3169. !ARGUMENT_PRESENT(pParams) ||
  3170. (NumParams + AUTHZP_NUM_FIXED_HEADER_PARAMS) > SE_MAX_AUDIT_PARAMETERS)
  3171. {
  3172. dwError = ERROR_INVALID_PARAMETER;
  3173. goto Cleanup;
  3174. }
  3175. va_start(arglist, pParams);
  3176. //
  3177. // If we are not impersonating we want to use the sid stored
  3178. // in the RM as the user sid of the audit.
  3179. //
  3180. b = AuthzpGetThreadTokenInfo(
  3181. &pUserSid,
  3182. &AuthIdThread
  3183. );
  3184. if (!b)
  3185. {
  3186. dwError = GetLastError();
  3187. if (dwError == ERROR_NO_TOKEN)
  3188. {
  3189. //
  3190. // We are not impersonating ...
  3191. //
  3192. pUserSid = pRM->pUserSID;
  3193. dwError = NO_ERROR;
  3194. b = TRUE;
  3195. }
  3196. else
  3197. {
  3198. goto Cleanup;
  3199. }
  3200. }
  3201. //
  3202. // This is only a temporary solution and should be replaced after .net ships.
  3203. //
  3204. if (wcsncmp(pRM->szResourceManagerName, L"DS", 2) == 0)
  3205. {
  3206. Flags |= AUTHZP_INIT_PARAMS_SOURCE_DS;
  3207. }
  3208. b = AuthzpInitializeAuditParamsV(
  3209. Flags,
  3210. pParams,
  3211. &pUserSid,
  3212. NULL,
  3213. 0,
  3214. NumParams,
  3215. arglist
  3216. );
  3217. Cleanup:
  3218. if ( dwError != NO_ERROR )
  3219. {
  3220. SetLastError( dwError );
  3221. b = FALSE;
  3222. }
  3223. if ( !b )
  3224. {
  3225. if (pUserSid != pRM->pUserSID)
  3226. {
  3227. AuthzpFreeNonNull( pUserSid );
  3228. }
  3229. }
  3230. else
  3231. {
  3232. //
  3233. // ugly hack to mark the dynamically allocated sid so we
  3234. // know we'll have to free it in AuthziFreeAuditParam.
  3235. //
  3236. if (pUserSid != pRM->pUserSID)
  3237. {
  3238. pParams->Parameters->Flags |= AUTHZP_PARAM_FREE_SID;
  3239. }
  3240. else
  3241. {
  3242. pParams->Parameters->Flags &= ~AUTHZP_PARAM_FREE_SID;
  3243. }
  3244. }
  3245. va_end (arglist);
  3246. return b;
  3247. }
  3248. BOOL
  3249. AuthziInitializeAuditParamsFromArray(
  3250. IN DWORD Flags,
  3251. IN AUTHZ_RESOURCE_MANAGER_HANDLE hResourceManager,
  3252. IN USHORT NumParams,
  3253. IN PAUDIT_PARAM pParamArray,
  3254. OUT PAUDIT_PARAMS pParams
  3255. )
  3256. /*++
  3257. Routine Description:
  3258. Initialize the AUDIT_PARAMS structure based on the passed
  3259. data.
  3260. Arguments:
  3261. pParams - pointer to AUDIT_PARAMS structure to be initialized
  3262. the size of pParams->Parameters member must be big enough
  3263. to hold NumParams elements. The caller must allocate
  3264. memory for this structure and its members.
  3265. hResourceManager - Handle to the Resource manager that is creating the audit.
  3266. Flags - control flags. one or more of the following:
  3267. APF_AuditSuccess
  3268. pParamArray - an array of type AUDIT_PARAM
  3269. Return Value:
  3270. TRUE on success
  3271. FALSE otherwise
  3272. call GetLastError() to retrieve the errorcode,
  3273. which will be one of the following:
  3274. ERROR_INVALID_PARAMETER if one of the params is incorrect
  3275. Notes:
  3276. --*/
  3277. {
  3278. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hResourceManager;
  3279. DWORD dwError = NO_ERROR;
  3280. BOOL b = TRUE;
  3281. BOOL bImpersonating = TRUE;
  3282. PAUDIT_PARAM pParam = NULL;
  3283. LUID AuthIdThread;
  3284. PSID pThreadSID = NULL;
  3285. DWORD i;
  3286. //
  3287. // the first two params are always fixed. thus the total number
  3288. // is 2 + the passed number.
  3289. //
  3290. if (!ARGUMENT_PRESENT(hResourceManager) ||
  3291. !ARGUMENT_PRESENT(pParams) ||
  3292. !ARGUMENT_PRESENT(pParamArray) ||
  3293. (NumParams + AUTHZP_NUM_FIXED_HEADER_PARAMS) > SE_MAX_AUDIT_PARAMETERS)
  3294. {
  3295. dwError = ERROR_INVALID_PARAMETER;
  3296. goto Cleanup;
  3297. }
  3298. b = AuthzpGetThreadTokenInfo(
  3299. &pThreadSID,
  3300. &AuthIdThread
  3301. );
  3302. if (!b)
  3303. {
  3304. dwError = GetLastError();
  3305. if (dwError == ERROR_NO_TOKEN)
  3306. {
  3307. bImpersonating = FALSE;
  3308. dwError = NO_ERROR;
  3309. b = TRUE;
  3310. }
  3311. else
  3312. {
  3313. goto Cleanup;
  3314. }
  3315. }
  3316. pParams->Length = 0;
  3317. pParams->Flags = Flags;
  3318. pParams->Count = NumParams+AUTHZP_NUM_FIXED_HEADER_PARAMS;
  3319. pParam = pParams->Parameters;
  3320. //
  3321. // the first param is always the sid of the user in thread token
  3322. // if thread is not impersonating, sid in the primary token is used.
  3323. //
  3324. pParam->Type = APT_Sid;
  3325. if (bImpersonating)
  3326. {
  3327. pParam->Data0 = (ULONG_PTR) pThreadSID;
  3328. //
  3329. // ugly hack to mark the dynamically allocated sid so we
  3330. // know we'll have to free it in AuthziFreeAuditParam.
  3331. //
  3332. pParam->Flags |= AUTHZP_PARAM_FREE_SID;
  3333. }
  3334. else
  3335. {
  3336. pParam->Data0 = (ULONG_PTR) pRM->pUserSID;
  3337. pParam->Flags &= ~AUTHZP_PARAM_FREE_SID;
  3338. }
  3339. pParam++;
  3340. //
  3341. // the second param is always the sub-system name
  3342. //
  3343. pParam->Type = APT_String;
  3344. pParam->Data0 = (ULONG_PTR) pRM->szResourceManagerName;
  3345. pParam++;
  3346. //
  3347. // now initialize the rest using the array.
  3348. //
  3349. RtlCopyMemory(
  3350. pParam,
  3351. pParamArray,
  3352. sizeof(AUDIT_PARAM) * NumParams
  3353. );
  3354. //
  3355. // Walk through the parameters and increment by 2 the Data1 member of
  3356. // any instance of AccessMask or ObjectTypeList. This is done to correct
  3357. // for the usersid / subsystem elements that are inserted in the param
  3358. // array. The data1 member of these 2 types should point to the ObjectTypeIndex,
  3359. // which is otherwise off by 2.
  3360. //
  3361. for (i = 0; i < pParams->Count; i++)
  3362. {
  3363. ULONG TypeFlags = pParams->Parameters[i].Type;
  3364. if ((ApExtractType(TypeFlags) == APT_ObjectTypeList) ||
  3365. (ApExtractType(TypeFlags) == APT_Ulong && FLAG_ON(ApExtractFlags(TypeFlags), AP_AccessMask)))
  3366. {
  3367. pParams->Parameters[i].Data1 += 2;
  3368. }
  3369. }
  3370. Cleanup:
  3371. if ( dwError != NO_ERROR )
  3372. {
  3373. SetLastError( dwError );
  3374. b = FALSE;
  3375. AuthzpFreeNonNull( pThreadSID );
  3376. }
  3377. return b;
  3378. }
  3379. BOOL
  3380. AuthziInitializeAuditParams(
  3381. IN DWORD dwFlags,
  3382. OUT PAUDIT_PARAMS pParams,
  3383. OUT PSID* ppUserSid,
  3384. IN PCWSTR SubsystemName,
  3385. IN USHORT NumParams,
  3386. ...
  3387. )
  3388. /*++
  3389. Routine Description:
  3390. Initialize the AUDIT_PARAMS structure based on the passed
  3391. data.
  3392. The caller passes in type ~ value pairs in the vararg section.
  3393. This function will initialize the corresponding array elements
  3394. based on each such pair. In case of certain types, there may
  3395. be more than one value argument required. This requirement
  3396. is documented next to each param-type.
  3397. Arguments:
  3398. pParams - pointer to AUDIT_PARAMS structure to be initialized
  3399. the size of pParams->Parameters member must be big enough
  3400. to hold NumParams elements. The caller must allocate
  3401. memory for this structure and its members.
  3402. ppUserSid - pointer to user sid allocated. This sid is referenced
  3403. by the first parameter (index 0) in AUDIT_PARAMS structure.
  3404. The caller should free this by calling LocalFree
  3405. *after* freeing the AUDIT_PARAMS structure.
  3406. SubsystemName - name of Subsystem that is generating audit
  3407. dwFlags - control flags. one or more of the following:
  3408. APF_AuditSuccess
  3409. NumParams - number of parameters passed in the var-arg section.
  3410. This must be SE_MAX_AUDIT_PARAMETERS or less.
  3411. ... - The format of the variable arg portion is as follows:
  3412. <one of APT_ * flags> <zero or more values>
  3413. APT_String <pointer to null terminated string>
  3414. Flags:
  3415. AP_Filespec : treats the string as a filename
  3416. APT_Ulong <ulong value> [<object-type-index>]
  3417. Flags:
  3418. AP_FormatHex : number appears in hex
  3419. in eventlog
  3420. AP_AccessMask: number is treated as
  3421. an access-mask
  3422. Index to object type must follow
  3423. APT_Pointer <pointer/handle>
  3424. 32 bit on 32 bit systems and
  3425. 64 bit on 64 bit systems
  3426. APT_Sid <pointer to sid>
  3427. APT_Luid <Luid>
  3428. APT_Guid <pointer to guid>
  3429. APT_LogonId [<logon-id>]
  3430. Flags:
  3431. AP_PrimaryLogonId : logon-id is captured
  3432. from the process token.
  3433. No need to specify one.
  3434. AP_ClientLogonId : logon-id is captured
  3435. from the thread token.
  3436. No need to specify one.
  3437. no flags : need to supply a logon-id
  3438. APT_ObjectTypeList <ptr to obj type list> <obj-type-index>
  3439. Index to object type must be specified
  3440. APT_Time <filetime>
  3441. APT_Int64 <ULONGLONG or LARGE_INTEGER>
  3442. Return Value:
  3443. TRUE on success
  3444. FALSE otherwise
  3445. call GetLastError() to retrieve the errorcode,
  3446. which will be one of the following:
  3447. ERROR_INVALID_PARAMETER if one of the params is incorrect
  3448. Notes:
  3449. --*/
  3450. {
  3451. BOOL fResult = TRUE;
  3452. va_list(arglist);
  3453. *ppUserSid = NULL;
  3454. va_start (arglist, NumParams);
  3455. //
  3456. // Turn off any flags that don't belong. Only success/failure flag is permitted.
  3457. //
  3458. dwFlags = dwFlags & APF_ValidFlags;
  3459. UNREFERENCED_PARAMETER(SubsystemName);
  3460. fResult = AuthzpInitializeAuditParamsV(
  3461. dwFlags,
  3462. pParams,
  3463. ppUserSid,
  3464. NULL, // subsystemname will be forced to "Security"
  3465. 0,
  3466. NumParams,
  3467. arglist
  3468. );
  3469. if (!fResult)
  3470. {
  3471. goto Cleanup;
  3472. }
  3473. Cleanup:
  3474. if (!fResult)
  3475. {
  3476. if (AUTHZ_NON_NULL_PTR(*ppUserSid))
  3477. {
  3478. AuthzpFree(*ppUserSid);
  3479. *ppUserSid = NULL;
  3480. }
  3481. }
  3482. va_end (arglist);
  3483. return fResult;
  3484. }
  3485. BOOL
  3486. AuthziFreeAuditParams(
  3487. PAUDIT_PARAMS pParams
  3488. )
  3489. /*++
  3490. Routine Description
  3491. Frees the AUDIT_PARAMS created by AuthzAllocateInitializeAuditParamsWithRM.
  3492. Arguments
  3493. pParams - pointer to AUDIT_PARAMS.
  3494. Return Value
  3495. Boolean: TRUE on success, FALSE on failure.
  3496. --*/
  3497. {
  3498. if (!ARGUMENT_PRESENT(pParams))
  3499. {
  3500. SetLastError(ERROR_INVALID_PARAMETER);
  3501. return FALSE;
  3502. }
  3503. if (pParams->Parameters)
  3504. {
  3505. if (pParams->Parameters->Data0 &&
  3506. pParams->Parameters->Type == APT_Sid &&
  3507. (pParams->Parameters->Flags & AUTHZP_PARAM_FREE_SID))
  3508. {
  3509. AuthzpFree((PVOID)(pParams->Parameters->Data0));
  3510. }
  3511. }
  3512. AuthzpFree(pParams);
  3513. return TRUE;
  3514. }
  3515. BOOL
  3516. AuthziInitializeAuditEvent(
  3517. IN DWORD Flags,
  3518. IN AUTHZ_RESOURCE_MANAGER_HANDLE hRM,
  3519. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAET OPTIONAL,
  3520. IN PAUDIT_PARAMS pAuditParams OPTIONAL,
  3521. IN AUTHZ_AUDIT_QUEUE_HANDLE hAuditQueue OPTIONAL,
  3522. IN DWORD dwTimeOut,
  3523. IN PWSTR szOperationType,
  3524. IN PWSTR szObjectType,
  3525. IN PWSTR szObjectName,
  3526. IN PWSTR szAdditionalInfo OPTIONAL,
  3527. OUT PAUTHZ_AUDIT_EVENT_HANDLE phAuditEvent
  3528. )
  3529. /*++
  3530. Routine Description:
  3531. Allocates and initializes an AUTHZ_AUDIT_EVENT_HANDLE. The handle is used for storing information
  3532. for audit generation per AuthzAccessCheck().
  3533. Arguments:
  3534. phAuditEvent - pointer to AUTHZ_AUDIT_EVENT_HANDLE. Space for this is allocated in the function.
  3535. Flags - Audit flags. Currently defined bits are:
  3536. AUTHZ_NO_SUCCESS_AUDIT - disables generation of success audits
  3537. AUTHZ_NO_FAILURE_AUDIT - disables generation of failure audits
  3538. AUTHZ_DS_CATEGORY_FLAG - swithces the default audit category from OBJECT_ACCESS to DS_ACCESS.
  3539. AUTHZ_NO_ALLOC_STRINGS - storage space is not allocated for the 4 wide character strings. Rather,
  3540. the handle will only hold pointers to resource manager memory.
  3541. hRM - handle to a Resource Manager.
  3542. hAET - pointer to an AUTHZ_AUDIT_EVENT_TYPE structure. This is needed if the resource manager
  3543. is creating its own audit types. This is not needed for generic object operation audits.
  3544. pAuditParams - If this is specified, then pAuditParams will be used to
  3545. create the audit. If NULL is passed, then a generic AUDIT_PARAMS will
  3546. be constructed that is suitable for the generic object access audit.
  3547. hAuditQueue - queue object created with AuthzInitializeAuditQueue. If none is specified, the
  3548. default RM queue will be used.
  3549. dwTimeOut - milliseconds that a thread attempting to generate an audit with this
  3550. AUTHZ_AUDIT_EVENT_HANDLE should wait for access to the queue. Use INFINITE to
  3551. specify an unlimited timeout.
  3552. szOperationType - Resource manager defined string that indicates the operation being
  3553. performed that is to be audited.
  3554. szObjectType - Resource manager defined string that indicates the type of object being
  3555. accessed.
  3556. szObjectName - the name of the specific object being accessed.
  3557. szAdditionalInfo - Resource Manager defined string for additional audit information.
  3558. Return Value:
  3559. Returns TRUE if successful, FALSE if unsuccessful.
  3560. Extended information available with GetLastError().
  3561. --*/
  3562. {
  3563. PAUTHZI_AUDIT_EVENT pAuditEvent = NULL;
  3564. BOOL b = TRUE;
  3565. BOOL bRef = FALSE;
  3566. DWORD dwStringSize = 0;
  3567. DWORD dwObjectTypeLength = 0;
  3568. DWORD dwObjectNameLength = 0;
  3569. DWORD dwOperationTypeLength = 0;
  3570. DWORD dwAdditionalInfoLength = 0;
  3571. PAUTHZI_RESOURCE_MANAGER pRM = (PAUTHZI_RESOURCE_MANAGER) hRM;
  3572. if (!ARGUMENT_PRESENT(phAuditEvent) ||
  3573. (!ARGUMENT_PRESENT(hAET) && !ARGUMENT_PRESENT(hRM)) ||
  3574. !ARGUMENT_PRESENT(szOperationType) ||
  3575. !ARGUMENT_PRESENT(szObjectType) ||
  3576. !ARGUMENT_PRESENT(szObjectName) ||
  3577. !ARGUMENT_PRESENT(szAdditionalInfo))
  3578. {
  3579. SetLastError(ERROR_INVALID_PARAMETER);
  3580. return FALSE;
  3581. }
  3582. *phAuditEvent = NULL;
  3583. //
  3584. // Allocate and initialize a new AUTHZI_AUDIT_EVENT.
  3585. //
  3586. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  3587. {
  3588. dwStringSize = 0;
  3589. }
  3590. else
  3591. {
  3592. dwOperationTypeLength = (DWORD) wcslen(szOperationType) + 1;
  3593. dwObjectTypeLength = (DWORD) wcslen(szObjectType) + 1;
  3594. dwObjectNameLength = (DWORD) wcslen(szObjectName) + 1;
  3595. dwAdditionalInfoLength = (DWORD) wcslen(szAdditionalInfo) + 1;
  3596. dwStringSize = sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength + dwAdditionalInfoLength);
  3597. }
  3598. pAuditEvent = (PAUTHZI_AUDIT_EVENT) AuthzpAlloc(sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize);
  3599. if (AUTHZ_ALLOCATION_FAILED(pAuditEvent))
  3600. {
  3601. b = FALSE;
  3602. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3603. goto Cleanup;
  3604. }
  3605. RtlZeroMemory(
  3606. pAuditEvent,
  3607. sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize
  3608. );
  3609. if (FLAG_ON(Flags, AUTHZ_NO_ALLOC_STRINGS))
  3610. {
  3611. pAuditEvent->szOperationType = szOperationType;
  3612. pAuditEvent->szObjectType = szObjectType;
  3613. pAuditEvent->szObjectName = szObjectName;
  3614. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  3615. }
  3616. else
  3617. {
  3618. //
  3619. // Set the string pointers into the contiguous memory.
  3620. //
  3621. pAuditEvent->szOperationType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT));
  3622. pAuditEvent->szObjectType = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3623. + (sizeof(WCHAR) * dwOperationTypeLength));
  3624. pAuditEvent->szObjectName = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3625. + (sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength)));
  3626. pAuditEvent->szAdditionalInfo = (PWSTR)((PUCHAR)pAuditEvent + sizeof(AUTHZI_AUDIT_EVENT)
  3627. + (sizeof(WCHAR) * (dwOperationTypeLength + dwObjectTypeLength + dwObjectNameLength)));
  3628. RtlCopyMemory(
  3629. pAuditEvent->szOperationType,
  3630. szOperationType,
  3631. sizeof(WCHAR) * dwOperationTypeLength
  3632. );
  3633. RtlCopyMemory(
  3634. pAuditEvent->szObjectType,
  3635. szObjectType,
  3636. sizeof(WCHAR) * dwObjectTypeLength
  3637. );
  3638. RtlCopyMemory(
  3639. pAuditEvent->szObjectName,
  3640. szObjectName,
  3641. sizeof(WCHAR) * dwObjectNameLength
  3642. );
  3643. RtlCopyMemory(
  3644. pAuditEvent->szAdditionalInfo,
  3645. szAdditionalInfo,
  3646. sizeof(WCHAR) * dwAdditionalInfoLength
  3647. );
  3648. }
  3649. //
  3650. // Use the passed audit event type if present, otherwise use the RM's generic Audit Event.
  3651. //
  3652. if (ARGUMENT_PRESENT(hAET))
  3653. {
  3654. pAuditEvent->hAET = hAET;
  3655. }
  3656. else
  3657. {
  3658. if (FLAG_ON(Flags, AUTHZ_DS_CATEGORY_FLAG))
  3659. {
  3660. pAuditEvent->hAET = pRM->hAETDS;
  3661. }
  3662. else
  3663. {
  3664. pAuditEvent->hAET = pRM->hAET;
  3665. }
  3666. }
  3667. AuthzpReferenceAuditEventType(pAuditEvent->hAET);
  3668. bRef = TRUE;
  3669. //
  3670. // Use the specified queue, if it exists. Else use the RM queue.
  3671. //
  3672. if (ARGUMENT_PRESENT(hAuditQueue))
  3673. {
  3674. pAuditEvent->hAuditQueue = hAuditQueue;
  3675. }
  3676. else if (ARGUMENT_PRESENT(hRM))
  3677. {
  3678. pAuditEvent->hAuditQueue = pRM->hAuditQueue;
  3679. }
  3680. pAuditEvent->pAuditParams = pAuditParams;
  3681. pAuditEvent->Flags = Flags;
  3682. pAuditEvent->dwTimeOut = dwTimeOut;
  3683. pAuditEvent->dwSize = sizeof(AUTHZI_AUDIT_EVENT) + dwStringSize;
  3684. Cleanup:
  3685. if (!b)
  3686. {
  3687. if (bRef)
  3688. {
  3689. AuthzpDereferenceAuditEventType(pAuditEvent->hAET);
  3690. }
  3691. AuthzpFreeNonNull(pAuditEvent);
  3692. }
  3693. else
  3694. {
  3695. *phAuditEvent = (AUTHZ_AUDIT_EVENT_HANDLE) pAuditEvent;
  3696. }
  3697. return b;
  3698. }
  3699. BOOL
  3700. AuthziModifyAuditEvent(
  3701. IN DWORD Flags,
  3702. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  3703. IN DWORD NewFlags,
  3704. IN PWSTR szOperationType,
  3705. IN PWSTR szObjectType,
  3706. IN PWSTR szObjectName,
  3707. IN PWSTR szAdditionalInfo
  3708. )
  3709. {
  3710. return AuthziModifyAuditEvent2(
  3711. Flags,
  3712. hAuditEvent,
  3713. NewFlags,
  3714. szOperationType,
  3715. szObjectType,
  3716. szObjectName,
  3717. szAdditionalInfo,
  3718. NULL
  3719. );
  3720. }
  3721. BOOL
  3722. AuthziModifyAuditEvent2(
  3723. IN DWORD Flags,
  3724. IN AUTHZ_AUDIT_EVENT_HANDLE hAuditEvent,
  3725. IN DWORD NewFlags,
  3726. IN PWSTR szOperationType,
  3727. IN PWSTR szObjectType,
  3728. IN PWSTR szObjectName,
  3729. IN PWSTR szAdditionalInfo,
  3730. IN PWSTR szAdditionalInfo2
  3731. )
  3732. /*++
  3733. Routine Description
  3734. Arguments
  3735. Flags - flags to specify which field of the hAuditEvent to modify. Valid flags are:
  3736. AUTHZ_AUDIT_EVENT_FLAGS
  3737. AUTHZ_AUDIT_EVENT_OPERATION_TYPE
  3738. AUTHZ_AUDIT_EVENT_OBJECT_TYPE
  3739. AUTHZ_AUDIT_EVENT_OBJECT_NAME
  3740. AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO
  3741. AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO2
  3742. hAuditEvent - handle to modify. Must be created with AUTHZ_NO_ALLOC_STRINGS flag.
  3743. NewFlags - replacement flags for hAuditEvent.
  3744. szOperationType - replacement string for hAuditEvent.
  3745. szObjectType - replacement string for hAuditEvent.
  3746. szObjectName - replacement string for hAuditEvent.
  3747. szAdditionalInfo - replacement string for hAuditEvent.
  3748. Return Value
  3749. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  3750. --*/
  3751. {
  3752. PAUTHZI_AUDIT_EVENT pAuditEvent = (PAUTHZI_AUDIT_EVENT) hAuditEvent;
  3753. if ((!ARGUMENT_PRESENT(hAuditEvent)) ||
  3754. (Flags & ~AUTHZ_VALID_MODIFY_AUDIT_EVENT_FLAGS) ||
  3755. (!FLAG_ON(pAuditEvent->Flags, AUTHZ_NO_ALLOC_STRINGS)))
  3756. {
  3757. SetLastError(ERROR_INVALID_PARAMETER);
  3758. return FALSE;
  3759. }
  3760. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_FLAGS))
  3761. {
  3762. pAuditEvent->Flags = NewFlags;
  3763. }
  3764. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OPERATION_TYPE))
  3765. {
  3766. pAuditEvent->szOperationType = szOperationType;
  3767. }
  3768. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OBJECT_TYPE))
  3769. {
  3770. pAuditEvent->szObjectType = szObjectType;
  3771. }
  3772. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_OBJECT_NAME))
  3773. {
  3774. pAuditEvent->szObjectName = szObjectName;
  3775. }
  3776. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO))
  3777. {
  3778. pAuditEvent->szAdditionalInfo = szAdditionalInfo;
  3779. }
  3780. if (FLAG_ON(Flags, AUTHZ_AUDIT_EVENT_ADDITIONAL_INFO2))
  3781. {
  3782. pAuditEvent->szAdditionalInfo2 = szAdditionalInfo2;
  3783. }
  3784. return TRUE;
  3785. }
  3786. BOOLEAN
  3787. AuthzInitialize(
  3788. IN PVOID hmod,
  3789. IN ULONG Reason,
  3790. IN PCONTEXT Context
  3791. )
  3792. /*++
  3793. Routine Description
  3794. This is the dll initialization rotuine.
  3795. Arguments
  3796. Standard arguments.
  3797. Return Value
  3798. Boolean: TRUE on success; FALSE on failure.
  3799. --*/
  3800. {
  3801. UNREFERENCED_PARAMETER(hmod);
  3802. UNREFERENCED_PARAMETER(Context);
  3803. switch (Reason)
  3804. {
  3805. case DLL_PROCESS_ATTACH:
  3806. SafeAllocaInitialize(
  3807. SAFEALLOCA_USE_DEFAULT,
  3808. SAFEALLOCA_USE_DEFAULT,
  3809. NULL,
  3810. NULL);
  3811. break;
  3812. case DLL_PROCESS_DETACH:
  3813. break;
  3814. }
  3815. return TRUE;
  3816. }
  3817. #define PER_USER_POLICY_KEY_NAME L"SYSTEM\\CurrentControlSet\\Control\\Lsa\\Audit\\PerUserAuditing"
  3818. #define PER_USER_POLICY_SYSTEM_KEY_NAME L"SYSTEM\\CurrentControlSet\\Control\\Lsa\\Audit\\PerUserAuditing\\System"
  3819. #define SYSTEM_RM_NAME L"System"
  3820. #define POLICY_BUFFER_BYTE_SIZE 8
  3821. BOOL
  3822. AuthziSetAuditPolicy(
  3823. IN DWORD dwFlags,
  3824. IN AUTHZ_CLIENT_CONTEXT_HANDLE hContext,
  3825. IN PCWSTR szResourceManager OPTIONAL,
  3826. IN PTOKEN_AUDIT_POLICY pPolicy
  3827. )
  3828. /*++
  3829. Routine Description:
  3830. This routine sets a per user policy for a user.
  3831. Arguments:
  3832. dwFlags - currently unused.
  3833. hContext - handle to a client context for which to set the policy.
  3834. szResourceManager - should be NULL. For future use.
  3835. pPolicy - the policy that is to be set for the user.
  3836. Return Value:
  3837. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  3838. --*/
  3839. {
  3840. PAUTHZI_CLIENT_CONTEXT pContext = (PAUTHZI_CLIENT_CONTEXT) hContext;
  3841. DWORD dwError = ERROR_SUCCESS;
  3842. HKEY hRMRoot = NULL;
  3843. LPWSTR szSid = NULL;
  3844. BOOL b;
  3845. DWORD Disposition;
  3846. UCHAR RegPolicy[POLICY_BUFFER_BYTE_SIZE];
  3847. UNREFERENCED_PARAMETER(dwFlags);
  3848. RtlZeroMemory(RegPolicy, sizeof(RegPolicy));
  3849. if (NULL == hContext || NULL == pPolicy)
  3850. {
  3851. b = FALSE;
  3852. dwError = ERROR_INVALID_PARAMETER;
  3853. goto Cleanup;
  3854. }
  3855. //
  3856. // Only allow System RM to be specified. If no RM is given then default to system.
  3857. //
  3858. if (NULL == szResourceManager || 0 == wcsncmp(
  3859. SYSTEM_RM_NAME,
  3860. szResourceManager,
  3861. sizeof(SYSTEM_RM_NAME) / sizeof(WCHAR)
  3862. ))
  3863. {
  3864. dwError = RegCreateKeyEx(
  3865. HKEY_LOCAL_MACHINE,
  3866. PER_USER_POLICY_SYSTEM_KEY_NAME,
  3867. 0,
  3868. NULL,
  3869. 0,
  3870. KEY_SET_VALUE,
  3871. NULL,
  3872. &hRMRoot,
  3873. &Disposition
  3874. );
  3875. if (ERROR_SUCCESS != dwError)
  3876. {
  3877. b = FALSE;
  3878. goto Cleanup;
  3879. }
  3880. }
  3881. else
  3882. {
  3883. b = FALSE;
  3884. dwError = ERROR_INVALID_PARAMETER;
  3885. goto Cleanup;
  3886. }
  3887. b = ConvertSidToStringSid(
  3888. pContext->Sids[0].Sid,
  3889. &szSid
  3890. );
  3891. if (!b)
  3892. {
  3893. dwError = GetLastError();
  3894. goto Cleanup;
  3895. }
  3896. b = AuthzpConstructRegistryPolicyPerUserAuditing(
  3897. pPolicy,
  3898. (PULONGLONG)RegPolicy
  3899. );
  3900. if (!b)
  3901. {
  3902. dwError = GetLastError();
  3903. goto Cleanup;
  3904. }
  3905. dwError = RegSetValueEx(
  3906. hRMRoot,
  3907. szSid,
  3908. 0,
  3909. REG_BINARY,
  3910. RegPolicy,
  3911. sizeof(RegPolicy)
  3912. );
  3913. if (ERROR_SUCCESS != dwError)
  3914. {
  3915. b = FALSE;
  3916. goto Cleanup;
  3917. }
  3918. Cleanup:
  3919. if (!b)
  3920. {
  3921. SetLastError(dwError);
  3922. }
  3923. if (hRMRoot)
  3924. {
  3925. dwError = RegCloseKey(hRMRoot);
  3926. ASSERT(ERROR_SUCCESS == dwError);
  3927. }
  3928. if (szSid)
  3929. {
  3930. AuthzpFree(szSid);
  3931. }
  3932. return b;
  3933. }
  3934. BOOL
  3935. AuthziQueryAuditPolicy(
  3936. IN DWORD dwFlags,
  3937. IN AUTHZ_CLIENT_CONTEXT_HANDLE hContext,
  3938. IN PCWSTR szResourceManager OPTIONAL,
  3939. IN DWORD dwEventID,
  3940. OUT PTOKEN_AUDIT_POLICY pPolicy,
  3941. IN OUT PDWORD pPolicySize
  3942. )
  3943. /*++
  3944. Routine Description:
  3945. This function retrieves the audit policy for a specific context handle.
  3946. Arguments:
  3947. dwFlags - TBD.
  3948. hContext - context handle for the target user.
  3949. szResourceManager - Must be NULL. For future use.
  3950. dwEventID - Should be zero. For future use.
  3951. pPolicy - pointer to a structure storing the policy.
  3952. pPolicySize - pointer to DWORD containing size of pPolicy buffer.
  3953. Return Value:
  3954. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  3955. --*/
  3956. {
  3957. PAUTHZI_CLIENT_CONTEXT pContext = (PAUTHZI_CLIENT_CONTEXT) hContext;
  3958. DWORD dwError = ERROR_SUCCESS;
  3959. HKEY hRMRoot = NULL;
  3960. DWORD Type;
  3961. BOOL b;
  3962. NTSTATUS Status;
  3963. UCHAR ValueBuffer[POLICY_BUFFER_BYTE_SIZE];
  3964. DWORD BufferSize = sizeof(ValueBuffer);
  3965. UNICODE_STRING szSid = {0};
  3966. WCHAR StringBuffer[256];
  3967. UNREFERENCED_PARAMETER(dwFlags);
  3968. UNREFERENCED_PARAMETER(dwEventID);
  3969. RtlZeroMemory(ValueBuffer, sizeof(ValueBuffer));
  3970. if (NULL == pContext || NULL == pPolicySize || NULL == pPolicy)
  3971. {
  3972. dwError = ERROR_INVALID_PARAMETER;
  3973. b = FALSE;
  3974. goto Cleanup;
  3975. }
  3976. if (NULL == szResourceManager || 0 == wcsncmp(
  3977. SYSTEM_RM_NAME,
  3978. szResourceManager,
  3979. sizeof(SYSTEM_RM_NAME) / sizeof(WCHAR)
  3980. ))
  3981. {
  3982. //
  3983. // Default to the system RM.
  3984. //
  3985. dwError = RegOpenKeyEx(
  3986. HKEY_LOCAL_MACHINE,
  3987. PER_USER_POLICY_SYSTEM_KEY_NAME,
  3988. 0,
  3989. KEY_QUERY_VALUE,
  3990. &hRMRoot
  3991. );
  3992. if (dwError != ERROR_SUCCESS)
  3993. {
  3994. b = FALSE;
  3995. goto Cleanup;
  3996. }
  3997. }
  3998. else
  3999. {
  4000. //
  4001. // For now no RM can be specified.
  4002. //
  4003. dwError = ERROR_INVALID_PARAMETER;
  4004. b = FALSE;
  4005. goto Cleanup;
  4006. }
  4007. RtlZeroMemory(
  4008. StringBuffer,
  4009. sizeof(StringBuffer)
  4010. );
  4011. szSid.Buffer = (PWSTR)StringBuffer;
  4012. szSid.Length = 0;
  4013. szSid.MaximumLength = sizeof(StringBuffer);
  4014. Status = RtlConvertSidToUnicodeString(
  4015. &szSid,
  4016. pContext->Sids[0].Sid,
  4017. FALSE
  4018. );
  4019. if (ERROR_BUFFER_OVERFLOW == Status)
  4020. {
  4021. Status = RtlConvertSidToUnicodeString(
  4022. &szSid,
  4023. pContext->Sids[0].Sid,
  4024. TRUE
  4025. );
  4026. }
  4027. if (!NT_SUCCESS(Status))
  4028. {
  4029. dwError = RtlNtStatusToDosError(Status);
  4030. b = FALSE;
  4031. goto Cleanup;
  4032. }
  4033. //
  4034. // Get the policy value for the SID under the given RM.
  4035. //
  4036. dwError = RegQueryValueEx(
  4037. hRMRoot,
  4038. szSid.Buffer,
  4039. NULL,
  4040. &Type,
  4041. ValueBuffer,
  4042. &BufferSize
  4043. );
  4044. if (ERROR_SUCCESS != dwError)
  4045. {
  4046. b = FALSE;
  4047. goto Cleanup;
  4048. }
  4049. //
  4050. // Sanity check the buffer type.
  4051. //
  4052. if (REG_BINARY != Type)
  4053. {
  4054. b = FALSE;
  4055. dwError = ERROR_INVALID_DATA;
  4056. goto Cleanup;
  4057. }
  4058. b = AuthzpConstructPolicyPerUserAuditing(
  4059. *((PULONGLONG) ValueBuffer),
  4060. (PTOKEN_AUDIT_POLICY) pPolicy,
  4061. pPolicySize
  4062. );
  4063. if (!b)
  4064. {
  4065. dwError = GetLastError();
  4066. goto Cleanup;
  4067. }
  4068. Cleanup:
  4069. if (!b)
  4070. {
  4071. SetLastError(dwError);
  4072. }
  4073. if (szSid.Buffer != StringBuffer)
  4074. {
  4075. RtlFreeUnicodeString(&szSid);
  4076. }
  4077. if (hRMRoot)
  4078. {
  4079. RegCloseKey(hRMRoot);
  4080. }
  4081. return b;
  4082. }
  4083. BOOL
  4084. AuthziSourceAudit(
  4085. IN DWORD dwFlags,
  4086. IN USHORT CategoryId,
  4087. IN USHORT AuditId,
  4088. IN PWSTR szSource,
  4089. IN PSID pUserSid OPTIONAL,
  4090. IN USHORT Count,
  4091. ...
  4092. )
  4093. /**
  4094. Routine Description:
  4095. This is used to generate an audit with any source. An audit of type
  4096. SE_AUDITID_GENERIC_AUDIT_EVENT is sent to the LSA, and the event viewer
  4097. interprets this audit in a special manner. The first 2 parameters will be
  4098. treated as the actual source and id to be displayed in the security log. The
  4099. source listed must be a valid source listed under the EventLog\Security key.
  4100. Arguments:
  4101. dwFlags - APF_AuditSuccess
  4102. CategoryId - The category of the audit.
  4103. AuditId - The audit id to be generated.
  4104. szSource - the Source that should be listed in the security log.
  4105. pUserSid - optional pointer to Sid for audit to be created as.
  4106. Count - number of parameters in the VA section.
  4107. ... - VA list of parameters, the semantics of which are described
  4108. in the comment for AuthziInitializeAuditParams.
  4109. Return Value:
  4110. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  4111. **/
  4112. {
  4113. BOOL b;
  4114. AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAET = NULL;
  4115. AUTHZ_AUDIT_EVENT_HANDLE hAE = NULL;
  4116. PAUDIT_PARAMS pParams = NULL;
  4117. PSID pDummySid = NULL;
  4118. va_list arglist;
  4119. va_start(
  4120. arglist,
  4121. Count
  4122. );
  4123. //
  4124. // add in 2 because we store the actual audit id and the source
  4125. // string in the audit params.
  4126. //
  4127. b = AuthziAllocateAuditParams(
  4128. &pParams,
  4129. Count + 2
  4130. );
  4131. if (!b)
  4132. {
  4133. goto Cleanup;
  4134. }
  4135. b = AuthziInitializeAuditEventType(
  4136. 0,
  4137. CategoryId,
  4138. SE_AUDITID_GENERIC_AUDIT_EVENT,
  4139. Count + 2,
  4140. &hAET
  4141. );
  4142. if (!b)
  4143. {
  4144. goto Cleanup;
  4145. }
  4146. b = AuthzpInitializeAuditParamsV(
  4147. dwFlags | AUTHZP_INIT_PARAMS_SOURCE_INFO,
  4148. pParams,
  4149. &pDummySid,
  4150. szSource,
  4151. AuditId,
  4152. Count,
  4153. arglist
  4154. );
  4155. if (!b)
  4156. {
  4157. goto Cleanup;
  4158. }
  4159. if (pUserSid)
  4160. {
  4161. //
  4162. // this is ugly, but currently there is no other way
  4163. //
  4164. pParams->Parameters[0].Data0 = (ULONG_PTR) pUserSid;
  4165. }
  4166. b = AuthziInitializeAuditEvent(
  4167. 0,
  4168. NULL,
  4169. hAET,
  4170. pParams,
  4171. NULL,
  4172. INFINITE,
  4173. L"",
  4174. L"",
  4175. L"",
  4176. L"",
  4177. &hAE
  4178. );
  4179. if (!b)
  4180. {
  4181. goto Cleanup;
  4182. }
  4183. b = AuthziLogAuditEvent(
  4184. 0,
  4185. hAE,
  4186. NULL
  4187. );
  4188. if (!b)
  4189. {
  4190. goto Cleanup;
  4191. }
  4192. Cleanup:
  4193. va_end(arglist);
  4194. if (hAET)
  4195. {
  4196. AuthziFreeAuditEventType(
  4197. hAET
  4198. );
  4199. }
  4200. if (hAE)
  4201. {
  4202. AuthzFreeAuditEvent(
  4203. hAE
  4204. );
  4205. }
  4206. if (pParams)
  4207. {
  4208. AuthziFreeAuditParams(
  4209. pParams
  4210. );
  4211. }
  4212. if (pDummySid)
  4213. {
  4214. AuthzpFree(
  4215. pDummySid
  4216. );
  4217. }
  4218. return b;
  4219. }
  4220. BOOL
  4221. AuthzInstallSecurityEventSource(
  4222. IN DWORD dwFlags,
  4223. IN PAUTHZ_SOURCE_SCHEMA_REGISTRATION pRegistration
  4224. )
  4225. /**
  4226. Routine Description:
  4227. This installs a 3rd party as a security event source.
  4228. - add the name to the security sources key
  4229. Arguments:
  4230. Return Value:
  4231. **/
  4232. {
  4233. HKEY hkSecurity = NULL;
  4234. DWORD dwError;
  4235. BOOL b = TRUE;
  4236. PWCHAR pBuffer = NULL;
  4237. DWORD dwDisp;
  4238. HKEY hkSource = NULL;
  4239. HKEY hkObjectNames = NULL;
  4240. DWORD i;
  4241. #if 0
  4242. DWORD dwType;
  4243. DWORD dwLength = 0;
  4244. DWORD dwBuffer;
  4245. #endif
  4246. UNREFERENCED_PARAMETER(dwFlags);
  4247. if (NULL == pRegistration)
  4248. {
  4249. b = FALSE;
  4250. dwError = ERROR_INVALID_PARAMETER;
  4251. goto Cleanup;
  4252. }
  4253. #define SECURITY_KEY_NAME L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security"
  4254. //
  4255. // Open the Security key.
  4256. //
  4257. dwError = RegOpenKeyEx(
  4258. HKEY_LOCAL_MACHINE,
  4259. SECURITY_KEY_NAME,
  4260. 0,
  4261. KEY_READ | KEY_WRITE,
  4262. &hkSecurity
  4263. );
  4264. if (ERROR_SUCCESS != dwError)
  4265. {
  4266. b = FALSE;
  4267. goto Cleanup;
  4268. }
  4269. //
  4270. // First make sure that there is not already an installed EventSource with the specified name.
  4271. // If createkey returns the wrong disposition then we know this source is already installed.
  4272. //
  4273. dwError = RegCreateKeyEx(
  4274. hkSecurity,
  4275. pRegistration->szEventSourceName,
  4276. 0,
  4277. NULL,
  4278. 0,
  4279. KEY_WRITE,
  4280. NULL,
  4281. &hkSource,
  4282. &dwDisp
  4283. );
  4284. if (ERROR_SUCCESS != dwError)
  4285. {
  4286. b = FALSE;
  4287. goto Cleanup;
  4288. }
  4289. if (REG_OPENED_EXISTING_KEY == dwDisp)
  4290. {
  4291. b = FALSE;
  4292. dwError = ERROR_OBJECT_ALREADY_EXISTS;
  4293. goto Cleanup;
  4294. }
  4295. ASSERT(dwDisp == REG_CREATED_NEW_KEY);
  4296. dwError = RegSetValueEx(
  4297. hkSource,
  4298. L"EventSourceFlags",
  4299. 0,
  4300. REG_DWORD,
  4301. (LPBYTE)&pRegistration->dwFlags,
  4302. sizeof(DWORD)
  4303. );
  4304. if (ERROR_SUCCESS != dwError)
  4305. {
  4306. b = FALSE;
  4307. goto Cleanup;
  4308. }
  4309. //
  4310. // We created the new key for the Source. We are the only instance of
  4311. // this EventSource being installed. Continue and add the message file
  4312. // and access bit file information under the newly formed Source key.
  4313. //
  4314. if (pRegistration->szEventMessageFile)
  4315. {
  4316. dwError = RegSetValueEx(
  4317. hkSource,
  4318. L"EventMessageFile",
  4319. 0,
  4320. REG_SZ,
  4321. (LPBYTE)pRegistration->szEventMessageFile,
  4322. (DWORD)(sizeof(WCHAR) * (wcslen(pRegistration->szEventMessageFile) + 1))
  4323. );
  4324. if (ERROR_SUCCESS != dwError)
  4325. {
  4326. b = FALSE;
  4327. goto Cleanup;
  4328. }
  4329. }
  4330. if (pRegistration->szEventAccessStringsFile)
  4331. {
  4332. dwError = RegSetValueEx(
  4333. hkSource,
  4334. L"ParameterMessageFile",
  4335. 0,
  4336. REG_SZ,
  4337. (LPBYTE)pRegistration->szEventAccessStringsFile,
  4338. (DWORD)(sizeof(WCHAR) * (wcslen(pRegistration->szEventAccessStringsFile) + 1))
  4339. );
  4340. if (ERROR_SUCCESS != dwError)
  4341. {
  4342. b = FALSE;
  4343. goto Cleanup;
  4344. }
  4345. }
  4346. if (pRegistration->szExecutableImagePath)
  4347. {
  4348. dwError = RegSetValueEx(
  4349. hkSource,
  4350. L"ExecutableImagePath",
  4351. 0,
  4352. REG_MULTI_SZ,
  4353. (LPBYTE)pRegistration->szExecutableImagePath,
  4354. (DWORD)(sizeof(WCHAR) * (wcslen(pRegistration->szExecutableImagePath) + 1))
  4355. );
  4356. if (ERROR_SUCCESS != dwError)
  4357. {
  4358. b = FALSE;
  4359. goto Cleanup;
  4360. }
  4361. }
  4362. if (pRegistration->szEventSourceXmlSchemaFile)
  4363. {
  4364. dwError = RegSetValueEx(
  4365. hkSource,
  4366. L"XmlSchemaFile",
  4367. 0,
  4368. REG_SZ,
  4369. (LPBYTE)pRegistration->szEventSourceXmlSchemaFile,
  4370. (DWORD)(sizeof(WCHAR) * (wcslen(pRegistration->szEventSourceXmlSchemaFile) + 1))
  4371. );
  4372. if (ERROR_SUCCESS != dwError)
  4373. {
  4374. b = FALSE;
  4375. goto Cleanup;
  4376. }
  4377. }
  4378. // if (pRegistration->szCategoryMessageFile)
  4379. // {
  4380. // dwError = RegSetValueEx(
  4381. // hkSource,
  4382. // L"CategoryMessageFile",
  4383. // 0,
  4384. // REG_SZ,
  4385. // (LPBYTE)pRegistration->szCategoryMessageFile,
  4386. // (DWORD)(sizeof(WCHAR) * (wcslen(pRegistration->szEventMessageFile) + 1))
  4387. // );
  4388. //
  4389. // if (ERROR_SUCCESS != dwError)
  4390. // {
  4391. // b = FALSE;
  4392. // goto Cleanup;
  4393. // }
  4394. // }
  4395. if (pRegistration->dwObjectTypeNameCount)
  4396. {
  4397. //
  4398. // There are object names to be registered. Create an ObjectNames subkey under
  4399. // hkSource and populate it.
  4400. //
  4401. dwError = RegCreateKeyEx(
  4402. hkSource,
  4403. L"ObjectNames",
  4404. 0,
  4405. NULL,
  4406. 0,
  4407. KEY_WRITE,
  4408. NULL,
  4409. &hkObjectNames,
  4410. &dwDisp
  4411. );
  4412. if (ERROR_SUCCESS != dwError)
  4413. {
  4414. b = FALSE;
  4415. goto Cleanup;
  4416. }
  4417. //
  4418. // It would be strange for this to not be a brand new key, given that we just
  4419. // created the parent of hkObjectNames a few lines above...
  4420. //
  4421. ASSERT(dwDisp == REG_CREATED_NEW_KEY);
  4422. for (i = 0; i < pRegistration->dwObjectTypeNameCount; i++)
  4423. {
  4424. dwError = RegSetValueEx(
  4425. hkObjectNames,
  4426. pRegistration->ObjectTypeNames[i].szObjectTypeName,
  4427. 0,
  4428. REG_DWORD,
  4429. (LPBYTE)&(pRegistration->ObjectTypeNames[i].dwOffset),
  4430. sizeof(DWORD)
  4431. );
  4432. if (ERROR_SUCCESS != dwError)
  4433. {
  4434. b = FALSE;
  4435. goto Cleanup;
  4436. }
  4437. }
  4438. }
  4439. #if 0
  4440. //
  4441. // The subkey for the source is now complete. All that remains is to add
  4442. // the source name to the REG_MULTI_SZ Sources value. First determine the
  4443. // size of the value.
  4444. //
  4445. dwError = RegQueryValueEx(
  4446. hkSecurity,
  4447. L"Sources",
  4448. NULL,
  4449. &dwType,
  4450. NULL,
  4451. &dwLength
  4452. );
  4453. if (ERROR_SUCCESS != dwError)
  4454. {
  4455. b = FALSE;
  4456. goto Cleanup;
  4457. }
  4458. ASSERT(dwType == REG_MULTI_SZ);
  4459. //
  4460. // Allocate space for the new value of Sources. We need space for
  4461. // the current value as well as the new event source to be added. +2
  4462. // because of the need for double terminators.
  4463. //
  4464. dwBuffer = dwLength + (wcslen(pRegistration->szEventSourceName) + 2) * sizeof(WCHAR);
  4465. pBuffer = AuthzpAlloc(dwBuffer);
  4466. if (NULL == pBuffer)
  4467. {
  4468. b = FALSE;
  4469. dwError = ERROR_NOT_ENOUGH_MEMORY;
  4470. goto Cleanup;
  4471. }
  4472. RtlZeroMemory(
  4473. pBuffer,
  4474. dwBuffer
  4475. );
  4476. //
  4477. // Read in the Sources value.
  4478. //
  4479. dwError = RegQueryValueEx(
  4480. hkSecurity,
  4481. L"Sources",
  4482. NULL,
  4483. &dwType,
  4484. (LPBYTE)pBuffer,
  4485. &dwLength
  4486. );
  4487. if (ERROR_SUCCESS != dwError)
  4488. {
  4489. b = FALSE;
  4490. goto Cleanup;
  4491. }
  4492. ASSERT(dwType == REG_MULTI_SZ);
  4493. //
  4494. // Now place the new event source into pBuffer at dwLength - 1
  4495. // position (to remove one of the double NULL terminators. We don't
  4496. // explicitly terminate the pBuffer because it has already been zeroed
  4497. // out.
  4498. //
  4499. dwLength -= sizeof(WCHAR);
  4500. RtlCopyMemory(
  4501. &((PUCHAR)pBuffer)[dwLength],
  4502. pRegistration->szEventSourceName,
  4503. wcslen(pRegistration->szEventSourceName) * sizeof(WCHAR)
  4504. );
  4505. dwLength += wcslen(pRegistration->szEventSourceName) * sizeof(WCHAR) + 2 * sizeof(WCHAR); // to add back in the double NULL
  4506. dwError = RegSetValueEx(
  4507. hkSecurity,
  4508. L"Sources",
  4509. 0,
  4510. REG_MULTI_SZ,
  4511. (LPBYTE)pBuffer,
  4512. dwLength
  4513. );
  4514. if (ERROR_SUCCESS != dwError)
  4515. {
  4516. b = FALSE;
  4517. goto Cleanup;
  4518. }
  4519. #endif
  4520. Cleanup:
  4521. if (!b)
  4522. {
  4523. SetLastError(dwError);
  4524. }
  4525. if (pBuffer)
  4526. {
  4527. LocalFree(pBuffer);
  4528. }
  4529. if (hkSecurity)
  4530. {
  4531. RegCloseKey(hkSecurity);
  4532. }
  4533. if (hkSource)
  4534. {
  4535. RegCloseKey(hkSource);
  4536. }
  4537. if (hkObjectNames)
  4538. {
  4539. RegCloseKey(hkObjectNames);
  4540. }
  4541. return b;
  4542. }
  4543. BOOL
  4544. AuthzUninstallSecurityEventSource(
  4545. IN DWORD dwFlags,
  4546. IN PCWSTR szEventSourceName
  4547. )
  4548. /**
  4549. Routine Description:
  4550. This will remove the source from the security key and remove the source string
  4551. from the list of valid sources.
  4552. Arguments:
  4553. Return Value:
  4554. **/
  4555. {
  4556. HKEY hkSecurity = NULL;
  4557. DWORD dwError;
  4558. BOOL b = TRUE;
  4559. PUCHAR pBuffer = NULL;
  4560. #if 0
  4561. DWORD dwLength = 0;
  4562. DWORD dwType;
  4563. PUCHAR pCurrentString = NULL;
  4564. PUCHAR pNextString = NULL;
  4565. BOOL bFound = FALSE;
  4566. DWORD dwSourceStringByteLength;
  4567. #endif
  4568. UNREFERENCED_PARAMETER(dwFlags);
  4569. if (NULL == szEventSourceName)
  4570. {
  4571. b = FALSE;
  4572. dwError = ERROR_INVALID_PARAMETER;
  4573. goto Cleanup;
  4574. }
  4575. //
  4576. // Open the Security key.
  4577. //
  4578. dwError = RegOpenKeyEx(
  4579. HKEY_LOCAL_MACHINE,
  4580. SECURITY_KEY_NAME,
  4581. 0,
  4582. KEY_READ | KEY_WRITE,
  4583. &hkSecurity
  4584. );
  4585. if (ERROR_SUCCESS != dwError)
  4586. {
  4587. b = FALSE;
  4588. goto Cleanup;
  4589. }
  4590. #if 0
  4591. //
  4592. // Remove the source name from the Sources value.
  4593. //
  4594. dwError = RegQueryValueEx(
  4595. hkSecurity,
  4596. L"Sources",
  4597. NULL,
  4598. &dwType,
  4599. NULL,
  4600. &dwLength
  4601. );
  4602. if (ERROR_SUCCESS != dwError)
  4603. {
  4604. b = FALSE;
  4605. goto Cleanup;
  4606. }
  4607. ASSERT(dwType == REG_MULTI_SZ);
  4608. //
  4609. // Allocate space for the current value of Sources.
  4610. //
  4611. pBuffer = AuthzpAlloc(dwLength);
  4612. if (NULL == pBuffer)
  4613. {
  4614. b = FALSE;
  4615. dwError = ERROR_NOT_ENOUGH_MEMORY;
  4616. goto Cleanup;
  4617. }
  4618. //
  4619. // Read in the Sources value.
  4620. //
  4621. dwError = RegQueryValueEx(
  4622. hkSecurity,
  4623. L"Sources",
  4624. NULL,
  4625. &dwType,
  4626. (LPBYTE)pBuffer,
  4627. &dwLength
  4628. );
  4629. if (ERROR_SUCCESS != dwError)
  4630. {
  4631. b = FALSE;
  4632. goto Cleanup;
  4633. }
  4634. ASSERT(dwType == REG_MULTI_SZ);
  4635. //
  4636. // Now find the substring in the pBuffer that matches the sourcename
  4637. // we wish to delete.
  4638. //
  4639. pCurrentString = pBuffer;
  4640. dwSourceStringByteLength = (DWORD)(sizeof(WCHAR) * (wcslen(szEventSourceName) + 1));
  4641. bFound = FALSE;
  4642. while (pCurrentString < (pBuffer + dwLength))
  4643. {
  4644. if (dwSourceStringByteLength == RtlCompareMemory(
  4645. szEventSourceName,
  4646. pCurrentString,
  4647. dwSourceStringByteLength
  4648. ))
  4649. {
  4650. //
  4651. // We have found the substring of Sources that matches the event source
  4652. // name.
  4653. //
  4654. bFound = TRUE;
  4655. break;
  4656. }
  4657. else
  4658. {
  4659. //
  4660. // Move the pointer to the next string location.
  4661. //
  4662. pCurrentString += (sizeof(WCHAR) * (1 + wcslen((PWCHAR)pCurrentString)));
  4663. }
  4664. }
  4665. if (bFound)
  4666. {
  4667. //
  4668. // pCurrentString points at the source name in the pBuffer.
  4669. // Remove this string from the value by copying over it.
  4670. //
  4671. pNextString = pCurrentString + dwSourceStringByteLength;
  4672. ASSERT(pNextString <= (pBuffer + dwLength));
  4673. RtlCopyMemory(
  4674. pCurrentString,
  4675. pNextString,
  4676. pBuffer + dwLength - pNextString
  4677. );
  4678. }
  4679. else
  4680. {
  4681. dwError = ERROR_INVALID_PARAMETER;
  4682. b = FALSE;
  4683. goto Cleanup;
  4684. }
  4685. dwError = RegSetValueEx(
  4686. hkSecurity,
  4687. L"Sources",
  4688. 0,
  4689. REG_MULTI_SZ,
  4690. (LPBYTE)pBuffer,
  4691. dwLength - dwSourceStringByteLength
  4692. );
  4693. if (ERROR_SUCCESS != dwError)
  4694. {
  4695. b = FALSE;
  4696. goto Cleanup;
  4697. }
  4698. #endif
  4699. //
  4700. // Delete the key for this source, and the ObjectNames subkey.
  4701. //
  4702. dwError = DeleteKeyRecursivelyW(
  4703. hkSecurity,
  4704. szEventSourceName
  4705. );
  4706. if (ERROR_SUCCESS != dwError)
  4707. {
  4708. b = FALSE;
  4709. goto Cleanup;
  4710. }
  4711. Cleanup:
  4712. if (pBuffer)
  4713. {
  4714. AuthzpFree(pBuffer);
  4715. }
  4716. if (hkSecurity)
  4717. {
  4718. RegCloseKey(hkSecurity);
  4719. }
  4720. if (!b)
  4721. {
  4722. SetLastError(dwError);
  4723. }
  4724. return b;
  4725. }
  4726. BOOL
  4727. AuthzEnumerateSecurityEventSources(
  4728. IN DWORD dwFlags,
  4729. OUT PAUTHZ_SOURCE_SCHEMA_REGISTRATION pBuffer,
  4730. OUT PDWORD pdwCount,
  4731. IN OUT PDWORD pdwLength
  4732. )
  4733. /**
  4734. Routine Description:
  4735. Arguments:
  4736. Return Value:
  4737. **/
  4738. {
  4739. HKEY hkSecurity = NULL;
  4740. HKEY hkSource = NULL;
  4741. DWORD dwSourceCount = 0;
  4742. DWORD dwLength = 0;
  4743. PWSTR pName = NULL;
  4744. WCHAR Buffer[128];
  4745. DWORD dwTotalLengthNeeded = 0;
  4746. BOOL b = TRUE;
  4747. DWORD dwError = ERROR_SUCCESS;
  4748. FILETIME Time;
  4749. UNREFERENCED_PARAMETER(dwFlags);
  4750. //
  4751. // Open the Security key.
  4752. //
  4753. dwError = RegOpenKeyEx(
  4754. HKEY_LOCAL_MACHINE,
  4755. SECURITY_KEY_NAME,
  4756. 0,
  4757. KEY_READ,
  4758. &hkSecurity
  4759. );
  4760. if (ERROR_SUCCESS != dwError)
  4761. {
  4762. b = FALSE;
  4763. goto Cleanup;
  4764. }
  4765. do
  4766. {
  4767. pName = Buffer;
  4768. dwLength = sizeof(Buffer) / sizeof(WCHAR);
  4769. dwError = RegEnumKeyEx(
  4770. hkSecurity,
  4771. dwSourceCount,
  4772. pName,
  4773. &dwLength,
  4774. NULL,
  4775. NULL,
  4776. NULL,
  4777. &Time
  4778. );
  4779. dwLength *= sizeof(WCHAR);
  4780. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  4781. {
  4782. pName = (PWSTR)AuthzpAlloc(dwLength);
  4783. if (NULL == pName)
  4784. {
  4785. b = FALSE;
  4786. dwError = ERROR_NOT_ENOUGH_MEMORY;
  4787. goto Cleanup;
  4788. }
  4789. else
  4790. {
  4791. dwLength /= sizeof(WCHAR);
  4792. dwError = RegEnumKeyEx(
  4793. hkSecurity,
  4794. dwSourceCount,
  4795. pName,
  4796. &dwLength,
  4797. NULL,
  4798. NULL,
  4799. NULL,
  4800. &Time
  4801. );
  4802. dwLength *= sizeof(WCHAR);
  4803. }
  4804. }
  4805. if (dwError == ERROR_NO_MORE_ITEMS)
  4806. {
  4807. //
  4808. // Do nothing. This will fall us through to the end of the
  4809. // while loop and still hit the correct cleanup code.
  4810. //
  4811. }
  4812. else if (dwError != ERROR_SUCCESS)
  4813. {
  4814. b = FALSE;
  4815. goto Cleanup;
  4816. }
  4817. else if (dwError == ERROR_SUCCESS)
  4818. {
  4819. //
  4820. // Space for the Structure
  4821. //
  4822. dwTotalLengthNeeded += sizeof(AUTHZ_SOURCE_SCHEMA_REGISTRATION);
  4823. //
  4824. // Space for the Source name + NULL terminator
  4825. //
  4826. dwTotalLengthNeeded += PtrAlignSize(dwLength + sizeof(WCHAR));
  4827. //
  4828. // Open the subkey identified by pName and determine the
  4829. // sizes of the values listed therein.
  4830. //
  4831. dwError = RegOpenKeyEx(
  4832. hkSecurity,
  4833. pName,
  4834. 0,
  4835. KEY_READ,
  4836. &hkSource
  4837. );
  4838. if (ERROR_SUCCESS != dwError)
  4839. {
  4840. b = FALSE;
  4841. goto Cleanup;
  4842. }
  4843. dwLength = 0;
  4844. dwError = RegQueryValueEx(
  4845. hkSource,
  4846. L"EventMessageFile",
  4847. NULL,
  4848. NULL,
  4849. NULL,
  4850. &dwLength
  4851. );
  4852. if (ERROR_FILE_NOT_FOUND == dwError)
  4853. {
  4854. dwError = ERROR_SUCCESS;
  4855. }
  4856. if (ERROR_SUCCESS != dwError)
  4857. {
  4858. b = FALSE;
  4859. goto Cleanup;
  4860. }
  4861. else
  4862. {
  4863. //
  4864. // Space for the value + NULL terminator
  4865. //
  4866. dwTotalLengthNeeded += PtrAlignSize(dwLength + sizeof(WCHAR));
  4867. }
  4868. dwLength = 0;
  4869. dwError = RegQueryValueEx(
  4870. hkSource,
  4871. L"ParameterMessageFile",
  4872. NULL,
  4873. NULL,
  4874. NULL,
  4875. &dwLength
  4876. );
  4877. if (ERROR_FILE_NOT_FOUND == dwError)
  4878. {
  4879. dwError = ERROR_SUCCESS;
  4880. }
  4881. if (ERROR_SUCCESS != dwError)
  4882. {
  4883. b = FALSE;
  4884. goto Cleanup;
  4885. }
  4886. else
  4887. {
  4888. //
  4889. // Space for the value + NULL terminator
  4890. //
  4891. dwTotalLengthNeeded += PtrAlignSize(dwLength + sizeof(WCHAR));
  4892. }
  4893. dwLength = 0;
  4894. dwError = RegQueryValueEx(
  4895. hkSource,
  4896. L"XmlSchemaFile",
  4897. NULL,
  4898. NULL,
  4899. NULL,
  4900. &dwLength
  4901. );
  4902. if (ERROR_FILE_NOT_FOUND == dwError)
  4903. {
  4904. dwError = ERROR_SUCCESS;
  4905. }
  4906. if (ERROR_SUCCESS != dwError)
  4907. {
  4908. b = FALSE;
  4909. goto Cleanup;
  4910. }
  4911. else
  4912. {
  4913. //
  4914. // Space for the value + NULL terminator
  4915. //
  4916. dwTotalLengthNeeded += PtrAlignSize(dwLength + sizeof(WCHAR));
  4917. }
  4918. RegCloseKey(hkSource);
  4919. hkSource = NULL;
  4920. dwSourceCount++;
  4921. }
  4922. if ((pName != NULL) && (pName != Buffer))
  4923. {
  4924. //
  4925. // free the temporary storage used for the key name.
  4926. //
  4927. AuthzpFree(pName);
  4928. }
  4929. }
  4930. while (dwError == ERROR_SUCCESS);
  4931. if (dwTotalLengthNeeded > *pdwLength)
  4932. {
  4933. b = FALSE;
  4934. dwError = ERROR_INSUFFICIENT_BUFFER;
  4935. goto Cleanup;
  4936. }
  4937. else
  4938. {
  4939. //
  4940. // The passed buffer is big enough. Set it up.
  4941. // Each structure contains string pointers, which point to memory in the
  4942. // blob after the structures.
  4943. //
  4944. PUCHAR pData;
  4945. DWORD i;
  4946. DWORD dwSpaceUsed = 0;
  4947. RtlZeroMemory(
  4948. pBuffer,
  4949. *pdwLength
  4950. );
  4951. //
  4952. // The data for the Schema structures begins at pData.
  4953. //
  4954. pData = (PUCHAR)((PUCHAR)pBuffer + PtrAlignSize(dwSourceCount * sizeof(AUTHZ_SOURCE_SCHEMA_REGISTRATION)));
  4955. dwSpaceUsed = PtrAlignSize(dwSourceCount * (sizeof(AUTHZ_SOURCE_SCHEMA_REGISTRATION)));
  4956. for (i = 0; i < dwSourceCount; i++)
  4957. {
  4958. pBuffer[i].szEventSourceName = (PWSTR)pData;
  4959. dwLength = (*pdwLength - dwSpaceUsed) / sizeof(WCHAR);
  4960. dwError = RegEnumKeyEx(
  4961. hkSecurity,
  4962. i,
  4963. pBuffer[i].szEventSourceName,
  4964. &dwLength,
  4965. NULL,
  4966. NULL,
  4967. NULL,
  4968. &Time
  4969. );
  4970. dwLength *= sizeof(WCHAR);
  4971. if (ERROR_NO_MORE_ITEMS == dwError)
  4972. {
  4973. b = TRUE;
  4974. goto Cleanup;
  4975. }
  4976. if (ERROR_SUCCESS != dwError)
  4977. {
  4978. b = FALSE;
  4979. goto Cleanup;
  4980. }
  4981. dwSpaceUsed += PtrAlignSize(dwLength + sizeof(WCHAR));
  4982. //
  4983. // Open the subkey identified by szEventSourceName and
  4984. // copy the values listed therein.
  4985. //
  4986. dwError = RegOpenKeyEx(
  4987. hkSecurity,
  4988. pBuffer[i].szEventSourceName,
  4989. 0,
  4990. KEY_READ,
  4991. &hkSource
  4992. );
  4993. if (ERROR_SUCCESS != dwError)
  4994. {
  4995. b = FALSE;
  4996. goto Cleanup;
  4997. }
  4998. pData += PtrAlignSize(dwLength + sizeof(WCHAR));
  4999. pBuffer[i].szEventMessageFile = (PWSTR)pData;
  5000. dwLength = *pdwLength - dwSpaceUsed;
  5001. dwError = RegQueryValueEx(
  5002. hkSource,
  5003. L"EventMessageFile",
  5004. NULL,
  5005. NULL,
  5006. (PBYTE)pBuffer[i].szEventMessageFile,
  5007. &dwLength
  5008. );
  5009. if (ERROR_FILE_NOT_FOUND == dwError)
  5010. {
  5011. dwError = ERROR_SUCCESS;
  5012. dwLength = 0;
  5013. pBuffer[i].szEventMessageFile = NULL;
  5014. }
  5015. if (ERROR_SUCCESS != dwError)
  5016. {
  5017. b = FALSE;
  5018. goto Cleanup;
  5019. }
  5020. dwSpaceUsed += PtrAlignSize(dwLength + sizeof(WCHAR));
  5021. pData += PtrAlignSize(dwLength + sizeof(WCHAR));
  5022. pBuffer[i].szEventAccessStringsFile = (PWSTR)pData;
  5023. dwLength = *pdwLength - dwSpaceUsed;
  5024. dwError = RegQueryValueEx(
  5025. hkSource,
  5026. L"ParameterMessageFile",
  5027. NULL,
  5028. NULL,
  5029. (PBYTE)pBuffer[i].szEventAccessStringsFile,
  5030. &dwLength
  5031. );
  5032. if (ERROR_FILE_NOT_FOUND == dwError)
  5033. {
  5034. dwError = ERROR_SUCCESS;
  5035. dwLength = 0;
  5036. pBuffer[i].szEventAccessStringsFile = NULL;
  5037. }
  5038. if (ERROR_SUCCESS != dwError)
  5039. {
  5040. b = FALSE;
  5041. goto Cleanup;
  5042. }
  5043. dwSpaceUsed += PtrAlignSize(dwLength + sizeof(WCHAR));
  5044. pData += PtrAlignSize(dwLength + sizeof(WCHAR));
  5045. pBuffer[i].szEventSourceXmlSchemaFile = (PWSTR)pData;
  5046. dwLength = *pdwLength - dwSpaceUsed;
  5047. dwError = RegQueryValueEx(
  5048. hkSource,
  5049. L"XmlSchemaFile",
  5050. NULL,
  5051. NULL,
  5052. (PBYTE)pBuffer[i].szEventSourceXmlSchemaFile,
  5053. &dwLength
  5054. );
  5055. if (ERROR_FILE_NOT_FOUND == dwError)
  5056. {
  5057. dwError = ERROR_SUCCESS;
  5058. dwLength = 0;
  5059. pBuffer[i].szEventSourceXmlSchemaFile = NULL;
  5060. }
  5061. if (ERROR_SUCCESS != dwError)
  5062. {
  5063. b = FALSE;
  5064. goto Cleanup;
  5065. }
  5066. RegCloseKey(hkSource);
  5067. hkSource = NULL;
  5068. }
  5069. }
  5070. Cleanup:
  5071. if (hkSecurity)
  5072. {
  5073. RegCloseKey(hkSecurity);
  5074. }
  5075. if (hkSource)
  5076. {
  5077. RegCloseKey(hkSource);
  5078. }
  5079. if ((pName != NULL) && (pName != (PWSTR)Buffer))
  5080. {
  5081. AuthzpFree(pName);
  5082. }
  5083. if (!b)
  5084. {
  5085. SetLastError(dwError);
  5086. }
  5087. *pdwLength = dwTotalLengthNeeded;
  5088. *pdwCount = dwSourceCount;
  5089. return b;
  5090. }
  5091. BOOL
  5092. AuthzRegisterSecurityEventSource(
  5093. IN DWORD dwFlags,
  5094. IN PCWSTR szEventSourceName,
  5095. OUT PAUTHZ_SECURITY_EVENT_PROVIDER_HANDLE phEventProvider
  5096. )
  5097. /**
  5098. Routine Description:
  5099. This allows the client to register a provider with the LSA.
  5100. Arguments:
  5101. dwFlags - TBD
  5102. szEventSourceName - the provider name
  5103. phEventProvider - pointer to provider handle to initialize.
  5104. Return Value:
  5105. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  5106. **/
  5107. {
  5108. NTSTATUS Status;
  5109. BOOL b = TRUE;
  5110. UNREFERENCED_PARAMETER(dwFlags);
  5111. if (NULL == szEventSourceName || wcslen(szEventSourceName) == 0 || NULL == phEventProvider)
  5112. {
  5113. b = FALSE;
  5114. SetLastError(ERROR_INVALID_PARAMETER);
  5115. goto Cleanup;
  5116. }
  5117. RpcTryExcept {
  5118. Status = LsarAdtRegisterSecurityEventSource(
  5119. 0,
  5120. szEventSourceName,
  5121. phEventProvider
  5122. );
  5123. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  5124. Status = RpcExceptionCode();
  5125. } RpcEndExcept;
  5126. if (!NT_SUCCESS(Status))
  5127. {
  5128. b = FALSE;
  5129. SetLastError(RtlNtStatusToDosError(Status));
  5130. goto Cleanup;
  5131. }
  5132. Cleanup:
  5133. return b;
  5134. }
  5135. BOOL
  5136. AuthzUnregisterSecurityEventSource(
  5137. IN DWORD dwFlags,
  5138. IN OUT PAUTHZ_SECURITY_EVENT_PROVIDER_HANDLE phEventProvider
  5139. )
  5140. /**
  5141. Routine Description:
  5142. Unregisters a provider with the LSA.
  5143. Arguments:
  5144. dwFlags - TBD
  5145. hEventProvider - the handle returned by AuthzRegisterSecurityEventSource
  5146. Return Value:
  5147. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  5148. **/
  5149. {
  5150. NTSTATUS Status;
  5151. BOOL b = TRUE;
  5152. UNREFERENCED_PARAMETER(dwFlags);
  5153. if (NULL == phEventProvider)
  5154. {
  5155. b = FALSE;
  5156. SetLastError(ERROR_INVALID_PARAMETER);
  5157. goto Cleanup;
  5158. }
  5159. RpcTryExcept {
  5160. Status = LsarAdtUnregisterSecurityEventSource(
  5161. 0,
  5162. phEventProvider
  5163. );
  5164. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  5165. Status = RpcExceptionCode();
  5166. } RpcEndExcept;
  5167. if (!NT_SUCCESS(Status))
  5168. {
  5169. b = FALSE;
  5170. SetLastError(RtlNtStatusToDosError(Status));
  5171. goto Cleanup;
  5172. }
  5173. Cleanup:
  5174. return b;
  5175. }
  5176. BOOL
  5177. AuthzReportSecurityEvent(
  5178. IN DWORD dwFlags,
  5179. IN AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider,
  5180. IN DWORD dwAuditId,
  5181. IN PSID pUserSid OPTIONAL,
  5182. IN DWORD dwCount,
  5183. ...
  5184. )
  5185. /**
  5186. Routine Description:
  5187. Allows a client to generate an audit.
  5188. Arguments:
  5189. dwFlags - APF_AuditSuccess APF_AuditFailure
  5190. hEventProvider - handle to the provider registered.
  5191. dwAuditId - the ID of the audit
  5192. pUserSid - the SID that the audit should appear as being generated by in
  5193. the eventlog
  5194. dwCount - the number of APF type-value pairs that follow in the VA section
  5195. Return Value:
  5196. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  5197. **/
  5198. {
  5199. BOOL b;
  5200. AUDIT_PARAMS AuditParams = {0};
  5201. AUDIT_PARAM ParamArray[SE_MAX_AUDIT_PARAMETERS] = {0};
  5202. va_list(arglist);
  5203. AuditParams.Count = (USHORT)dwCount;
  5204. AuditParams.Parameters = ParamArray;
  5205. va_start (arglist, dwCount);
  5206. b = AuthzpInitializeAuditParamsV(
  5207. dwFlags | AUTHZP_INIT_PARAMS_SKIP_HEADER,
  5208. &AuditParams,
  5209. NULL,
  5210. NULL,
  5211. 0,
  5212. (USHORT)dwCount,
  5213. arglist
  5214. );
  5215. if (!b)
  5216. {
  5217. goto Cleanup;
  5218. }
  5219. b = AuthzReportSecurityEventFromParams(
  5220. dwFlags,
  5221. hEventProvider,
  5222. dwAuditId,
  5223. pUserSid,
  5224. &AuditParams
  5225. );
  5226. if (!b)
  5227. {
  5228. goto Cleanup;
  5229. }
  5230. Cleanup:
  5231. return b;
  5232. }
  5233. BOOL
  5234. AuthzReportSecurityEventFromParams(
  5235. IN DWORD dwFlags,
  5236. IN AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider,
  5237. IN DWORD dwAuditId,
  5238. IN PSID pUserSid OPTIONAL,
  5239. IN PAUDIT_PARAMS pParams
  5240. )
  5241. /**
  5242. Routine Description:
  5243. This generates an audit from the passed parameter array.
  5244. Arguments:
  5245. dwFlags - APF_AuditSuccess APF_AuditFailure
  5246. hEventProvider - handle to the provider registered
  5247. dwAuditId - the ID of the audit
  5248. pUserSid - the SID that the audit should appear as being generated by in. If NULL the
  5249. effective token is used.
  5250. pParams - array of audit parameters.
  5251. Return Value:
  5252. Boolean: TRUE on success; FALSE on failure. Extended information available with GetLastError().
  5253. **/
  5254. {
  5255. NTSTATUS Status;
  5256. LUID Luid;
  5257. BOOL b = TRUE;
  5258. BOOL bFreeSid = FALSE;
  5259. UNREFERENCED_PARAMETER(dwFlags);
  5260. if (NULL == hEventProvider || NULL == pParams)
  5261. {
  5262. b = FALSE;
  5263. SetLastError(ERROR_INVALID_PARAMETER);
  5264. goto Cleanup;
  5265. }
  5266. if (NULL == pUserSid)
  5267. {
  5268. bFreeSid = TRUE;
  5269. b = AuthzpGetThreadTokenInfo(
  5270. &pUserSid,
  5271. &Luid
  5272. );
  5273. if (!b)
  5274. {
  5275. //
  5276. // Failed to get the thread token, try for the process
  5277. // token.
  5278. //
  5279. b = AuthzpGetProcessTokenInfo(
  5280. &pUserSid,
  5281. &Luid
  5282. );
  5283. if (!b)
  5284. {
  5285. goto Cleanup;
  5286. }
  5287. }
  5288. }
  5289. RpcTryExcept {
  5290. Status = LsarAdtReportSecurityEvent(
  5291. 0,
  5292. hEventProvider,
  5293. dwAuditId,
  5294. pUserSid,
  5295. pParams
  5296. );
  5297. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  5298. Status = RpcExceptionCode();
  5299. } RpcEndExcept;
  5300. if (!NT_SUCCESS(Status))
  5301. {
  5302. b = FALSE;
  5303. SetLastError(RtlNtStatusToDosError(Status));
  5304. goto Cleanup;
  5305. }
  5306. Cleanup:
  5307. if (bFreeSid && pUserSid)
  5308. {
  5309. AuthzpFree(pUserSid);
  5310. }
  5311. return b;
  5312. }
  5313. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  5314. DWORD
  5315. DeleteKeyRecursivelyW(
  5316. IN HKEY hkey,
  5317. IN LPCWSTR pwszSubKey
  5318. )
  5319. {
  5320. DWORD dwRet;
  5321. HKEY hkSubKey;
  5322. // Open the subkey so we can enumerate any children
  5323. dwRet = RegOpenKeyExW(hkey, pwszSubKey, 0, MAXIMUM_ALLOWED, &hkSubKey);
  5324. if (ERROR_SUCCESS == dwRet)
  5325. {
  5326. DWORD dwIndex;
  5327. WCHAR wszSubKeyName[MAX_PATH + 1];
  5328. DWORD cchSubKeyName = ARRAYSIZE(wszSubKeyName);
  5329. // I can't just call RegEnumKey with an ever-increasing index, because
  5330. // I'm deleting the subkeys as I go, which alters the indices of the
  5331. // remaining subkeys in an implementation-dependent way. In order to
  5332. // be safe, I have to count backwards while deleting the subkeys.
  5333. // Find out how many subkeys there are
  5334. dwRet = RegQueryInfoKeyW(hkSubKey, NULL, NULL, NULL,
  5335. &dwIndex, // The # of subkeys -- all we need
  5336. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  5337. if (NO_ERROR == dwRet)
  5338. {
  5339. // dwIndex is now the count of subkeys, but it needs to be
  5340. // zero-based for RegEnumKey, so I'll pre-decrement, rather
  5341. // than post-decrement.
  5342. while (ERROR_SUCCESS == RegEnumKeyW(hkSubKey, --dwIndex, wszSubKeyName, cchSubKeyName))
  5343. {
  5344. DeleteKeyRecursivelyW(hkSubKey, wszSubKeyName);
  5345. }
  5346. }
  5347. RegCloseKey(hkSubKey);
  5348. if (pwszSubKey)
  5349. {
  5350. dwRet = RegDeleteKeyW(hkey, pwszSubKey);
  5351. }
  5352. else
  5353. {
  5354. // we want to delete all the values by hand
  5355. cchSubKeyName = ARRAYSIZE(wszSubKeyName);
  5356. while (ERROR_SUCCESS == RegEnumValueW(hkey, 0, wszSubKeyName, &cchSubKeyName, NULL, NULL, NULL, NULL))
  5357. {
  5358. // avoid looping infinitely when we cant delete the value
  5359. if (RegDeleteValueW(hkey, wszSubKeyName))
  5360. break;
  5361. cchSubKeyName = ARRAYSIZE(wszSubKeyName);
  5362. }
  5363. }
  5364. }
  5365. return dwRet;
  5366. }