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

1176 lines
33 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. //
  94. // Data describing the well-known SIDs created by ScCreateWellKnownSids.
  95. //
  96. struct _SID_DATA {
  97. PSID *Sid;
  98. SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
  99. ULONG SubAuthority;
  100. } SidData[] = {
  101. {&NullSid, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID},
  102. {&WorldSid, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID},
  103. {&LocalSid, SECURITY_LOCAL_SID_AUTHORITY, SECURITY_LOCAL_RID},
  104. {&NetworkSid, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_RID},
  105. {&LocalSystemSid, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID},
  106. {&LocalServiceSid, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SERVICE_RID},
  107. {&NetworkServiceSid, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_SERVICE_RID},
  108. {&BuiltinDomainSid, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID},
  109. {&AuthenticatedUserSid, SECURITY_NT_AUTHORITY, SECURITY_AUTHENTICATED_USER_RID},
  110. {&AnonymousLogonSid, SECURITY_NT_AUTHORITY, SECURITY_ANONYMOUS_LOGON_RID}
  111. };
  112. struct _BUILTIN_DOMAIN_SID_DATA {
  113. PSID *Sid;
  114. ULONG RelativeId;
  115. } BuiltinDomainSidData[] = {
  116. { &AliasAdminsSid, DOMAIN_ALIAS_RID_ADMINS },
  117. { &AliasUsersSid, DOMAIN_ALIAS_RID_USERS },
  118. { &AliasGuestsSid, DOMAIN_ALIAS_RID_GUESTS },
  119. { &AliasPowerUsersSid, DOMAIN_ALIAS_RID_POWER_USERS },
  120. { &AliasAccountOpsSid, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
  121. { &AliasSystemOpsSid, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  122. { &AliasPrintOpsSid, DOMAIN_ALIAS_RID_PRINT_OPS },
  123. { &AliasBackupOpsSid, DOMAIN_ALIAS_RID_BACKUP_OPS }
  124. };
  125. NTSTATUS
  126. ScCreateWellKnownSids(
  127. VOID
  128. )
  129. /*++
  130. Routine Description:
  131. This function creates some well-known SIDs and store them in global
  132. variables:
  133. //
  134. // NT well-known SIDs
  135. //
  136. PSID NullSid; // No members SID
  137. PSID WorldSid; // All users SID
  138. PSID LocalSid; // NT local users SID
  139. PSID NetworkSid; // NT remote users SID
  140. PSID LocalSystemSid; // NT system processes SID
  141. PSID LocalServiceSid; // NT LocalService SID
  142. PSID NetworkServiceSid; // NT NetworkService SID
  143. PSID BuiltinDomainSid; // Domain Id of the Builtin Domain
  144. PSID AuthenticatedUserSid; // NT authenticated users SID
  145. PSID AnonymousLogonSid; // NT anonymous logon
  146. //
  147. // Well Known Aliases.
  148. //
  149. // These are aliases that are relative to the built-in domain.
  150. //
  151. PSID AliasAdminsSid;
  152. PSID AliasUsersSid;
  153. PSID AliasGuestsSid;
  154. PSID AliasPowerUsersSid;
  155. PSID AliasAccountOpsSid;
  156. PSID AliasSystemOpsSid;
  157. PSID AliasPrintOpsSid;
  158. PSID AliasBackupOpsSid;
  159. Arguments:
  160. None.
  161. Return Value:
  162. STATUS_SUCCESS - if successful
  163. STATUS_NO_MEMORY - if cannot allocate memory for SID
  164. --*/
  165. {
  166. NTSTATUS ntstatus;
  167. ULONG i;
  168. //
  169. // Allocate and initialize well-known SIDs which aren't relative to
  170. // the domain Id.
  171. //
  172. for (i = 0; i < (sizeof(SidData) / sizeof(SidData[0])) ; i++) {
  173. ntstatus = ScAllocateAndInitializeSid(
  174. SidData[i].Sid,
  175. &(SidData[i].IdentifierAuthority),
  176. 1);
  177. if (! NT_SUCCESS(ntstatus)) {
  178. return STATUS_NO_MEMORY;
  179. }
  180. *(RtlSubAuthoritySid(*(SidData[i].Sid), 0)) = SidData[i].SubAuthority;
  181. }
  182. //
  183. // Build each SID which is relative to the Builtin Domain Id.
  184. //
  185. for ( i = 0;
  186. i < (sizeof(BuiltinDomainSidData) / sizeof(BuiltinDomainSidData[0]));
  187. i++) {
  188. ntstatus = ScDomainIdToSid(
  189. BuiltinDomainSid,
  190. BuiltinDomainSidData[i].RelativeId,
  191. BuiltinDomainSidData[i].Sid );
  192. if (! NT_SUCCESS(ntstatus)) {
  193. return STATUS_NO_MEMORY;
  194. }
  195. }
  196. return STATUS_SUCCESS;
  197. }
  198. NTSTATUS
  199. ScAllocateAndInitializeSid(
  200. OUT PSID *Sid,
  201. IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
  202. IN ULONG SubAuthorityCount
  203. )
  204. /*++
  205. Routine Description:
  206. This function allocates memory for a SID and initializes it.
  207. Arguments:
  208. None.
  209. Return Value:
  210. STATUS_SUCCESS - if successful
  211. STATUS_NO_MEMORY - if cannot allocate memory for SID
  212. --*/
  213. {
  214. *Sid = (PSID) RtlAllocateHeap(
  215. RtlProcessHeap(), 0,
  216. RtlLengthRequiredSid(SubAuthorityCount)
  217. );
  218. if (*Sid == NULL) {
  219. return STATUS_NO_MEMORY;
  220. }
  221. (VOID) RtlInitializeSid(
  222. *Sid,
  223. IdentifierAuthority,
  224. (UCHAR)SubAuthorityCount );
  225. return STATUS_SUCCESS;
  226. }
  227. NTSTATUS
  228. ScDomainIdToSid(
  229. IN PSID DomainId,
  230. IN ULONG RelativeId,
  231. OUT PSID *Sid
  232. )
  233. /*++
  234. Routine Description:
  235. Given a domain Id and a relative ID create a SID.
  236. Arguments:
  237. DomainId - The template SID to use.
  238. RelativeId - The relative Id to append to the DomainId.
  239. Sid - Returns a pointer to an allocated buffer containing the resultant
  240. Sid. Free this buffer using RtlFreeHeap.
  241. Return Value:
  242. STATUS_SUCCESS - if successful
  243. STATUS_NO_MEMORY - if cannot allocate memory for SID
  244. Any error status from RtlCopySid
  245. --*/
  246. {
  247. NTSTATUS ntstatus;
  248. UCHAR DomainIdSubAuthorityCount; // Number of sub authorities in domain ID
  249. ULONG SidLength; // Length of newly allocated SID
  250. PVOID HeapHandle = RtlProcessHeap();
  251. //
  252. // Allocate a Sid which has one more sub-authority than the domain ID.
  253. //
  254. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  255. SidLength = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  256. if ((*Sid = (PSID) RtlAllocateHeap(
  257. HeapHandle, 0,
  258. SidLength
  259. )) == NULL) {
  260. return STATUS_NO_MEMORY;
  261. }
  262. //
  263. // Initialize the new SID to have the same inital value as the
  264. // domain ID.
  265. //
  266. ntstatus = RtlCopySid(SidLength, *Sid, DomainId);
  267. if (! NT_SUCCESS(ntstatus)) {
  268. (void) RtlFreeHeap(HeapHandle, 0, *Sid);
  269. return ntstatus;
  270. }
  271. //
  272. // Adjust the sub-authority count and
  273. // add the relative Id unique to the newly allocated SID
  274. //
  275. (*(RtlSubAuthorityCountSid( *Sid ))) ++;
  276. *RtlSubAuthoritySid( *Sid, DomainIdSubAuthorityCount ) = RelativeId;
  277. return STATUS_SUCCESS;
  278. }
  279. NTSTATUS
  280. ScCreateAndSetSD(
  281. IN PSC_ACE_DATA AceData,
  282. IN ULONG AceCount,
  283. IN PSID OwnerSid OPTIONAL,
  284. IN PSID GroupSid OPTIONAL,
  285. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  286. )
  287. /*++
  288. Routine Description:
  289. This function creates an absolute security descriptor containing
  290. the supplied ACE information.
  291. A sample usage of this function:
  292. //
  293. // Order matters! These ACEs are inserted into the DACL in the
  294. // following order. Security access is granted or denied based on
  295. // the order of the ACEs in the DACL.
  296. //
  297. SE_ACE_DATA AceData[4] = {
  298. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  299. GENERIC_ALL, &AliasAdminsSid},
  300. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  301. GENERIC_ALL, &NetworkSid},
  302. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  303. WKSTA_CONFIG_GUEST_INFO_GET |
  304. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  305. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  306. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  307. };
  308. PSECURITY_DESCRIPTOR WkstaSecurityDescriptor;
  309. return SeCreateAndSetSD(
  310. AceData,
  311. 4,
  312. LocalSystemSid,
  313. LocalSystemSid,
  314. &WkstaSecurityDescriptor
  315. );
  316. Arguments:
  317. AceData - Supplies the structure of information that describes the DACL.
  318. AceCount - Supplies the number of entries in AceData structure.
  319. OwnerSid - Supplies the pointer to the SID of the security descriptor
  320. owner. If not specified, a security descriptor with no owner
  321. will be created.
  322. GroupSid - Supplies the pointer to the SID of the security descriptor
  323. primary group. If not specified, a security descriptor with no primary
  324. group will be created.
  325. NewDescriptor - Returns a pointer to the absolute security descriptor
  326. allocated using RtlAllocateHeap.
  327. Return Value:
  328. STATUS_SUCCESS - if successful
  329. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  330. security descriptor.
  331. Any other status codes returned from the security Rtl routines.
  332. NOTE : the user security object created by calling this function may be
  333. freed up by calling RtlDeleteSecurityObject().
  334. --*/
  335. {
  336. NTSTATUS ntstatus;
  337. ULONG i;
  338. //
  339. // Pointer to memory dynamically allocated by this routine to hold
  340. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  341. //
  342. // +---------------------------------------------------------------+
  343. // | Security Descriptor |
  344. // +-------------------------------+-------+---------------+-------+
  345. // | DACL | ACE 1 | . . . | ACE n |
  346. // +-------------------------------+-------+---------------+-------+
  347. // | SACL | ACE 1 | . . . | ACE n |
  348. // +-------------------------------+-------+---------------+-------+
  349. //
  350. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  351. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  352. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  353. ULONG DaclSize = sizeof(ACL);
  354. ULONG SaclSize = sizeof(ACL);
  355. ULONG MaxAceSize = 0;
  356. PACCESS_ALLOWED_ACE MaxAce = NULL;
  357. PCHAR CurrentAvailable;
  358. ULONG Size;
  359. PVOID HeapHandle = RtlProcessHeap();
  360. ASSERT( AceCount > 0 );
  361. //
  362. // Compute the total size of the DACL and SACL ACEs and the maximum
  363. // size of any ACE.
  364. //
  365. for (i = 0; i < AceCount; i++) {
  366. ULONG AceSize;
  367. AceSize = RtlLengthSid(*(AceData[i].Sid));
  368. switch (AceData[i].AceType) {
  369. case ACCESS_ALLOWED_ACE_TYPE:
  370. AceSize += sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG);
  371. DaclSize += AceSize;
  372. break;
  373. case ACCESS_DENIED_ACE_TYPE:
  374. AceSize += sizeof(ACCESS_DENIED_ACE) - sizeof(ULONG);
  375. DaclSize += AceSize;
  376. break;
  377. case SYSTEM_AUDIT_ACE_TYPE:
  378. AceSize += sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG);
  379. SaclSize += AceSize;
  380. break;
  381. default:
  382. return STATUS_INVALID_PARAMETER;
  383. }
  384. MaxAceSize = max( MaxAceSize, AceSize );
  385. }
  386. //
  387. // Allocate a chunk of memory large enough for the security
  388. // descriptor, the DACL, the SACL and all ACEs.
  389. //
  390. // A security descriptor is of opaque data type but
  391. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  392. //
  393. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  394. if ( DaclSize != sizeof(ACL) ) {
  395. Size += DaclSize;
  396. }
  397. if ( SaclSize != sizeof(ACL) ) {
  398. Size += SaclSize;
  399. }
  400. if ((AbsoluteSd = RtlAllocateHeap(
  401. HeapHandle, 0,
  402. Size
  403. )) == NULL) {
  404. KdPrint(("SeCreateAndSetSD: No memory to create absolute SD\n"));
  405. ntstatus = STATUS_NO_MEMORY;
  406. goto Cleanup;
  407. }
  408. //
  409. // Initialize the Dacl and Sacl
  410. //
  411. CurrentAvailable = (PCHAR)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  412. if ( DaclSize != sizeof(ACL) ) {
  413. Dacl = (PACL)CurrentAvailable;
  414. CurrentAvailable += DaclSize;
  415. ntstatus = RtlCreateAcl( Dacl, DaclSize, ACL_REVISION );
  416. if ( !NT_SUCCESS(ntstatus) ) {
  417. KdPrint(("ScCreateAndSetSD: Fail DACL Create %08lx\n",
  418. ntstatus));
  419. goto Cleanup;
  420. }
  421. }
  422. if ( SaclSize != sizeof(ACL) ) {
  423. Sacl = (PACL)CurrentAvailable;
  424. CurrentAvailable += SaclSize;
  425. ntstatus = RtlCreateAcl( Sacl, SaclSize, ACL_REVISION );
  426. if ( !NT_SUCCESS(ntstatus) ) {
  427. KdPrint(("ScCreateAndSetSD: Fail SACL Create %08lx\n",
  428. ntstatus));
  429. goto Cleanup;
  430. }
  431. }
  432. //
  433. // Allocate a temporary buffer big enough for the biggest ACE.
  434. //
  435. if ((MaxAce = (PACCESS_ALLOWED_ACE) RtlAllocateHeap(
  436. HeapHandle, 0,
  437. MaxAceSize
  438. )) == NULL ) {
  439. KdPrint(("ScCreateAndSetSD: No memory to create max ace\n"));
  440. ntstatus = STATUS_NO_MEMORY;
  441. goto Cleanup;
  442. }
  443. //
  444. // Initialize each ACE, and append it into the end of the DACL or SACL.
  445. //
  446. for (i = 0; i < AceCount; i++) {
  447. ULONG AceSize;
  448. PACL CurrentAcl;
  449. AceSize = RtlLengthSid(*(AceData[i].Sid));
  450. switch (AceData[i].AceType) {
  451. case ACCESS_ALLOWED_ACE_TYPE:
  452. AceSize += sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG);
  453. CurrentAcl = Dacl;
  454. ntstatus = ScInitializeAllowedAce(
  455. MaxAce,
  456. (USHORT) AceSize,
  457. AceData[i].InheritFlags,
  458. AceData[i].AceFlags,
  459. AceData[i].Mask,
  460. *(AceData[i].Sid)
  461. );
  462. break;
  463. case ACCESS_DENIED_ACE_TYPE:
  464. AceSize += sizeof(ACCESS_DENIED_ACE) - sizeof(ULONG);
  465. CurrentAcl = Dacl;
  466. ntstatus = ScInitializeDeniedAce(
  467. (PACCESS_DENIED_ACE) MaxAce,
  468. (USHORT) AceSize,
  469. AceData[i].InheritFlags,
  470. AceData[i].AceFlags,
  471. AceData[i].Mask,
  472. *(AceData[i].Sid)
  473. );
  474. break;
  475. case SYSTEM_AUDIT_ACE_TYPE:
  476. AceSize += sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG);
  477. CurrentAcl = Sacl;
  478. ntstatus = ScInitializeAuditAce(
  479. MaxAce,
  480. (USHORT) AceSize,
  481. AceData[i].InheritFlags,
  482. AceData[i].AceFlags,
  483. AceData[i].Mask,
  484. *(AceData[i].Sid)
  485. );
  486. break;
  487. default:
  488. SC_LOG2(ERROR,
  489. "ScCreateAndSetSD: Invalid AceType %d in ACE %d\n",
  490. AceData[i].AceType,
  491. i);
  492. ASSERT(FALSE);
  493. CurrentAcl = NULL;
  494. ntstatus = STATUS_UNSUCCESSFUL;
  495. }
  496. if ( !NT_SUCCESS( ntstatus ) ) {
  497. KdPrint((
  498. "ScCreateAndSetSD: Fail InitAce i: %d ntstatus: %08lx\n",
  499. i, ntstatus));
  500. goto Cleanup;
  501. }
  502. //
  503. // Append the initialized ACE to the end of DACL or SACL
  504. //
  505. if (! NT_SUCCESS (ntstatus = RtlAddAce(
  506. CurrentAcl,
  507. ACL_REVISION,
  508. MAXULONG,
  509. MaxAce,
  510. AceSize
  511. ))) {
  512. KdPrint((
  513. "ScCreateAndSetSD: Fail add ace i: %d ntstatus: %08lx\n",
  514. i, ntstatus));
  515. goto Cleanup;
  516. }
  517. }
  518. //
  519. // Create the security descriptor with absolute pointers to SIDs
  520. // and ACLs.
  521. //
  522. // Owner = OwnerSid
  523. // Group = GroupSid
  524. // Dacl = Dacl
  525. // Sacl = Sacl
  526. //
  527. if (! NT_SUCCESS(ntstatus = RtlCreateSecurityDescriptor(
  528. AbsoluteSd,
  529. SECURITY_DESCRIPTOR_REVISION
  530. ))) {
  531. goto Cleanup;
  532. }
  533. if (! NT_SUCCESS(ntstatus = RtlSetOwnerSecurityDescriptor(
  534. AbsoluteSd,
  535. OwnerSid,
  536. FALSE
  537. ))) {
  538. goto Cleanup;
  539. }
  540. if (! NT_SUCCESS(ntstatus = RtlSetGroupSecurityDescriptor(
  541. AbsoluteSd,
  542. GroupSid,
  543. FALSE
  544. ))) {
  545. goto Cleanup;
  546. }
  547. if (! NT_SUCCESS(ntstatus = RtlSetDaclSecurityDescriptor(
  548. AbsoluteSd,
  549. (BOOLEAN)(Dacl ? TRUE : FALSE),
  550. Dacl,
  551. FALSE
  552. ))) {
  553. goto Cleanup;
  554. }
  555. if (! NT_SUCCESS(ntstatus = RtlSetSaclSecurityDescriptor(
  556. AbsoluteSd,
  557. (BOOLEAN)(Sacl ? TRUE : FALSE),
  558. Sacl,
  559. FALSE
  560. ))) {
  561. goto Cleanup;
  562. }
  563. //
  564. // Done
  565. //
  566. ntstatus = STATUS_SUCCESS;
  567. //
  568. // Clean up
  569. //
  570. Cleanup:
  571. //
  572. // Either return the security descriptor to the caller or delete it
  573. //
  574. if ( NT_SUCCESS( ntstatus ) ) {
  575. *NewDescriptor = AbsoluteSd;
  576. } else if ( AbsoluteSd != NULL ) {
  577. RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  578. }
  579. //
  580. // Delete the temporary ACE
  581. //
  582. if ( MaxAce != NULL ) {
  583. RtlFreeHeap(HeapHandle, 0, MaxAce);
  584. }
  585. return ntstatus;
  586. }
  587. NTSTATUS
  588. ScCreateUserSecurityObject(
  589. IN PSECURITY_DESCRIPTOR ParentSD,
  590. IN PSC_ACE_DATA AceData,
  591. IN ULONG AceCount,
  592. IN PSID OwnerSid,
  593. IN PSID GroupSid,
  594. IN BOOLEAN IsDirectoryObject,
  595. IN BOOLEAN UseImpersonationToken,
  596. IN PGENERIC_MAPPING GenericMapping,
  597. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  598. )
  599. /*++
  600. Routine Description:
  601. This function creates the DACL for the security descriptor based on
  602. on the ACE information specified, and creates the security descriptor
  603. which becomes the user-mode security object.
  604. A sample usage of this function:
  605. //
  606. // Structure that describes the mapping of Generic access rights to
  607. // object specific access rights for the ConfigurationInfo object.
  608. //
  609. GENERIC_MAPPING WsConfigInfoMapping = {
  610. STANDARD_RIGHTS_READ | // Generic read
  611. WKSTA_CONFIG_GUEST_INFO_GET |
  612. WKSTA_CONFIG_USER_INFO_GET |
  613. WKSTA_CONFIG_ADMIN_INFO_GET,
  614. STANDARD_RIGHTS_WRITE | // Generic write
  615. WKSTA_CONFIG_INFO_SET,
  616. STANDARD_RIGHTS_EXECUTE, // Generic execute
  617. WKSTA_CONFIG_ALL_ACCESS // Generic all
  618. };
  619. //
  620. // Order matters! These ACEs are inserted into the DACL in the
  621. // following order. Security access is granted or denied based on
  622. // the order of the ACEs in the DACL.
  623. //
  624. SE_ACE_DATA AceData[4] = {
  625. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  626. GENERIC_ALL, &AliasAdminsSid},
  627. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  628. GENERIC_ALL, &NetworkSid},
  629. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  630. WKSTA_CONFIG_GUEST_INFO_GET |
  631. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  632. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  633. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  634. };
  635. PSECURITY_DESCRIPTOR WkstaSecurityObject;
  636. return ScCreateUserSecurityObject(
  637. AceData,
  638. 4,
  639. LocalSystemSid,
  640. LocalSystemSid,
  641. FALSE,
  642. &WsConfigInfoMapping,
  643. &WkstaSecurityObject
  644. );
  645. Arguments:
  646. AceData - Supplies the structure of information that describes the DACL.
  647. AceCount - Supplies the number of entries in AceData structure.
  648. OwnerSid - Supplies the pointer to the SID of the security descriptor
  649. owner.
  650. GroupSid - Supplies the pointer to the SID of the security descriptor
  651. primary group.
  652. IsDirectoryObject - Supplies the flag which indicates whether the
  653. user-mode object is a directory object.
  654. GenericMapping - Supplies the pointer to a generic mapping array denoting
  655. the mapping between each generic right to specific rights.
  656. NewDescriptor - Returns a pointer to the self-relative security descriptor
  657. which represents the user-mode object.
  658. Return Value:
  659. STATUS_SUCCESS - if successful
  660. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  661. security descriptor.
  662. Any other status codes returned from the security Rtl routines.
  663. NOTE : the user security object created by calling this function may be
  664. freed up by calling RtlDeleteSecurityObject().
  665. --*/
  666. {
  667. NTSTATUS ntstatus;
  668. PSECURITY_DESCRIPTOR AbsoluteSd;
  669. HANDLE TokenHandle;
  670. PVOID HeapHandle = RtlProcessHeap();
  671. ntstatus = ScCreateAndSetSD(
  672. AceData,
  673. AceCount,
  674. OwnerSid,
  675. GroupSid,
  676. &AbsoluteSd
  677. );
  678. if (! NT_SUCCESS(ntstatus)) {
  679. KdPrint((
  680. "ScCreateUserSecurityObject: ScCreateAndSetSD returned "
  681. "%08lx\n", ntstatus));
  682. return ntstatus;
  683. }
  684. if (UseImpersonationToken) {
  685. ntstatus = NtOpenThreadToken(
  686. NtCurrentThread(),
  687. TOKEN_QUERY,
  688. FALSE,
  689. &TokenHandle
  690. );
  691. }
  692. else {
  693. ntstatus = NtOpenProcessToken(
  694. NtCurrentProcess(),
  695. TOKEN_QUERY,
  696. &TokenHandle
  697. );
  698. }
  699. if (! NT_SUCCESS(ntstatus)) {
  700. KdPrint((
  701. "ScCreateUserSecurityObject: NtOpen...Token returned "
  702. "%08lx\n", ntstatus));
  703. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  704. return ntstatus;
  705. }
  706. //
  707. // Create the security object (a user-mode object is really a pseudo-
  708. // object represented by a security descriptor that have relative
  709. // pointers to SIDs and ACLs). This routine allocates the memory to
  710. // hold the relative security descriptor so the memory allocated for the
  711. // DACL, ACEs, and the absolute descriptor can be freed.
  712. //
  713. ntstatus = RtlNewSecurityObject(
  714. ParentSD, // Parent descriptor
  715. AbsoluteSd, // Creator descriptor
  716. NewDescriptor, // Pointer to new descriptor
  717. IsDirectoryObject, // Is directory object
  718. TokenHandle, // Token
  719. GenericMapping // Generic mapping
  720. );
  721. (void) NtClose(TokenHandle);
  722. if (! NT_SUCCESS(ntstatus)) {
  723. KdPrint((
  724. "RtlCreateUserSecurityObject: RtlNewSecurityObject returned "
  725. "%08lx\n", ntstatus));
  726. }
  727. //
  728. // Free dynamic memory before returning
  729. //
  730. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  731. return ntstatus;
  732. }
  733. NTSTATUS
  734. ScInitializeAllowedAce(
  735. IN PACCESS_ALLOWED_ACE AllowedAce,
  736. IN USHORT AceSize,
  737. IN UCHAR InheritFlags,
  738. IN UCHAR AceFlags,
  739. IN ACCESS_MASK Mask,
  740. IN PSID AllowedSid
  741. )
  742. /*++
  743. Routine Description:
  744. This function assigns the specified ACE values into an allowed type ACE.
  745. Arguments:
  746. AllowedAce - Supplies a pointer to the ACE that is initialized.
  747. AceSize - Supplies the size of the ACE in bytes.
  748. InheritFlags - Supplies ACE inherit flags.
  749. AceFlags - Supplies ACE type specific control flags.
  750. Mask - Supplies the allowed access masks.
  751. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  752. the specified access.
  753. Return Value:
  754. Returns status from RtlCopySid.
  755. --*/
  756. {
  757. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  758. AllowedAce->Header.AceSize = AceSize;
  759. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  760. AllowedAce->Mask = Mask;
  761. return RtlCopySid(
  762. RtlLengthSid(AllowedSid),
  763. &(AllowedAce->SidStart),
  764. AllowedSid
  765. );
  766. }
  767. NTSTATUS
  768. ScInitializeDeniedAce(
  769. IN PACCESS_DENIED_ACE DeniedAce,
  770. IN USHORT AceSize,
  771. IN UCHAR InheritFlags,
  772. IN UCHAR AceFlags,
  773. IN ACCESS_MASK Mask,
  774. IN PSID DeniedSid
  775. )
  776. /*++
  777. Routine Description:
  778. This function assigns the specified ACE values into a denied type ACE.
  779. Arguments:
  780. DeniedAce - Supplies a pointer to the ACE that is initialized.
  781. AceSize - Supplies the size of the ACE in bytes.
  782. InheritFlags - Supplies ACE inherit flags.
  783. AceFlags - Supplies ACE type specific control flags.
  784. Mask - Supplies the denied access masks.
  785. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  786. the specified access.
  787. Return Value:
  788. Returns status from RtlCopySid.
  789. --*/
  790. {
  791. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  792. DeniedAce->Header.AceSize = AceSize;
  793. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  794. DeniedAce->Mask = Mask;
  795. return RtlCopySid(
  796. RtlLengthSid(DeniedSid),
  797. &(DeniedAce->SidStart),
  798. DeniedSid
  799. );
  800. }
  801. NTSTATUS
  802. ScInitializeAuditAce(
  803. IN PACCESS_ALLOWED_ACE AuditAce,
  804. IN USHORT AceSize,
  805. IN UCHAR InheritFlags,
  806. IN UCHAR AceFlags,
  807. IN ACCESS_MASK Mask,
  808. IN PSID AuditSid
  809. )
  810. /*++
  811. Routine Description:
  812. This function assigns the specified ACE values into an audit type ACE.
  813. Arguments:
  814. AuditAce - Supplies a pointer to the ACE that is initialized.
  815. AceSize - Supplies the size of the ACE in bytes.
  816. InheritFlags - Supplies ACE inherit flags.
  817. AceFlags - Supplies ACE type specific control flags.
  818. Mask - Supplies the allowed access masks.
  819. AuditSid - Supplies the pointer to the SID of user/group which is to be
  820. audited.
  821. Return Value:
  822. Returns status from RtlCopySid.
  823. --*/
  824. {
  825. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  826. AuditAce->Header.AceSize = AceSize;
  827. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  828. AuditAce->Mask = Mask;
  829. return RtlCopySid(
  830. RtlLengthSid(AuditSid),
  831. &(AuditAce->SidStart),
  832. AuditSid
  833. );
  834. }
  835. DWORD
  836. ScCreateStartEventSD(
  837. PSECURITY_DESCRIPTOR *pEventSD
  838. )
  839. /*++
  840. Routine Description:
  841. This routine creates a security descriptor for the
  842. SC_INTERNAL_START_EVENT. This function may be called from
  843. either the client or server side.
  844. NOTE: it is up to the caller to free the memory for the
  845. security descriptor.
  846. Arguments:
  847. pEventSD - Pointer to a location where the pointer to
  848. the newly created security descriptor can be placed.
  849. Return Value:
  850. NO_ERROR - indicates success.
  851. all other values indicate failure.
  852. --*/
  853. {
  854. NTSTATUS ntstatus;
  855. PSECURITY_DESCRIPTOR SecurityDescriptor;
  856. SID_IDENTIFIER_AUTHORITY WorldSidAuth[1] = {
  857. SECURITY_WORLD_SID_AUTHORITY};
  858. SID_IDENTIFIER_AUTHORITY LocalSystemSidAuth[1] = {
  859. SECURITY_NT_AUTHORITY};
  860. SC_ACE_DATA AceData[2] = {
  861. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  862. SYNCHRONIZE, &WorldSid},
  863. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  864. GENERIC_ALL, &LocalSystemSid}
  865. };
  866. //
  867. // Check against NULL for these SIDs as the client-side code calls
  868. // this routine and doesn't call ScCreateWellKnownSids. These
  869. // should always be non-NULL by this point in services.exe itself.
  870. //
  871. if (WorldSid == NULL) {
  872. if (!AllocateAndInitializeSid(
  873. WorldSidAuth,
  874. 1,
  875. SECURITY_WORLD_RID,
  876. 0,0,0,0,0,0,0,
  877. &WorldSid)) {
  878. SC_LOG1(ERROR, "AllocateAndInitWorldSid failed %d\n",GetLastError());
  879. return(GetLastError());
  880. }
  881. }
  882. if (LocalSystemSid == NULL) {
  883. if (!AllocateAndInitializeSid(
  884. LocalSystemSidAuth,
  885. 1,
  886. SECURITY_LOCAL_SYSTEM_RID,
  887. 0,0,0,0,0,0,0,
  888. &LocalSystemSid)) {
  889. SC_LOG1(ERROR, "AllocateAndInitLocalSysSid failed %d\n",GetLastError());
  890. return(GetLastError());
  891. }
  892. }
  893. ntstatus = ScCreateAndSetSD(
  894. AceData,
  895. 2,
  896. LocalSystemSid,
  897. LocalSystemSid,
  898. &SecurityDescriptor);
  899. if (! NT_SUCCESS(ntstatus)) {
  900. SC_LOG1(ERROR, "ScCreateAndSetSD failed %0x%lx\n",ntstatus);
  901. return(RtlNtStatusToDosError(ntstatus));
  902. }
  903. *pEventSD = SecurityDescriptor;
  904. return(NO_ERROR);
  905. }