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.

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