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.

2132 lines
57 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. seurtl.c
  5. Abstract:
  6. This Module implements many security rtl routines defined in nturtl.h
  7. Author:
  8. Robert Reichel (RobertRe) 1-Mar-1991
  9. Environment:
  10. Pure Runtime Library Routine
  11. User mode callable only
  12. Revision History:
  13. --*/
  14. #include <ntos.h>
  15. #include <nturtl.h>
  16. #include <ntlsa.h> // needed for RtlGetPrimaryDomain
  17. #include "seopaque.h"
  18. #include "sertlp.h"
  19. #include "ldrp.h"
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // //
  22. // Exported Procedures //
  23. // //
  24. ///////////////////////////////////////////////////////////////////////////////
  25. #if WHEN_LSAUDLL_MOVED_TO_NTDLL
  26. NTSTATUS
  27. RtlGetPrimaryDomain(
  28. IN ULONG SidLength,
  29. OUT PBOOLEAN PrimaryDomainPresent,
  30. OUT PUNICODE_STRING PrimaryDomainName,
  31. OUT PUSHORT RequiredNameLength,
  32. OUT PSID PrimaryDomainSid OPTIONAL,
  33. OUT PULONG RequiredSidLength
  34. )
  35. /*++
  36. Routine Description:
  37. This procedure opens the LSA policy object and retrieves
  38. the primary domain information for this machine.
  39. Arguments:
  40. SidLength - Specifies the length of the PrimaryDomainSid
  41. parameter.
  42. PrimaryDomainPresent - Receives a boolean value indicating
  43. whether this machine has a primary domain or not. TRUE
  44. indicates the machine does have a primary domain. FALSE
  45. indicates the machine does not.
  46. PrimaryDomainName - Points to the unicode string to receive
  47. the primary domain name. This parameter will only be
  48. used if there is a primary domain.
  49. RequiredNameLength - Recevies the length of the primary
  50. domain name (in bytes). This parameter will only be
  51. used if there is a primary domain.
  52. PrimaryDomainSid - This optional parameter, if present,
  53. points to a buffer to receive the primary domain's
  54. SID. This parameter will only be used if there is a
  55. primary domain.
  56. RequiredSidLength - Recevies the length of the primary
  57. domain SID (in bytes). This parameter will only be
  58. used if there is a primary domain.
  59. Return Value:
  60. STATUS_SUCCESS - The requested information has been retrieved.
  61. STATUS_BUFFER_TOO_SMALL - One of the return buffers was not
  62. large enough to receive the corresponding information.
  63. The RequiredNameLength and RequiredSidLength parameter
  64. values have been set to indicate the needed length.
  65. Other status values as may be returned by:
  66. LsaOpenPolicy()
  67. LsaQueryInformationPolicy()
  68. RtlCopySid()
  69. --*/
  70. {
  71. NTSTATUS Status, IgnoreStatus;
  72. OBJECT_ATTRIBUTES ObjectAttributes;
  73. LSA_HANDLE LsaHandle;
  74. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  75. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo;
  76. //
  77. // Set up the Security Quality Of Service
  78. //
  79. SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  80. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  81. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  82. SecurityQualityOfService.EffectiveOnly = FALSE;
  83. //
  84. // Set up the object attributes to open the Lsa policy object
  85. //
  86. InitializeObjectAttributes(&ObjectAttributes,
  87. NULL,
  88. 0L,
  89. (HANDLE)NULL,
  90. NULL);
  91. ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
  92. //
  93. // Open the local LSA policy object
  94. //
  95. Status = LsaOpenPolicy( NULL,
  96. &ObjectAttributes,
  97. POLICY_VIEW_LOCAL_INFORMATION,
  98. &LsaHandle
  99. );
  100. if (NT_SUCCESS(Status)) {
  101. //
  102. // Get the primary domain info
  103. //
  104. Status = LsaQueryInformationPolicy(LsaHandle,
  105. PolicyPrimaryDomainInformation,
  106. (PVOID *)&PrimaryDomainInfo);
  107. IgnoreStatus = LsaClose(LsaHandle);
  108. ASSERT(NT_SUCCESS(IgnoreStatus));
  109. }
  110. if (NT_SUCCESS(Status)) {
  111. //
  112. // Is there a primary domain?
  113. //
  114. if (PrimaryDomainInfo->Sid != NULL) {
  115. //
  116. // Yes
  117. //
  118. (*PrimaryDomainPresent) = TRUE;
  119. (*RequiredNameLength) = PrimaryDomainInfo->Name.Length;
  120. (*RequiredSidLength) = RtlLengthSid(PrimaryDomainInfo->Sid);
  121. //
  122. // Copy the name
  123. //
  124. if (PrimaryDomainName->MaximumLength >=
  125. PrimaryDomainInfo->Name.Length) {
  126. RtlCopyUnicodeString(
  127. PrimaryDomainName,
  128. &PrimaryDomainInfo->Name
  129. );
  130. } else {
  131. Status = STATUS_BUFFER_TOO_SMALL;
  132. }
  133. //
  134. // Copy the SID (if appropriate)
  135. //
  136. if (PrimaryDomainSid != NULL && NT_SUCCESS(Status)) {
  137. Status = RtlCopySid(SidLength,
  138. PrimaryDomainSid,
  139. PrimaryDomainInfo->Sid
  140. );
  141. }
  142. } else {
  143. (*PrimaryDomainPresent) = FALSE;
  144. }
  145. //
  146. // We're finished with the buffer returned by LSA
  147. //
  148. IgnoreStatus = LsaFreeMemory(PrimaryDomainInfo);
  149. ASSERT(NT_SUCCESS(IgnoreStatus));
  150. }
  151. return(Status);
  152. }
  153. #endif //WHEN_LSAUDLL_MOVED_TO_NTDLL
  154. NTSTATUS
  155. RtlNewSecurityObjectWithMultipleInheritance (
  156. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  157. IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
  158. OUT PSECURITY_DESCRIPTOR * NewDescriptor,
  159. IN GUID **pObjectType OPTIONAL,
  160. IN ULONG GuidCount,
  161. IN BOOLEAN IsDirectoryObject,
  162. IN ULONG AutoInheritFlags,
  163. IN HANDLE Token OPTIONAL,
  164. IN PGENERIC_MAPPING GenericMapping
  165. )
  166. /*++
  167. Routine Description:
  168. See RtlpNewSecurityObject.
  169. - - WARNING - -
  170. This service is for use by protected subsystems that project their own
  171. type of object. This service is explicitly not for use by the
  172. executive for executive objects and must not be called from kernel
  173. mode.
  174. Arguments:
  175. See RtlpNewSecurityObject.
  176. Return Value:
  177. See RtlpNewSecurityObject.
  178. --*/
  179. {
  180. //
  181. // Simple call the newer RtlpNewSecurityObject
  182. //
  183. return RtlpNewSecurityObject (
  184. ParentDescriptor,
  185. CreatorDescriptor,
  186. NewDescriptor,
  187. pObjectType,
  188. GuidCount,
  189. IsDirectoryObject,
  190. AutoInheritFlags,
  191. Token,
  192. GenericMapping );
  193. }
  194. NTSTATUS
  195. RtlNewSecurityObjectEx (
  196. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  197. IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
  198. OUT PSECURITY_DESCRIPTOR * NewDescriptor,
  199. IN GUID *ObjectType OPTIONAL,
  200. IN BOOLEAN IsDirectoryObject,
  201. IN ULONG AutoInheritFlags,
  202. IN HANDLE Token OPTIONAL,
  203. IN PGENERIC_MAPPING GenericMapping
  204. )
  205. /*++
  206. Routine Description:
  207. See RtlpNewSecurityObject.
  208. - - WARNING - -
  209. This service is for use by protected subsystems that project their own
  210. type of object. This service is explicitly not for use by the
  211. executive for executive objects and must not be called from kernel
  212. mode.
  213. Arguments:
  214. See RtlpNewSecurityObject.
  215. Return Value:
  216. See RtlpNewSecurityObject.
  217. --*/
  218. {
  219. //
  220. // Simple call the newer RtlpNewSecurityObject
  221. //
  222. return RtlpNewSecurityObject (
  223. ParentDescriptor,
  224. CreatorDescriptor,
  225. NewDescriptor,
  226. ObjectType ? &ObjectType : NULL,
  227. ObjectType ? 1 : 0,
  228. IsDirectoryObject,
  229. AutoInheritFlags,
  230. Token,
  231. GenericMapping );
  232. }
  233. NTSTATUS
  234. RtlNewSecurityObject (
  235. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  236. IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
  237. OUT PSECURITY_DESCRIPTOR * NewDescriptor,
  238. IN BOOLEAN IsDirectoryObject,
  239. IN HANDLE Token,
  240. IN PGENERIC_MAPPING GenericMapping
  241. )
  242. /*++
  243. Routine Description:
  244. See RtlpNewSecurityObject.
  245. - - WARNING - -
  246. This service is for use by protected subsystems that project their own
  247. type of object. This service is explicitly not for use by the
  248. executive for executive objects and must not be called from kernel
  249. mode.
  250. Arguments:
  251. See RtlpNewSecurityObject.
  252. Return Value:
  253. See RtlpNewSecurityObject.
  254. --*/
  255. {
  256. //
  257. // Simple call the newer RtlpNewSecurityObject
  258. //
  259. return RtlpNewSecurityObject (
  260. ParentDescriptor,
  261. CreatorDescriptor,
  262. NewDescriptor,
  263. NULL, // No ObjectType
  264. 0,
  265. IsDirectoryObject,
  266. 0, // No Automatic inheritance
  267. Token,
  268. GenericMapping );
  269. }
  270. NTSTATUS
  271. RtlSetSecurityObject (
  272. IN SECURITY_INFORMATION SecurityInformation,
  273. IN PSECURITY_DESCRIPTOR ModificationDescriptor,
  274. IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
  275. IN PGENERIC_MAPPING GenericMapping,
  276. IN HANDLE Token OPTIONAL
  277. )
  278. /*++
  279. Routine Description:
  280. See RtlpSetSecurityObject.
  281. Arguments:
  282. See RtlpSetSecurityObject.
  283. Return Value:
  284. See RtlpSetSecurityObject.
  285. --*/
  286. {
  287. //
  288. // Simply call RtlpSetSecurityObject specifying no auto inheritance.
  289. //
  290. return RtlpSetSecurityObject( NULL,
  291. SecurityInformation,
  292. ModificationDescriptor,
  293. ObjectsSecurityDescriptor,
  294. 0, // No AutoInheritance
  295. PagedPool,
  296. GenericMapping,
  297. Token );
  298. }
  299. NTSTATUS
  300. RtlSetSecurityObjectEx (
  301. IN SECURITY_INFORMATION SecurityInformation,
  302. IN PSECURITY_DESCRIPTOR ModificationDescriptor,
  303. IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
  304. IN ULONG AutoInheritFlags,
  305. IN PGENERIC_MAPPING GenericMapping,
  306. IN HANDLE Token OPTIONAL
  307. )
  308. /*++
  309. Routine Description:
  310. See RtlpSetSecurityObject.
  311. Arguments:
  312. See RtlpSetSecurityObject.
  313. Return Value:
  314. See RtlpSetSecurityObject.
  315. --*/
  316. {
  317. //
  318. // Simply call RtlpSetSecurityObject specifying no auto inheritance.
  319. //
  320. return RtlpSetSecurityObject( NULL,
  321. SecurityInformation,
  322. ModificationDescriptor,
  323. ObjectsSecurityDescriptor,
  324. AutoInheritFlags,
  325. PagedPool,
  326. GenericMapping,
  327. Token );
  328. }
  329. NTSTATUS
  330. RtlQuerySecurityObject (
  331. IN PSECURITY_DESCRIPTOR ObjectDescriptor,
  332. IN SECURITY_INFORMATION SecurityInformation,
  333. OUT PSECURITY_DESCRIPTOR ResultantDescriptor,
  334. IN ULONG DescriptorLength,
  335. OUT PULONG ReturnLength
  336. )
  337. /*++
  338. Routine Description:
  339. Query information from a protected server object's existing security
  340. descriptor.
  341. This procedure, called only from user mode, is used to retrieve
  342. information from a security descriptor on an existing protected
  343. server's object. All access checking is expected to be done before
  344. calling this routine. This includes checking for READ_CONTROL, and
  345. privilege to read a system ACL as appropriate.
  346. - - WARNING - -
  347. This service is for use by protected subsystems that project their own
  348. type of object. This service is explicitly not for use by the
  349. executive for executive objects and must not be called from kernel
  350. mode.
  351. Arguments:
  352. ObjectDescriptor - Points to a pointer to a security descriptor to be
  353. queried.
  354. SecurityInformation - Identifies the security information being
  355. requested.
  356. ResultantDescriptor - Points to buffer to receive the resultant
  357. security descriptor. The resultant security descriptor will
  358. contain all information requested by the SecurityInformation
  359. parameter.
  360. DescriptorLength - Is an unsigned integer which indicates the length,
  361. in bytes, of the buffer provided to receive the resultant
  362. descriptor.
  363. ReturnLength - Receives an unsigned integer indicating the actual
  364. number of bytes needed in the ResultantDescriptor to store the
  365. requested information. If the value returned is greater than the
  366. value passed via the DescriptorLength parameter, then
  367. STATUS_BUFFER_TOO_SMALL is returned and no information is returned.
  368. Return Value:
  369. STATUS_SUCCESS - The operation was successful.
  370. STATUS_BUFFER_TOO_SMALL - The buffer provided to receive the requested
  371. information was not large enough to hold the information. No
  372. information has been returned.
  373. STATUS_BAD_DESCRIPTOR_FORMAT - Indicates the provided object's security
  374. descriptor was not in self-relative format.
  375. --*/
  376. {
  377. PSID Group;
  378. PSID Owner;
  379. PACL Dacl;
  380. PACL Sacl;
  381. ULONG GroupSize = 0;
  382. ULONG DaclSize = 0;
  383. ULONG SaclSize = 0;
  384. ULONG OwnerSize = 0;
  385. PCHAR Field;
  386. PCHAR Base;
  387. PISECURITY_DESCRIPTOR IObjectDescriptor;
  388. PISECURITY_DESCRIPTOR_RELATIVE IResultantDescriptor;
  389. IResultantDescriptor = (PISECURITY_DESCRIPTOR_RELATIVE)ResultantDescriptor;
  390. IObjectDescriptor = (PISECURITY_DESCRIPTOR)ObjectDescriptor;
  391. //
  392. // For each item specified in the SecurityInformation, extract it
  393. // and get it to the point where it can be copied into a new
  394. // descriptor.
  395. //
  396. if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
  397. Group = RtlpGroupAddrSecurityDescriptor(IObjectDescriptor);
  398. if (Group != NULL) {
  399. GroupSize = LongAlignSize(SeLengthSid(Group));
  400. }
  401. }
  402. if (SecurityInformation & DACL_SECURITY_INFORMATION) {
  403. Dacl = RtlpDaclAddrSecurityDescriptor( IObjectDescriptor );
  404. if (Dacl != NULL) {
  405. DaclSize = LongAlignSize(Dacl->AclSize);
  406. }
  407. }
  408. if (SecurityInformation & SACL_SECURITY_INFORMATION) {
  409. Sacl = RtlpSaclAddrSecurityDescriptor( IObjectDescriptor );
  410. if (Sacl != NULL) {
  411. SaclSize = LongAlignSize(Sacl->AclSize);
  412. }
  413. }
  414. if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
  415. Owner = RtlpOwnerAddrSecurityDescriptor ( IObjectDescriptor );
  416. if (Owner != NULL) {
  417. OwnerSize = LongAlignSize(SeLengthSid(Owner));
  418. }
  419. }
  420. *ReturnLength = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) +
  421. GroupSize +
  422. DaclSize +
  423. SaclSize +
  424. OwnerSize;
  425. if (*ReturnLength > DescriptorLength) {
  426. return( STATUS_BUFFER_TOO_SMALL );
  427. }
  428. RtlCreateSecurityDescriptorRelative(
  429. IResultantDescriptor,
  430. SECURITY_DESCRIPTOR_REVISION
  431. );
  432. RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE );
  433. Base = (PCHAR)(IResultantDescriptor);
  434. Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  435. if (SecurityInformation & SACL_SECURITY_INFORMATION) {
  436. if (SaclSize > 0) {
  437. RtlMoveMemory( Field, Sacl, SaclSize );
  438. IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field);
  439. Field += SaclSize;
  440. }
  441. RtlpPropagateControlBits(
  442. IResultantDescriptor,
  443. IObjectDescriptor,
  444. SE_SACL_PRESENT | SE_SACL_DEFAULTED
  445. );
  446. }
  447. if (SecurityInformation & DACL_SECURITY_INFORMATION) {
  448. if (DaclSize > 0) {
  449. RtlMoveMemory( Field, Dacl, DaclSize );
  450. IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field);
  451. Field += DaclSize;
  452. }
  453. RtlpPropagateControlBits(
  454. IResultantDescriptor,
  455. IObjectDescriptor,
  456. SE_DACL_PRESENT | SE_DACL_DEFAULTED
  457. );
  458. }
  459. if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
  460. if (OwnerSize > 0) {
  461. RtlMoveMemory( Field, Owner, OwnerSize );
  462. IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field);
  463. Field += OwnerSize;
  464. }
  465. RtlpPropagateControlBits(
  466. IResultantDescriptor,
  467. IObjectDescriptor,
  468. SE_OWNER_DEFAULTED
  469. );
  470. }
  471. if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
  472. if (GroupSize > 0) {
  473. RtlMoveMemory( Field, Group, GroupSize );
  474. IResultantDescriptor->Group = RtlPointerToOffset(Base,Field);
  475. }
  476. RtlpPropagateControlBits(
  477. IResultantDescriptor,
  478. IObjectDescriptor,
  479. SE_GROUP_DEFAULTED
  480. );
  481. }
  482. return( STATUS_SUCCESS );
  483. }
  484. NTSTATUS
  485. RtlDeleteSecurityObject (
  486. IN OUT PSECURITY_DESCRIPTOR * ObjectDescriptor
  487. )
  488. /*++
  489. Routine Description:
  490. Delete a protected server object's security descriptor.
  491. This procedure, called only from user mode, is used to delete a
  492. security descriptor associated with a protected server's object. This
  493. routine will normally be called by a protected server during object
  494. deletion.
  495. - - WARNING - -
  496. This service is for use by protected subsystems that project their own
  497. type of object. This service is explicitly not for use by the
  498. executive for executive objects and must not be called from kernel
  499. mode.
  500. Arguments:
  501. ObjectDescriptor - Points to a pointer to a security descriptor to be
  502. deleted.
  503. Return Value:
  504. STATUS_SUCCESS - The operation was successful.
  505. --*/
  506. {
  507. RtlFreeHeap( RtlProcessHeap(), 0, (PVOID)*ObjectDescriptor );
  508. return( STATUS_SUCCESS );
  509. }
  510. NTSTATUS
  511. RtlNewInstanceSecurityObject(
  512. IN BOOLEAN ParentDescriptorChanged,
  513. IN BOOLEAN CreatorDescriptorChanged,
  514. IN PLUID OldClientTokenModifiedId,
  515. OUT PLUID NewClientTokenModifiedId,
  516. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  517. IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
  518. OUT PSECURITY_DESCRIPTOR * NewDescriptor,
  519. IN BOOLEAN IsDirectoryObject,
  520. IN HANDLE Token,
  521. IN PGENERIC_MAPPING GenericMapping
  522. )
  523. /*++
  524. Routine Description:
  525. If the return status is STATUS_SUCCESS and the NewSecurity return
  526. value is NULL, then the security desscriptor of the original
  527. instance of the object is valid for this instance as well.
  528. Arguments:
  529. ParentDescriptorChanged - Supplies a flag indicating whether the
  530. parent security descriptor has changed since the last time
  531. this set of parameters was used.
  532. CreatorDescriptorChanged - Supplies a flag indicating whether the
  533. creator security descriptor has changed since the last time
  534. this set of parameters was used.
  535. OldClientTokenModifiedId - Supplies the ModifiedId from the passed
  536. token that was in effect when this call was last made with
  537. these parameters. If the current ModifiedId is different from
  538. the one passed in here, the security descriptor must be
  539. rebuilt.
  540. NewClientTokenModifiedId - Returns the current ModifiedId from the
  541. passed token.
  542. ParentDescriptor - Supplies the Security Descriptor for the parent
  543. directory under which a new object is being created. If there is
  544. no parent directory, then this argument is specified as NULL.
  545. CreatorDescriptor - (Optionally) Points to a security descriptor
  546. presented by the creator of the object. If the creator of the
  547. object did not explicitly pass security information for the new
  548. object, then a null pointer should be passed.
  549. NewDescriptor - Points to a pointer that is to be made to point to the
  550. newly allocated self-relative security descriptor.
  551. IsDirectoryObject - Specifies if the new object is going to be a
  552. directory object. A value of TRUE indicates the object is a
  553. container of other objects.
  554. Token - Supplies the token for the client on whose behalf the
  555. object is being created. If it is an impersonation token,
  556. then it must be at SecurityIdentification level or higher. If
  557. it is not an impersonation token, the operation proceeds
  558. normally.
  559. A client token is used to retrieve default security
  560. information for the new object, such as default owner, primary
  561. group, and discretionary access control. The token must be
  562. open for TOKEN_QUERY access.
  563. GenericMapping - Supplies a pointer to a generic mapping array denoting
  564. the mapping between each generic right to specific rights.
  565. Return Value:
  566. return-value - Description of conditions needed to return value. - or -
  567. None.
  568. --*/
  569. {
  570. TOKEN_STATISTICS ClientTokenStatistics;
  571. ULONG ReturnLength;
  572. NTSTATUS Status;
  573. //
  574. // Get the current token modified LUID
  575. //
  576. Status = NtQueryInformationToken(
  577. Token, // Handle
  578. TokenStatistics, // TokenInformationClass
  579. &ClientTokenStatistics, // TokenInformation
  580. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  581. &ReturnLength // ReturnLength
  582. );
  583. if ( !NT_SUCCESS( Status )) {
  584. return( Status );
  585. }
  586. *NewClientTokenModifiedId = ClientTokenStatistics.ModifiedId;
  587. if ( RtlEqualLuid(NewClientTokenModifiedId, OldClientTokenModifiedId) ) {
  588. if ( !(ParentDescriptorChanged || CreatorDescriptorChanged) ) {
  589. //
  590. // The old security descriptor is valid for this new instance
  591. // of the object type as well. Pass back success and NULL for
  592. // the NewDescriptor.
  593. //
  594. *NewDescriptor = NULL;
  595. return( STATUS_SUCCESS );
  596. }
  597. }
  598. //
  599. // Something has changed, take the long route and build a new
  600. // descriptor
  601. //
  602. return( RtlNewSecurityObject( ParentDescriptor,
  603. CreatorDescriptor,
  604. NewDescriptor,
  605. IsDirectoryObject,
  606. Token,
  607. GenericMapping
  608. ));
  609. }
  610. NTSTATUS
  611. RtlNewSecurityGrantedAccess(
  612. IN ACCESS_MASK DesiredAccess,
  613. OUT PPRIVILEGE_SET Privileges,
  614. IN OUT PULONG Length,
  615. IN HANDLE Token OPTIONAL,
  616. IN PGENERIC_MAPPING GenericMapping,
  617. OUT PACCESS_MASK RemainingDesiredAccess
  618. )
  619. /*++
  620. Routine Description:
  621. This routine implements privilege policy by examining the bits in
  622. a DesiredAccess mask and adjusting them based on privilege checks.
  623. Currently, a request for ACCESS_SYSTEM_SECURITY may only be satisfied
  624. by the caller having SeSecurityPrivilege.
  625. Note that this routine is only to be called when an object is being
  626. created. When an object is being opened, it is expected that
  627. NtAccessCheck will be called, and that routine will implement
  628. another policy for substituting privileges for DACL access.
  629. Arguments:
  630. DesiredAccess - Supplies the user's desired access mask
  631. Privileges - Supplies a pointer to an empty buffer in which will
  632. be returned a privilege set describing any privileges that were
  633. used to gain access.
  634. Note that this is not an optional parameter, that is, enough
  635. room for a single privilege must always be passed.
  636. Length - Supplies the length of the Privileges parameter in bytes.
  637. If the supplies length is not adequate to store the entire
  638. privilege set, this field will return the minimum length required.
  639. Token - (optionally) Supplies the token for the client on whose
  640. behalf the object is being accessed. If this value is
  641. specified as null, then the token on the thread is opened and
  642. examined to see if it is an impersonation token. If it is,
  643. then it must be at SecurityIdentification level or higher. If
  644. it is not an impersonation token, the operation proceeds
  645. normally.
  646. GenericMapping - Supplies the generic mapping associated with this
  647. object type.
  648. RemainingDesiredAccess - Returns the DesiredAccess mask after any bits
  649. have been masked off. If no access types could be granted, this
  650. mask will be identical to the one passed in.
  651. Return Value:
  652. STATUS_SUCCESS - The operation completed successfully.
  653. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  654. to contain the information being returned.
  655. STATUS_BAD_IMPERSONATION_LEVEL - The caller or passed token was
  656. impersonating, but not at a high enough level.
  657. --*/
  658. {
  659. PRIVILEGE_SET RequiredPrivilege;
  660. BOOLEAN Result = FALSE;
  661. NTSTATUS Status;
  662. ULONG PrivilegeCount = 0;
  663. HANDLE ThreadToken;
  664. BOOLEAN TokenPassed;
  665. TOKEN_STATISTICS ThreadTokenStatistics;
  666. ULONG ReturnLength;
  667. ULONG SizeRequired;
  668. ULONG PrivilegeNumber = 0;
  669. //
  670. // If the caller hasn't passed a token, call the kernel and get
  671. // his impersonation token. This call will fail if the caller is
  672. // not impersonating a client, so if the caller is not
  673. // impersonating someone, he'd better have passed in an explicit
  674. // token.
  675. //
  676. if (!ARGUMENT_PRESENT( Token )) {
  677. Status = NtOpenThreadToken(
  678. NtCurrentThread(),
  679. TOKEN_QUERY,
  680. TRUE,
  681. &ThreadToken
  682. );
  683. TokenPassed = FALSE;
  684. if (!NT_SUCCESS( Status )) {
  685. return( Status );
  686. }
  687. } else {
  688. ThreadToken = Token;
  689. TokenPassed = TRUE;
  690. }
  691. Status = NtQueryInformationToken(
  692. ThreadToken, // Handle
  693. TokenStatistics, // TokenInformationClass
  694. &ThreadTokenStatistics, // TokenInformation
  695. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  696. &ReturnLength // ReturnLength
  697. );
  698. ASSERT( NT_SUCCESS(Status) );
  699. RtlMapGenericMask(
  700. &DesiredAccess,
  701. GenericMapping
  702. );
  703. *RemainingDesiredAccess = DesiredAccess;
  704. if ( DesiredAccess & ACCESS_SYSTEM_SECURITY ) {
  705. RequiredPrivilege.PrivilegeCount = 1;
  706. RequiredPrivilege.Control = PRIVILEGE_SET_ALL_NECESSARY;
  707. RequiredPrivilege.Privilege[0].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
  708. RequiredPrivilege.Privilege[0].Attributes = 0;
  709. //
  710. // NtPrivilegeCheck will make sure we are impersonating
  711. // properly.
  712. //
  713. Status = NtPrivilegeCheck(
  714. ThreadToken,
  715. &RequiredPrivilege,
  716. &Result
  717. );
  718. if ( (!NT_SUCCESS ( Status )) || (!Result) ) {
  719. if (!TokenPassed) {
  720. NtClose( ThreadToken );
  721. }
  722. if ( !NT_SUCCESS( Status )) {
  723. return( Status );
  724. }
  725. if ( !Result ) {
  726. return( STATUS_PRIVILEGE_NOT_HELD );
  727. }
  728. }
  729. //
  730. // We have the required privilege, turn off the bit in
  731. // copy of the input mask and remember that we need to return
  732. // this privilege.
  733. //
  734. *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
  735. }
  736. if (!TokenPassed) {
  737. NtClose( ThreadToken );
  738. }
  739. SizeRequired = sizeof(PRIVILEGE_SET);
  740. if ( SizeRequired > *Length ) {
  741. *Length = SizeRequired;
  742. return( STATUS_BUFFER_TOO_SMALL );
  743. }
  744. if (Result) {
  745. Privileges->PrivilegeCount = 1;
  746. Privileges->Control = 0;
  747. Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
  748. Privileges->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
  749. } else {
  750. Privileges->PrivilegeCount = 0;
  751. Privileges->Control = 0;
  752. Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(0);
  753. Privileges->Privilege[PrivilegeNumber].Attributes = 0;
  754. }
  755. return( STATUS_SUCCESS );
  756. }
  757. NTSTATUS
  758. RtlCopySecurityDescriptor(
  759. IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
  760. OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor
  761. )
  762. /*++
  763. Routine Description:
  764. This routine will copy a self-relative security descriptor from
  765. any memory into the correct type of memory required by security
  766. descriptor Rtl routines.
  767. This allows security descriptors to be kept in whatever kind of
  768. storage is most convenient for the current application. A security
  769. descriptor should be copied via this routine and the copy passed
  770. into any Rtl routine that in any way modify the security descriptor
  771. (eg RtlSetSecurityObject).
  772. The storage allocated by this routine must be freed by
  773. RtlDeleteSecurityObject.
  774. Arguments:
  775. InputSecurityDescriptor - contains the source security descriptor
  776. OutputSecurityDescriptor - returns a copy of the security descriptor
  777. in the correct kind of memory.
  778. Return Value:
  779. STATUS_NO_MEMORY - There was not enough memory available to the current
  780. process to complete this operation.
  781. --*/
  782. {
  783. PACL Dacl;
  784. PACL Sacl;
  785. PSID Owner;
  786. PSID PrimaryGroup;
  787. ULONG DaclSize;
  788. ULONG OwnerSize;
  789. ULONG PrimaryGroupSize;
  790. ULONG SaclSize;
  791. ULONG TotalSize;
  792. PISECURITY_DESCRIPTOR ISecurityDescriptor =
  793. (PISECURITY_DESCRIPTOR)InputSecurityDescriptor;
  794. RtlpQuerySecurityDescriptor(
  795. ISecurityDescriptor,
  796. &Owner,
  797. &OwnerSize,
  798. &PrimaryGroup,
  799. &PrimaryGroupSize,
  800. &Dacl,
  801. &DaclSize,
  802. &Sacl,
  803. &SaclSize
  804. );
  805. TotalSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
  806. OwnerSize +
  807. PrimaryGroupSize +
  808. DaclSize +
  809. SaclSize;
  810. *OutputSecurityDescriptor = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( SE_TAG ), TotalSize );
  811. if ( *OutputSecurityDescriptor == NULL ) {
  812. return( STATUS_NO_MEMORY );
  813. }
  814. RtlMoveMemory( *OutputSecurityDescriptor,
  815. ISecurityDescriptor,
  816. TotalSize
  817. );
  818. return( STATUS_SUCCESS );
  819. }
  820. NTSTATUS
  821. RtlpInitializeAllowedAce(
  822. IN PACCESS_ALLOWED_ACE AllowedAce,
  823. IN USHORT AceSize,
  824. IN UCHAR InheritFlags,
  825. IN UCHAR AceFlags,
  826. IN ACCESS_MASK Mask,
  827. IN PSID AllowedSid
  828. )
  829. /*++
  830. Routine Description:
  831. This function assigns the specified ACE values into an allowed type ACE.
  832. Arguments:
  833. AllowedAce - Supplies a pointer to the ACE that is initialized.
  834. AceSize - Supplies the size of the ACE in bytes.
  835. InheritFlags - Supplies ACE inherit flags.
  836. AceFlags - Supplies ACE type specific control flags.
  837. Mask - Supplies the allowed access masks.
  838. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  839. the specified access.
  840. Return Value:
  841. Returns status from RtlCopySid.
  842. --*/
  843. {
  844. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  845. AllowedAce->Header.AceSize = AceSize;
  846. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  847. AllowedAce->Mask = Mask;
  848. return RtlCopySid(
  849. RtlLengthSid(AllowedSid),
  850. &(AllowedAce->SidStart),
  851. AllowedSid
  852. );
  853. }
  854. NTSTATUS
  855. RtlpInitializeDeniedAce(
  856. IN PACCESS_DENIED_ACE DeniedAce,
  857. IN USHORT AceSize,
  858. IN UCHAR InheritFlags,
  859. IN UCHAR AceFlags,
  860. IN ACCESS_MASK Mask,
  861. IN PSID DeniedSid
  862. )
  863. /*++
  864. Routine Description:
  865. This function assigns the specified ACE values into a denied type ACE.
  866. Arguments:
  867. DeniedAce - Supplies a pointer to the ACE that is initialized.
  868. AceSize - Supplies the size of the ACE in bytes.
  869. InheritFlags - Supplies ACE inherit flags.
  870. AceFlags - Supplies ACE type specific control flags.
  871. Mask - Supplies the denied access masks.
  872. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  873. the specified access.
  874. Return Value:
  875. Returns status from RtlCopySid.
  876. --*/
  877. {
  878. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  879. DeniedAce->Header.AceSize = AceSize;
  880. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  881. DeniedAce->Mask = Mask;
  882. return RtlCopySid(
  883. RtlLengthSid(DeniedSid),
  884. &(DeniedAce->SidStart),
  885. DeniedSid
  886. );
  887. }
  888. NTSTATUS
  889. RtlpInitializeAuditAce(
  890. IN PACCESS_ALLOWED_ACE AuditAce,
  891. IN USHORT AceSize,
  892. IN UCHAR InheritFlags,
  893. IN UCHAR AceFlags,
  894. IN ACCESS_MASK Mask,
  895. IN PSID AuditSid
  896. )
  897. /*++
  898. Routine Description:
  899. This function assigns the specified ACE values into an audit type ACE.
  900. Arguments:
  901. AuditAce - Supplies a pointer to the ACE that is initialized.
  902. AceSize - Supplies the size of the ACE in bytes.
  903. InheritFlags - Supplies ACE inherit flags.
  904. AceFlags - Supplies ACE type specific control flags.
  905. Mask - Supplies the allowed access masks.
  906. AuditSid - Supplies the pointer to the SID of user/group which is to be
  907. audited.
  908. Return Value:
  909. Returns status from RtlCopySid.
  910. --*/
  911. {
  912. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  913. AuditAce->Header.AceSize = AceSize;
  914. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  915. AuditAce->Mask = Mask;
  916. return RtlCopySid(
  917. RtlLengthSid(AuditSid),
  918. &(AuditAce->SidStart),
  919. AuditSid
  920. );
  921. }
  922. NTSTATUS
  923. RtlCreateAndSetSD(
  924. IN PRTL_ACE_DATA AceData,
  925. IN ULONG AceCount,
  926. IN PSID OwnerSid OPTIONAL,
  927. IN PSID GroupSid OPTIONAL,
  928. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  929. )
  930. /*++
  931. Routine Description:
  932. This function creates an absolute security descriptor containing
  933. the supplied ACE information.
  934. A sample usage of this function:
  935. //
  936. // Order matters! These ACEs are inserted into the DACL in the
  937. // following order. Security access is granted or denied based on
  938. // the order of the ACEs in the DACL.
  939. //
  940. RTL_ACE_DATA AceData[4] = {
  941. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  942. GENERIC_ALL, &LocalAdminSid},
  943. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  944. GENERIC_ALL, &NetworkSid},
  945. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  946. WKSTA_CONFIG_GUEST_INFO_GET |
  947. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  948. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  949. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  950. };
  951. PSECURITY_DESCRIPTOR WkstaSecurityDescriptor;
  952. return RtlCreateAndSetSD(
  953. AceData,
  954. 4,
  955. LocalSystemSid,
  956. LocalSystemSid,
  957. &WkstaSecurityDescriptor
  958. );
  959. Arguments:
  960. AceData - Supplies the structure of information that describes the DACL.
  961. AceCount - Supplies the number of entries in AceData structure.
  962. OwnerSid - Supplies the pointer to the SID of the security descriptor
  963. owner. If not specified, a security descriptor with no owner
  964. will be created.
  965. GroupSid - Supplies the pointer to the SID of the security descriptor
  966. primary group. If not specified, a security descriptor with no primary
  967. group will be created.
  968. NewDescriptor - Returns a pointer to the absolute security descriptor
  969. allocated using RtlAllocateHeap.
  970. Return Value:
  971. STATUS_SUCCESS - if successful
  972. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  973. security descriptor.
  974. Any other status codes returned from the security Rtl routines.
  975. NOTE : the user security object created by calling this function may be
  976. freed up by calling RtlDeleteSecurityObject().
  977. --*/
  978. {
  979. NTSTATUS ntstatus = STATUS_SUCCESS;
  980. ULONG i;
  981. //
  982. // Pointer to memory dynamically allocated by this routine to hold
  983. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  984. //
  985. // +---------------------------------------------------------------+
  986. // | Security Descriptor |
  987. // +-------------------------------+-------+---------------+-------+
  988. // | DACL | ACE 1 | . . . | ACE n |
  989. // +-------------------------------+-------+---------------+-------+
  990. // | SACL | ACE 1 | . . . | ACE n |
  991. // +-------------------------------+-------+---------------+-------+
  992. //
  993. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  994. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  995. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  996. ULONG DaclSize = sizeof(ACL);
  997. ULONG SaclSize = sizeof(ACL);
  998. ULONG MaxAceSize = 0;
  999. PVOID MaxAce = NULL;
  1000. PCHAR CurrentAvailable;
  1001. ULONG Size;
  1002. PVOID HeapHandle = RtlProcessHeap();
  1003. ASSERT( AceCount > 0 );
  1004. //
  1005. // Compute the total size of the DACL and SACL ACEs and the maximum
  1006. // size of any ACE.
  1007. //
  1008. for (i = 0; i < AceCount; i++) {
  1009. ULONG AceSize;
  1010. AceSize = RtlLengthSid(*(AceData[i].Sid));
  1011. switch (AceData[i].AceType) {
  1012. case ACCESS_ALLOWED_ACE_TYPE:
  1013. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  1014. DaclSize += AceSize;
  1015. break;
  1016. case ACCESS_DENIED_ACE_TYPE:
  1017. AceSize += sizeof(ACCESS_DENIED_ACE);
  1018. DaclSize += AceSize;
  1019. break;
  1020. case SYSTEM_AUDIT_ACE_TYPE:
  1021. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  1022. SaclSize += AceSize;
  1023. break;
  1024. default:
  1025. return STATUS_INVALID_PARAMETER;
  1026. }
  1027. MaxAceSize = MaxAceSize > AceSize ? MaxAceSize : AceSize;
  1028. }
  1029. //
  1030. // Allocate a chunk of memory large enough for the security descriptor,
  1031. // the DACL, the SACL and all ACEs.
  1032. //
  1033. // A security descriptor is of opaque data type but
  1034. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  1035. //
  1036. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  1037. if ( DaclSize != sizeof(ACL) ) {
  1038. Size += DaclSize;
  1039. }
  1040. if ( SaclSize != sizeof(ACL) ) {
  1041. Size += SaclSize;
  1042. }
  1043. if ((AbsoluteSd = RtlAllocateHeap(
  1044. HeapHandle, MAKE_TAG( SE_TAG ),
  1045. Size
  1046. )) == NULL) {
  1047. ntstatus = STATUS_NO_MEMORY;
  1048. goto Cleanup;
  1049. }
  1050. //
  1051. // Initialize the Dacl and Sacl
  1052. //
  1053. CurrentAvailable = (PCHAR)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  1054. if ( DaclSize != sizeof(ACL) ) {
  1055. Dacl = (PACL)CurrentAvailable;
  1056. CurrentAvailable += DaclSize;
  1057. ntstatus = RtlCreateAcl( Dacl, DaclSize, ACL_REVISION );
  1058. if ( !NT_SUCCESS(ntstatus) ) {
  1059. goto Cleanup;
  1060. }
  1061. }
  1062. if ( SaclSize != sizeof(ACL) ) {
  1063. Sacl = (PACL)CurrentAvailable;
  1064. CurrentAvailable += SaclSize;
  1065. ntstatus = RtlCreateAcl( Sacl, SaclSize, ACL_REVISION );
  1066. if ( !NT_SUCCESS(ntstatus) ) {
  1067. goto Cleanup;
  1068. }
  1069. }
  1070. //
  1071. // Allocate a temporary buffer big enough for the biggest ACE.
  1072. //
  1073. if ((MaxAce = RtlAllocateHeap(
  1074. HeapHandle, MAKE_TAG( SE_TAG ),
  1075. MaxAceSize
  1076. )) == NULL ) {
  1077. ntstatus = STATUS_NO_MEMORY;
  1078. goto Cleanup;
  1079. }
  1080. //
  1081. // Initialize each ACE, and append it into the end of the DACL or SACL.
  1082. //
  1083. for (i = 0; i < AceCount; i++) {
  1084. ULONG AceSize;
  1085. PACL CurrentAcl;
  1086. AceSize = RtlLengthSid(*(AceData[i].Sid));
  1087. switch (AceData[i].AceType) {
  1088. case ACCESS_ALLOWED_ACE_TYPE:
  1089. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  1090. CurrentAcl = Dacl;
  1091. ntstatus = RtlpInitializeAllowedAce(
  1092. MaxAce,
  1093. (USHORT) AceSize,
  1094. AceData[i].InheritFlags,
  1095. AceData[i].AceFlags,
  1096. AceData[i].Mask,
  1097. *(AceData[i].Sid)
  1098. );
  1099. break;
  1100. case ACCESS_DENIED_ACE_TYPE:
  1101. AceSize += sizeof(ACCESS_DENIED_ACE);
  1102. CurrentAcl = Dacl;
  1103. ntstatus = RtlpInitializeDeniedAce(
  1104. MaxAce,
  1105. (USHORT) AceSize,
  1106. AceData[i].InheritFlags,
  1107. AceData[i].AceFlags,
  1108. AceData[i].Mask,
  1109. *(AceData[i].Sid)
  1110. );
  1111. break;
  1112. case SYSTEM_AUDIT_ACE_TYPE:
  1113. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  1114. CurrentAcl = Sacl;
  1115. ntstatus = RtlpInitializeAuditAce(
  1116. MaxAce,
  1117. (USHORT) AceSize,
  1118. AceData[i].InheritFlags,
  1119. AceData[i].AceFlags,
  1120. AceData[i].Mask,
  1121. *(AceData[i].Sid)
  1122. );
  1123. break;
  1124. }
  1125. if ( !NT_SUCCESS( ntstatus ) ) {
  1126. goto Cleanup;
  1127. }
  1128. //
  1129. // Append the initialized ACE to the end of DACL or SACL
  1130. //
  1131. if (! NT_SUCCESS (ntstatus = RtlAddAce(
  1132. CurrentAcl,
  1133. ACL_REVISION,
  1134. MAXULONG,
  1135. MaxAce,
  1136. AceSize
  1137. ))) {
  1138. goto Cleanup;
  1139. }
  1140. }
  1141. //
  1142. // Create the security descriptor with absolute pointers to SIDs
  1143. // and ACLs.
  1144. //
  1145. // Owner = OwnerSid
  1146. // Group = GroupSid
  1147. // Dacl = Dacl
  1148. // Sacl = Sacl
  1149. //
  1150. if (! NT_SUCCESS(ntstatus = RtlCreateSecurityDescriptor(
  1151. AbsoluteSd,
  1152. SECURITY_DESCRIPTOR_REVISION
  1153. ))) {
  1154. goto Cleanup;
  1155. }
  1156. if (! NT_SUCCESS(ntstatus = RtlSetOwnerSecurityDescriptor(
  1157. AbsoluteSd,
  1158. OwnerSid,
  1159. FALSE
  1160. ))) {
  1161. goto Cleanup;
  1162. }
  1163. if (! NT_SUCCESS(ntstatus = RtlSetGroupSecurityDescriptor(
  1164. AbsoluteSd,
  1165. GroupSid,
  1166. FALSE
  1167. ))) {
  1168. goto Cleanup;
  1169. }
  1170. if (! NT_SUCCESS(ntstatus = RtlSetDaclSecurityDescriptor(
  1171. AbsoluteSd,
  1172. TRUE,
  1173. Dacl,
  1174. FALSE
  1175. ))) {
  1176. goto Cleanup;
  1177. }
  1178. if (! NT_SUCCESS(ntstatus = RtlSetSaclSecurityDescriptor(
  1179. AbsoluteSd,
  1180. FALSE,
  1181. Sacl,
  1182. FALSE
  1183. ))) {
  1184. goto Cleanup;
  1185. }
  1186. //
  1187. // Done
  1188. //
  1189. ntstatus = STATUS_SUCCESS;
  1190. //
  1191. // Clean up
  1192. //
  1193. Cleanup:
  1194. //
  1195. // Either return the security descriptor to the caller or delete it
  1196. //
  1197. if ( NT_SUCCESS( ntstatus ) ) {
  1198. *NewDescriptor = AbsoluteSd;
  1199. } else if ( AbsoluteSd != NULL ) {
  1200. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1201. }
  1202. //
  1203. // Delete the temporary ACE
  1204. //
  1205. if ( MaxAce != NULL ) {
  1206. (void) RtlFreeHeap(HeapHandle, 0, MaxAce);
  1207. }
  1208. return ntstatus;
  1209. }
  1210. NTSTATUS
  1211. RtlCreateUserSecurityObject(
  1212. IN PRTL_ACE_DATA AceData,
  1213. IN ULONG AceCount,
  1214. IN PSID OwnerSid,
  1215. IN PSID GroupSid,
  1216. IN BOOLEAN IsDirectoryObject,
  1217. IN PGENERIC_MAPPING GenericMapping,
  1218. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. This function creates the DACL for the security descriptor based on
  1223. on the ACE information specified, and creates the security descriptor
  1224. which becomes the user-mode security object.
  1225. A sample usage of this function:
  1226. //
  1227. // Structure that describes the mapping of Generic access rights to
  1228. // object specific access rights for the ConfigurationInfo object.
  1229. //
  1230. GENERIC_MAPPING WsConfigInfoMapping = {
  1231. STANDARD_RIGHTS_READ | // Generic read
  1232. WKSTA_CONFIG_GUEST_INFO_GET |
  1233. WKSTA_CONFIG_USER_INFO_GET |
  1234. WKSTA_CONFIG_ADMIN_INFO_GET,
  1235. STANDARD_RIGHTS_WRITE | // Generic write
  1236. WKSTA_CONFIG_INFO_SET,
  1237. STANDARD_RIGHTS_EXECUTE, // Generic execute
  1238. WKSTA_CONFIG_ALL_ACCESS // Generic all
  1239. };
  1240. //
  1241. // Order matters! These ACEs are inserted into the DACL in the
  1242. // following order. Security access is granted or denied based on
  1243. // the order of the ACEs in the DACL.
  1244. //
  1245. RTL_ACE_DATA AceData[4] = {
  1246. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1247. GENERIC_ALL, &LocalAdminSid},
  1248. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  1249. GENERIC_ALL, &NetworkSid},
  1250. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1251. WKSTA_CONFIG_GUEST_INFO_GET |
  1252. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  1253. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1254. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  1255. };
  1256. PSECURITY_DESCRIPTOR WkstaSecurityObject;
  1257. return RtlCreateUserSecurityObject(
  1258. AceData,
  1259. 4,
  1260. LocalSystemSid,
  1261. LocalSystemSid,
  1262. FALSE,
  1263. &WsConfigInfoMapping,
  1264. &WkstaSecurityObject
  1265. );
  1266. Arguments:
  1267. AceData - Supplies the structure of information that describes the DACL.
  1268. AceCount - Supplies the number of entries in AceData structure.
  1269. OwnerSid - Supplies the pointer to the SID of the security descriptor
  1270. owner.
  1271. GroupSid - Supplies the pointer to the SID of the security descriptor
  1272. primary group.
  1273. IsDirectoryObject - Supplies the flag which indicates whether the
  1274. user-mode object is a directory object.
  1275. GenericMapping - Supplies the pointer to a generic mapping array denoting
  1276. the mapping between each generic right to specific rights.
  1277. NewDescriptor - Returns a pointer to the self-relative security descriptor
  1278. which represents the user-mode object.
  1279. Return Value:
  1280. STATUS_SUCCESS - if successful
  1281. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  1282. security descriptor.
  1283. Any other status codes returned from the security Rtl routines.
  1284. NOTE : the user security object created by calling this function may be
  1285. freed up by calling RtlDeleteSecurityObject().
  1286. --*/
  1287. {
  1288. NTSTATUS ntstatus;
  1289. PSECURITY_DESCRIPTOR AbsoluteSd;
  1290. HANDLE TokenHandle;
  1291. PVOID HeapHandle = RtlProcessHeap();
  1292. ntstatus = RtlCreateAndSetSD(
  1293. AceData,
  1294. AceCount,
  1295. OwnerSid,
  1296. GroupSid,
  1297. &AbsoluteSd
  1298. );
  1299. if (! NT_SUCCESS(ntstatus)) {
  1300. return ntstatus;
  1301. }
  1302. ntstatus = NtOpenProcessToken(
  1303. NtCurrentProcess(),
  1304. TOKEN_QUERY,
  1305. &TokenHandle
  1306. );
  1307. if (! NT_SUCCESS(ntstatus)) {
  1308. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1309. return ntstatus;
  1310. }
  1311. //
  1312. // Create the security object (a user-mode object is really a pseudo-
  1313. // object represented by a security descriptor that have relative
  1314. // pointers to SIDs and ACLs). This routine allocates the memory to
  1315. // hold the relative security descriptor so the memory allocated for the
  1316. // DACL, ACEs, and the absolute descriptor can be freed.
  1317. //
  1318. ntstatus = RtlNewSecurityObject(
  1319. NULL, // Parent descriptor
  1320. AbsoluteSd, // Creator descriptor
  1321. NewDescriptor, // Pointer to new descriptor
  1322. IsDirectoryObject, // Is directory object
  1323. TokenHandle, // Token
  1324. GenericMapping // Generic mapping
  1325. );
  1326. (void) NtClose(TokenHandle);
  1327. //
  1328. // Free dynamic memory before returning
  1329. //
  1330. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1331. return ntstatus;
  1332. }
  1333. NTSTATUS
  1334. RtlConvertToAutoInheritSecurityObject(
  1335. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  1336. IN PSECURITY_DESCRIPTOR CurrentSecurityDescriptor,
  1337. OUT PSECURITY_DESCRIPTOR *NewSecurityDescriptor,
  1338. IN GUID *ObjectType OPTIONAL,
  1339. IN BOOLEAN IsDirectoryObject,
  1340. IN PGENERIC_MAPPING GenericMapping
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. This is a converts a security descriptor whose ACLs are not marked
  1345. as AutoInherit to a security descriptor whose ACLs are marked as
  1346. AutoInherit.
  1347. See further detailed description on ConvertToAutoInheritPrivateObjectSecurity.
  1348. Arguments:
  1349. ParentDescriptor - Supplies the Security Descriptor for the parent
  1350. directory under which a object exists. If there is
  1351. no parent directory, then this argument is specified as NULL.
  1352. CurrentSecurityDescriptor - Supplies a pointer to the objects security descriptor
  1353. that is going to be altered by this procedure.
  1354. NewSecurityDescriptor Points to a pointer that is to be made to point to the
  1355. newly allocated self-relative security descriptor. When no
  1356. longer needed, this descriptor must be freed using
  1357. DestroyPrivateObjectSecurity().
  1358. ObjectType - GUID of the object type being created. If the object being
  1359. created has no GUID associated with it, then this argument is
  1360. specified as NULL.
  1361. IsDirectoryObject - Specifies if the object is a
  1362. directory object. A value of TRUE indicates the object is a
  1363. container of other objects.
  1364. GenericMapping - Supplies a pointer to a generic mapping array denoting
  1365. the mapping between each generic right to specific rights.
  1366. Return Value:
  1367. STATUS_SUCCESS - The operation was successful.
  1368. STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that
  1369. is unknown to this routine. (Only revision 2 ACLs are support by this routine.)
  1370. STATUS_INVALID_ACL - The structure of one of the ACLs in invalid.
  1371. --*/
  1372. {
  1373. //
  1374. // Simply call the corresponding Rtlp routine telling it which allocator
  1375. // to use.
  1376. //
  1377. return RtlpConvertToAutoInheritSecurityObject(
  1378. ParentDescriptor,
  1379. CurrentSecurityDescriptor,
  1380. NewSecurityDescriptor,
  1381. ObjectType,
  1382. IsDirectoryObject,
  1383. GenericMapping );
  1384. }
  1385. NTSTATUS
  1386. RtlDefaultNpAcl(
  1387. OUT PACL * pAcl
  1388. )
  1389. /*++
  1390. Routine Description:
  1391. This routine constructs a default ACL to be applied to
  1392. named pipe objects when the caller has not specified one.
  1393. See NT bug 131090.
  1394. The ACL constructed is as follows:
  1395. Need to build an ACL that looks like the following:
  1396. Local System : F
  1397. Administrators: F
  1398. Owner: F
  1399. Everyone: R
  1400. Anonymous: R
  1401. The owner is determined by querying the currently effective
  1402. token and extracting the default owner.
  1403. Arguments:
  1404. pAcl - Receives a pointer to an ACL to apply to the named pipe
  1405. being created. Guaranteed to be NULL on return if an error
  1406. occurs.
  1407. This must be freed by calling RtlFreeHeap.
  1408. Return Value:
  1409. NT Status.
  1410. --*/
  1411. {
  1412. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1413. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  1414. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1415. ULONG AclSize = 0;
  1416. NTSTATUS Status = STATUS_SUCCESS;
  1417. ULONG ReturnLength = 0;
  1418. PTOKEN_OWNER OwnerSid = NULL;
  1419. HANDLE hToken;
  1420. //
  1421. // Initialize OUT parameters
  1422. //
  1423. *pAcl = NULL;
  1424. //
  1425. // Open thread token
  1426. //
  1427. Status = NtOpenThreadToken(
  1428. NtCurrentThread(),
  1429. TOKEN_QUERY,
  1430. TRUE,
  1431. &hToken
  1432. );
  1433. if (STATUS_NO_TOKEN == Status) {
  1434. //
  1435. // Not impersonating, get process token
  1436. //
  1437. Status = NtOpenProcessToken(
  1438. NtCurrentProcess(),
  1439. TOKEN_QUERY,
  1440. &hToken
  1441. );
  1442. }
  1443. if (NT_SUCCESS( Status )) {
  1444. //
  1445. // Get the default owner
  1446. //
  1447. Status = NtQueryInformationToken (
  1448. hToken,
  1449. TokenOwner,
  1450. NULL,
  1451. 0,
  1452. &ReturnLength
  1453. );
  1454. if (STATUS_BUFFER_TOO_SMALL == Status) {
  1455. OwnerSid = (PTOKEN_OWNER)RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
  1456. if (OwnerSid) {
  1457. Status = NtQueryInformationToken (
  1458. hToken,
  1459. TokenOwner,
  1460. OwnerSid,
  1461. ReturnLength,
  1462. &ReturnLength
  1463. );
  1464. if (NT_SUCCESS( Status )) {
  1465. //
  1466. // Compute the size needed
  1467. //
  1468. UCHAR SidBuffer[16];
  1469. ASSERT( 16 == RtlLengthRequiredSid( 2 ));
  1470. AclSize += RtlLengthRequiredSid( 1 ); // LocalSystem Sid
  1471. AclSize += RtlLengthRequiredSid( 2 ); // Administrators
  1472. AclSize += RtlLengthRequiredSid( 1 ); // Everyone (World)
  1473. AclSize += RtlLengthRequiredSid( 1 ); // Anonymous Logon Sid
  1474. AclSize += RtlLengthSid( OwnerSid->Owner ); // Owner
  1475. AclSize += sizeof( ACL ); // Header
  1476. AclSize += 5 * (sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ));
  1477. //
  1478. // Allocate the Acl out of the local process heap
  1479. //
  1480. *pAcl = (PACL)RtlAllocateHeap( RtlProcessHeap(), 0, AclSize );
  1481. if (*pAcl != NULL) {
  1482. RtlCreateAcl( *pAcl, AclSize, ACL_REVISION );
  1483. //
  1484. // Create each SID in turn and copy the resultant ACE into
  1485. // the new ACL
  1486. //
  1487. //
  1488. // Local System - Generic All
  1489. //
  1490. RtlInitializeSid( SidBuffer, &NtAuthority, 1);
  1491. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  1492. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
  1493. //
  1494. // Admins - Generic All
  1495. //
  1496. RtlInitializeSid( SidBuffer, &NtAuthority, 2);
  1497. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  1498. *(RtlSubAuthoritySid( SidBuffer, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
  1499. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
  1500. //
  1501. // Owner - Generic All
  1502. //
  1503. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, OwnerSid->Owner );
  1504. //
  1505. // World - Generic Read
  1506. //
  1507. RtlInitializeSid( SidBuffer, &WorldSidAuthority, 1 );
  1508. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_WORLD_RID;
  1509. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_READ, (PSID)SidBuffer );
  1510. //
  1511. // Anonymous Logon - Generic Read
  1512. //
  1513. RtlInitializeSid( SidBuffer, &NtAuthority, 1);
  1514. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_ANONYMOUS_LOGON_RID;
  1515. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_READ, (PSID)SidBuffer );
  1516. } else {
  1517. Status = STATUS_NO_MEMORY;
  1518. }
  1519. }
  1520. RtlFreeHeap( RtlProcessHeap(), 0, OwnerSid );
  1521. } else {
  1522. Status = STATUS_NO_MEMORY;
  1523. }
  1524. }
  1525. NtClose( hToken );
  1526. }
  1527. if (!NT_SUCCESS( Status )) {
  1528. //
  1529. // Something failed, clean up OUT
  1530. // parameters.
  1531. //
  1532. if (*pAcl != NULL) {
  1533. RtlFreeHeap( RtlProcessHeap(), 0, *pAcl );
  1534. *pAcl = NULL;
  1535. }
  1536. }
  1537. return( Status );
  1538. }