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.

1351 lines
36 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. scseclib.c
  5. Abstract:
  6. This module provides support routines to simplify the creation of
  7. security descriptors.
  8. Author:
  9. Rita Wong (ritaw) 27-Feb-1991
  10. Cliff Van Dyke (cliffv)
  11. Richard Ward (richardw) 8-April-92 Modified for Cairo
  12. Environment:
  13. Contains NT specific code.
  14. Revision History:
  15. 13-Apr-1992 JohnRo
  16. Made changes suggested by PC-LINT.
  17. --*/
  18. #include <scpragma.h>
  19. extern "C"
  20. {
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. }
  25. #include <windef.h> // DWORD (needed by scdebug.h).
  26. #include <winbase.h>
  27. #include <stdlib.h> // max()
  28. #include <scdebug.h> // STATIC.
  29. #include <scseclib.h>
  30. //-------------------------------------------------------------------//
  31. // //
  32. // Local function prototypes //
  33. // //
  34. //-------------------------------------------------------------------//
  35. NTSTATUS
  36. ScInitializeAllowedAce(
  37. IN PACCESS_ALLOWED_ACE AllowedAce,
  38. IN USHORT AceSize,
  39. IN UCHAR InheritFlags,
  40. IN UCHAR AceFlags,
  41. IN ACCESS_MASK Mask,
  42. IN PSID AllowedSid
  43. );
  44. NTSTATUS
  45. ScInitializeDeniedAce(
  46. IN PACCESS_DENIED_ACE DeniedAce,
  47. IN USHORT AceSize,
  48. IN UCHAR InheritFlags,
  49. IN UCHAR AceFlags,
  50. IN ACCESS_MASK Mask,
  51. IN PSID DeniedSid
  52. );
  53. NTSTATUS
  54. ScInitializeAuditAce(
  55. IN PACCESS_ALLOWED_ACE AuditAce,
  56. IN USHORT AceSize,
  57. IN UCHAR InheritFlags,
  58. IN UCHAR AceFlags,
  59. IN ACCESS_MASK Mask,
  60. IN PSID AuditSid
  61. );
  62. //-------------------------------------------------------------------//
  63. // //
  64. // Global variables //
  65. // //
  66. //-------------------------------------------------------------------//
  67. //
  68. // NT well-known SIDs
  69. //
  70. PSID NullSid = NULL; // No members SID
  71. PSID WorldSid = NULL; // All users SID
  72. PSID LocalSid = NULL; // NT local users SID
  73. PSID NetworkSid = NULL; // NT remote users SID
  74. PSID LocalSystemSid = NULL; // NT system processes SID
  75. PSID LocalServiceSid = NULL; // NT LocalService SID
  76. PSID NetworkServiceSid = NULL; // NT NetworkService SID
  77. PSID BuiltinDomainSid = NULL; // Domain Id of the Builtin Domain
  78. PSID AuthenticatedUserSid = NULL; // NT authenticated users SID
  79. PSID AnonymousLogonSid = NULL; // Anonymous Logon SID
  80. //
  81. // Well Known Aliases.
  82. //
  83. // These are aliases that are relative to the built-in domain.
  84. //
  85. PSID AliasAdminsSid = NULL;
  86. PSID AliasUsersSid = NULL;
  87. PSID AliasGuestsSid = NULL;
  88. PSID AliasPowerUsersSid = NULL;
  89. PSID AliasAccountOpsSid = NULL;
  90. PSID AliasSystemOpsSid = NULL;
  91. PSID AliasPrintOpsSid = NULL;
  92. PSID AliasBackupOpsSid = NULL;
  93. #if DBG
  94. //
  95. // Debug flag
  96. //
  97. ULONG RtlSeDebugFlag = 0;
  98. #define RTL_SE_DUMP_ACLS 0x00000001
  99. typedef struct _STANDARD_ACE {
  100. ACE_HEADER Header;
  101. ACCESS_MASK Mask;
  102. PSID Sid;
  103. } STANDARD_ACE;
  104. typedef STANDARD_ACE *PSTANDARD_ACE;
  105. //
  106. // The following macros used by DumpAcl(), these macros and DumpAcl() are
  107. // stolen from private\ntos\se\ctaccess.c (written by robertre) for
  108. // debugging purposes.
  109. //
  110. //
  111. // Returns a pointer to the first Ace in an Acl (even if the Acl is empty).
  112. //
  113. #define FirstAce(Acl) ((PSTANDARD_ACE)((PUCHAR)(Acl) + sizeof(ACL)))
  114. //
  115. // Returns a pointer to the next Ace in a sequence (even if the input
  116. // Ace is the one in the sequence).
  117. //
  118. #define NextAce(Ace) \
  119. ((PSTANDARD_ACE)((PUCHAR)(Ace) + ((PACE_HEADER)(PVOID)(Ace))->AceSize))
  120. VOID
  121. DumpAcl(
  122. IN PACL Acl
  123. );
  124. #endif //ifdef DBG
  125. //
  126. // Data describing the well-known SIDs created by ScCreateWellKnownSids.
  127. //
  128. struct _SID_DATA {
  129. PSID *Sid;
  130. SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
  131. ULONG SubAuthority;
  132. } SidData[] = {
  133. {&NullSid, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID},
  134. {&WorldSid, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID},
  135. {&LocalSid, SECURITY_LOCAL_SID_AUTHORITY, SECURITY_LOCAL_RID},
  136. {&NetworkSid, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_RID},
  137. {&LocalSystemSid, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID},
  138. {&LocalServiceSid, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SERVICE_RID},
  139. {&NetworkServiceSid, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_SERVICE_RID},
  140. {&BuiltinDomainSid, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID},
  141. {&AuthenticatedUserSid, SECURITY_NT_AUTHORITY, SECURITY_AUTHENTICATED_USER_RID},
  142. {&AnonymousLogonSid, SECURITY_NT_AUTHORITY, SECURITY_ANONYMOUS_LOGON_RID}
  143. };
  144. struct _BUILTIN_DOMAIN_SID_DATA {
  145. PSID *Sid;
  146. ULONG RelativeId;
  147. } BuiltinDomainSidData[] = {
  148. { &AliasAdminsSid, DOMAIN_ALIAS_RID_ADMINS },
  149. { &AliasUsersSid, DOMAIN_ALIAS_RID_USERS },
  150. { &AliasGuestsSid, DOMAIN_ALIAS_RID_GUESTS },
  151. { &AliasPowerUsersSid, DOMAIN_ALIAS_RID_POWER_USERS },
  152. { &AliasAccountOpsSid, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
  153. { &AliasSystemOpsSid, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  154. { &AliasPrintOpsSid, DOMAIN_ALIAS_RID_PRINT_OPS },
  155. { &AliasBackupOpsSid, DOMAIN_ALIAS_RID_BACKUP_OPS }
  156. };
  157. NTSTATUS
  158. ScCreateWellKnownSids(
  159. VOID
  160. )
  161. /*++
  162. Routine Description:
  163. This function creates some well-known SIDs and store them in global
  164. variables:
  165. //
  166. // NT well-known SIDs
  167. //
  168. PSID NullSid; // No members SID
  169. PSID WorldSid; // All users SID
  170. PSID LocalSid; // NT local users SID
  171. PSID NetworkSid; // NT remote users SID
  172. PSID LocalSystemSid; // NT system processes SID
  173. PSID LocalServiceSid; // NT LocalService SID
  174. PSID NetworkServiceSid; // NT NetworkService SID
  175. PSID BuiltinDomainSid; // Domain Id of the Builtin Domain
  176. PSID AuthenticatedUserSid; // NT authenticated users SID
  177. PSID AnonymousLogonSid; // NT anonymous logon
  178. //
  179. // Well Known Aliases.
  180. //
  181. // These are aliases that are relative to the built-in domain.
  182. //
  183. PSID AliasAdminsSid;
  184. PSID AliasUsersSid;
  185. PSID AliasGuestsSid;
  186. PSID AliasPowerUsersSid;
  187. PSID AliasAccountOpsSid;
  188. PSID AliasSystemOpsSid;
  189. PSID AliasPrintOpsSid;
  190. PSID AliasBackupOpsSid;
  191. Arguments:
  192. None.
  193. Return Value:
  194. STATUS_SUCCESS - if successful
  195. STATUS_NO_MEMORY - if cannot allocate memory for SID
  196. --*/
  197. {
  198. NTSTATUS ntstatus;
  199. ULONG i;
  200. //
  201. // Allocate and initialize well-known SIDs which aren't relative to
  202. // the domain Id.
  203. //
  204. for (i = 0; i < (sizeof(SidData) / sizeof(SidData[0])) ; i++) {
  205. ntstatus = ScAllocateAndInitializeSid(
  206. SidData[i].Sid,
  207. &(SidData[i].IdentifierAuthority),
  208. 1);
  209. if (! NT_SUCCESS(ntstatus)) {
  210. return STATUS_NO_MEMORY;
  211. }
  212. *(RtlSubAuthoritySid(*(SidData[i].Sid), 0)) = SidData[i].SubAuthority;
  213. }
  214. //
  215. // Build each SID which is relative to the Builtin Domain Id.
  216. //
  217. for ( i = 0;
  218. i < (sizeof(BuiltinDomainSidData) / sizeof(BuiltinDomainSidData[0]));
  219. i++) {
  220. ntstatus = ScDomainIdToSid(
  221. BuiltinDomainSid,
  222. BuiltinDomainSidData[i].RelativeId,
  223. BuiltinDomainSidData[i].Sid );
  224. if (! NT_SUCCESS(ntstatus)) {
  225. return STATUS_NO_MEMORY;
  226. }
  227. }
  228. return STATUS_SUCCESS;
  229. }
  230. NTSTATUS
  231. ScAllocateAndInitializeSid(
  232. OUT PSID *Sid,
  233. IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
  234. IN ULONG SubAuthorityCount
  235. )
  236. /*++
  237. Routine Description:
  238. This function allocates memory for a SID and initializes it.
  239. Arguments:
  240. None.
  241. Return Value:
  242. STATUS_SUCCESS - if successful
  243. STATUS_NO_MEMORY - if cannot allocate memory for SID
  244. --*/
  245. {
  246. *Sid = (PSID) RtlAllocateHeap(
  247. RtlProcessHeap(), 0,
  248. RtlLengthRequiredSid(SubAuthorityCount)
  249. );
  250. if (*Sid == NULL) {
  251. return STATUS_NO_MEMORY;
  252. }
  253. (VOID) RtlInitializeSid(
  254. *Sid,
  255. IdentifierAuthority,
  256. (UCHAR)SubAuthorityCount );
  257. return STATUS_SUCCESS;
  258. }
  259. NTSTATUS
  260. ScDomainIdToSid(
  261. IN PSID DomainId,
  262. IN ULONG RelativeId,
  263. OUT PSID *Sid
  264. )
  265. /*++
  266. Routine Description:
  267. Given a domain Id and a relative ID create a SID.
  268. Arguments:
  269. DomainId - The template SID to use.
  270. RelativeId - The relative Id to append to the DomainId.
  271. Sid - Returns a pointer to an allocated buffer containing the resultant
  272. Sid. Free this buffer using RtlFreeHeap.
  273. Return Value:
  274. STATUS_SUCCESS - if successful
  275. STATUS_NO_MEMORY - if cannot allocate memory for SID
  276. Any error status from RtlCopySid
  277. --*/
  278. {
  279. NTSTATUS ntstatus;
  280. UCHAR DomainIdSubAuthorityCount; // Number of sub authorities in domain ID
  281. ULONG SidLength; // Length of newly allocated SID
  282. PVOID HeapHandle = RtlProcessHeap();
  283. //
  284. // Allocate a Sid which has one more sub-authority than the domain ID.
  285. //
  286. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  287. SidLength = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  288. if ((*Sid = (PSID) RtlAllocateHeap(
  289. HeapHandle, 0,
  290. SidLength
  291. )) == NULL) {
  292. return STATUS_NO_MEMORY;
  293. }
  294. //
  295. // Initialize the new SID to have the same inital value as the
  296. // domain ID.
  297. //
  298. ntstatus = RtlCopySid(SidLength, *Sid, DomainId);
  299. if (! NT_SUCCESS(ntstatus)) {
  300. (void) RtlFreeHeap(HeapHandle, 0, *Sid);
  301. return ntstatus;
  302. }
  303. //
  304. // Adjust the sub-authority count and
  305. // add the relative Id unique to the newly allocated SID
  306. //
  307. (*(RtlSubAuthorityCountSid( *Sid ))) ++;
  308. *RtlSubAuthoritySid( *Sid, DomainIdSubAuthorityCount ) = RelativeId;
  309. return STATUS_SUCCESS;
  310. }
  311. NTSTATUS
  312. ScCreateAndSetSD(
  313. IN PSC_ACE_DATA AceData,
  314. IN ULONG AceCount,
  315. IN PSID OwnerSid OPTIONAL,
  316. IN PSID GroupSid OPTIONAL,
  317. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  318. )
  319. /*++
  320. Routine Description:
  321. This function creates an absolute security descriptor containing
  322. the supplied ACE information.
  323. A sample usage of this function:
  324. //
  325. // Order matters! These ACEs are inserted into the DACL in the
  326. // following order. Security access is granted or denied based on
  327. // the order of the ACEs in the DACL.
  328. //
  329. SE_ACE_DATA AceData[4] = {
  330. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  331. GENERIC_ALL, &AliasAdminsSid},
  332. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  333. GENERIC_ALL, &NetworkSid},
  334. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  335. WKSTA_CONFIG_GUEST_INFO_GET |
  336. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  337. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  338. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  339. };
  340. PSECURITY_DESCRIPTOR WkstaSecurityDescriptor;
  341. return SeCreateAndSetSD(
  342. AceData,
  343. 4,
  344. LocalSystemSid,
  345. LocalSystemSid,
  346. &WkstaSecurityDescriptor
  347. );
  348. Arguments:
  349. AceData - Supplies the structure of information that describes the DACL.
  350. AceCount - Supplies the number of entries in AceData structure.
  351. OwnerSid - Supplies the pointer to the SID of the security descriptor
  352. owner. If not specified, a security descriptor with no owner
  353. will be created.
  354. GroupSid - Supplies the pointer to the SID of the security descriptor
  355. primary group. If not specified, a security descriptor with no primary
  356. group will be created.
  357. NewDescriptor - Returns a pointer to the absolute security descriptor
  358. allocated using RtlAllocateHeap.
  359. Return Value:
  360. STATUS_SUCCESS - if successful
  361. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  362. security descriptor.
  363. Any other status codes returned from the security Rtl routines.
  364. NOTE : the user security object created by calling this function may be
  365. freed up by calling RtlDeleteSecurityObject().
  366. --*/
  367. {
  368. NTSTATUS ntstatus;
  369. ULONG i;
  370. //
  371. // Pointer to memory dynamically allocated by this routine to hold
  372. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  373. //
  374. // +---------------------------------------------------------------+
  375. // | Security Descriptor |
  376. // +-------------------------------+-------+---------------+-------+
  377. // | DACL | ACE 1 | . . . | ACE n |
  378. // +-------------------------------+-------+---------------+-------+
  379. // | SACL | ACE 1 | . . . | ACE n |
  380. // +-------------------------------+-------+---------------+-------+
  381. //
  382. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  383. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  384. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  385. ULONG DaclSize = sizeof(ACL);
  386. ULONG SaclSize = sizeof(ACL);
  387. ULONG MaxAceSize = 0;
  388. PACCESS_ALLOWED_ACE MaxAce = NULL;
  389. PCHAR CurrentAvailable;
  390. ULONG Size;
  391. PVOID HeapHandle = RtlProcessHeap();
  392. ASSERT( AceCount > 0 );
  393. //
  394. // Compute the total size of the DACL and SACL ACEs and the maximum
  395. // size of any ACE.
  396. //
  397. for (i = 0; i < AceCount; i++) {
  398. ULONG AceSize;
  399. AceSize = RtlLengthSid(*(AceData[i].Sid));
  400. switch (AceData[i].AceType) {
  401. case ACCESS_ALLOWED_ACE_TYPE:
  402. AceSize += sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG);
  403. DaclSize += AceSize;
  404. break;
  405. case ACCESS_DENIED_ACE_TYPE:
  406. AceSize += sizeof(ACCESS_DENIED_ACE) - sizeof(ULONG);
  407. DaclSize += AceSize;
  408. break;
  409. case SYSTEM_AUDIT_ACE_TYPE:
  410. AceSize += sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG);
  411. SaclSize += AceSize;
  412. break;
  413. default:
  414. return STATUS_INVALID_PARAMETER;
  415. }
  416. MaxAceSize = max( MaxAceSize, AceSize );
  417. }
  418. //
  419. // Allocate a chunk of memory large enough the security descriptor
  420. // the DACL, the SACL and all ACEs.
  421. //
  422. // A security descriptor is of opaque data type but
  423. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  424. //
  425. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  426. if ( DaclSize != sizeof(ACL) ) {
  427. Size += DaclSize;
  428. }
  429. if ( SaclSize != sizeof(ACL) ) {
  430. Size += SaclSize;
  431. }
  432. if ((AbsoluteSd = RtlAllocateHeap(
  433. HeapHandle, 0,
  434. Size
  435. )) == NULL) {
  436. KdPrint(("SeCreateAndSetSD: No memory to create absolute SD\n"));
  437. ntstatus = STATUS_NO_MEMORY;
  438. goto Cleanup;
  439. }
  440. //
  441. // Initialize the Dacl and Sacl
  442. //
  443. CurrentAvailable = (PCHAR)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  444. if ( DaclSize != sizeof(ACL) ) {
  445. Dacl = (PACL)CurrentAvailable;
  446. CurrentAvailable += DaclSize;
  447. ntstatus = RtlCreateAcl( Dacl, DaclSize, ACL_REVISION );
  448. if ( !NT_SUCCESS(ntstatus) ) {
  449. KdPrint(("ScCreateAndSetSD: Fail DACL Create %08lx\n",
  450. ntstatus));
  451. goto Cleanup;
  452. }
  453. }
  454. if ( SaclSize != sizeof(ACL) ) {
  455. Sacl = (PACL)CurrentAvailable;
  456. CurrentAvailable += SaclSize;
  457. ntstatus = RtlCreateAcl( Sacl, SaclSize, ACL_REVISION );
  458. if ( !NT_SUCCESS(ntstatus) ) {
  459. KdPrint(("ScCreateAndSetSD: Fail SACL Create %08lx\n",
  460. ntstatus));
  461. goto Cleanup;
  462. }
  463. }
  464. //
  465. // Allocate a temporary buffer big enough for the biggest ACE.
  466. //
  467. if ((MaxAce = (PACCESS_ALLOWED_ACE) RtlAllocateHeap(
  468. HeapHandle, 0,
  469. MaxAceSize
  470. )) == NULL ) {
  471. KdPrint(("ScCreateAndSetSD: No memory to create max ace\n"));
  472. ntstatus = STATUS_NO_MEMORY;
  473. goto Cleanup;
  474. }
  475. //
  476. // Initialize each ACE, and append it into the end of the DACL or SACL.
  477. //
  478. for (i = 0; i < AceCount; i++) {
  479. ULONG AceSize;
  480. PACL CurrentAcl;
  481. AceSize = RtlLengthSid(*(AceData[i].Sid));
  482. switch (AceData[i].AceType) {
  483. case ACCESS_ALLOWED_ACE_TYPE:
  484. AceSize += sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG);
  485. CurrentAcl = Dacl;
  486. ntstatus = ScInitializeAllowedAce(
  487. MaxAce,
  488. (USHORT) AceSize,
  489. AceData[i].InheritFlags,
  490. AceData[i].AceFlags,
  491. AceData[i].Mask,
  492. *(AceData[i].Sid)
  493. );
  494. break;
  495. case ACCESS_DENIED_ACE_TYPE:
  496. AceSize += sizeof(ACCESS_DENIED_ACE) - sizeof(ULONG);
  497. CurrentAcl = Dacl;
  498. ntstatus = ScInitializeDeniedAce(
  499. (PACCESS_DENIED_ACE) MaxAce,
  500. (USHORT) AceSize,
  501. AceData[i].InheritFlags,
  502. AceData[i].AceFlags,
  503. AceData[i].Mask,
  504. *(AceData[i].Sid)
  505. );
  506. break;
  507. case SYSTEM_AUDIT_ACE_TYPE:
  508. AceSize += sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG);
  509. CurrentAcl = Sacl;
  510. ntstatus = ScInitializeAuditAce(
  511. MaxAce,
  512. (USHORT) AceSize,
  513. AceData[i].InheritFlags,
  514. AceData[i].AceFlags,
  515. AceData[i].Mask,
  516. *(AceData[i].Sid)
  517. );
  518. break;
  519. default:
  520. SC_LOG2(ERROR,
  521. "ScCreateAndSetSD: Invalid AceType %d in ACE %d\n",
  522. AceData[i].AceType,
  523. i);
  524. ASSERT(FALSE);
  525. CurrentAcl = NULL;
  526. ntstatus = STATUS_UNSUCCESSFUL;
  527. }
  528. if ( !NT_SUCCESS( ntstatus ) ) {
  529. KdPrint((
  530. "ScCreateAndSetSD: Fail InitAce i: %d ntstatus: %08lx\n",
  531. i, ntstatus));
  532. goto Cleanup;
  533. }
  534. //
  535. // Append the initialized ACE to the end of DACL or SACL
  536. //
  537. if (! NT_SUCCESS (ntstatus = RtlAddAce(
  538. CurrentAcl,
  539. ACL_REVISION,
  540. MAXULONG,
  541. MaxAce,
  542. AceSize
  543. ))) {
  544. KdPrint((
  545. "ScCreateAndSetSD: Fail add ace i: %d ntstatus: %08lx\n",
  546. i, ntstatus));
  547. goto Cleanup;
  548. }
  549. }
  550. #if DBG
  551. DumpAcl(Dacl);
  552. if (Sacl) {
  553. DumpAcl(Sacl);
  554. }
  555. #endif
  556. //
  557. // Create the security descriptor with absolute pointers to SIDs
  558. // and ACLs.
  559. //
  560. // Owner = OwnerSid
  561. // Group = GroupSid
  562. // Dacl = Dacl
  563. // Sacl = Sacl
  564. //
  565. if (! NT_SUCCESS(ntstatus = RtlCreateSecurityDescriptor(
  566. AbsoluteSd,
  567. SECURITY_DESCRIPTOR_REVISION
  568. ))) {
  569. goto Cleanup;
  570. }
  571. if (! NT_SUCCESS(ntstatus = RtlSetOwnerSecurityDescriptor(
  572. AbsoluteSd,
  573. OwnerSid,
  574. FALSE
  575. ))) {
  576. goto Cleanup;
  577. }
  578. if (! NT_SUCCESS(ntstatus = RtlSetGroupSecurityDescriptor(
  579. AbsoluteSd,
  580. GroupSid,
  581. FALSE
  582. ))) {
  583. goto Cleanup;
  584. }
  585. if (! NT_SUCCESS(ntstatus = RtlSetDaclSecurityDescriptor(
  586. AbsoluteSd,
  587. (BOOLEAN)(Dacl ? TRUE : FALSE),
  588. Dacl,
  589. FALSE
  590. ))) {
  591. goto Cleanup;
  592. }
  593. if (! NT_SUCCESS(ntstatus = RtlSetSaclSecurityDescriptor(
  594. AbsoluteSd,
  595. (BOOLEAN)(Sacl ? TRUE : FALSE),
  596. Sacl,
  597. FALSE
  598. ))) {
  599. goto Cleanup;
  600. }
  601. //
  602. // Done
  603. //
  604. ntstatus = STATUS_SUCCESS;
  605. //
  606. // Clean up
  607. //
  608. Cleanup:
  609. //
  610. // Either return the security descriptor to the caller or delete it
  611. //
  612. if ( NT_SUCCESS( ntstatus ) ) {
  613. *NewDescriptor = AbsoluteSd;
  614. } else if ( AbsoluteSd != NULL ) {
  615. RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  616. }
  617. //
  618. // Delete the temporary ACE
  619. //
  620. if ( MaxAce != NULL ) {
  621. RtlFreeHeap(HeapHandle, 0, MaxAce);
  622. }
  623. return ntstatus;
  624. }
  625. NTSTATUS
  626. ScCreateUserSecurityObject(
  627. IN PSECURITY_DESCRIPTOR ParentSD,
  628. IN PSC_ACE_DATA AceData,
  629. IN ULONG AceCount,
  630. IN PSID OwnerSid,
  631. IN PSID GroupSid,
  632. IN BOOLEAN IsDirectoryObject,
  633. IN BOOLEAN UseImpersonationToken,
  634. IN PGENERIC_MAPPING GenericMapping,
  635. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  636. )
  637. /*++
  638. Routine Description:
  639. This function creates the DACL for the security descriptor based on
  640. on the ACE information specified, and creates the security descriptor
  641. which becomes the user-mode security object.
  642. A sample usage of this function:
  643. //
  644. // Structure that describes the mapping of Generic access rights to
  645. // object specific access rights for the ConfigurationInfo object.
  646. //
  647. GENERIC_MAPPING WsConfigInfoMapping = {
  648. STANDARD_RIGHTS_READ | // Generic read
  649. WKSTA_CONFIG_GUEST_INFO_GET |
  650. WKSTA_CONFIG_USER_INFO_GET |
  651. WKSTA_CONFIG_ADMIN_INFO_GET,
  652. STANDARD_RIGHTS_WRITE | // Generic write
  653. WKSTA_CONFIG_INFO_SET,
  654. STANDARD_RIGHTS_EXECUTE, // Generic execute
  655. WKSTA_CONFIG_ALL_ACCESS // Generic all
  656. };
  657. //
  658. // Order matters! These ACEs are inserted into the DACL in the
  659. // following order. Security access is granted or denied based on
  660. // the order of the ACEs in the DACL.
  661. //
  662. SE_ACE_DATA AceData[4] = {
  663. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  664. GENERIC_ALL, &AliasAdminsSid},
  665. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  666. GENERIC_ALL, &NetworkSid},
  667. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  668. WKSTA_CONFIG_GUEST_INFO_GET |
  669. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  670. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  671. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  672. };
  673. PSECURITY_DESCRIPTOR WkstaSecurityObject;
  674. return ScCreateUserSecurityObject(
  675. AceData,
  676. 4,
  677. LocalSystemSid,
  678. LocalSystemSid,
  679. FALSE,
  680. &WsConfigInfoMapping,
  681. &WkstaSecurityObject
  682. );
  683. Arguments:
  684. AceData - Supplies the structure of information that describes the DACL.
  685. AceCount - Supplies the number of entries in AceData structure.
  686. OwnerSid - Supplies the pointer to the SID of the security descriptor
  687. owner.
  688. GroupSid - Supplies the pointer to the SID of the security descriptor
  689. primary group.
  690. IsDirectoryObject - Supplies the flag which indicates whether the
  691. user-mode object is a directory object.
  692. GenericMapping - Supplies the pointer to a generic mapping array denoting
  693. the mapping between each generic right to specific rights.
  694. NewDescriptor - Returns a pointer to the self-relative security descriptor
  695. which represents the user-mode object.
  696. Return Value:
  697. STATUS_SUCCESS - if successful
  698. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  699. security descriptor.
  700. Any other status codes returned from the security Rtl routines.
  701. NOTE : the user security object created by calling this function may be
  702. freed up by calling RtlDeleteSecurityObject().
  703. --*/
  704. {
  705. NTSTATUS ntstatus;
  706. PSECURITY_DESCRIPTOR AbsoluteSd;
  707. HANDLE TokenHandle;
  708. PVOID HeapHandle = RtlProcessHeap();
  709. ntstatus = ScCreateAndSetSD(
  710. AceData,
  711. AceCount,
  712. OwnerSid,
  713. GroupSid,
  714. &AbsoluteSd
  715. );
  716. if (! NT_SUCCESS(ntstatus)) {
  717. KdPrint((
  718. "ScCreateUserSecurityObject: ScCreateAndSetSD returned "
  719. "%08lx\n", ntstatus));
  720. return ntstatus;
  721. }
  722. if (UseImpersonationToken) {
  723. ntstatus = NtOpenThreadToken(
  724. NtCurrentThread(),
  725. TOKEN_QUERY,
  726. FALSE,
  727. &TokenHandle
  728. );
  729. }
  730. else {
  731. ntstatus = NtOpenProcessToken(
  732. NtCurrentProcess(),
  733. TOKEN_QUERY,
  734. &TokenHandle
  735. );
  736. }
  737. if (! NT_SUCCESS(ntstatus)) {
  738. KdPrint((
  739. "ScCreateUserSecurityObject: NtOpen...Token returned "
  740. "%08lx\n", ntstatus));
  741. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  742. return ntstatus;
  743. }
  744. //
  745. // Create the security object (a user-mode object is really a pseudo-
  746. // object represented by a security descriptor that have relative
  747. // pointers to SIDs and ACLs). This routine allocates the memory to
  748. // hold the relative security descriptor so the memory allocated for the
  749. // DACL, ACEs, and the absolute descriptor can be freed.
  750. //
  751. ntstatus = RtlNewSecurityObject(
  752. ParentSD, // Parent descriptor
  753. AbsoluteSd, // Creator descriptor
  754. NewDescriptor, // Pointer to new descriptor
  755. IsDirectoryObject, // Is directory object
  756. TokenHandle, // Token
  757. GenericMapping // Generic mapping
  758. );
  759. (void) NtClose(TokenHandle);
  760. if (! NT_SUCCESS(ntstatus)) {
  761. KdPrint((
  762. "RtlCreateUserSecurityObject: RtlNewSecurityObject returned "
  763. "%08lx\n", ntstatus));
  764. }
  765. //
  766. // Free dynamic memory before returning
  767. //
  768. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  769. return ntstatus;
  770. }
  771. NTSTATUS
  772. ScInitializeAllowedAce(
  773. IN PACCESS_ALLOWED_ACE AllowedAce,
  774. IN USHORT AceSize,
  775. IN UCHAR InheritFlags,
  776. IN UCHAR AceFlags,
  777. IN ACCESS_MASK Mask,
  778. IN PSID AllowedSid
  779. )
  780. /*++
  781. Routine Description:
  782. This function assigns the specified ACE values into an allowed type ACE.
  783. Arguments:
  784. AllowedAce - Supplies a pointer to the ACE that is initialized.
  785. AceSize - Supplies the size of the ACE in bytes.
  786. InheritFlags - Supplies ACE inherit flags.
  787. AceFlags - Supplies ACE type specific control flags.
  788. Mask - Supplies the allowed access masks.
  789. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  790. the specified access.
  791. Return Value:
  792. Returns status from RtlCopySid.
  793. --*/
  794. {
  795. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  796. AllowedAce->Header.AceSize = AceSize;
  797. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  798. AllowedAce->Mask = Mask;
  799. return RtlCopySid(
  800. RtlLengthSid(AllowedSid),
  801. &(AllowedAce->SidStart),
  802. AllowedSid
  803. );
  804. }
  805. NTSTATUS
  806. ScInitializeDeniedAce(
  807. IN PACCESS_DENIED_ACE DeniedAce,
  808. IN USHORT AceSize,
  809. IN UCHAR InheritFlags,
  810. IN UCHAR AceFlags,
  811. IN ACCESS_MASK Mask,
  812. IN PSID DeniedSid
  813. )
  814. /*++
  815. Routine Description:
  816. This function assigns the specified ACE values into a denied type ACE.
  817. Arguments:
  818. DeniedAce - Supplies a pointer to the ACE that is initialized.
  819. AceSize - Supplies the size of the ACE in bytes.
  820. InheritFlags - Supplies ACE inherit flags.
  821. AceFlags - Supplies ACE type specific control flags.
  822. Mask - Supplies the denied access masks.
  823. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  824. the specified access.
  825. Return Value:
  826. Returns status from RtlCopySid.
  827. --*/
  828. {
  829. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  830. DeniedAce->Header.AceSize = AceSize;
  831. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  832. DeniedAce->Mask = Mask;
  833. return RtlCopySid(
  834. RtlLengthSid(DeniedSid),
  835. &(DeniedAce->SidStart),
  836. DeniedSid
  837. );
  838. }
  839. NTSTATUS
  840. ScInitializeAuditAce(
  841. IN PACCESS_ALLOWED_ACE AuditAce,
  842. IN USHORT AceSize,
  843. IN UCHAR InheritFlags,
  844. IN UCHAR AceFlags,
  845. IN ACCESS_MASK Mask,
  846. IN PSID AuditSid
  847. )
  848. /*++
  849. Routine Description:
  850. This function assigns the specified ACE values into an audit type ACE.
  851. Arguments:
  852. AuditAce - Supplies a pointer to the ACE that is initialized.
  853. AceSize - Supplies the size of the ACE in bytes.
  854. InheritFlags - Supplies ACE inherit flags.
  855. AceFlags - Supplies ACE type specific control flags.
  856. Mask - Supplies the allowed access masks.
  857. AuditSid - Supplies the pointer to the SID of user/group which is to be
  858. audited.
  859. Return Value:
  860. Returns status from RtlCopySid.
  861. --*/
  862. {
  863. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  864. AuditAce->Header.AceSize = AceSize;
  865. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  866. AuditAce->Mask = Mask;
  867. return RtlCopySid(
  868. RtlLengthSid(AuditSid),
  869. &(AuditAce->SidStart),
  870. AuditSid
  871. );
  872. }
  873. DWORD
  874. ScCreateStartEventSD(
  875. PSECURITY_DESCRIPTOR *pEventSD
  876. )
  877. /*++
  878. Routine Description:
  879. This routine creates a security descriptor for the
  880. SC_INTERNAL_START_EVENT. This function may be called from
  881. either the client or server side.
  882. NOTE: it is up to the caller to free the memory for the
  883. security descriptor.
  884. Arguments:
  885. pEventSD - Pointer to a location where the pointer to
  886. the newly created security descriptor can be placed.
  887. Return Value:
  888. NO_ERROR - indicates success.
  889. all other values indicate failure.
  890. --*/
  891. {
  892. NTSTATUS ntstatus;
  893. PSECURITY_DESCRIPTOR SecurityDescriptor;
  894. SID_IDENTIFIER_AUTHORITY WorldSidAuth[1] = {
  895. SECURITY_WORLD_SID_AUTHORITY};
  896. SID_IDENTIFIER_AUTHORITY LocalSystemSidAuth[1] = {
  897. SECURITY_NT_AUTHORITY};
  898. SC_ACE_DATA AceData[2] = {
  899. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  900. SYNCHRONIZE, &WorldSid},
  901. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  902. GENERIC_ALL, &LocalSystemSid}
  903. };
  904. if (WorldSid == NULL) {
  905. if (!AllocateAndInitializeSid(
  906. WorldSidAuth,
  907. 1,
  908. SECURITY_WORLD_RID,
  909. 0,0,0,0,0,0,0,
  910. &WorldSid)) {
  911. SC_LOG1(ERROR, "AllocateAndInitWorldSid failed %d\n",GetLastError());
  912. return(GetLastError());
  913. }
  914. }
  915. if (LocalSystemSid == NULL) {
  916. if (!AllocateAndInitializeSid(
  917. LocalSystemSidAuth,
  918. 1,
  919. SECURITY_LOCAL_SYSTEM_RID,
  920. 0,0,0,0,0,0,0,
  921. &LocalSystemSid)) {
  922. SC_LOG1(ERROR, "AllocateAndInitLocalSysSid failed %d\n",GetLastError());
  923. return(GetLastError());
  924. }
  925. }
  926. ntstatus = ScCreateAndSetSD(
  927. AceData,
  928. 2,
  929. LocalSystemSid,
  930. LocalSystemSid,
  931. &SecurityDescriptor);
  932. if (! NT_SUCCESS(ntstatus)) {
  933. SC_LOG1(ERROR, "ScCreateAndSetSD failed %0x%lx\n",ntstatus);
  934. return(RtlNtStatusToDosError(ntstatus));
  935. }
  936. *pEventSD = SecurityDescriptor;
  937. return(NO_ERROR);
  938. }
  939. #if DBG
  940. VOID
  941. DumpAcl(
  942. IN PACL Acl
  943. )
  944. /*++
  945. Routine Description:
  946. This routine dumps via (DbgPrint) an Acl for debug purposes. It is
  947. specialized to dump standard aces.
  948. Arguments:
  949. Acl - Supplies the Acl to dump
  950. Return Value:
  951. None
  952. --*/
  953. {
  954. ULONG i;
  955. PSTANDARD_ACE Ace;
  956. if (RtlSeDebugFlag & RTL_SE_DUMP_ACLS) {
  957. (VOID) DbgPrint("DumpAcl @%08lx\n", Acl);
  958. //
  959. // Check if the Acl is null
  960. //
  961. if (Acl == NULL) {
  962. return;
  963. }
  964. //
  965. // Dump the Acl header
  966. //
  967. (VOID) DbgPrint(" Revision: %02x", Acl->AclRevision);
  968. (VOID) DbgPrint(" Size: %04x", Acl->AclSize);
  969. (VOID) DbgPrint(" AceCount: %04x\n", Acl->AceCount);
  970. //
  971. // Now for each Ace we want do dump it
  972. //
  973. for (i = 0, Ace = FirstAce(Acl);
  974. i < Acl->AceCount;
  975. i++, Ace = NextAce(Ace) ) {
  976. //
  977. // print out the ace header
  978. //
  979. (VOID) DbgPrint(" AceHeader: %08lx ", *(PULONG)Ace);
  980. //
  981. // special case on the standard ace types
  982. //
  983. if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
  984. (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
  985. (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
  986. (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) {
  987. //
  988. // The following array is indexed by ace types and must
  989. // follow the allowed, denied, audit, alarm seqeuence
  990. //
  991. static PCHAR AceTypes[] = { "Access Allowed",
  992. "Access Denied ",
  993. "System Audit ",
  994. "System Alarm "
  995. };
  996. (VOID) DbgPrint(AceTypes[Ace->Header.AceType]);
  997. (VOID) DbgPrint("\nAccess Mask: %08lx ", Ace->Mask);
  998. } else {
  999. (VOID) DbgPrint("Unknown Ace Type\n");
  1000. }
  1001. (VOID) DbgPrint("\n");
  1002. (VOID) DbgPrint("AceSize = %d\n",Ace->Header.AceSize);
  1003. (VOID) DbgPrint("Ace Flags = ");
  1004. if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
  1005. (VOID) DbgPrint("OBJECT_INHERIT_ACE\n");
  1006. (VOID) DbgPrint(" ");
  1007. }
  1008. if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
  1009. (VOID) DbgPrint("CONTAINER_INHERIT_ACE\n");
  1010. (VOID) DbgPrint(" ");
  1011. }
  1012. if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
  1013. (VOID) DbgPrint("NO_PROPAGATE_INHERIT_ACE\n");
  1014. (VOID) DbgPrint(" ");
  1015. }
  1016. if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
  1017. (VOID) DbgPrint("INHERIT_ONLY_ACE\n");
  1018. (VOID) DbgPrint(" ");
  1019. }
  1020. if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
  1021. (VOID) DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n");
  1022. (VOID) DbgPrint(" ");
  1023. }
  1024. if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
  1025. (VOID) DbgPrint("FAILED_ACCESS_ACE_FLAG\n");
  1026. (VOID) DbgPrint(" ");
  1027. }
  1028. (VOID) DbgPrint("\n");
  1029. }
  1030. }
  1031. }
  1032. #endif // if DBG