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.

1275 lines
33 KiB

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