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.

2137 lines
59 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 "ldrp.h"
  15. #include <ntos.h>
  16. #include <nturtl.h>
  17. #include <ntlsa.h> // needed for RtlGetPrimaryDomain
  18. #include "seopaque.h"
  19. #include "sertlp.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. Dacl = NULL;
  390. Sacl = NULL;
  391. Group = NULL;
  392. Owner = NULL;
  393. IResultantDescriptor = (PISECURITY_DESCRIPTOR_RELATIVE)ResultantDescriptor;
  394. IObjectDescriptor = (PISECURITY_DESCRIPTOR)ObjectDescriptor;
  395. //
  396. // For each item specified in the SecurityInformation, extract it
  397. // and get it to the point where it can be copied into a new
  398. // descriptor.
  399. //
  400. if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
  401. Group = RtlpGroupAddrSecurityDescriptor(IObjectDescriptor);
  402. if (Group != NULL) {
  403. GroupSize = LongAlignSize(SeLengthSid(Group));
  404. }
  405. }
  406. if (SecurityInformation & DACL_SECURITY_INFORMATION) {
  407. Dacl = RtlpDaclAddrSecurityDescriptor( IObjectDescriptor );
  408. if (Dacl != NULL) {
  409. DaclSize = LongAlignSize(Dacl->AclSize);
  410. }
  411. }
  412. if (SecurityInformation & SACL_SECURITY_INFORMATION) {
  413. Sacl = RtlpSaclAddrSecurityDescriptor( IObjectDescriptor );
  414. if (Sacl != NULL) {
  415. SaclSize = LongAlignSize(Sacl->AclSize);
  416. }
  417. }
  418. if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
  419. Owner = RtlpOwnerAddrSecurityDescriptor ( IObjectDescriptor );
  420. if (Owner != NULL) {
  421. OwnerSize = LongAlignSize(SeLengthSid(Owner));
  422. }
  423. }
  424. *ReturnLength = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) +
  425. GroupSize +
  426. DaclSize +
  427. SaclSize +
  428. OwnerSize;
  429. if (*ReturnLength > DescriptorLength) {
  430. return( STATUS_BUFFER_TOO_SMALL );
  431. }
  432. RtlCreateSecurityDescriptorRelative(
  433. IResultantDescriptor,
  434. SECURITY_DESCRIPTOR_REVISION
  435. );
  436. RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE );
  437. Base = (PCHAR)(IResultantDescriptor);
  438. Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  439. if (SecurityInformation & SACL_SECURITY_INFORMATION) {
  440. if (SaclSize > 0) {
  441. RtlMoveMemory( Field, Sacl, SaclSize );
  442. IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field);
  443. Field += SaclSize;
  444. }
  445. RtlpPropagateControlBits(
  446. IResultantDescriptor,
  447. IObjectDescriptor,
  448. SE_SACL_PRESENT | SE_SACL_DEFAULTED
  449. );
  450. }
  451. if (SecurityInformation & DACL_SECURITY_INFORMATION) {
  452. if (DaclSize > 0) {
  453. RtlMoveMemory( Field, Dacl, DaclSize );
  454. IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field);
  455. Field += DaclSize;
  456. }
  457. RtlpPropagateControlBits(
  458. IResultantDescriptor,
  459. IObjectDescriptor,
  460. SE_DACL_PRESENT | SE_DACL_DEFAULTED
  461. );
  462. }
  463. if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
  464. if (OwnerSize > 0) {
  465. RtlMoveMemory( Field, Owner, OwnerSize );
  466. IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field);
  467. Field += OwnerSize;
  468. }
  469. RtlpPropagateControlBits(
  470. IResultantDescriptor,
  471. IObjectDescriptor,
  472. SE_OWNER_DEFAULTED
  473. );
  474. }
  475. if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
  476. if (GroupSize > 0) {
  477. RtlMoveMemory( Field, Group, GroupSize );
  478. IResultantDescriptor->Group = RtlPointerToOffset(Base,Field);
  479. }
  480. RtlpPropagateControlBits(
  481. IResultantDescriptor,
  482. IObjectDescriptor,
  483. SE_GROUP_DEFAULTED
  484. );
  485. }
  486. return( STATUS_SUCCESS );
  487. }
  488. NTSTATUS
  489. RtlDeleteSecurityObject (
  490. IN OUT PSECURITY_DESCRIPTOR * ObjectDescriptor
  491. )
  492. /*++
  493. Routine Description:
  494. Delete a protected server object's security descriptor.
  495. This procedure, called only from user mode, is used to delete a
  496. security descriptor associated with a protected server's object. This
  497. routine will normally be called by a protected server during object
  498. deletion.
  499. - - WARNING - -
  500. This service is for use by protected subsystems that project their own
  501. type of object. This service is explicitly not for use by the
  502. executive for executive objects and must not be called from kernel
  503. mode.
  504. Arguments:
  505. ObjectDescriptor - Points to a pointer to a security descriptor to be
  506. deleted.
  507. Return Value:
  508. STATUS_SUCCESS - The operation was successful.
  509. --*/
  510. {
  511. RtlFreeHeap( RtlProcessHeap(), 0, (PVOID)*ObjectDescriptor );
  512. return( STATUS_SUCCESS );
  513. }
  514. NTSTATUS
  515. RtlNewInstanceSecurityObject(
  516. IN BOOLEAN ParentDescriptorChanged,
  517. IN BOOLEAN CreatorDescriptorChanged,
  518. IN PLUID OldClientTokenModifiedId,
  519. OUT PLUID NewClientTokenModifiedId,
  520. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  521. IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
  522. OUT PSECURITY_DESCRIPTOR * NewDescriptor,
  523. IN BOOLEAN IsDirectoryObject,
  524. IN HANDLE Token,
  525. IN PGENERIC_MAPPING GenericMapping
  526. )
  527. /*++
  528. Routine Description:
  529. If the return status is STATUS_SUCCESS and the NewSecurity return
  530. value is NULL, then the security desscriptor of the original
  531. instance of the object is valid for this instance as well.
  532. Arguments:
  533. ParentDescriptorChanged - Supplies a flag indicating whether the
  534. parent security descriptor has changed since the last time
  535. this set of parameters was used.
  536. CreatorDescriptorChanged - Supplies a flag indicating whether the
  537. creator security descriptor has changed since the last time
  538. this set of parameters was used.
  539. OldClientTokenModifiedId - Supplies the ModifiedId from the passed
  540. token that was in effect when this call was last made with
  541. these parameters. If the current ModifiedId is different from
  542. the one passed in here, the security descriptor must be
  543. rebuilt.
  544. NewClientTokenModifiedId - Returns the current ModifiedId from the
  545. passed token.
  546. ParentDescriptor - Supplies the Security Descriptor for the parent
  547. directory under which a new object is being created. If there is
  548. no parent directory, then this argument is specified as NULL.
  549. CreatorDescriptor - (Optionally) Points to a security descriptor
  550. presented by the creator of the object. If the creator of the
  551. object did not explicitly pass security information for the new
  552. object, then a null pointer should be passed.
  553. NewDescriptor - Points to a pointer that is to be made to point to the
  554. newly allocated self-relative security descriptor.
  555. IsDirectoryObject - Specifies if the new object is going to be a
  556. directory object. A value of TRUE indicates the object is a
  557. container of other objects.
  558. Token - Supplies the token for the client on whose behalf the
  559. object is being created. If it is an impersonation token,
  560. then it must be at SecurityIdentification level or higher. If
  561. it is not an impersonation token, the operation proceeds
  562. normally.
  563. A client token is used to retrieve default security
  564. information for the new object, such as default owner, primary
  565. group, and discretionary access control. The token must be
  566. open for TOKEN_QUERY access.
  567. GenericMapping - Supplies a pointer to a generic mapping array denoting
  568. the mapping between each generic right to specific rights.
  569. Return Value:
  570. return-value - Description of conditions needed to return value. - or -
  571. None.
  572. --*/
  573. {
  574. TOKEN_STATISTICS ClientTokenStatistics;
  575. ULONG ReturnLength;
  576. NTSTATUS Status;
  577. //
  578. // Get the current token modified LUID
  579. //
  580. Status = NtQueryInformationToken(
  581. Token, // Handle
  582. TokenStatistics, // TokenInformationClass
  583. &ClientTokenStatistics, // TokenInformation
  584. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  585. &ReturnLength // ReturnLength
  586. );
  587. if ( !NT_SUCCESS( Status )) {
  588. return( Status );
  589. }
  590. *NewClientTokenModifiedId = ClientTokenStatistics.ModifiedId;
  591. if ( RtlEqualLuid(NewClientTokenModifiedId, OldClientTokenModifiedId) ) {
  592. if ( !(ParentDescriptorChanged || CreatorDescriptorChanged) ) {
  593. //
  594. // The old security descriptor is valid for this new instance
  595. // of the object type as well. Pass back success and NULL for
  596. // the NewDescriptor.
  597. //
  598. *NewDescriptor = NULL;
  599. return( STATUS_SUCCESS );
  600. }
  601. }
  602. //
  603. // Something has changed, take the long route and build a new
  604. // descriptor
  605. //
  606. return( RtlNewSecurityObject( ParentDescriptor,
  607. CreatorDescriptor,
  608. NewDescriptor,
  609. IsDirectoryObject,
  610. Token,
  611. GenericMapping
  612. ));
  613. }
  614. NTSTATUS
  615. RtlNewSecurityGrantedAccess(
  616. IN ACCESS_MASK DesiredAccess,
  617. OUT PPRIVILEGE_SET Privileges,
  618. IN OUT PULONG Length,
  619. IN HANDLE Token OPTIONAL,
  620. IN PGENERIC_MAPPING GenericMapping,
  621. OUT PACCESS_MASK RemainingDesiredAccess
  622. )
  623. /*++
  624. Routine Description:
  625. This routine implements privilege policy by examining the bits in
  626. a DesiredAccess mask and adjusting them based on privilege checks.
  627. Currently, a request for ACCESS_SYSTEM_SECURITY may only be satisfied
  628. by the caller having SeSecurityPrivilege.
  629. Note that this routine is only to be called when an object is being
  630. created. When an object is being opened, it is expected that
  631. NtAccessCheck will be called, and that routine will implement
  632. another policy for substituting privileges for DACL access.
  633. Arguments:
  634. DesiredAccess - Supplies the user's desired access mask
  635. Privileges - Supplies a pointer to an empty buffer in which will
  636. be returned a privilege set describing any privileges that were
  637. used to gain access.
  638. Note that this is not an optional parameter, that is, enough
  639. room for a single privilege must always be passed.
  640. Length - Supplies the length of the Privileges parameter in bytes.
  641. If the supplies length is not adequate to store the entire
  642. privilege set, this field will return the minimum length required.
  643. Token - (optionally) Supplies the token for the client on whose
  644. behalf the object is being accessed. If this value is
  645. specified as null, then the token on the thread is opened and
  646. examined to see if it is an impersonation token. If it is,
  647. then it must be at SecurityIdentification level or higher. If
  648. it is not an impersonation token, the operation proceeds
  649. normally.
  650. GenericMapping - Supplies the generic mapping associated with this
  651. object type.
  652. RemainingDesiredAccess - Returns the DesiredAccess mask after any bits
  653. have been masked off. If no access types could be granted, this
  654. mask will be identical to the one passed in.
  655. Return Value:
  656. STATUS_SUCCESS - The operation completed successfully.
  657. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  658. to contain the information being returned.
  659. STATUS_BAD_IMPERSONATION_LEVEL - The caller or passed token was
  660. impersonating, but not at a high enough level.
  661. --*/
  662. {
  663. PRIVILEGE_SET RequiredPrivilege;
  664. BOOLEAN Result = FALSE;
  665. NTSTATUS Status;
  666. HANDLE ThreadToken;
  667. BOOLEAN TokenPassed;
  668. TOKEN_STATISTICS ThreadTokenStatistics;
  669. ULONG ReturnLength;
  670. ULONG SizeRequired;
  671. ULONG PrivilegeNumber = 0;
  672. //
  673. // If the caller hasn't passed a token, call the kernel and get
  674. // his impersonation token. This call will fail if the caller is
  675. // not impersonating a client, so if the caller is not
  676. // impersonating someone, he'd better have passed in an explicit
  677. // token.
  678. //
  679. if (!ARGUMENT_PRESENT( Token )) {
  680. Status = NtOpenThreadToken(
  681. NtCurrentThread(),
  682. TOKEN_QUERY,
  683. TRUE,
  684. &ThreadToken
  685. );
  686. TokenPassed = FALSE;
  687. if (!NT_SUCCESS( Status )) {
  688. return( Status );
  689. }
  690. } else {
  691. ThreadToken = Token;
  692. TokenPassed = TRUE;
  693. }
  694. Status = NtQueryInformationToken(
  695. ThreadToken, // Handle
  696. TokenStatistics, // TokenInformationClass
  697. &ThreadTokenStatistics, // TokenInformation
  698. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  699. &ReturnLength // ReturnLength
  700. );
  701. ASSERT( NT_SUCCESS(Status) );
  702. RtlMapGenericMask(
  703. &DesiredAccess,
  704. GenericMapping
  705. );
  706. *RemainingDesiredAccess = DesiredAccess;
  707. if ( DesiredAccess & ACCESS_SYSTEM_SECURITY ) {
  708. RequiredPrivilege.PrivilegeCount = 1;
  709. RequiredPrivilege.Control = PRIVILEGE_SET_ALL_NECESSARY;
  710. RequiredPrivilege.Privilege[0].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
  711. RequiredPrivilege.Privilege[0].Attributes = 0;
  712. //
  713. // NtPrivilegeCheck will make sure we are impersonating
  714. // properly.
  715. //
  716. Status = NtPrivilegeCheck(
  717. ThreadToken,
  718. &RequiredPrivilege,
  719. &Result
  720. );
  721. if ( (!NT_SUCCESS ( Status )) || (!Result) ) {
  722. if (!TokenPassed) {
  723. NtClose( ThreadToken );
  724. }
  725. if ( !NT_SUCCESS( Status )) {
  726. return( Status );
  727. }
  728. if ( !Result ) {
  729. return( STATUS_PRIVILEGE_NOT_HELD );
  730. }
  731. }
  732. //
  733. // We have the required privilege, turn off the bit in
  734. // copy of the input mask and remember that we need to return
  735. // this privilege.
  736. //
  737. *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
  738. }
  739. if (!TokenPassed) {
  740. NtClose( ThreadToken );
  741. }
  742. SizeRequired = sizeof(PRIVILEGE_SET);
  743. if ( SizeRequired > *Length ) {
  744. *Length = SizeRequired;
  745. return( STATUS_BUFFER_TOO_SMALL );
  746. }
  747. if (Result) {
  748. Privileges->PrivilegeCount = 1;
  749. Privileges->Control = 0;
  750. Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
  751. Privileges->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
  752. } else {
  753. Privileges->PrivilegeCount = 0;
  754. Privileges->Control = 0;
  755. Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(0);
  756. Privileges->Privilege[PrivilegeNumber].Attributes = 0;
  757. }
  758. return( STATUS_SUCCESS );
  759. }
  760. NTSTATUS
  761. RtlCopySecurityDescriptor(
  762. IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
  763. OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor
  764. )
  765. /*++
  766. Routine Description:
  767. This routine will copy a self-relative security descriptor from
  768. any memory into the correct type of memory required by security
  769. descriptor Rtl routines.
  770. This allows security descriptors to be kept in whatever kind of
  771. storage is most convenient for the current application. A security
  772. descriptor should be copied via this routine and the copy passed
  773. into any Rtl routine that in any way modify the security descriptor
  774. (eg RtlSetSecurityObject).
  775. The storage allocated by this routine must be freed by
  776. RtlDeleteSecurityObject.
  777. Arguments:
  778. InputSecurityDescriptor - contains the source security descriptor
  779. OutputSecurityDescriptor - returns a copy of the security descriptor
  780. in the correct kind of memory.
  781. Return Value:
  782. STATUS_NO_MEMORY - There was not enough memory available to the current
  783. process to complete this operation.
  784. --*/
  785. {
  786. PACL Dacl;
  787. PACL Sacl;
  788. PSID Owner;
  789. PSID PrimaryGroup;
  790. ULONG DaclSize;
  791. ULONG OwnerSize;
  792. ULONG PrimaryGroupSize;
  793. ULONG SaclSize;
  794. ULONG TotalSize;
  795. PISECURITY_DESCRIPTOR ISecurityDescriptor =
  796. (PISECURITY_DESCRIPTOR)InputSecurityDescriptor;
  797. RtlpQuerySecurityDescriptor(
  798. ISecurityDescriptor,
  799. &Owner,
  800. &OwnerSize,
  801. &PrimaryGroup,
  802. &PrimaryGroupSize,
  803. &Dacl,
  804. &DaclSize,
  805. &Sacl,
  806. &SaclSize
  807. );
  808. TotalSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
  809. OwnerSize +
  810. PrimaryGroupSize +
  811. DaclSize +
  812. SaclSize;
  813. *OutputSecurityDescriptor = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( SE_TAG ), TotalSize );
  814. if ( *OutputSecurityDescriptor == NULL ) {
  815. return( STATUS_NO_MEMORY );
  816. }
  817. RtlCopyMemory( *OutputSecurityDescriptor,
  818. ISecurityDescriptor,
  819. TotalSize
  820. );
  821. return( STATUS_SUCCESS );
  822. }
  823. NTSTATUS
  824. RtlpInitializeAllowedAce(
  825. IN PACCESS_ALLOWED_ACE AllowedAce,
  826. IN USHORT AceSize,
  827. IN UCHAR InheritFlags,
  828. IN UCHAR AceFlags,
  829. IN ACCESS_MASK Mask,
  830. IN PSID AllowedSid
  831. )
  832. /*++
  833. Routine Description:
  834. This function assigns the specified ACE values into an allowed type ACE.
  835. Arguments:
  836. AllowedAce - Supplies a pointer to the ACE that is initialized.
  837. AceSize - Supplies the size of the ACE in bytes.
  838. InheritFlags - Supplies ACE inherit flags.
  839. AceFlags - Supplies ACE type specific control flags.
  840. Mask - Supplies the allowed access masks.
  841. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  842. the specified access.
  843. Return Value:
  844. Returns status from RtlCopySid.
  845. --*/
  846. {
  847. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  848. AllowedAce->Header.AceSize = AceSize;
  849. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  850. AllowedAce->Mask = Mask;
  851. return RtlCopySid(
  852. RtlLengthSid(AllowedSid),
  853. &(AllowedAce->SidStart),
  854. AllowedSid
  855. );
  856. }
  857. NTSTATUS
  858. RtlpInitializeDeniedAce(
  859. IN PACCESS_DENIED_ACE DeniedAce,
  860. IN USHORT AceSize,
  861. IN UCHAR InheritFlags,
  862. IN UCHAR AceFlags,
  863. IN ACCESS_MASK Mask,
  864. IN PSID DeniedSid
  865. )
  866. /*++
  867. Routine Description:
  868. This function assigns the specified ACE values into a denied type ACE.
  869. Arguments:
  870. DeniedAce - Supplies a pointer to the ACE that is initialized.
  871. AceSize - Supplies the size of the ACE in bytes.
  872. InheritFlags - Supplies ACE inherit flags.
  873. AceFlags - Supplies ACE type specific control flags.
  874. Mask - Supplies the denied access masks.
  875. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  876. the specified access.
  877. Return Value:
  878. Returns status from RtlCopySid.
  879. --*/
  880. {
  881. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  882. DeniedAce->Header.AceSize = AceSize;
  883. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  884. DeniedAce->Mask = Mask;
  885. return RtlCopySid(
  886. RtlLengthSid(DeniedSid),
  887. &(DeniedAce->SidStart),
  888. DeniedSid
  889. );
  890. }
  891. NTSTATUS
  892. RtlpInitializeAuditAce(
  893. IN PACCESS_ALLOWED_ACE AuditAce,
  894. IN USHORT AceSize,
  895. IN UCHAR InheritFlags,
  896. IN UCHAR AceFlags,
  897. IN ACCESS_MASK Mask,
  898. IN PSID AuditSid
  899. )
  900. /*++
  901. Routine Description:
  902. This function assigns the specified ACE values into an audit type ACE.
  903. Arguments:
  904. AuditAce - Supplies a pointer to the ACE that is initialized.
  905. AceSize - Supplies the size of the ACE in bytes.
  906. InheritFlags - Supplies ACE inherit flags.
  907. AceFlags - Supplies ACE type specific control flags.
  908. Mask - Supplies the allowed access masks.
  909. AuditSid - Supplies the pointer to the SID of user/group which is to be
  910. audited.
  911. Return Value:
  912. Returns status from RtlCopySid.
  913. --*/
  914. {
  915. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  916. AuditAce->Header.AceSize = AceSize;
  917. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  918. AuditAce->Mask = Mask;
  919. return RtlCopySid(
  920. RtlLengthSid(AuditSid),
  921. &(AuditAce->SidStart),
  922. AuditSid
  923. );
  924. }
  925. NTSTATUS
  926. RtlCreateAndSetSD(
  927. IN PRTL_ACE_DATA AceData,
  928. IN ULONG AceCount,
  929. IN PSID OwnerSid OPTIONAL,
  930. IN PSID GroupSid OPTIONAL,
  931. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  932. )
  933. /*++
  934. Routine Description:
  935. This function creates an absolute security descriptor containing
  936. the supplied ACE information.
  937. A sample usage of this function:
  938. //
  939. // Order matters! These ACEs are inserted into the DACL in the
  940. // following order. Security access is granted or denied based on
  941. // the order of the ACEs in the DACL.
  942. //
  943. RTL_ACE_DATA AceData[4] = {
  944. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  945. GENERIC_ALL, &LocalAdminSid},
  946. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  947. GENERIC_ALL, &NetworkSid},
  948. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  949. WKSTA_CONFIG_GUEST_INFO_GET |
  950. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  951. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  952. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  953. };
  954. PSECURITY_DESCRIPTOR WkstaSecurityDescriptor;
  955. return RtlCreateAndSetSD(
  956. AceData,
  957. 4,
  958. LocalSystemSid,
  959. LocalSystemSid,
  960. &WkstaSecurityDescriptor
  961. );
  962. Arguments:
  963. AceData - Supplies the structure of information that describes the DACL.
  964. AceCount - Supplies the number of entries in AceData structure.
  965. OwnerSid - Supplies the pointer to the SID of the security descriptor
  966. owner. If not specified, a security descriptor with no owner
  967. will be created.
  968. GroupSid - Supplies the pointer to the SID of the security descriptor
  969. primary group. If not specified, a security descriptor with no primary
  970. group will be created.
  971. NewDescriptor - Returns a pointer to the absolute security descriptor
  972. allocated using RtlAllocateHeap.
  973. Return Value:
  974. STATUS_SUCCESS - if successful
  975. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  976. security descriptor.
  977. Any other status codes returned from the security Rtl routines.
  978. NOTE : the user security object created by calling this function may be
  979. freed up by calling RtlDeleteSecurityObject().
  980. --*/
  981. {
  982. NTSTATUS ntstatus = STATUS_SUCCESS;
  983. ULONG i;
  984. //
  985. // Pointer to memory dynamically allocated by this routine to hold
  986. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  987. //
  988. // +---------------------------------------------------------------+
  989. // | Security Descriptor |
  990. // +-------------------------------+-------+---------------+-------+
  991. // | DACL | ACE 1 | . . . | ACE n |
  992. // +-------------------------------+-------+---------------+-------+
  993. // | SACL | ACE 1 | . . . | ACE n |
  994. // +-------------------------------+-------+---------------+-------+
  995. //
  996. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  997. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  998. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  999. ULONG DaclSize = sizeof(ACL);
  1000. ULONG SaclSize = sizeof(ACL);
  1001. ULONG MaxAceSize = 0;
  1002. PVOID MaxAce = NULL;
  1003. PCHAR CurrentAvailable;
  1004. ULONG Size;
  1005. PVOID HeapHandle = RtlProcessHeap();
  1006. ASSERT( AceCount > 0 );
  1007. //
  1008. // Compute the total size of the DACL and SACL ACEs and the maximum
  1009. // size of any ACE.
  1010. //
  1011. for (i = 0; i < AceCount; i++) {
  1012. ULONG AceSize;
  1013. AceSize = RtlLengthSid(*(AceData[i].Sid));
  1014. switch (AceData[i].AceType) {
  1015. case ACCESS_ALLOWED_ACE_TYPE:
  1016. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  1017. DaclSize += AceSize;
  1018. break;
  1019. case ACCESS_DENIED_ACE_TYPE:
  1020. AceSize += sizeof(ACCESS_DENIED_ACE);
  1021. DaclSize += AceSize;
  1022. break;
  1023. case SYSTEM_AUDIT_ACE_TYPE:
  1024. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  1025. SaclSize += AceSize;
  1026. break;
  1027. default:
  1028. return STATUS_INVALID_PARAMETER;
  1029. }
  1030. MaxAceSize = MaxAceSize > AceSize ? MaxAceSize : AceSize;
  1031. }
  1032. //
  1033. // Allocate a chunk of memory large enough for the security descriptor,
  1034. // the DACL, the SACL and all ACEs.
  1035. //
  1036. // A security descriptor is of opaque data type but
  1037. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  1038. //
  1039. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  1040. if ( DaclSize != sizeof(ACL) ) {
  1041. Size += DaclSize;
  1042. }
  1043. if ( SaclSize != sizeof(ACL) ) {
  1044. Size += SaclSize;
  1045. }
  1046. if ((AbsoluteSd = RtlAllocateHeap(
  1047. HeapHandle, MAKE_TAG( SE_TAG ),
  1048. Size
  1049. )) == NULL) {
  1050. ntstatus = STATUS_NO_MEMORY;
  1051. goto Cleanup;
  1052. }
  1053. //
  1054. // Initialize the Dacl and Sacl
  1055. //
  1056. CurrentAvailable = (PCHAR)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  1057. if ( DaclSize != sizeof(ACL) ) {
  1058. Dacl = (PACL)CurrentAvailable;
  1059. CurrentAvailable += DaclSize;
  1060. ntstatus = RtlCreateAcl( Dacl, DaclSize, ACL_REVISION );
  1061. if ( !NT_SUCCESS(ntstatus) ) {
  1062. goto Cleanup;
  1063. }
  1064. }
  1065. if ( SaclSize != sizeof(ACL) ) {
  1066. Sacl = (PACL)CurrentAvailable;
  1067. CurrentAvailable += SaclSize;
  1068. ntstatus = RtlCreateAcl( Sacl, SaclSize, ACL_REVISION );
  1069. if ( !NT_SUCCESS(ntstatus) ) {
  1070. goto Cleanup;
  1071. }
  1072. }
  1073. //
  1074. // Allocate a temporary buffer big enough for the biggest ACE.
  1075. //
  1076. if ((MaxAce = RtlAllocateHeap(
  1077. HeapHandle, MAKE_TAG( SE_TAG ),
  1078. MaxAceSize
  1079. )) == NULL ) {
  1080. ntstatus = STATUS_NO_MEMORY;
  1081. goto Cleanup;
  1082. }
  1083. //
  1084. // Initialize each ACE, and append it into the end of the DACL or SACL.
  1085. //
  1086. for (i = 0; i < AceCount; i++) {
  1087. ULONG AceSize;
  1088. PACL CurrentAcl;
  1089. CurrentAcl = NULL;
  1090. AceSize = RtlLengthSid(*(AceData[i].Sid));
  1091. switch (AceData[i].AceType) {
  1092. case ACCESS_ALLOWED_ACE_TYPE:
  1093. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  1094. CurrentAcl = Dacl;
  1095. ntstatus = RtlpInitializeAllowedAce(
  1096. MaxAce,
  1097. (USHORT) AceSize,
  1098. AceData[i].InheritFlags,
  1099. AceData[i].AceFlags,
  1100. AceData[i].Mask,
  1101. *(AceData[i].Sid)
  1102. );
  1103. break;
  1104. case ACCESS_DENIED_ACE_TYPE:
  1105. AceSize += sizeof(ACCESS_DENIED_ACE);
  1106. CurrentAcl = Dacl;
  1107. ntstatus = RtlpInitializeDeniedAce(
  1108. MaxAce,
  1109. (USHORT) AceSize,
  1110. AceData[i].InheritFlags,
  1111. AceData[i].AceFlags,
  1112. AceData[i].Mask,
  1113. *(AceData[i].Sid)
  1114. );
  1115. break;
  1116. case SYSTEM_AUDIT_ACE_TYPE:
  1117. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  1118. CurrentAcl = Sacl;
  1119. ntstatus = RtlpInitializeAuditAce(
  1120. MaxAce,
  1121. (USHORT) AceSize,
  1122. AceData[i].InheritFlags,
  1123. AceData[i].AceFlags,
  1124. AceData[i].Mask,
  1125. *(AceData[i].Sid)
  1126. );
  1127. break;
  1128. }
  1129. if ( !NT_SUCCESS( ntstatus ) ) {
  1130. goto Cleanup;
  1131. }
  1132. //
  1133. // Append the initialized ACE to the end of DACL or SACL
  1134. //
  1135. ntstatus = RtlAddAce(
  1136. CurrentAcl,
  1137. ACL_REVISION,
  1138. MAXULONG,
  1139. MaxAce,
  1140. AceSize
  1141. );
  1142. if (! NT_SUCCESS ( ntstatus ) ) {
  1143. goto Cleanup;
  1144. }
  1145. }
  1146. //
  1147. // Create the security descriptor with absolute pointers to SIDs
  1148. // and ACLs.
  1149. //
  1150. // Owner = OwnerSid
  1151. // Group = GroupSid
  1152. // Dacl = Dacl
  1153. // Sacl = Sacl
  1154. //
  1155. if (! NT_SUCCESS(ntstatus = RtlCreateSecurityDescriptor(
  1156. AbsoluteSd,
  1157. SECURITY_DESCRIPTOR_REVISION
  1158. ))) {
  1159. goto Cleanup;
  1160. }
  1161. if (! NT_SUCCESS(ntstatus = RtlSetOwnerSecurityDescriptor(
  1162. AbsoluteSd,
  1163. OwnerSid,
  1164. FALSE
  1165. ))) {
  1166. goto Cleanup;
  1167. }
  1168. if (! NT_SUCCESS(ntstatus = RtlSetGroupSecurityDescriptor(
  1169. AbsoluteSd,
  1170. GroupSid,
  1171. FALSE
  1172. ))) {
  1173. goto Cleanup;
  1174. }
  1175. if (! NT_SUCCESS(ntstatus = RtlSetDaclSecurityDescriptor(
  1176. AbsoluteSd,
  1177. TRUE,
  1178. Dacl,
  1179. FALSE
  1180. ))) {
  1181. goto Cleanup;
  1182. }
  1183. if (! NT_SUCCESS(ntstatus = RtlSetSaclSecurityDescriptor(
  1184. AbsoluteSd,
  1185. Sacl ? TRUE : FALSE,
  1186. Sacl,
  1187. FALSE
  1188. ))) {
  1189. goto Cleanup;
  1190. }
  1191. //
  1192. // Done
  1193. //
  1194. ntstatus = STATUS_SUCCESS;
  1195. //
  1196. // Clean up
  1197. //
  1198. Cleanup:
  1199. //
  1200. // Either return the security descriptor to the caller or delete it
  1201. //
  1202. if ( NT_SUCCESS( ntstatus ) ) {
  1203. *NewDescriptor = AbsoluteSd;
  1204. } else if ( AbsoluteSd != NULL ) {
  1205. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1206. }
  1207. //
  1208. // Delete the temporary ACE
  1209. //
  1210. if ( MaxAce != NULL ) {
  1211. (void) RtlFreeHeap(HeapHandle, 0, MaxAce);
  1212. }
  1213. return ntstatus;
  1214. }
  1215. NTSTATUS
  1216. RtlCreateUserSecurityObject(
  1217. IN PRTL_ACE_DATA AceData,
  1218. IN ULONG AceCount,
  1219. IN PSID OwnerSid,
  1220. IN PSID GroupSid,
  1221. IN BOOLEAN IsDirectoryObject,
  1222. IN PGENERIC_MAPPING GenericMapping,
  1223. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. This function creates the DACL for the security descriptor based on
  1228. on the ACE information specified, and creates the security descriptor
  1229. which becomes the user-mode security object.
  1230. A sample usage of this function:
  1231. //
  1232. // Structure that describes the mapping of Generic access rights to
  1233. // object specific access rights for the ConfigurationInfo object.
  1234. //
  1235. GENERIC_MAPPING WsConfigInfoMapping = {
  1236. STANDARD_RIGHTS_READ | // Generic read
  1237. WKSTA_CONFIG_GUEST_INFO_GET |
  1238. WKSTA_CONFIG_USER_INFO_GET |
  1239. WKSTA_CONFIG_ADMIN_INFO_GET,
  1240. STANDARD_RIGHTS_WRITE | // Generic write
  1241. WKSTA_CONFIG_INFO_SET,
  1242. STANDARD_RIGHTS_EXECUTE, // Generic execute
  1243. WKSTA_CONFIG_ALL_ACCESS // Generic all
  1244. };
  1245. //
  1246. // Order matters! These ACEs are inserted into the DACL in the
  1247. // following order. Security access is granted or denied based on
  1248. // the order of the ACEs in the DACL.
  1249. //
  1250. RTL_ACE_DATA AceData[4] = {
  1251. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1252. GENERIC_ALL, &LocalAdminSid},
  1253. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  1254. GENERIC_ALL, &NetworkSid},
  1255. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1256. WKSTA_CONFIG_GUEST_INFO_GET |
  1257. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  1258. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1259. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  1260. };
  1261. PSECURITY_DESCRIPTOR WkstaSecurityObject;
  1262. return RtlCreateUserSecurityObject(
  1263. AceData,
  1264. 4,
  1265. LocalSystemSid,
  1266. LocalSystemSid,
  1267. FALSE,
  1268. &WsConfigInfoMapping,
  1269. &WkstaSecurityObject
  1270. );
  1271. Arguments:
  1272. AceData - Supplies the structure of information that describes the DACL.
  1273. AceCount - Supplies the number of entries in AceData structure.
  1274. OwnerSid - Supplies the pointer to the SID of the security descriptor
  1275. owner.
  1276. GroupSid - Supplies the pointer to the SID of the security descriptor
  1277. primary group.
  1278. IsDirectoryObject - Supplies the flag which indicates whether the
  1279. user-mode object is a directory object.
  1280. GenericMapping - Supplies the pointer to a generic mapping array denoting
  1281. the mapping between each generic right to specific rights.
  1282. NewDescriptor - Returns a pointer to the self-relative security descriptor
  1283. which represents the user-mode object.
  1284. Return Value:
  1285. STATUS_SUCCESS - if successful
  1286. STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
  1287. security descriptor.
  1288. Any other status codes returned from the security Rtl routines.
  1289. NOTE : the user security object created by calling this function may be
  1290. freed up by calling RtlDeleteSecurityObject().
  1291. --*/
  1292. {
  1293. NTSTATUS ntstatus;
  1294. PSECURITY_DESCRIPTOR AbsoluteSd;
  1295. HANDLE TokenHandle;
  1296. PVOID HeapHandle = RtlProcessHeap();
  1297. ntstatus = RtlCreateAndSetSD(
  1298. AceData,
  1299. AceCount,
  1300. OwnerSid,
  1301. GroupSid,
  1302. &AbsoluteSd
  1303. );
  1304. if (! NT_SUCCESS(ntstatus)) {
  1305. return ntstatus;
  1306. }
  1307. ntstatus = NtOpenProcessToken(
  1308. NtCurrentProcess(),
  1309. TOKEN_QUERY,
  1310. &TokenHandle
  1311. );
  1312. if (! NT_SUCCESS(ntstatus)) {
  1313. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1314. return ntstatus;
  1315. }
  1316. //
  1317. // Create the security object (a user-mode object is really a pseudo-
  1318. // object represented by a security descriptor that have relative
  1319. // pointers to SIDs and ACLs). This routine allocates the memory to
  1320. // hold the relative security descriptor so the memory allocated for the
  1321. // DACL, ACEs, and the absolute descriptor can be freed.
  1322. //
  1323. ntstatus = RtlNewSecurityObject(
  1324. NULL, // Parent descriptor
  1325. AbsoluteSd, // Creator descriptor
  1326. NewDescriptor, // Pointer to new descriptor
  1327. IsDirectoryObject, // Is directory object
  1328. TokenHandle, // Token
  1329. GenericMapping // Generic mapping
  1330. );
  1331. (void) NtClose(TokenHandle);
  1332. //
  1333. // Free dynamic memory before returning
  1334. //
  1335. (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
  1336. return ntstatus;
  1337. }
  1338. NTSTATUS
  1339. RtlConvertToAutoInheritSecurityObject(
  1340. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  1341. IN PSECURITY_DESCRIPTOR CurrentSecurityDescriptor,
  1342. OUT PSECURITY_DESCRIPTOR *NewSecurityDescriptor,
  1343. IN GUID *ObjectType OPTIONAL,
  1344. IN BOOLEAN IsDirectoryObject,
  1345. IN PGENERIC_MAPPING GenericMapping
  1346. )
  1347. /*++
  1348. Routine Description:
  1349. This is a converts a security descriptor whose ACLs are not marked
  1350. as AutoInherit to a security descriptor whose ACLs are marked as
  1351. AutoInherit.
  1352. See further detailed description on ConvertToAutoInheritPrivateObjectSecurity.
  1353. Arguments:
  1354. ParentDescriptor - Supplies the Security Descriptor for the parent
  1355. directory under which a object exists. If there is
  1356. no parent directory, then this argument is specified as NULL.
  1357. CurrentSecurityDescriptor - Supplies a pointer to the objects security descriptor
  1358. that is going to be altered by this procedure.
  1359. NewSecurityDescriptor Points to a pointer that is to be made to point to the
  1360. newly allocated self-relative security descriptor. When no
  1361. longer needed, this descriptor must be freed using
  1362. DestroyPrivateObjectSecurity().
  1363. ObjectType - GUID of the object type being created. If the object being
  1364. created has no GUID associated with it, then this argument is
  1365. specified as NULL.
  1366. IsDirectoryObject - Specifies if the object is a
  1367. directory object. A value of TRUE indicates the object is a
  1368. container of other objects.
  1369. GenericMapping - Supplies a pointer to a generic mapping array denoting
  1370. the mapping between each generic right to specific rights.
  1371. Return Value:
  1372. STATUS_SUCCESS - The operation was successful.
  1373. STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that
  1374. is unknown to this routine. (Only revision 2 ACLs are support by this routine.)
  1375. STATUS_INVALID_ACL - The structure of one of the ACLs in invalid.
  1376. --*/
  1377. {
  1378. //
  1379. // Simply call the corresponding Rtlp routine telling it which allocator
  1380. // to use.
  1381. //
  1382. return RtlpConvertToAutoInheritSecurityObject(
  1383. ParentDescriptor,
  1384. CurrentSecurityDescriptor,
  1385. NewSecurityDescriptor,
  1386. ObjectType,
  1387. IsDirectoryObject,
  1388. GenericMapping );
  1389. }
  1390. NTSTATUS
  1391. RtlDefaultNpAcl(
  1392. OUT PACL * pAcl
  1393. )
  1394. /*++
  1395. Routine Description:
  1396. This routine constructs a default ACL to be applied to
  1397. named pipe objects when the caller has not specified one.
  1398. See NT bug 131090.
  1399. The ACL constructed is as follows:
  1400. Need to build an ACL that looks like the following:
  1401. Local System : F
  1402. Administrators: F
  1403. Owner: F
  1404. Everyone: R
  1405. Anonymous: R
  1406. The owner is determined by querying the currently effective
  1407. token and extracting the default owner.
  1408. Arguments:
  1409. pAcl - Receives a pointer to an ACL to apply to the named pipe
  1410. being created. Guaranteed to be NULL on return if an error
  1411. occurs.
  1412. This must be freed by calling RtlFreeHeap.
  1413. Return Value:
  1414. NT Status.
  1415. --*/
  1416. {
  1417. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1418. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1419. ULONG AclSize = 0;
  1420. NTSTATUS Status = STATUS_SUCCESS;
  1421. ULONG ReturnLength = 0;
  1422. PTOKEN_OWNER OwnerSid = NULL;
  1423. HANDLE hToken;
  1424. //
  1425. // Initialize OUT parameters
  1426. //
  1427. *pAcl = NULL;
  1428. //
  1429. // Open thread token
  1430. //
  1431. Status = NtOpenThreadToken(
  1432. NtCurrentThread(),
  1433. TOKEN_QUERY,
  1434. TRUE,
  1435. &hToken
  1436. );
  1437. if (STATUS_NO_TOKEN == Status) {
  1438. //
  1439. // Not impersonating, get process token
  1440. //
  1441. Status = NtOpenProcessToken(
  1442. NtCurrentProcess(),
  1443. TOKEN_QUERY,
  1444. &hToken
  1445. );
  1446. }
  1447. if (NT_SUCCESS( Status )) {
  1448. //
  1449. // Get the default owner
  1450. //
  1451. Status = NtQueryInformationToken (
  1452. hToken,
  1453. TokenOwner,
  1454. NULL,
  1455. 0,
  1456. &ReturnLength
  1457. );
  1458. if (STATUS_BUFFER_TOO_SMALL == Status) {
  1459. OwnerSid = (PTOKEN_OWNER)RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
  1460. if (OwnerSid) {
  1461. Status = NtQueryInformationToken (
  1462. hToken,
  1463. TokenOwner,
  1464. OwnerSid,
  1465. ReturnLength,
  1466. &ReturnLength
  1467. );
  1468. if (NT_SUCCESS( Status )) {
  1469. //
  1470. // Compute the size needed
  1471. //
  1472. UCHAR SidBuffer[16];
  1473. ASSERT( 16 == RtlLengthRequiredSid( 2 ));
  1474. AclSize += RtlLengthRequiredSid( 1 ); // LocalSystem Sid
  1475. AclSize += RtlLengthRequiredSid( 2 ); // Administrators
  1476. AclSize += RtlLengthRequiredSid( 1 ); // Everyone (World)
  1477. AclSize += RtlLengthRequiredSid( 1 ); // Anonymous Logon Sid
  1478. AclSize += RtlLengthSid( OwnerSid->Owner ); // Owner
  1479. AclSize += sizeof( ACL ); // Header
  1480. AclSize += 5 * (sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ));
  1481. //
  1482. // Allocate the Acl out of the local process heap
  1483. //
  1484. *pAcl = (PACL)RtlAllocateHeap( RtlProcessHeap(), 0, AclSize );
  1485. if (*pAcl != NULL) {
  1486. RtlCreateAcl( *pAcl, AclSize, ACL_REVISION );
  1487. //
  1488. // Create each SID in turn and copy the resultant ACE into
  1489. // the new ACL
  1490. //
  1491. //
  1492. // Local System - Generic All
  1493. //
  1494. RtlInitializeSid( SidBuffer, &NtAuthority, 1);
  1495. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  1496. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
  1497. //
  1498. // Admins - Generic All
  1499. //
  1500. RtlInitializeSid( SidBuffer, &NtAuthority, 2);
  1501. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  1502. *(RtlSubAuthoritySid( SidBuffer, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
  1503. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
  1504. //
  1505. // Owner - Generic All
  1506. //
  1507. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, OwnerSid->Owner );
  1508. //
  1509. // World - Generic Read
  1510. //
  1511. RtlInitializeSid( SidBuffer, &WorldSidAuthority, 1 );
  1512. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_WORLD_RID;
  1513. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_READ, (PSID)SidBuffer );
  1514. //
  1515. // Anonymous Logon - Generic Read
  1516. //
  1517. RtlInitializeSid( SidBuffer, &NtAuthority, 1);
  1518. *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_ANONYMOUS_LOGON_RID;
  1519. RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_READ, (PSID)SidBuffer );
  1520. } else {
  1521. Status = STATUS_NO_MEMORY;
  1522. }
  1523. }
  1524. RtlFreeHeap( RtlProcessHeap(), 0, OwnerSid );
  1525. } else {
  1526. Status = STATUS_NO_MEMORY;
  1527. }
  1528. }
  1529. NtClose( hToken );
  1530. }
  1531. if (!NT_SUCCESS( Status )) {
  1532. //
  1533. // Something failed, clean up OUT
  1534. // parameters.
  1535. //
  1536. if (*pAcl != NULL) {
  1537. RtlFreeHeap( RtlProcessHeap(), 0, *pAcl );
  1538. *pAcl = NULL;
  1539. }
  1540. }
  1541. return( Status );
  1542. }