Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2855 lines
65 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Acledit.c
  5. Abstract:
  6. This Module implements the Acl rtl editing functions that are defined in
  7. ntseapi.h
  8. Author:
  9. Gary Kimura (GaryKi) 9-Nov-1989
  10. Environment:
  11. Pure Runtime Library Routine
  12. Revision History:
  13. --*/
  14. #include <ntrtlp.h>
  15. #include <seopaque.h>
  16. //
  17. // Define the local macros and procedure for this module
  18. //
  19. //
  20. // Return a pointer to the first Ace in an Acl (even if the Acl is empty).
  21. //
  22. // PACE_HEADER
  23. // FirstAce (
  24. // IN PACL Acl
  25. // );
  26. //
  27. #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))
  28. //
  29. // Return a pointer to the next Ace in a sequence (even if the input
  30. // Ace is the one in the sequence).
  31. //
  32. // PACE_HEADER
  33. // NextAce (
  34. // IN PACE_HEADER Ace
  35. // );
  36. //
  37. #define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize))
  38. #define LongAligned( ptr ) (LongAlign(ptr) == ((PVOID)(ptr)))
  39. #define WordAligned( ptr ) (WordAlign(ptr) == ((PVOID)(ptr)))
  40. VOID
  41. RtlpAddData (
  42. IN PVOID From,
  43. IN ULONG FromSize,
  44. IN PVOID To,
  45. IN ULONG ToSize
  46. );
  47. VOID
  48. RtlpDeleteData (
  49. IN PVOID Data,
  50. IN ULONG RemoveSize,
  51. IN ULONG TotalSize
  52. );
  53. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  54. NTSTATUS
  55. RtlpAddKnownAce (
  56. IN OUT PACL Acl,
  57. IN ULONG AceRevision,
  58. IN ULONG AceFlags,
  59. IN ACCESS_MASK AccessMask,
  60. IN PSID Sid,
  61. IN UCHAR NewType
  62. );
  63. NTSTATUS
  64. RtlpAddKnownObjectAce (
  65. IN OUT PACL Acl,
  66. IN ULONG AceRevision,
  67. IN ULONG AceFlags,
  68. IN ACCESS_MASK AccessMask,
  69. IN GUID *ObjectTypeGuid OPTIONAL,
  70. IN GUID *InheritedObjectTypeGuid OPTIONAL,
  71. IN PSID Sid,
  72. IN UCHAR NewType
  73. );
  74. #pragma alloc_text(PAGE,RtlCreateAcl)
  75. #pragma alloc_text(PAGE,RtlValidAcl)
  76. #pragma alloc_text(PAGE,RtlQueryInformationAcl)
  77. #pragma alloc_text(PAGE,RtlSetInformationAcl)
  78. #pragma alloc_text(PAGE,RtlAddAce)
  79. #pragma alloc_text(PAGE,RtlDeleteAce)
  80. #pragma alloc_text(PAGE,RtlGetAce)
  81. #pragma alloc_text(PAGE,RtlAddCompoundAce)
  82. #pragma alloc_text(PAGE,RtlpAddKnownAce)
  83. #pragma alloc_text(PAGE,RtlpAddKnownObjectAce)
  84. #pragma alloc_text(PAGE,RtlAddAccessAllowedAce)
  85. #pragma alloc_text(PAGE,RtlAddAccessAllowedAceEx)
  86. #pragma alloc_text(PAGE,RtlAddAccessDeniedAce)
  87. #pragma alloc_text(PAGE,RtlAddAccessDeniedAceEx)
  88. #pragma alloc_text(PAGE,RtlAddAuditAccessAce)
  89. #pragma alloc_text(PAGE,RtlAddAuditAccessAceEx)
  90. #pragma alloc_text(PAGE,RtlAddAccessAllowedObjectAce)
  91. #pragma alloc_text(PAGE,RtlAddAccessDeniedObjectAce)
  92. #pragma alloc_text(PAGE,RtlAddAuditAccessObjectAce)
  93. #pragma alloc_text(PAGE,RtlFirstFreeAce)
  94. #pragma alloc_text(PAGE,RtlpAddData)
  95. #pragma alloc_text(PAGE,RtlpDeleteData)
  96. #endif
  97. NTSTATUS
  98. RtlCreateAcl (
  99. IN PACL Acl,
  100. IN ULONG AclLength,
  101. IN ULONG AclRevision
  102. )
  103. /*++
  104. Routine Description:
  105. This routine initializes an ACL data structure. After initialization
  106. it is an ACL with no ACE (i.e., a deny all access type ACL)
  107. Arguments:
  108. Acl - Supplies the buffer containing the ACL being initialized
  109. AclLength - Supplies the length of the ace buffer in bytes
  110. AclRevision - Supplies the revision for this Acl
  111. Return Value:
  112. NTSTATUS - STATUS_SUCCESS if successful
  113. STATUS_BUFFER_TOO_SMALL if the AclLength is too small,
  114. STATUS_INVALID_PARAMETER if the revision is out of range
  115. --*/
  116. {
  117. RTL_PAGED_CODE();
  118. //
  119. // Check to see the size of the buffer is large enough to hold at
  120. // least the ACL header
  121. //
  122. if (AclLength < sizeof(ACL)) {
  123. //
  124. // Buffer to small even for the ACL header
  125. //
  126. return STATUS_BUFFER_TOO_SMALL;
  127. }
  128. //
  129. // Check to see if the revision is currently valid. Later versions
  130. // of this procedure might accept more revision levels
  131. //
  132. if (AclRevision < MIN_ACL_REVISION || AclRevision > MAX_ACL_REVISION) {
  133. //
  134. // Revision not current
  135. //
  136. return STATUS_INVALID_PARAMETER;
  137. }
  138. if ( AclLength > MAXUSHORT ) {
  139. return STATUS_INVALID_PARAMETER;
  140. }
  141. //
  142. // Initialize the ACL
  143. //
  144. Acl->AclRevision = (UCHAR)AclRevision; // Used to hardwire ACL_REVISION2 here
  145. Acl->Sbz1 = 0;
  146. Acl->AclSize = (USHORT) (AclLength & 0xfffc);
  147. Acl->AceCount = 0;
  148. Acl->Sbz2 = 0;
  149. //
  150. // And return to our caller
  151. //
  152. return STATUS_SUCCESS;
  153. }
  154. BOOLEAN
  155. RtlValidAcl (
  156. IN PACL Acl
  157. )
  158. /*++
  159. Routine Description:
  160. This procedure validates an ACL.
  161. This involves validating the revision level of the ACL and ensuring
  162. that the number of ACEs specified in the AceCount fit in the space
  163. specified by the AclSize field of the ACL header.
  164. Arguments:
  165. Acl - Pointer to the ACL structure to validate.
  166. Return Value:
  167. BOOLEAN - TRUE if the structure of Acl is valid.
  168. --*/
  169. {
  170. RTL_PAGED_CODE();
  171. try {
  172. PACE_HEADER Ace;
  173. PISID Sid;
  174. PISID Sid2;
  175. ULONG i;
  176. UCHAR AclRevision = ACL_REVISION2;
  177. //
  178. // Check the ACL revision level
  179. //
  180. if (!ValidAclRevision(Acl)) {
  181. return(FALSE);
  182. }
  183. if (!WordAligned(&Acl->AclSize)) {
  184. return(FALSE);
  185. }
  186. if (Acl->AclSize < sizeof(ACL)) {
  187. return(FALSE);
  188. }
  189. //
  190. // Validate all of the ACEs.
  191. //
  192. Ace = ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)));
  193. for (i = 0; i < Acl->AceCount; i++) {
  194. //
  195. // Check to make sure we haven't overrun the Acl buffer
  196. // with our ace pointer. Make sure the ACE_HEADER is in
  197. // the ACL also.
  198. //
  199. if ((PUCHAR)Ace + sizeof(ACE_HEADER) >= ((PUCHAR)Acl + Acl->AclSize)) {
  200. return(FALSE);
  201. }
  202. if (!WordAligned(&Ace->AceSize)) {
  203. return(FALSE);
  204. }
  205. if ((PUCHAR)Ace + Ace->AceSize > ((PUCHAR)Acl + Acl->AclSize)) {
  206. return(FALSE);
  207. }
  208. //
  209. // It is now safe to reference fields in the ACE header.
  210. //
  211. //
  212. // The ACE header fits into the ACL, if this is a known type of ACE,
  213. // make sure the SID is within the bounds of the ACE
  214. //
  215. if (IsKnownAceType(Ace)) {
  216. if (!LongAligned(Ace->AceSize)) {
  217. return(FALSE);
  218. }
  219. if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + sizeof(SID) - sizeof(ULONG)) {
  220. return(FALSE);
  221. }
  222. //
  223. // It's now safe to reference the parts of the SID structure, though
  224. // not the SID itself.
  225. //
  226. Sid = (PISID) & (((PKNOWN_ACE)Ace)->SidStart);
  227. if (Sid->Revision != SID_REVISION) {
  228. return(FALSE);
  229. }
  230. if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
  231. return(FALSE);
  232. }
  233. //
  234. // SeLengthSid computes the size of the SID based on the subauthority count,
  235. // so it is safe to use even though we don't know that the body of the SID
  236. // is safe to reference.
  237. //
  238. if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + SeLengthSid( Sid )) {
  239. return(FALSE);
  240. }
  241. //
  242. // If it's a compound ACE, then perform roughly the same set of tests, but
  243. // check the validity of both SIDs.
  244. //
  245. } else if (IsCompoundAceType(Ace)) {
  246. //
  247. // Compound ACEs became valid in revision 3
  248. //
  249. if ( Acl->AclRevision < ACL_REVISION3 ) {
  250. return FALSE;
  251. }
  252. if (!LongAligned(Ace->AceSize)) {
  253. return(FALSE);
  254. }
  255. if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + sizeof(SID)) {
  256. return(FALSE);
  257. }
  258. //
  259. // The only currently defined Compound ACE is an Impersonation ACE.
  260. //
  261. if (((PKNOWN_COMPOUND_ACE)Ace)->CompoundAceType != COMPOUND_ACE_IMPERSONATION) {
  262. return(FALSE);
  263. }
  264. //
  265. // Examine the first SID and make sure it's structurally valid,
  266. // and it lies within the boundaries of the ACE.
  267. //
  268. Sid = (PISID) & (((PKNOWN_COMPOUND_ACE)Ace)->SidStart);
  269. if (Sid->Revision != SID_REVISION) {
  270. return(FALSE);
  271. }
  272. if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
  273. return(FALSE);
  274. }
  275. //
  276. // Compound ACEs contain two SIDs. Make sure this ACE is large enough to contain
  277. // not only the first SID, but the body of the 2nd.
  278. //
  279. if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + sizeof(SID)) {
  280. return(FALSE);
  281. }
  282. //
  283. // It is safe to reference the interior of the 2nd SID.
  284. //
  285. Sid2 = (PISID) ((PUCHAR)Sid + SeLengthSid( Sid ));
  286. if (Sid2->Revision != SID_REVISION) {
  287. return(FALSE);
  288. }
  289. if (Sid2->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
  290. return(FALSE);
  291. }
  292. if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + SeLengthSid( Sid2 )) {
  293. return(FALSE);
  294. }
  295. //
  296. // If it's an object ACE, then perform roughly the same set of tests.
  297. //
  298. } else if (IsObjectAceType(Ace)) {
  299. ULONG GuidSize=0;
  300. //
  301. // Object ACEs became valid in revision 4
  302. //
  303. if ( Acl->AclRevision < ACL_REVISION4 ) {
  304. return FALSE;
  305. }
  306. if (!LongAligned(Ace->AceSize)) {
  307. return(FALSE);
  308. }
  309. //
  310. // Ensure there is room for the ACE header.
  311. //
  312. if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG)) {
  313. return(FALSE);
  314. }
  315. //
  316. // Ensure there is room for the GUIDs and SID header
  317. //
  318. if ( RtlObjectAceObjectTypePresent( Ace ) ) {
  319. GuidSize += sizeof(GUID);
  320. }
  321. if ( RtlObjectAceInheritedObjectTypePresent( Ace ) ) {
  322. GuidSize += sizeof(GUID);
  323. }
  324. if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG) + GuidSize + sizeof(SID)) {
  325. return(FALSE);
  326. }
  327. //
  328. // It's now safe to reference the parts of the SID structure, though
  329. // not the SID itself.
  330. //
  331. Sid = (PISID) RtlObjectAceSid( Ace );
  332. if (Sid->Revision != SID_REVISION) {
  333. return(FALSE);
  334. }
  335. if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
  336. return(FALSE);
  337. }
  338. if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG) + GuidSize + SeLengthSid( Sid ) ) {
  339. return(FALSE);
  340. }
  341. }
  342. //
  343. // And move Ace to the next ace position
  344. //
  345. Ace = ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize));
  346. }
  347. return(TRUE);
  348. } except(EXCEPTION_EXECUTE_HANDLER) {
  349. return FALSE;
  350. }
  351. }
  352. NTSTATUS
  353. RtlQueryInformationAcl (
  354. IN PACL Acl,
  355. OUT PVOID AclInformation,
  356. IN ULONG AclInformationLength,
  357. IN ACL_INFORMATION_CLASS AclInformationClass
  358. )
  359. /*++
  360. Routine Description:
  361. This routine returns to the caller information about an ACL. The requested
  362. information can be AclRevisionInformation, or AclSizeInformation.
  363. Arguments:
  364. Acl - Supplies the Acl being examined
  365. AclInformation - Supplies the buffer to receive the information being
  366. requested
  367. AclInformationLength - Supplies the length of the AclInformation buffer
  368. in bytes
  369. AclInformationClass - Supplies the type of information being requested
  370. Return Value:
  371. NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
  372. status otherwise
  373. --*/
  374. {
  375. PACL_REVISION_INFORMATION RevisionInfo;
  376. PACL_SIZE_INFORMATION SizeInfo;
  377. PVOID FirstFree;
  378. NTSTATUS Status;
  379. RTL_PAGED_CODE();
  380. //
  381. // Check the ACL revision level
  382. //
  383. if (!ValidAclRevision( Acl )) {
  384. return STATUS_INVALID_PARAMETER;
  385. }
  386. //
  387. // Case on the information class being requested
  388. //
  389. switch (AclInformationClass) {
  390. case AclRevisionInformation:
  391. //
  392. // Make sure the buffer size is correct
  393. //
  394. if (AclInformationLength < sizeof(ACL_REVISION_INFORMATION)) {
  395. return STATUS_BUFFER_TOO_SMALL;
  396. }
  397. //
  398. // Get the Acl revision and return
  399. //
  400. RevisionInfo = (PACL_REVISION_INFORMATION)AclInformation;
  401. RevisionInfo->AclRevision = Acl->AclRevision;
  402. break;
  403. case AclSizeInformation:
  404. //
  405. // Make sure the buffer size is correct
  406. //
  407. if (AclInformationLength < sizeof(ACL_SIZE_INFORMATION)) {
  408. return STATUS_BUFFER_TOO_SMALL;
  409. }
  410. //
  411. // Locate the first free spot in the Acl
  412. //
  413. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  414. //
  415. // The input Acl is ill-formed
  416. //
  417. return STATUS_INVALID_PARAMETER;
  418. }
  419. //
  420. // Given a pointer to the first free spot we can now easily compute
  421. // the number of free bytes and used bytes in the Acl.
  422. //
  423. SizeInfo = (PACL_SIZE_INFORMATION)AclInformation;
  424. SizeInfo->AceCount = Acl->AceCount;
  425. if (FirstFree == NULL) {
  426. //
  427. // With a null first free we don't have any free space in the Acl
  428. //
  429. SizeInfo->AclBytesInUse = Acl->AclSize;
  430. SizeInfo->AclBytesFree = 0;
  431. } else {
  432. //
  433. // The first free is not null so we have some free room left in
  434. // the acl
  435. //
  436. SizeInfo->AclBytesInUse = (ULONG)((PUCHAR)FirstFree - (PUCHAR)Acl);
  437. SizeInfo->AclBytesFree = Acl->AclSize - SizeInfo->AclBytesInUse;
  438. }
  439. break;
  440. default:
  441. return STATUS_INVALID_INFO_CLASS;
  442. }
  443. //
  444. // and return to our caller
  445. //
  446. return STATUS_SUCCESS;
  447. }
  448. NTSTATUS
  449. RtlSetInformationAcl (
  450. IN PACL Acl,
  451. IN PVOID AclInformation,
  452. IN ULONG AclInformationLength,
  453. IN ACL_INFORMATION_CLASS AclInformationClass
  454. )
  455. /*++
  456. Routine Description:
  457. This routine sets the state of an ACL. For now only the revision
  458. level can be set and for now only a revision level of 1 is accepted
  459. so this procedure is rather simple
  460. Arguments:
  461. Acl - Supplies the Acl being altered
  462. AclInformation - Supplies the buffer containing the information being
  463. set
  464. AclInformationLength - Supplies the length of the Acl information buffer
  465. AclInformationClass - Supplies the type of information begin set
  466. Return Value:
  467. NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
  468. status otherwise
  469. --*/
  470. {
  471. PACL_REVISION_INFORMATION RevisionInfo;
  472. RTL_PAGED_CODE();
  473. //
  474. // Check the ACL revision level
  475. //
  476. if (!ValidAclRevision( Acl )) {
  477. return STATUS_INVALID_PARAMETER;
  478. }
  479. //
  480. // Case on the information class being requested
  481. //
  482. switch (AclInformationClass) {
  483. case AclRevisionInformation:
  484. //
  485. // Make sure the buffer size is correct
  486. //
  487. if (AclInformationLength < sizeof(ACL_REVISION_INFORMATION)) {
  488. return STATUS_BUFFER_TOO_SMALL;
  489. }
  490. //
  491. // Get the Acl requested ACL revision level
  492. //
  493. RevisionInfo = (PACL_REVISION_INFORMATION)AclInformation;
  494. //
  495. // Don't let them lower the revision of an ACL.
  496. //
  497. if (RevisionInfo->AclRevision < Acl->AclRevision ) {
  498. return STATUS_INVALID_PARAMETER;
  499. }
  500. //
  501. // Assign the new revision.
  502. //
  503. Acl->AclRevision = (UCHAR)RevisionInfo->AclRevision;
  504. break;
  505. default:
  506. return STATUS_INVALID_INFO_CLASS;
  507. }
  508. //
  509. // and return to our caller
  510. //
  511. return STATUS_SUCCESS;
  512. }
  513. NTSTATUS
  514. RtlAddAce (
  515. IN OUT PACL Acl,
  516. IN ULONG AceRevision,
  517. IN ULONG StartingAceIndex,
  518. IN PVOID AceList,
  519. IN ULONG AceListLength
  520. )
  521. /*++
  522. Routine Description:
  523. This routine adds a string of ACEs to an ACL.
  524. Arguments:
  525. Acl - Supplies the Acl being modified
  526. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  527. StartingAceIndex - Supplies the ACE index which will be the index of
  528. the first ace inserted in the acl. 0 for the beginning of the list
  529. and MAXULONG for the end of the list.
  530. AceList - Supplies the list of Aces to be added to the Acl
  531. AceListLength - Supplies the size, in bytes, of the AceList buffer
  532. Return Value:
  533. NTSTATUS - STATUS_SUCCESS if successful, and an appropriate error
  534. status otherwise
  535. --*/
  536. {
  537. PVOID FirstFree;
  538. PACE_HEADER Ace;
  539. ULONG NewAceCount;
  540. PVOID AcePosition;
  541. ULONG i;
  542. UCHAR NewRevision;
  543. RTL_PAGED_CODE();
  544. //
  545. // Check the ACL structure
  546. //
  547. if (!RtlValidAcl(Acl)) {
  548. return STATUS_INVALID_PARAMETER;
  549. }
  550. //
  551. // Locate the first free ace and check to see that the Acl is
  552. // well formed.
  553. //
  554. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  555. return STATUS_INVALID_PARAMETER;
  556. }
  557. //
  558. // If the AceRevision is greater than the ACL revision, then we want to
  559. // increase the ACL revision to be the same as the new ACE revision.
  560. // We can do this because our previously defined ACE types ( 0 -> 3 ) have
  561. // not changed structure nor been discontinued in the new revision. So
  562. // we can bump the revision and the older types will not be misinterpreted.
  563. //
  564. // Compute what the final revision of the ACL is going to be, and save it
  565. // for later so we can update it once we know we're going to succeed.
  566. //
  567. NewRevision = (UCHAR)AceRevision > Acl->AclRevision ? (UCHAR)AceRevision : Acl->AclRevision;
  568. //
  569. // Check that the AceList is well formed, we do this by simply zooming
  570. // down the Ace list until we're equal to or have exceeded the ace list
  571. // length. If we are equal to the length then we're well formed otherwise
  572. // we're ill-formed. We'll also calculate how many Ace's there are
  573. // in the AceList
  574. //
  575. // In addition, now we have to make sure that we haven't been handed an
  576. // ACE type that is inappropriate for the AceRevision that was passed
  577. // in.
  578. //
  579. for (Ace = AceList, NewAceCount = 0;
  580. Ace < (PACE_HEADER)((PUCHAR)AceList + AceListLength);
  581. Ace = NextAce( Ace ), NewAceCount++) {
  582. //
  583. // Ensure the ACL revision allows this ACE type.
  584. //
  585. if ( Ace->AceType <= ACCESS_MAX_MS_V2_ACE_TYPE ) {
  586. // V2 ACE are always valid.
  587. } else if ( Ace->AceType <= ACCESS_MAX_MS_V3_ACE_TYPE ) {
  588. if ( AceRevision < ACL_REVISION3 ) {
  589. return STATUS_INVALID_PARAMETER;
  590. }
  591. } else if ( Ace->AceType <= ACCESS_MAX_MS_V4_ACE_TYPE ) {
  592. if ( AceRevision < ACL_REVISION4 ) {
  593. return STATUS_INVALID_PARAMETER;
  594. }
  595. }
  596. }
  597. //
  598. // Check to see if we've exceeded the ace list length
  599. //
  600. if (Ace > (PACE_HEADER)((PUCHAR)AceList + AceListLength)) {
  601. return STATUS_INVALID_PARAMETER;
  602. }
  603. //
  604. // Check to see if there is enough room in the Acl to store the additional
  605. // Ace list
  606. //
  607. if (FirstFree == NULL ||
  608. (PUCHAR)FirstFree + AceListLength > (PUCHAR)Acl + Acl->AclSize) {
  609. return STATUS_BUFFER_TOO_SMALL;
  610. }
  611. //
  612. // All of the input has checked okay, we now need to locate the position
  613. // where to insert the new ace list. We won't check the acl for
  614. // validity because we did earlier when got the first free ace position.
  615. //
  616. AcePosition = FirstAce( Acl );
  617. for (i = 0; i < StartingAceIndex && i < Acl->AceCount; i++) {
  618. AcePosition = NextAce( AcePosition );
  619. }
  620. //
  621. // Now Ace points to where we want to insert the ace list, We do the
  622. // insertion by adding ace list to the acl and shoving over the remainder
  623. // of the list down the acl. We know this will work because we earlier
  624. // check to make sure the new acl list will fit in the acl size
  625. //
  626. RtlpAddData( AceList, AceListLength,
  627. AcePosition, (ULONG) ((PUCHAR)FirstFree - (PUCHAR)AcePosition));
  628. //
  629. // Update the Acl Header
  630. //
  631. Acl->AceCount = (USHORT)(Acl->AceCount + NewAceCount);
  632. Acl->AclRevision = NewRevision;
  633. //
  634. // And return to our caller
  635. //
  636. return STATUS_SUCCESS;
  637. }
  638. NTSTATUS
  639. RtlDeleteAce (
  640. IN OUT PACL Acl,
  641. IN ULONG AceIndex
  642. )
  643. /*++
  644. Routine Description:
  645. This routine deletes one ACE from an ACL.
  646. Arguments:
  647. Acl - Supplies the Acl being modified
  648. AceIndex - Supplies the index of the Ace to delete.
  649. Return Value:
  650. NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
  651. status otherwise
  652. --*/
  653. {
  654. PVOID FirstFree;
  655. PACE_HEADER Ace;
  656. ULONG i;
  657. RTL_PAGED_CODE();
  658. //
  659. // Check the ACL structure
  660. //
  661. if (!RtlValidAcl(Acl)) {
  662. return STATUS_INVALID_PARAMETER;
  663. }
  664. //
  665. // Make sure the AceIndex is within proper range, it's ulong so we know
  666. // it can't be negative
  667. //
  668. if (AceIndex >= Acl->AceCount) {
  669. return STATUS_INVALID_PARAMETER;
  670. }
  671. //
  672. // Locate the first free spot, this will tell us how much data
  673. // we'll need to colapse. If the results is false then the acl is
  674. // ill-formed
  675. //
  676. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  677. return STATUS_INVALID_PARAMETER;
  678. }
  679. //
  680. // Now locate the ace that we're going to delete. This loop
  681. // doesn't need to check the acl for being well formed.
  682. //
  683. Ace = FirstAce( Acl );
  684. for (i = 0; i < AceIndex; i++) {
  685. Ace = NextAce( Ace );
  686. }
  687. //
  688. // We've found the ace to delete to simply copy over the rest of
  689. // the acl over this ace. The delete data procedure also deletes
  690. // rest of the string that it's moving over so we don't have to
  691. //
  692. RtlpDeleteData( Ace, Ace->AceSize, (ULONG) ((PUCHAR)FirstFree - (PUCHAR)Ace));
  693. //
  694. // Update the Acl header
  695. //
  696. Acl->AceCount--;
  697. //
  698. // And return to our caller
  699. //
  700. return STATUS_SUCCESS;
  701. }
  702. NTSTATUS
  703. RtlGetAce (
  704. IN PACL Acl,
  705. ULONG AceIndex,
  706. OUT PVOID *Ace
  707. )
  708. /*++
  709. Routine Description:
  710. This routine returns a pointer to an ACE in an ACl referenced by
  711. ACE index
  712. Arguments:
  713. Acl - Supplies the ACL being queried
  714. AceIndex - Supplies the Ace index to locate
  715. Ace - Receives the address of the ACE within the ACL
  716. Return Value:
  717. NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
  718. status otherwise
  719. --*/
  720. {
  721. ULONG i;
  722. RTL_PAGED_CODE();
  723. //
  724. // Check the ACL revision level
  725. //
  726. if (!ValidAclRevision(Acl)) {
  727. return STATUS_INVALID_PARAMETER;
  728. }
  729. //
  730. // Check the AceIndex against the Ace count of the Acl, it's ulong so
  731. // we know it can't be negative
  732. //
  733. if (AceIndex >= Acl->AceCount) {
  734. return STATUS_INVALID_PARAMETER;
  735. }
  736. //
  737. // To find the Ace requested by zooming down the Ace List.
  738. //
  739. *Ace = FirstAce( Acl );
  740. for (i = 0; i < AceIndex; i++) {
  741. //
  742. // Check to make sure we haven't overrun the Acl buffer
  743. // with our ace pointer. If we have then our input is bogus
  744. //
  745. if (*Ace >= (PVOID)((PUCHAR)Acl + Acl->AclSize)) {
  746. return STATUS_INVALID_PARAMETER;
  747. }
  748. //
  749. // And move Ace to the next ace position
  750. //
  751. *Ace = NextAce( *Ace );
  752. }
  753. //
  754. // Now Ace points to the Ace we're after, but make sure we aren't
  755. // beyond the Acl.
  756. //
  757. if (*Ace >= (PVOID)((PUCHAR)Acl + Acl->AclSize)) {
  758. return STATUS_INVALID_PARAMETER;
  759. }
  760. //
  761. // The Ace is still within the Acl so return success to our caller
  762. //
  763. return STATUS_SUCCESS;
  764. }
  765. NTSTATUS
  766. RtlAddCompoundAce (
  767. IN PACL Acl,
  768. IN ULONG AceRevision,
  769. IN UCHAR CompoundAceType,
  770. IN ACCESS_MASK AccessMask,
  771. IN PSID ServerSid,
  772. IN PSID ClientSid
  773. )
  774. /*++
  775. Routine Description:
  776. This routine adds a KNOWN_COMPOUND_ACE to an ACL. This is
  777. expected to be a common form of ACL modification.
  778. Arguments:
  779. Acl - Supplies the Acl being modified
  780. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  781. CompoundAceType - Supplies the type of compound ACE being added.
  782. Currently the only defined type is COMPOUND_ACE_IMPERSONATION.
  783. AccessMask - The mask of accesses to be granted to the specified SID pair.
  784. ServerSid - Pointer to the Server SID to be placed in the ACE.
  785. ClientSid - Pointer to the Client SID to be placed in the ACE.
  786. Return Value:
  787. NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
  788. status otherwise
  789. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  790. --*/
  791. {
  792. PVOID FirstFree;
  793. USHORT AceSize;
  794. PKNOWN_COMPOUND_ACE GrantAce;
  795. UCHAR NewRevision;
  796. RTL_PAGED_CODE();
  797. //
  798. // Validate the structure of the SID
  799. //
  800. if (!RtlValidSid(ServerSid) || !RtlValidSid(ClientSid)) {
  801. return STATUS_INVALID_SID;
  802. }
  803. //
  804. // Check the ACL & ACE revision levels
  805. // Compund ACEs become valid in version 3.
  806. //
  807. if ( Acl->AclRevision > ACL_REVISION4 ||
  808. AceRevision < ACL_REVISION3 ||
  809. AceRevision > ACL_REVISION4 ) {
  810. return STATUS_REVISION_MISMATCH;
  811. }
  812. //
  813. // Calculate the new revision of the ACL. The new revision is the maximum
  814. // of the old revision and and new ACE's revision. This is possible because
  815. // the format of previously defined ACEs did not change across revisions.
  816. //
  817. NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
  818. //
  819. // Locate the first free ace and check to see that the Acl is
  820. // well formed.
  821. //
  822. if (!RtlValidAcl( Acl )) {
  823. return STATUS_INVALID_ACL;
  824. }
  825. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  826. return STATUS_INVALID_ACL;
  827. }
  828. //
  829. // Check to see if there is enough room in the Acl to store the new
  830. // ACE
  831. //
  832. AceSize = (USHORT)(sizeof(KNOWN_COMPOUND_ACE) -
  833. sizeof(ULONG) +
  834. SeLengthSid(ClientSid) +
  835. SeLengthSid(ServerSid)
  836. );
  837. if ( FirstFree == NULL ||
  838. ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
  839. ) {
  840. return STATUS_ALLOTTED_SPACE_EXCEEDED;
  841. }
  842. //
  843. // Add the ACE to the end of the ACL
  844. //
  845. GrantAce = (PKNOWN_COMPOUND_ACE)FirstFree;
  846. GrantAce->Header.AceFlags = 0;
  847. GrantAce->Header.AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE;
  848. GrantAce->Header.AceSize = AceSize;
  849. GrantAce->Mask = AccessMask;
  850. GrantAce->CompoundAceType = CompoundAceType;
  851. RtlCopySid( SeLengthSid(ServerSid), (PSID)(&GrantAce->SidStart), ServerSid );
  852. RtlCopySid( SeLengthSid(ClientSid), (PSID)(((PCHAR)&GrantAce->SidStart) + SeLengthSid(ServerSid)), ClientSid );
  853. //
  854. // Increment the number of ACEs by 1.
  855. //
  856. Acl->AceCount += 1;
  857. //
  858. // Adjust the Acl revision, if necessary
  859. //
  860. Acl->AclRevision = NewRevision;
  861. //
  862. // And return to our caller
  863. //
  864. return STATUS_SUCCESS;
  865. }
  866. NTSTATUS
  867. RtlpAddKnownAce (
  868. IN OUT PACL Acl,
  869. IN ULONG AceRevision,
  870. IN ULONG AceFlags,
  871. IN ACCESS_MASK AccessMask,
  872. IN PSID Sid,
  873. IN UCHAR NewType
  874. )
  875. /*++
  876. Routine Description:
  877. This routine adds KNOWN_ACE to an ACL. This is
  878. expected to be a common form of ACL modification.
  879. A very bland ACE header is placed in the ACE. It provides no
  880. inheritance and no ACE flags. The type is specified by the caller.
  881. Arguments:
  882. Acl - Supplies the Acl being modified
  883. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  884. AceFlags - Supplies the inherit flags for the ACE.
  885. AccessMask - The mask of accesses to be denied to the specified SID.
  886. Sid - Pointer to the SID being denied access.
  887. NewType - Type of ACE to be added.
  888. Return Value:
  889. STATUS_SUCCESS - The ACE was successfully added.
  890. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  891. STATUS_REVISION_MISMATCH - The specified revision is not known
  892. or is incompatible with that of the ACL.
  893. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  894. ACL. A larger ACL buffer is required.
  895. STATUS_INVALID_SID - The provided SID is not a structurally valid
  896. SID.
  897. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  898. --*/
  899. {
  900. PVOID FirstFree;
  901. USHORT AceSize;
  902. PKNOWN_ACE GrantAce;
  903. UCHAR NewRevision;
  904. ULONG TestedAceFlags;
  905. RTL_PAGED_CODE();
  906. //
  907. // Validate the structure of the SID
  908. //
  909. if (!RtlValidSid(Sid)) {
  910. return STATUS_INVALID_SID;
  911. }
  912. //
  913. // Check the ACL & ACE revision levels
  914. //
  915. if ( Acl->AclRevision > ACL_REVISION4 || AceRevision > ACL_REVISION4 ) {
  916. return STATUS_REVISION_MISMATCH;
  917. }
  918. //
  919. // Calculate the new revision of the ACL. The new revision is the maximum
  920. // of the old revision and and new ACE's revision. This is possible because
  921. // the format of previously defined ACEs did not change across revisions.
  922. //
  923. NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
  924. //
  925. // Validate the AceFlags.
  926. //
  927. TestedAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
  928. if ( TestedAceFlags != 0 ) {
  929. if ( NewType == SYSTEM_AUDIT_ACE_TYPE ) {
  930. TestedAceFlags &=
  931. ~(SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG);
  932. }
  933. if ( TestedAceFlags != 0 ) {
  934. return STATUS_INVALID_PARAMETER;
  935. }
  936. }
  937. //
  938. // Locate the first free ace and check to see that the Acl is
  939. // well formed.
  940. //
  941. if (!RtlValidAcl( Acl )) {
  942. return STATUS_INVALID_ACL;
  943. }
  944. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  945. return STATUS_INVALID_ACL;
  946. }
  947. //
  948. // Check to see if there is enough room in the Acl to store the new
  949. // ACE
  950. //
  951. AceSize = (USHORT)(sizeof(ACE_HEADER) +
  952. sizeof(ACCESS_MASK) +
  953. SeLengthSid(Sid));
  954. if ( FirstFree == NULL ||
  955. ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
  956. ) {
  957. return STATUS_ALLOTTED_SPACE_EXCEEDED;
  958. }
  959. //
  960. // Add the ACE to the end of the ACL
  961. //
  962. GrantAce = (PKNOWN_ACE)FirstFree;
  963. GrantAce->Header.AceFlags = (UCHAR)AceFlags;
  964. GrantAce->Header.AceType = NewType;
  965. GrantAce->Header.AceSize = AceSize;
  966. GrantAce->Mask = AccessMask;
  967. RtlCopySid( SeLengthSid(Sid), (PSID)(&GrantAce->SidStart), Sid );
  968. //
  969. // Increment the number of ACEs by 1.
  970. //
  971. Acl->AceCount += 1;
  972. //
  973. // Adjust the Acl revision, if necessary
  974. //
  975. Acl->AclRevision = NewRevision;
  976. //
  977. // And return to our caller
  978. //
  979. return STATUS_SUCCESS;
  980. }
  981. NTSTATUS
  982. RtlpAddKnownObjectAce (
  983. IN OUT PACL Acl,
  984. IN ULONG AceRevision,
  985. IN ULONG AceFlags,
  986. IN ACCESS_MASK AccessMask,
  987. IN GUID *ObjectTypeGuid OPTIONAL,
  988. IN GUID *InheritedObjectTypeGuid OPTIONAL,
  989. IN PSID Sid,
  990. IN UCHAR NewType
  991. )
  992. /*++
  993. Routine Description:
  994. This routine adds KNOWN_ACE to an ACL. This is
  995. expected to be a common form of ACL modification.
  996. A very bland ACE header is placed in the ACE. It provides no
  997. inheritance and no ACE flags. The type is specified by the caller.
  998. Arguments:
  999. Acl - Supplies the Acl being modified
  1000. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1001. AceFlags - Supplies the inherit flags for the ACE.
  1002. AccessMask - The mask of accesses to be denied to the specified SID.
  1003. ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
  1004. If NULL, no object type GUID is placed in the ACE.
  1005. InheritedObjectTypeGuid - Supplies the GUID of the object type that will
  1006. inherit this ACE. If NULL, no inherited object type GUID is placed in
  1007. the ACE.
  1008. Sid - Pointer to the SID being denied access.
  1009. NewType - Type of ACE to be added.
  1010. Return Value:
  1011. STATUS_SUCCESS - The ACE was successfully added.
  1012. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1013. STATUS_REVISION_MISMATCH - The specified revision is not known
  1014. or is incompatible with that of the ACL.
  1015. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1016. ACL. A larger ACL buffer is required.
  1017. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1018. SID.
  1019. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1020. --*/
  1021. {
  1022. PVOID FirstFree;
  1023. USHORT AceSize;
  1024. PKNOWN_OBJECT_ACE GrantAce;
  1025. UCHAR NewRevision;
  1026. ULONG TestedAceFlags;
  1027. ULONG AceObjectFlags = 0;
  1028. ULONG SidSize;
  1029. PCHAR Where;
  1030. RTL_PAGED_CODE();
  1031. //
  1032. // Validate the structure of the SID
  1033. //
  1034. if (!RtlValidSid(Sid)) {
  1035. return STATUS_INVALID_SID;
  1036. }
  1037. //
  1038. // Check the ACL & ACE revision levels
  1039. // Object ACEs became valid in version 4.
  1040. //
  1041. if ( Acl->AclRevision > ACL_REVISION4 || AceRevision != ACL_REVISION4 ) {
  1042. return STATUS_REVISION_MISMATCH;
  1043. }
  1044. //
  1045. // Calculate the new revision of the ACL. The new revision is the maximum
  1046. // of the old revision and and new ACE's revision. This is possible because
  1047. // the format of previously defined ACEs did not change across revisions.
  1048. //
  1049. NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
  1050. //
  1051. // Validate the AceFlags.
  1052. //
  1053. TestedAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
  1054. if ( TestedAceFlags != 0 ) {
  1055. if ( NewType == SYSTEM_AUDIT_ACE_TYPE ||
  1056. NewType == SYSTEM_AUDIT_OBJECT_ACE_TYPE ) {
  1057. TestedAceFlags &=
  1058. ~(SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG);
  1059. }
  1060. if ( TestedAceFlags != 0 ) {
  1061. return STATUS_INVALID_PARAMETER;
  1062. }
  1063. }
  1064. //
  1065. // Locate the first free ace and check to see that the Acl is
  1066. // well formed.
  1067. //
  1068. if (!RtlValidAcl( Acl )) {
  1069. return STATUS_INVALID_ACL;
  1070. }
  1071. if (!RtlFirstFreeAce( Acl, &FirstFree )) {
  1072. return STATUS_INVALID_ACL;
  1073. }
  1074. //
  1075. // Check to see if there is enough room in the Acl to store the new
  1076. // ACE
  1077. //
  1078. SidSize = SeLengthSid(Sid);
  1079. AceSize = (USHORT)(sizeof(ACE_HEADER) +
  1080. sizeof(ACCESS_MASK) +
  1081. sizeof(ULONG) +
  1082. SidSize);
  1083. if ( ARGUMENT_PRESENT(ObjectTypeGuid) ) {
  1084. AceObjectFlags |= ACE_OBJECT_TYPE_PRESENT;
  1085. AceSize += sizeof(GUID);
  1086. }
  1087. if ( ARGUMENT_PRESENT(InheritedObjectTypeGuid) ) {
  1088. AceObjectFlags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  1089. AceSize += sizeof(GUID);
  1090. }
  1091. if ( FirstFree == NULL ||
  1092. ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
  1093. ) {
  1094. return STATUS_ALLOTTED_SPACE_EXCEEDED;
  1095. }
  1096. //
  1097. // Add the ACE to the end of the ACL
  1098. //
  1099. GrantAce = (PKNOWN_OBJECT_ACE)FirstFree;
  1100. GrantAce->Header.AceFlags = (UCHAR) AceFlags;
  1101. GrantAce->Header.AceType = NewType;
  1102. GrantAce->Header.AceSize = AceSize;
  1103. GrantAce->Mask = AccessMask;
  1104. GrantAce->Flags = AceObjectFlags;
  1105. Where = (PCHAR) (&GrantAce->SidStart);
  1106. if ( ARGUMENT_PRESENT(ObjectTypeGuid) ) {
  1107. RtlCopyMemory( Where, ObjectTypeGuid, sizeof(GUID) );
  1108. Where += sizeof(GUID);
  1109. }
  1110. if ( ARGUMENT_PRESENT(InheritedObjectTypeGuid) ) {
  1111. RtlCopyMemory( Where, InheritedObjectTypeGuid, sizeof(GUID) );
  1112. Where += sizeof(GUID);
  1113. }
  1114. RtlCopySid( SidSize, (PSID)Where, Sid );
  1115. Where += SidSize;
  1116. //
  1117. // Increment the number of ACEs by 1.
  1118. //
  1119. Acl->AceCount += 1;
  1120. //
  1121. // Adjust the Acl revision, if necessary
  1122. //
  1123. Acl->AclRevision = NewRevision;
  1124. //
  1125. // And return to our caller
  1126. //
  1127. return STATUS_SUCCESS;
  1128. }
  1129. NTSTATUS
  1130. RtlAddAccessAllowedAce (
  1131. IN OUT PACL Acl,
  1132. IN ULONG AceRevision,
  1133. IN ACCESS_MASK AccessMask,
  1134. IN PSID Sid
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. This routine adds an ACCESS_ALLOWED ACE to an ACL. This is
  1139. expected to be a common form of ACL modification.
  1140. A very bland ACE header is placed in the ACE. It provides no
  1141. inheritance and no ACE flags.
  1142. Arguments:
  1143. Acl - Supplies the Acl being modified
  1144. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1145. AccessMask - The mask of accesses to be granted to the specified SID.
  1146. Sid - Pointer to the SID being granted access.
  1147. Return Value:
  1148. STATUS_SUCCESS - The ACE was successfully added.
  1149. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1150. STATUS_REVISION_MISMATCH - The specified revision is not known
  1151. or is incompatible with that of the ACL.
  1152. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1153. ACL. A larger ACL buffer is required.
  1154. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1155. SID.
  1156. --*/
  1157. {
  1158. RTL_PAGED_CODE();
  1159. return RtlpAddKnownAce (
  1160. Acl,
  1161. AceRevision,
  1162. 0, // No inherit flags
  1163. AccessMask,
  1164. Sid,
  1165. ACCESS_ALLOWED_ACE_TYPE
  1166. );
  1167. }
  1168. NTSTATUS
  1169. RtlAddAccessAllowedAceEx (
  1170. IN OUT PACL Acl,
  1171. IN ULONG AceRevision,
  1172. IN ULONG AceFlags,
  1173. IN ACCESS_MASK AccessMask,
  1174. IN PSID Sid
  1175. )
  1176. /*++
  1177. Routine Description:
  1178. This routine adds an ACCESS_ALLOWED ACE to an ACL. This is
  1179. expected to be a common form of ACL modification.
  1180. Arguments:
  1181. Acl - Supplies the Acl being modified
  1182. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1183. AceFlags - Supplies the inherit flags for the ACE.
  1184. AccessMask - The mask of accesses to be granted to the specified SID.
  1185. Sid - Pointer to the SID being granted access.
  1186. Return Value:
  1187. STATUS_SUCCESS - The ACE was successfully added.
  1188. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1189. STATUS_REVISION_MISMATCH - The specified revision is not known
  1190. or is incompatible with that of the ACL.
  1191. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1192. ACL. A larger ACL buffer is required.
  1193. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1194. SID.
  1195. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1196. --*/
  1197. {
  1198. RTL_PAGED_CODE();
  1199. return RtlpAddKnownAce (
  1200. Acl,
  1201. AceRevision,
  1202. AceFlags,
  1203. AccessMask,
  1204. Sid,
  1205. ACCESS_ALLOWED_ACE_TYPE
  1206. );
  1207. }
  1208. NTSTATUS
  1209. RtlAddAccessDeniedAce (
  1210. IN OUT PACL Acl,
  1211. IN ULONG AceRevision,
  1212. IN ACCESS_MASK AccessMask,
  1213. IN PSID Sid
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. This routine adds an ACCESS_DENIED ACE to an ACL. This is
  1218. expected to be a common form of ACL modification.
  1219. A very bland ACE header is placed in the ACE. It provides no
  1220. inheritance and no ACE flags.
  1221. Arguments:
  1222. Acl - Supplies the Acl being modified
  1223. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1224. AccessMask - The mask of accesses to be denied to the specified SID.
  1225. Sid - Pointer to the SID being denied access.
  1226. Return Value:
  1227. STATUS_SUCCESS - The ACE was successfully added.
  1228. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1229. STATUS_REVISION_MISMATCH - The specified revision is not known
  1230. or is incompatible with that of the ACL.
  1231. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1232. ACL. A larger ACL buffer is required.
  1233. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1234. SID.
  1235. --*/
  1236. {
  1237. RTL_PAGED_CODE();
  1238. return RtlpAddKnownAce (
  1239. Acl,
  1240. AceRevision,
  1241. 0, // No inherit flags
  1242. AccessMask,
  1243. Sid,
  1244. ACCESS_DENIED_ACE_TYPE
  1245. );
  1246. }
  1247. NTSTATUS
  1248. RtlAddAccessDeniedAceEx (
  1249. IN OUT PACL Acl,
  1250. IN ULONG AceRevision,
  1251. IN ULONG AceFlags,
  1252. IN ACCESS_MASK AccessMask,
  1253. IN PSID Sid
  1254. )
  1255. /*++
  1256. Routine Description:
  1257. This routine adds an ACCESS_DENIED ACE to an ACL. This is
  1258. expected to be a common form of ACL modification.
  1259. Arguments:
  1260. Acl - Supplies the Acl being modified
  1261. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1262. AceFlags - Supplies the inherit flags for the ACE.
  1263. AccessMask - The mask of accesses to be denied to the specified SID.
  1264. Sid - Pointer to the SID being denied access.
  1265. Return Value:
  1266. STATUS_SUCCESS - The ACE was successfully added.
  1267. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1268. STATUS_REVISION_MISMATCH - The specified revision is not known
  1269. or is incompatible with that of the ACL.
  1270. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1271. ACL. A larger ACL buffer is required.
  1272. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1273. SID.
  1274. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1275. --*/
  1276. {
  1277. RTL_PAGED_CODE();
  1278. return RtlpAddKnownAce (
  1279. Acl,
  1280. AceRevision,
  1281. AceFlags,
  1282. AccessMask,
  1283. Sid,
  1284. ACCESS_DENIED_ACE_TYPE
  1285. );
  1286. }
  1287. NTSTATUS
  1288. RtlAddAuditAccessAce (
  1289. IN OUT PACL Acl,
  1290. IN ULONG AceRevision,
  1291. IN ACCESS_MASK AccessMask,
  1292. IN PSID Sid,
  1293. IN BOOLEAN AuditSuccess,
  1294. IN BOOLEAN AuditFailure
  1295. )
  1296. /*++
  1297. Routine Description:
  1298. This routine adds a SYSTEM_AUDIT ACE to an ACL. This is
  1299. expected to be a common form of ACL modification.
  1300. A very bland ACE header is placed in the ACE. It provides no
  1301. inheritance.
  1302. Parameters are used to indicate whether auditing is to be performed
  1303. on success, failure, or both.
  1304. Arguments:
  1305. Acl - Supplies the Acl being modified
  1306. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1307. AccessMask - The mask of accesses to be denied to the specified SID.
  1308. Sid - Pointer to the SID to be audited.
  1309. AuditSuccess - If TRUE, indicates successful access attempts are to be
  1310. audited.
  1311. AuditFailure - If TRUE, indicated failed access attempts are to be
  1312. audited.
  1313. Return Value:
  1314. STATUS_SUCCESS - The ACE was successfully added.
  1315. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1316. STATUS_REVISION_MISMATCH - The specified revision is not known
  1317. or is incompatible with that of the ACL.
  1318. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1319. ACL. A larger ACL buffer is required.
  1320. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1321. SID.
  1322. --*/
  1323. {
  1324. ULONG AceFlags = 0;
  1325. RTL_PAGED_CODE();
  1326. if (AuditSuccess) {
  1327. AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
  1328. }
  1329. if (AuditFailure) {
  1330. AceFlags |= FAILED_ACCESS_ACE_FLAG;
  1331. }
  1332. return RtlpAddKnownAce (
  1333. Acl,
  1334. AceRevision,
  1335. AceFlags,
  1336. AccessMask,
  1337. Sid,
  1338. SYSTEM_AUDIT_ACE_TYPE );
  1339. }
  1340. NTSTATUS
  1341. RtlAddAuditAccessAceEx (
  1342. IN OUT PACL Acl,
  1343. IN ULONG AceRevision,
  1344. IN ULONG AceFlags,
  1345. IN ACCESS_MASK AccessMask,
  1346. IN PSID Sid,
  1347. IN BOOLEAN AuditSuccess,
  1348. IN BOOLEAN AuditFailure
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. This routine adds a SYSTEM_AUDIT ACE to an ACL. This is
  1353. expected to be a common form of ACL modification.
  1354. A very bland ACE header is placed in the ACE. It provides no
  1355. inheritance.
  1356. Parameters are used to indicate whether auditing is to be performed
  1357. on success, failure, or both.
  1358. Arguments:
  1359. Acl - Supplies the Acl being modified
  1360. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1361. AceFlags - Supplies the inherit flags for the ACE.
  1362. AccessMask - The mask of accesses to be denied to the specified SID.
  1363. Sid - Pointer to the SID to be audited.
  1364. AuditSuccess - If TRUE, indicates successful access attempts are to be
  1365. audited.
  1366. AuditFailure - If TRUE, indicated failed access attempts are to be
  1367. audited.
  1368. Return Value:
  1369. STATUS_SUCCESS - The ACE was successfully added.
  1370. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1371. STATUS_REVISION_MISMATCH - The specified revision is not known
  1372. or is incompatible with that of the ACL.
  1373. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1374. ACL. A larger ACL buffer is required.
  1375. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1376. SID.
  1377. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1378. --*/
  1379. {
  1380. RTL_PAGED_CODE();
  1381. if (AuditSuccess) {
  1382. AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
  1383. }
  1384. if (AuditFailure) {
  1385. AceFlags |= FAILED_ACCESS_ACE_FLAG;
  1386. }
  1387. return RtlpAddKnownAce (
  1388. Acl,
  1389. AceRevision,
  1390. AceFlags,
  1391. AccessMask,
  1392. Sid,
  1393. SYSTEM_AUDIT_ACE_TYPE );
  1394. }
  1395. NTSTATUS
  1396. RtlAddAccessAllowedObjectAce (
  1397. IN OUT PACL Acl,
  1398. IN ULONG AceRevision,
  1399. IN ULONG AceFlags,
  1400. IN ACCESS_MASK AccessMask,
  1401. IN GUID *ObjectTypeGuid OPTIONAL,
  1402. IN GUID *InheritedObjectTypeGuid OPTIONAL,
  1403. IN PSID Sid
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. This routine adds an object specific ACCESS_ALLOWED ACE to an ACL. This is
  1408. expected to be a common form of ACL modification.
  1409. Arguments:
  1410. Acl - Supplies the Acl being modified
  1411. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1412. AceFlags - Supplies the inherit flags for the ACE.
  1413. AccessMask - The mask of accesses to be granted to the specified SID.
  1414. ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
  1415. If NULL, no object type GUID is placed in the ACE.
  1416. InheritedObjectTypeGuid - Supplies the GUID of the object type that will
  1417. inherit this ACE. If NULL, no inherited object type GUID is placed in
  1418. the ACE.
  1419. Sid - Pointer to the SID being granted access.
  1420. Return Value:
  1421. STATUS_SUCCESS - The ACE was successfully added.
  1422. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1423. STATUS_REVISION_MISMATCH - The specified revision is not known
  1424. or is incompatible with that of the ACL.
  1425. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1426. ACL. A larger ACL buffer is required.
  1427. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1428. SID.
  1429. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1430. --*/
  1431. {
  1432. RTL_PAGED_CODE();
  1433. //
  1434. // If no object types are specified,
  1435. // build a non-object ACE.
  1436. //
  1437. if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
  1438. return RtlpAddKnownAce (
  1439. Acl,
  1440. AceRevision,
  1441. AceFlags,
  1442. AccessMask,
  1443. Sid,
  1444. ACCESS_ALLOWED_ACE_TYPE
  1445. );
  1446. }
  1447. return RtlpAddKnownObjectAce (
  1448. Acl,
  1449. AceRevision,
  1450. AceFlags,
  1451. AccessMask,
  1452. ObjectTypeGuid,
  1453. InheritedObjectTypeGuid,
  1454. Sid,
  1455. ACCESS_ALLOWED_OBJECT_ACE_TYPE
  1456. );
  1457. }
  1458. NTSTATUS
  1459. RtlAddAccessDeniedObjectAce (
  1460. IN OUT PACL Acl,
  1461. IN ULONG AceRevision,
  1462. IN ULONG AceFlags,
  1463. IN ACCESS_MASK AccessMask,
  1464. IN GUID *ObjectTypeGuid OPTIONAL,
  1465. IN GUID *InheritedObjectTypeGuid OPTIONAL,
  1466. IN PSID Sid
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. This routine adds an object specific ACCESS_DENIED ACE to an ACL. This is
  1471. expected to be a common form of ACL modification.
  1472. Arguments:
  1473. Acl - Supplies the Acl being modified
  1474. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1475. AceFlags - Supplies the inherit flags for the ACE.
  1476. AccessMask - The mask of accesses to be granted to the specified SID.
  1477. ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
  1478. If NULL, no object type GUID is placed in the ACE.
  1479. InheritedObjectTypeGuid - Supplies the GUID of the object type that will
  1480. inherit this ACE. If NULL, no inherited object type GUID is placed in
  1481. the ACE.
  1482. Sid - Pointer to the SID being denied access.
  1483. Return Value:
  1484. STATUS_SUCCESS - The ACE was successfully added.
  1485. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1486. STATUS_REVISION_MISMATCH - The specified revision is not known
  1487. or is incompatible with that of the ACL.
  1488. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1489. ACL. A larger ACL buffer is required.
  1490. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1491. SID.
  1492. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1493. --*/
  1494. {
  1495. RTL_PAGED_CODE();
  1496. //
  1497. // If no object types are specified,
  1498. // build a non-object ACE.
  1499. //
  1500. if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
  1501. return RtlpAddKnownAce (
  1502. Acl,
  1503. AceRevision,
  1504. AceFlags,
  1505. AccessMask,
  1506. Sid,
  1507. ACCESS_DENIED_ACE_TYPE
  1508. );
  1509. }
  1510. return RtlpAddKnownObjectAce (
  1511. Acl,
  1512. AceRevision,
  1513. AceFlags,
  1514. AccessMask,
  1515. ObjectTypeGuid,
  1516. InheritedObjectTypeGuid,
  1517. Sid,
  1518. ACCESS_DENIED_OBJECT_ACE_TYPE
  1519. );
  1520. }
  1521. NTSTATUS
  1522. RtlAddAuditAccessObjectAce (
  1523. IN OUT PACL Acl,
  1524. IN ULONG AceRevision,
  1525. IN ULONG AceFlags,
  1526. IN ACCESS_MASK AccessMask,
  1527. IN GUID *ObjectTypeGuid OPTIONAL,
  1528. IN GUID *InheritedObjectTypeGuid OPTIONAL,
  1529. IN PSID Sid,
  1530. IN BOOLEAN AuditSuccess,
  1531. IN BOOLEAN AuditFailure
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This routine adds an object specific ACCESS_DENIED ACE to an ACL. This is
  1536. expected to be a common form of ACL modification.
  1537. Arguments:
  1538. Acl - Supplies the Acl being modified
  1539. AceRevision - Supplies the Acl/Ace revision of the ACE being added
  1540. AceFlags - Supplies the inherit flags for the ACE.
  1541. AccessMask - The mask of accesses to be granted to the specified SID.
  1542. ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
  1543. If NULL, no object type GUID is placed in the ACE.
  1544. InheritedObjectTypeGuid - Supplies the GUID of the object type that will
  1545. inherit this ACE. If NULL, no inherited object type GUID is placed in
  1546. the ACE.
  1547. Sid - Pointer to the SID to be audited.
  1548. AuditSuccess - If TRUE, indicates successful access attempts are to be
  1549. audited.
  1550. AuditFailure - If TRUE, indicated failed access attempts are to be
  1551. audited.
  1552. Return Value:
  1553. STATUS_SUCCESS - The ACE was successfully added.
  1554. STATUS_INVALID_ACL - The specified ACL is not properly formed.
  1555. STATUS_REVISION_MISMATCH - The specified revision is not known
  1556. or is incompatible with that of the ACL.
  1557. STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
  1558. ACL. A larger ACL buffer is required.
  1559. STATUS_INVALID_SID - The provided SID is not a structurally valid
  1560. SID.
  1561. STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
  1562. --*/
  1563. {
  1564. RTL_PAGED_CODE();
  1565. if (AuditSuccess) {
  1566. AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
  1567. }
  1568. if (AuditFailure) {
  1569. AceFlags |= FAILED_ACCESS_ACE_FLAG;
  1570. }
  1571. //
  1572. // If no object types are specified,
  1573. // build a non-object ACE.
  1574. //
  1575. if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
  1576. return RtlpAddKnownAce (
  1577. Acl,
  1578. AceRevision,
  1579. AceFlags,
  1580. AccessMask,
  1581. Sid,
  1582. SYSTEM_AUDIT_ACE_TYPE
  1583. );
  1584. }
  1585. return RtlpAddKnownObjectAce (
  1586. Acl,
  1587. AceRevision,
  1588. AceFlags,
  1589. AccessMask,
  1590. ObjectTypeGuid,
  1591. InheritedObjectTypeGuid,
  1592. Sid,
  1593. SYSTEM_AUDIT_OBJECT_ACE_TYPE
  1594. );
  1595. }
  1596. #if 0
  1597. NTSTATUS
  1598. RtlMakePosixAcl(
  1599. IN ULONG AclRevision,
  1600. IN PSID UserSid,
  1601. IN PSID GroupSid,
  1602. IN ACCESS_MASK UserAccess,
  1603. IN ACCESS_MASK GroupAccess,
  1604. IN ACCESS_MASK OtherAccess,
  1605. IN ULONG AclLength,
  1606. OUT PACL Acl,
  1607. OUT PULONG ReturnLength
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. NOTE: THIS ROUTINE IS STILL BEING SPEC'D.
  1612. Make an ACL representing Posix protection from AccessMask and
  1613. security account ID (SID) information.
  1614. Arguments:
  1615. AclRevision - Indicates the ACL revision level of the access masks
  1616. provided. The ACL generated will be revision compatible with this
  1617. value and will not be a higher revision than this value.
  1618. UserSid - Provides the SID of the user (owner).
  1619. GroupSid - Provides the SID of the primary group.
  1620. UserAccess - Specifies the accesses to be given to the user (owner).
  1621. GroupAccess - Specifies the accesses to be given to the primary group.
  1622. OtherAccess - Specifies the accesses to be given to others (WORLD).
  1623. AclLength - Provides the length (in bytes) of the Acl buffer.
  1624. Acl - Points to a buffer to receive the generated ACL.
  1625. ReturnLength - Returns the actual length needed to store the resultant
  1626. ACL. If this length is greater than that specified in AclLength,
  1627. then STATUS_BUFFER_TOO_SMALL is returned and no ACL is generated.
  1628. Return Values:
  1629. STATUS_SUCCESS - The service completed successfully.
  1630. STATUS_UNKNOWN_REVISION - The revision level specified is not supported
  1631. by this service.
  1632. STATUS_BUFFER_TOO_SMALL - Indicates the length of the output buffer
  1633. wasn't large enough to hold the generated ACL. The length needed
  1634. is returned via the ReturnLength parameter.
  1635. --*/
  1636. {
  1637. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1638. ULONG UserSidLength;
  1639. ULONG GroupSidLength;
  1640. ULONG WorldSidLength;
  1641. ULONG RequiredAclSize;
  1642. ULONG AceSize;
  1643. ULONG CurrentAce;
  1644. PACCESS_ALLOWED_ACE Ace;
  1645. NTSTATUS Status;
  1646. RTL_PAGED_CODE();
  1647. if (!RtlValidSid( UserSid ) || !RtlValidSid( GroupSid )) {
  1648. return( STATUS_INVALID_SID );
  1649. }
  1650. UserSidLength = SeLengthSid( UserSid );
  1651. GroupSidLength = SeLengthSid( GroupSid );
  1652. WorldSidLength = RtlLengthRequiredSid( 1 );
  1653. //
  1654. // Figure out how much room we need for an ACL and three
  1655. // ACCESS_ALLOWED Ace's
  1656. //
  1657. RequiredAclSize = sizeof( ACL );
  1658. AceSize = sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG );
  1659. RequiredAclSize += (AceSize * 3) +
  1660. UserSidLength +
  1661. GroupSidLength +
  1662. WorldSidLength ;
  1663. if (RequiredAclSize > AclLength) {
  1664. *ReturnLength = RequiredAclSize;
  1665. return( STATUS_BUFFER_TOO_SMALL );
  1666. }
  1667. //
  1668. // The passed buffer is big enough, build the ACL in it.
  1669. //
  1670. Status = RtlCreateAcl(
  1671. Acl,
  1672. RequiredAclSize,
  1673. AclRevision
  1674. );
  1675. if (!NT_SUCCESS( Status )) {
  1676. return( Status );
  1677. }
  1678. CurrentAce = (ULONG)Acl + sizeof( ACL );
  1679. Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
  1680. //
  1681. // Build the user (owner) ACE
  1682. //
  1683. Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  1684. Ace->Header.AceSize = (USHORT)(UserSidLength + AceSize);
  1685. Ace->Header.AceFlags = 0;
  1686. Ace->Mask = UserAccess;
  1687. RtlCopyMemory(
  1688. (PVOID)(Ace->SidStart),
  1689. UserSid,
  1690. UserSidLength
  1691. );
  1692. CurrentAce += (ULONG)(Ace->Header.AceSize);
  1693. Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
  1694. //
  1695. // Build the group ACE
  1696. //
  1697. Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  1698. Ace->Header.AceSize = (USHORT)(GroupSidLength + AceSize);
  1699. Ace->Header.AceFlags = 0;
  1700. Ace->Mask = GroupAccess;
  1701. RtlCopyMemory(
  1702. (PVOID)(Ace->SidStart),
  1703. GroupSid,
  1704. GroupSidLength
  1705. );
  1706. CurrentAce += (ULONG)(Ace->Header.AceSize);
  1707. Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
  1708. //
  1709. // Build the World ACE
  1710. //
  1711. Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  1712. Ace->Header.AceSize = (USHORT)(GroupSidLength + AceSize);
  1713. Ace->Header.AceFlags = 0;
  1714. Ace->Mask = OtherAccess;
  1715. RtlInitializeSid(
  1716. (PSID)(Ace->SidStart),
  1717. &WorldSidAuthority,
  1718. 1
  1719. );
  1720. *(RtlSubAuthoritySid((PSID)(Ace->SidStart), 0 )) = SECURITY_WORLD_RID;
  1721. return( STATUS_SUCCESS );
  1722. }
  1723. NTSTATUS
  1724. RtlInterpretPosixAcl(
  1725. IN ULONG AclRevision,
  1726. IN PSID UserSid,
  1727. IN PSID GroupSid,
  1728. IN PACL Acl,
  1729. OUT PACCESS_MASK UserAccess,
  1730. OUT PACCESS_MASK GroupAccess,
  1731. OUT PACCESS_MASK OtherAccess
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. NOTE: THIS ROUTINE IS STILL BEING SPEC'D.
  1736. Interpret an ACL representing Posix protection, returning AccessMasks.
  1737. Use security account IDs (SIDs) for object owner and primary group
  1738. identification.
  1739. This algorithm will pick up the first match of a given SID and ignore
  1740. all further matches of that SID. The first unrecognized SID becomes
  1741. the "other" SID.
  1742. Arguments:
  1743. AclRevision - Indicates the ACL revision level of the access masks to
  1744. be returned.
  1745. UserSid - Provides the SID of the user (owner).
  1746. GroupSid - Provides the SID of the primary group.
  1747. Acl - Points to a buffer containing the ACL to interpret.
  1748. UserAccess - Receives the accesses allowed for the user (owner).
  1749. GroupAccess - Receives the accesses allowed for the primary group.
  1750. OtherAccess - Receives the accesses allowed for others (WORLD).
  1751. Return Values:
  1752. STATUS_SUCCESS - The service completed successfully.
  1753. STATUS_UNKNOWN_REVISION - The revision level specified is not supported
  1754. by this service.
  1755. STATUS_EXTRENEOUS_INFORMATION - This warning status value indicates the
  1756. ACL contained protection or other information unrelated to Posix
  1757. style protection. This is a warning only. The interpretation was
  1758. otherwise successful and all access masks were returned.
  1759. STATUS_COULD_NOT_INTERPRET - Indicates the ACL does not contain
  1760. sufficient Posix style (user/group) protection information. The
  1761. ACL could not be interpreted.
  1762. --*/
  1763. {
  1764. NTSTATUS Status = STATUS_SUCCESS;
  1765. BOOLEAN UserFound = FALSE;
  1766. BOOLEAN GroupFound = FALSE;
  1767. BOOLEAN OtherFound = FALSE;
  1768. ULONG i;
  1769. PKNOWN_ACE Ace;
  1770. RTL_PAGED_CODE();
  1771. if (AclRevision != ACL_REVISION2) {
  1772. return( STATUS_UNKNOWN_REVISION );
  1773. }
  1774. if (Acl->AceCount > 3) {
  1775. Status = STATUS_EXTRANEOUS_INFORMATION;
  1776. }
  1777. for (i=0, Ace = FirstAce( Acl );
  1778. (i < Acl->AceCount) && (!UserFound || !GroupFound || !OtherFound);
  1779. i++, Ace = NextAce( Ace )) {
  1780. if (Ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
  1781. Status = STATUS_EXTRANEOUS_INFORMATION;
  1782. continue;
  1783. }
  1784. if (RtlEqualSid(
  1785. (PSID)(Ace->SidStart),
  1786. UserSid
  1787. ) && !UserFound) {
  1788. *UserAccess = Ace->Mask;
  1789. UserFound = TRUE;
  1790. continue;
  1791. }
  1792. if (RtlEqualSid(
  1793. (PSID)(Ace->SidStart),
  1794. GroupSid
  1795. ) && !GroupFound) {
  1796. *GroupAccess = Ace->Mask;
  1797. GroupFound = TRUE;
  1798. continue;
  1799. }
  1800. //
  1801. // It isn't the user, and it isn't the group, pick it up
  1802. // as "other"
  1803. //
  1804. if (!OtherFound) {
  1805. *OtherAccess = Ace->Mask;
  1806. OtherFound = TRUE;
  1807. continue;
  1808. }
  1809. }
  1810. //
  1811. // Make sure we got everything we need, error otherwise
  1812. //
  1813. if (!UserFound || !GroupFound || !OtherFound) {
  1814. Status = STATUS_COULD_NOT_INTERPRET;
  1815. }
  1816. return( Status );
  1817. }
  1818. #endif // 0
  1819. //
  1820. // Internal support routine
  1821. //
  1822. BOOLEAN
  1823. RtlFirstFreeAce (
  1824. IN PACL Acl,
  1825. OUT PVOID *FirstFree
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. This routine returns a pointer to the first free byte in an Acl
  1830. or NULL if the acl is ill-formed. If the Acl is full then the
  1831. return pointer is to the byte immediately following the acl, and
  1832. TRUE will be returned.
  1833. Arguments:
  1834. Acl - Supplies a pointer to the Acl to examine
  1835. FirstFree - Receives a pointer to the first free position in the Acl
  1836. Return Value:
  1837. BOOLEAN - TRUE if the Acl is well formed and FALSE otherwise
  1838. --*/
  1839. {
  1840. PACE_HEADER Ace;
  1841. ULONG i;
  1842. RTL_PAGED_CODE();
  1843. //
  1844. // To find the first free spot in the Acl we need to search for
  1845. // the last ace. We do this by zooming down the list until
  1846. // we've exhausted the ace count or the ace size (which ever comes
  1847. // first). In the following loop Ace points to the next spot
  1848. // for an Ace and I is the ace index
  1849. //
  1850. *FirstFree = NULL;
  1851. for ( i=0, Ace = FirstAce( Acl );
  1852. i < Acl->AceCount;
  1853. i++, Ace = NextAce( Ace )) {
  1854. //
  1855. // Check to make sure we haven't overrun the Acl buffer
  1856. // with our Ace pointer. If we have then our input is bogus.
  1857. //
  1858. if (Ace >= (PACE_HEADER)((PUCHAR)Acl + Acl->AclSize)) {
  1859. return FALSE;
  1860. }
  1861. }
  1862. //
  1863. // Now Ace points to the first free spot in the Acl so set the
  1864. // output variable and check to make sure it is still in the Acl
  1865. // or just one beyond the end of the acl (i.e., the acl is full).
  1866. //
  1867. if (Ace <= (PACE_HEADER)((PUCHAR)Acl + Acl->AclSize)) {
  1868. *FirstFree = Ace;
  1869. }
  1870. //
  1871. // The Acl is well formed so return the first free spot we've found
  1872. // (or NULL if there is no free space for another ACE)
  1873. //
  1874. return TRUE;
  1875. }
  1876. //
  1877. // Internal support routine
  1878. //
  1879. VOID
  1880. RtlpAddData (
  1881. IN PVOID From,
  1882. IN ULONG FromSize,
  1883. IN PVOID To,
  1884. IN ULONG ToSize
  1885. )
  1886. /*++
  1887. Routine Description:
  1888. This routine copies data to a string of bytes. It does this by moving
  1889. over data in the to string so that the from string will fit. It also
  1890. assumes that the checks that the data will fit in memory have already
  1891. been done. Pictorally the results are as follows.
  1892. Before:
  1893. From -> ffffffffff
  1894. To -> tttttttttttttttt
  1895. After:
  1896. From -> ffffffffff
  1897. To -> fffffffffftttttttttttttttt
  1898. Arguments:
  1899. From - Supplies a pointer to the source buffer
  1900. FromSize - Supplies the size of the from buffer in bytes
  1901. To - Supplies a pointer to the destination buffer
  1902. ToSize - Supplies the size of the to buffer in bytes
  1903. Return Value:
  1904. None
  1905. --*/
  1906. {
  1907. LONG i;
  1908. //
  1909. // Shift over the To buffer enough to fit in the From buffer
  1910. //
  1911. for (i = ToSize - 1; i >= 0; i--) {
  1912. ((PUCHAR)To)[i+FromSize] = ((PUCHAR)To)[i];
  1913. }
  1914. //
  1915. // Now copy over the From buffer
  1916. //
  1917. for (i = 0; (ULONG)i < FromSize; i += 1) {
  1918. ((PUCHAR)To)[i] = ((PUCHAR)From)[i];
  1919. }
  1920. //
  1921. // and return to our caller
  1922. //
  1923. return;
  1924. }
  1925. //
  1926. // Internal support routine
  1927. //
  1928. VOID
  1929. RtlpDeleteData (
  1930. IN PVOID Data,
  1931. IN ULONG RemoveSize,
  1932. IN ULONG TotalSize
  1933. )
  1934. /*++
  1935. Routine Description:
  1936. This routine deletes a string of bytes from the front of a data buffer
  1937. and compresses the data. It also zeros out the part of the string
  1938. that is no longer in use. Pictorially the results are as follows
  1939. Before:
  1940. Data = DDDDDddddd
  1941. RemoveSize = 5
  1942. TotalSize = 10
  1943. After:
  1944. Data = ddddd00000
  1945. Arguments:
  1946. Data - Supplies a pointer to the data being altered
  1947. RemoveSize - Supplies the number of bytes to delete from the front
  1948. of the data buffer
  1949. TotalSize - Supplies the total number of bytes in the data buffer
  1950. before the delete operation
  1951. Return Value:
  1952. None
  1953. --*/
  1954. {
  1955. ULONG i;
  1956. //
  1957. // Shift over the buffer to remove the amount
  1958. //
  1959. for (i = RemoveSize; i < TotalSize; i++) {
  1960. ((PUCHAR)Data)[i-RemoveSize] = ((PUCHAR)Data)[i];
  1961. }
  1962. //
  1963. // Now as a safety precaution we'll zero out the rest of the string
  1964. //
  1965. for (i = TotalSize - RemoveSize; i < TotalSize; i++) {
  1966. ((PUCHAR)Data)[i] = 0;
  1967. }
  1968. //
  1969. // And return to our caller
  1970. //
  1971. return;
  1972. }