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.

1433 lines
37 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. eztrust.c
  5. Abstract:
  6. This file contains routines to support the Easy Trust creation DCR.
  7. Author:
  8. Colin Brace (ColinBr) May 19, 2001
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <lsapch2.h>
  14. #include "dbp.h"
  15. #include <permit.h>
  16. //
  17. // Forwards
  18. //
  19. NTSTATUS
  20. LsapGetDelegatedTDOQuotas(
  21. OUT ULONG *PerUserQuota OPTIONAL,
  22. OUT ULONG *GlobalQuota OPTIONAL,
  23. OUT ULONG *PerUserDeletedQuota OPTIONAL
  24. );
  25. //
  26. // This flags indicates to only search for deleted TDO's with
  27. // the mdds-CreatorSid attribute equal to CreatorSid
  28. //
  29. #define LSAP_GET_DELEGATED_TDO_DELETED_ONLY 0x00000001
  30. NTSTATUS
  31. LsapGetDelegatedTDOCount(
  32. IN ULONG Flags,
  33. IN PSID CreatorSid OPTIONAL,
  34. OUT ULONG *Count
  35. );
  36. //
  37. // Definitions
  38. //
  39. NTSTATUS
  40. LsapGetCurrentOwnerAndPrimaryGroup(
  41. OUT PTOKEN_OWNER * Owner,
  42. OUT PTOKEN_PRIMARY_GROUP * PrimaryGroup OPTIONAL
  43. )
  44. /*++
  45. Routine Description
  46. This routine Impersonates the Client and obtains the owner and
  47. its primary group from the Token
  48. Parameters:
  49. Owner -- The Owner sid is returned in here
  50. PrimaryGroup The User's Primary Group is returned in here
  51. Return Values:
  52. STATUS_SUCCESS
  53. STATUS_INSUFFICIENT_RESOURCES
  54. --*/
  55. {
  56. HANDLE ClientToken = INVALID_HANDLE_VALUE;
  57. BOOLEAN fImpersonating = FALSE;
  58. ULONG RequiredLength=0;
  59. NTSTATUS NtStatus = STATUS_SUCCESS;
  60. BOOLEAN ImpersonatingNullSession = FALSE;
  61. //
  62. // Initialize Return Values
  63. //
  64. *Owner = NULL;
  65. if (PrimaryGroup) {
  66. *PrimaryGroup = NULL;
  67. }
  68. //
  69. // Impersonate the Client
  70. //
  71. NtStatus = I_RpcMapWin32Status(RpcImpersonateClient(0));
  72. if (!NT_SUCCESS(NtStatus))
  73. goto Error;
  74. fImpersonating = TRUE;
  75. //
  76. // Grab the User's Sid
  77. //
  78. NtStatus = NtOpenThreadToken(
  79. NtCurrentThread(),
  80. TOKEN_QUERY,
  81. TRUE, //OpenAsSelf
  82. &ClientToken
  83. );
  84. if (!NT_SUCCESS(NtStatus))
  85. goto Error;
  86. //
  87. // Query the Client Token For User's SID
  88. //
  89. NtStatus = NtQueryInformationToken(
  90. ClientToken,
  91. TokenOwner,
  92. NULL,
  93. 0,
  94. &RequiredLength
  95. );
  96. if ((STATUS_BUFFER_TOO_SMALL == NtStatus) && ( RequiredLength > 0))
  97. {
  98. //
  99. // Alloc Memory
  100. //
  101. *Owner = LsapAllocateLsaHeap(RequiredLength);
  102. if (NULL==*Owner)
  103. {
  104. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  105. goto Error;
  106. }
  107. //
  108. // Query the Token
  109. //
  110. NtStatus = NtQueryInformationToken(
  111. ClientToken,
  112. TokenOwner,
  113. *Owner,
  114. RequiredLength,
  115. &RequiredLength
  116. );
  117. }
  118. if (!NT_SUCCESS(NtStatus))
  119. {
  120. goto Error;
  121. }
  122. //
  123. // Query the Client Token For User's PrimaryGroup
  124. //
  125. if (PrimaryGroup) {
  126. RequiredLength = 0;
  127. NtStatus = NtQueryInformationToken(
  128. ClientToken,
  129. TokenPrimaryGroup,
  130. NULL,
  131. 0,
  132. &RequiredLength
  133. );
  134. if ((STATUS_BUFFER_TOO_SMALL == NtStatus) && ( RequiredLength > 0))
  135. {
  136. //
  137. // Alloc Memory
  138. //
  139. *PrimaryGroup = LsapAllocateLsaHeap(RequiredLength);
  140. if (NULL==*PrimaryGroup)
  141. {
  142. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  143. goto Error;
  144. }
  145. //
  146. // Query the Token
  147. //
  148. NtStatus = NtQueryInformationToken(
  149. ClientToken,
  150. TokenPrimaryGroup,
  151. *PrimaryGroup,
  152. RequiredLength,
  153. &RequiredLength
  154. );
  155. }
  156. if (!NT_SUCCESS(NtStatus))
  157. {
  158. goto Error;
  159. }
  160. }
  161. Error:
  162. //
  163. // Clean up on Error
  164. //
  165. if (!NT_SUCCESS(NtStatus))
  166. {
  167. if (*Owner)
  168. {
  169. LsapFreeLsaHeap(*Owner);
  170. *Owner = NULL;
  171. }
  172. if (PrimaryGroup && *PrimaryGroup)
  173. {
  174. LsapFreeLsaHeap(*PrimaryGroup);
  175. *PrimaryGroup = NULL;
  176. }
  177. }
  178. if (fImpersonating)
  179. I_RpcMapWin32Status(RpcRevertToSelf());
  180. if (INVALID_HANDLE_VALUE!=ClientToken)
  181. NtClose(ClientToken);
  182. return NtStatus;
  183. }
  184. NTSTATUS
  185. LsapIsAccessControlGranted(
  186. IN DSNAME* DsObject,
  187. IN ULONG ClassId,
  188. IN GUID* ControlAccessRight,
  189. IN LSAP_DB_OBJECT_TYPE_ID ObjectTypeId
  190. )
  191. /*++
  192. Routine Description:
  193. This routine checks if the network client has ControlAccessRight
  194. on the DsObject for the class ClassId.
  195. Arguments:
  196. DsObject -- an object in DS whose security descriptor will be used
  197. for the access check.
  198. ClassId -- which class of DsObject the ControlAccessRight should be
  199. checked agaist.
  200. ControlAccessRight -- a GUID
  201. ObjectTypeId -- the LSA object for which this access check applies (not
  202. necessarily the same type of object as DsObject).
  203. Return Values:
  204. STATUS_SUCCESS,
  205. STATUS_ACCESS_DENIED,
  206. STATUS_NO_SECURITY_ON_OBJECT (if DsObject doesn't have a security
  207. descriptor)
  208. resource error otherwise.
  209. --*/
  210. {
  211. NTSTATUS NtStatus = STATUS_SUCCESS;
  212. NTSTATUS SecondaryStatus = STATUS_SUCCESS;
  213. OBJECT_TYPE_LIST ObjList[2];
  214. DWORD Results[2];
  215. DWORD GrantedAccess[2];
  216. PSECURITY_DESCRIPTOR pSD = NULL;
  217. GENERIC_MAPPING GenericMapping = DS_GENERIC_MAPPING;
  218. ACCESS_MASK DesiredAccess;
  219. GUID ClassGuid;
  220. ULONG ClassGuidLength = sizeof(GUID);
  221. BOOLEAN bTemp = FALSE;
  222. UNICODE_STRING ObjectName;
  223. ASSERT(DsObject && DsObject->NameLen > 0);
  224. //
  225. // Setup the object name
  226. //
  227. ObjectName.Length = ObjectName.MaximumLength = (USHORT)(DsObject->NameLen * sizeof(WCHAR));
  228. ObjectName.Buffer = DsObject->StringName;
  229. //
  230. // Obtain the security descriptor
  231. //
  232. NtStatus = LsapDsReadObjectSDByDsName(DsObject,
  233. &pSD);
  234. if (!NT_SUCCESS(NtStatus)) {
  235. goto IsAccessControlGrantedError;
  236. }
  237. //
  238. // Get the Class GUID of the object
  239. //
  240. NtStatus = SampGetClassAttribute(ClassId,
  241. ATT_SCHEMA_ID_GUID,
  242. &ClassGuidLength,
  243. &ClassGuid);
  244. if (!NT_SUCCESS(NtStatus)) {
  245. goto IsAccessControlGrantedError;
  246. }
  247. //
  248. // Setup Object List
  249. //
  250. ObjList[0].Level = ACCESS_OBJECT_GUID;
  251. ObjList[0].Sbz = 0;
  252. ObjList[0].ObjectType = &ClassGuid;
  253. //
  254. // Every control access guid is considered to be in it's own property
  255. // set. To achieve this, we treat control access guids as property set
  256. // guids.
  257. //
  258. ObjList[1].Level = ACCESS_PROPERTY_SET_GUID;
  259. ObjList[1].Sbz = 0;
  260. ObjList[1].ObjectType = ControlAccessRight;
  261. //
  262. // Assume full access
  263. //
  264. Results[0] = 0;
  265. Results[1] = 0;
  266. //
  267. // Impersonate the client
  268. //
  269. NtStatus = I_RpcMapWin32Status(RpcImpersonateClient(0));
  270. if (!NT_SUCCESS(NtStatus)) {
  271. goto IsAccessControlGrantedError;
  272. }
  273. //
  274. // Set the desired access
  275. //
  276. DesiredAccess = RIGHT_DS_CONTROL_ACCESS;
  277. //
  278. // Map the desired access to contain no
  279. // generic accesses.
  280. //
  281. MapGenericMask(&DesiredAccess, &GenericMapping);
  282. NtStatus = NtAccessCheckByTypeResultListAndAuditAlarm(
  283. &LsapState.SubsystemName, // SubSystemName
  284. NULL, // HandleId or NULL
  285. &LsapDbObjectTypeNames[ObjectTypeId], // ObjectTypeName
  286. &ObjectName, // ObjectName
  287. pSD, // Domain NC head's SD
  288. NULL, // Self SID
  289. DesiredAccess, // Desired Access
  290. AuditEventDirectoryServiceAccess, // Audit Type
  291. 0, // Flags
  292. ObjList, // Object Type List
  293. 2, // Object Type List Length
  294. &GenericMapping, // Generic Mapping
  295. FALSE, // Object Creation
  296. GrantedAccess, // Granted Status
  297. Results, // Access Status
  298. &bTemp); // Generate On Close
  299. //
  300. // Stop impersonating the client
  301. //
  302. SecondaryStatus = I_RpcMapWin32Status(RpcRevertToSelf());
  303. if (NT_SUCCESS(NtStatus)) {
  304. NtStatus = SecondaryStatus;
  305. }
  306. if (NT_SUCCESS(NtStatus)) {
  307. //
  308. // Ok, we checked access, Now, access is granted if either
  309. // we were granted access on the entire object (i.e. Results[0]
  310. // is NULL ) or we were granted explicit rights on the access
  311. // guid (i.e. Results[1] is NULL).
  312. //
  313. if ( Results[0] && Results[1] ) {
  314. NtStatus = STATUS_ACCESS_DENIED;
  315. }
  316. }
  317. IsAccessControlGrantedError:
  318. if (pSD) {
  319. LsapFreeLsaHeap(pSD);
  320. }
  321. return NtStatus;
  322. }
  323. NTSTATUS
  324. LsapMakeNewSelfRelativeSecurityDescriptor(
  325. IN PSID Owner,
  326. IN PSID Group,
  327. IN PACL Dacl,
  328. IN PACL Sacl,
  329. OUT PULONG SecurityDescriptorLength,
  330. OUT PSECURITY_DESCRIPTOR * SecurityDescriptor
  331. )
  332. /*++
  333. Routine Description:
  334. Given the 4 components of a security descriptor this routine makes a new
  335. self relative Security descriptor.
  336. Parameters:
  337. Owner -- The Sid of the owner
  338. Group -- The Sid of the group
  339. Dacl -- The Dacl to Use
  340. Sacl -- The Sacl to Use
  341. Return Values:
  342. STATUS_SUCCESS
  343. STATUS_INSUFFICIENT_RESOURCES
  344. STATUS_UNSUCCESSFUL
  345. --*/
  346. {
  347. SECURITY_DESCRIPTOR SdAbsolute;
  348. NTSTATUS NtStatus = STATUS_SUCCESS;
  349. *SecurityDescriptorLength = 0;
  350. *SecurityDescriptor = NULL;
  351. if (!InitializeSecurityDescriptor(&SdAbsolute,SECURITY_DESCRIPTOR_REVISION))
  352. {
  353. NtStatus = STATUS_UNSUCCESSFUL;
  354. goto Error;
  355. }
  356. //
  357. // Set the owner, default the owner to administrators alias
  358. //
  359. if (NULL!=Owner)
  360. {
  361. if (!SetSecurityDescriptorOwner(&SdAbsolute,Owner,FALSE))
  362. {
  363. NtStatus = STATUS_UNSUCCESSFUL;
  364. goto Error;
  365. }
  366. }
  367. if (NULL!=Group)
  368. {
  369. if (!SetSecurityDescriptorGroup(&SdAbsolute,Group,FALSE))
  370. {
  371. NtStatus = STATUS_UNSUCCESSFUL;
  372. goto Error;
  373. }
  374. }
  375. //
  376. // Set the Dacl if there is one
  377. //
  378. if (NULL!=Dacl)
  379. {
  380. if (!SetSecurityDescriptorDacl(&SdAbsolute,TRUE,Dacl,FALSE))
  381. {
  382. NtStatus = STATUS_UNSUCCESSFUL;
  383. goto Error;
  384. }
  385. }
  386. //
  387. // Set the Sacl if there is one
  388. //
  389. if (NULL!=Sacl)
  390. {
  391. if (!SetSecurityDescriptorSacl(&SdAbsolute,TRUE,Sacl,FALSE))
  392. {
  393. NtStatus = STATUS_UNSUCCESSFUL;
  394. goto Error;
  395. }
  396. }
  397. //
  398. // Make a new security Descriptor
  399. //
  400. *SecurityDescriptorLength = GetSecurityDescriptorLength(&SdAbsolute);
  401. *SecurityDescriptor = LsapAllocateLsaHeap(*SecurityDescriptorLength);
  402. if (NULL==*SecurityDescriptor)
  403. {
  404. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  405. goto Error;
  406. }
  407. if (!MakeSelfRelativeSD(&SdAbsolute,*SecurityDescriptor,SecurityDescriptorLength))
  408. {
  409. NtStatus = STATUS_UNSUCCESSFUL;
  410. if (*SecurityDescriptor)
  411. {
  412. LsapFreeLsaHeap(*SecurityDescriptor);
  413. *SecurityDescriptor = NULL;
  414. }
  415. }
  416. Error:
  417. return NtStatus;
  418. }
  419. //
  420. // The per user trust quota
  421. //
  422. #define LSAP_CHECK_TDO_QUOTA_USER 0x00000001
  423. //
  424. // The all users trust quota
  425. //
  426. #define LSAP_CHECK_TDO_QUOTA_GLOBAL 0x00000002
  427. //
  428. // The per user tombstone deletion check
  429. //
  430. #define LSAP_CHECK_TDO_QUOTA_USER_DELETED 0x00000004
  431. NTSTATUS
  432. LsapCheckDelegatedTDOQuotas(
  433. IN PSID ClientSid OPTIONAL,
  434. IN ULONG Flags
  435. )
  436. /*++
  437. Routine Description:
  438. This routine verifies the three quota relating to delegated trust
  439. creation and deletion.
  440. Arguments:
  441. ClientSid -- the SID to check against
  442. Flags -- see defn's above functions
  443. Return Values:
  444. STATUS_SUCCESS, a resource error otherwise
  445. --*/
  446. {
  447. NTSTATUS NtStatus = STATUS_SUCCESS;
  448. ULONG GlobalQuota = 0, PerUserQuota = 0, DeletedQuota = 0;
  449. ULONG GlobalCount = 0, UserCount = 0, DeletedCount = 0;
  450. PTOKEN_OWNER TokenOwnerInformation = NULL;
  451. PSID CreatorSid;
  452. //
  453. // Get the SID of the user
  454. //
  455. if (NULL == ClientSid) {
  456. NtStatus = LsapGetCurrentOwnerAndPrimaryGroup(&TokenOwnerInformation,
  457. NULL);
  458. if (!NT_SUCCESS(NtStatus)) {
  459. goto CheckDelegatedTDOCreationQuotasExit;
  460. }
  461. CreatorSid = TokenOwnerInformation->Owner;
  462. } else {
  463. CreatorSid = ClientSid;
  464. }
  465. //
  466. // Get the domain wide quota settings
  467. //
  468. NtStatus = LsapGetDelegatedTDOQuotas(&PerUserQuota,
  469. &GlobalQuota,
  470. &DeletedQuota);
  471. if (!NT_SUCCESS(NtStatus)) {
  472. goto CheckDelegatedTDOCreationQuotasExit;
  473. }
  474. //
  475. // Do the checks
  476. //
  477. if (Flags & LSAP_CHECK_TDO_QUOTA_USER) {
  478. NtStatus = LsapGetDelegatedTDOCount(0, // no flags
  479. CreatorSid,
  480. &UserCount);
  481. if ( NT_SUCCESS(NtStatus)
  482. && (UserCount >= PerUserQuota) ) {
  483. NtStatus = STATUS_PER_USER_TRUST_QUOTA_EXCEEDED;
  484. }
  485. if (!NT_SUCCESS(NtStatus)) {
  486. goto CheckDelegatedTDOCreationQuotasExit;
  487. }
  488. }
  489. if (Flags & LSAP_CHECK_TDO_QUOTA_GLOBAL) {
  490. NtStatus = LsapGetDelegatedTDOCount(0, // no flags
  491. NULL, // all delegated TDO's
  492. &GlobalCount);
  493. if ( NT_SUCCESS(NtStatus)
  494. && (GlobalCount >= GlobalQuota) ) {
  495. NtStatus = STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED;
  496. }
  497. if (!NT_SUCCESS(NtStatus)) {
  498. goto CheckDelegatedTDOCreationQuotasExit;
  499. }
  500. }
  501. if (Flags & LSAP_CHECK_TDO_QUOTA_USER_DELETED) {
  502. NtStatus = LsapGetDelegatedTDOCount(LSAP_GET_DELEGATED_TDO_DELETED_ONLY,
  503. CreatorSid,
  504. &DeletedCount);
  505. if ( NT_SUCCESS(NtStatus)
  506. && (DeletedCount >= DeletedQuota) ) {
  507. NtStatus = STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED;
  508. }
  509. if (!NT_SUCCESS(NtStatus)) {
  510. goto CheckDelegatedTDOCreationQuotasExit;
  511. }
  512. }
  513. CheckDelegatedTDOCreationQuotasExit:
  514. if (TokenOwnerInformation) {
  515. LsapFreeLsaHeap( TokenOwnerInformation );
  516. }
  517. return NtStatus;
  518. }
  519. NTSTATUS
  520. LsapCheckTDOCreationByControlAccess(
  521. IN PLSAP_DB_OBJECT_INFORMATION ObjectInformation,
  522. IN PLSAP_DB_ATTRIBUTE Attributes,
  523. IN ULONG AttributeCount
  524. )
  525. /*++
  526. Routine Description:
  527. This routine determines if the caller has access to create a trusted
  528. domain object by "right", as opposed to the standard DS access check
  529. model which is assumed to have failed at this point.
  530. The determination is made by the following rules:
  531. 1) If the trust is an inbound-only forest trust and
  532. 2) If the caller has the "right to create an inbound trust" on the
  533. domain object and
  534. 3) the user's quota for trust object creations hasn't been exceeded and
  535. 4) the global quota for trust object creations, created in this manner,
  536. hasn't been exceeded
  537. Then return STATUS_SUCCESS.
  538. Else, return a processing error, or STATUS_ACCESS_DENIED.
  539. Arguments:
  540. ObjectInformation -- information about the trust being created (the name,
  541. etc)
  542. Attributes -- the requested attributes of the trust (inbound, forest, etc)
  543. AttributeCount -- the number of attributes
  544. Return Values:
  545. NTSTATUS, see routine description.
  546. --*/
  547. {
  548. NTSTATUS Status = STATUS_SUCCESS;
  549. ULONG i;
  550. BOOLEAN ForestTrust = FALSE;
  551. BOOLEAN InboundOnlyTrust = FALSE;
  552. //
  553. // Is this an inbound only forest trust?
  554. //
  555. for (i = 0; i < AttributeCount; i++) {
  556. ULONG BitMask;
  557. if (Attributes[i].DbNameIndex == TrDmTrLA) {
  558. ASSERT(Attributes[i].AttribType == LsapDbAttribULong);
  559. BitMask = *((ULONG*)Attributes[i].AttributeValue);
  560. if (BitMask & TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
  561. ForestTrust = TRUE;
  562. }
  563. }
  564. if (Attributes[i].DbNameIndex == TrDmTrDi) {
  565. ASSERT(Attributes[i].AttribType == LsapDbAttribULong);
  566. BitMask = *((ULONG*)Attributes[i].AttributeValue);
  567. if ( (BitMask & TRUST_DIRECTION_INBOUND)
  568. && ((BitMask & TRUST_DIRECTION_OUTBOUND) == 0) ) {
  569. InboundOnlyTrust = TRUE;
  570. }
  571. }
  572. }
  573. if (!(ForestTrust && InboundOnlyTrust)) {
  574. Status = STATUS_ACCESS_DENIED;
  575. goto CheckTDOCreationByControlAccessError;
  576. }
  577. //
  578. // Does the caller have the control access right?
  579. //
  580. Status = LsapIsAccessControlGranted(LsaDsStateInfo.DsRoot,
  581. CLASS_DOMAIN_DNS,
  582. &LsapDsGuidList[LsapDsGuidDelegatedTrustCreation],
  583. ObjectInformation->ObjectTypeId
  584. );
  585. if (!NT_SUCCESS(Status)) {
  586. goto CheckTDOCreationByControlAccessError;
  587. }
  588. //
  589. // Are the quota restrictions satisfied?
  590. //
  591. Status = LsapCheckDelegatedTDOQuotas(NULL, // we don't have the client sid
  592. LSAP_CHECK_TDO_QUOTA_GLOBAL |
  593. LSAP_CHECK_TDO_QUOTA_USER);
  594. if (!NT_SUCCESS(Status)) {
  595. goto CheckTDOCreationByControlAccessError;
  596. }
  597. CheckTDOCreationByControlAccessError:
  598. return Status;
  599. }
  600. NTSTATUS
  601. LsapUpdateTDOAttributesForCreation(
  602. IN PUNICODE_STRING ObjectName,
  603. IN PLSAP_DB_ATTRIBUTE Attributes,
  604. IN OUT ULONG* AttributeCount,
  605. IN ULONG AttributesAllocated
  606. )
  607. /*++
  608. Routine Description:
  609. This routine adds the necessary attributes to a trusted domain object
  610. that is created by the control access right (aka easy trust).
  611. Specifically, it adds the DS-Creator-Sid (as the network caller) and
  612. gives the network caller access to write to the incoming auth blob.
  613. Arguments:
  614. ObjectName -- the name of the trust object in the DS
  615. Attributes -- the list of statically declared attributes to be set
  616. on the trust object.
  617. AttributeCount -- in, the number of attributes; out, the updated count
  618. AttributesAllocated -- the total number of attributes allocated, but
  619. not necessarily used.
  620. Return Values:
  621. STATUS_SUCCESS, a resource error otherwise
  622. --*/
  623. {
  624. NTSTATUS NtStatus = STATUS_SUCCESS;
  625. PLSAP_DB_ATTRIBUTE NextAttribute;
  626. PTOKEN_OWNER TokenOwnerInformation = NULL;
  627. DSNAME *DsName = NULL;
  628. PSECURITY_DESCRIPTOR pSD = NULL, pNewSD = NULL, pNewSDForAttr = NULL;
  629. ULONG cbNewSD = 0;
  630. ULONG Size;
  631. PSID CreatorSid = 0;
  632. PPOLICY_DNS_DOMAIN_INFO LocalDnsDomainInfo = NULL;
  633. BOOL fSuccess;
  634. ULONG DomainAdminsSidBuffer[SECURITY_MAX_SID_SIZE/sizeof( ULONG ) + 1 ];
  635. PSID DomainAdminsSid = (PSID) DomainAdminsSidBuffer;
  636. ASSERT(((*AttributeCount + 2) <= AttributesAllocated)
  637. && "Must preallocate more attributes for trusted domain creation");
  638. //
  639. // Generate the Domain Admin's SID to use as the security descriptor
  640. // owner.
  641. //
  642. NtStatus = LsaIQueryInformationPolicyTrusted(PolicyDnsDomainInformation,
  643. (PLSAPR_POLICY_INFORMATION *) &LocalDnsDomainInfo);
  644. if (!NT_SUCCESS(NtStatus)) {
  645. goto UpdateTdoAttributesForCreationExit;
  646. }
  647. Size = sizeof(DomainAdminsSidBuffer);
  648. fSuccess = CreateWellKnownSid(WinAccountDomainAdminsSid,
  649. LocalDnsDomainInfo->Sid,
  650. DomainAdminsSid,
  651. &Size);
  652. if (!fSuccess) {
  653. NtStatus = STATUS_NO_MEMORY;
  654. goto UpdateTdoAttributesForCreationExit;
  655. }
  656. //
  657. // Init the start of the new attributes
  658. //
  659. NextAttribute = &Attributes[(*AttributeCount)];
  660. //
  661. // Get the SID of the creator
  662. //
  663. NtStatus = LsapGetCurrentOwnerAndPrimaryGroup(&TokenOwnerInformation,
  664. NULL);
  665. if (!NT_SUCCESS(NtStatus)) {
  666. goto UpdateTdoAttributesForCreationExit;
  667. }
  668. Size = RtlLengthSid(TokenOwnerInformation->Owner);
  669. CreatorSid = midl_user_allocate(Size);
  670. if (NULL == CreatorSid) {
  671. NtStatus = STATUS_NO_MEMORY;
  672. goto UpdateTdoAttributesForCreationExit;
  673. }
  674. RtlCopySid(Size, CreatorSid, TokenOwnerInformation->Owner);
  675. //
  676. // Add the creator sid
  677. //
  678. LsapDbInitializeAttributeDs(
  679. NextAttribute,
  680. TrDmCrSid,
  681. CreatorSid,
  682. RtlLengthSid(CreatorSid),
  683. TRUE // to be freed
  684. );
  685. NextAttribute++;
  686. (*AttributeCount)++;
  687. CreatorSid = NULL;
  688. //
  689. // Generate the new security descriptor
  690. //
  691. //
  692. // Build the DSName
  693. //
  694. NtStatus = LsapAllocAndInitializeDsNameFromUnicode(
  695. ObjectName,
  696. &DsName);
  697. if (NT_SUCCESS(NtStatus)) {
  698. NtStatus = LsapDsReadObjectSDByDsName(DsName,
  699. &pSD);
  700. if (NT_SUCCESS(NtStatus)) {
  701. //
  702. // Set the owner to Administrators
  703. //
  704. NtStatus = LsapMakeNewSelfRelativeSecurityDescriptor(
  705. DomainAdminsSid,
  706. DomainAdminsSid,
  707. LsapGetDacl(pSD),
  708. LsapGetSacl(pSD),
  709. &cbNewSD,
  710. &pNewSD
  711. );
  712. }
  713. }
  714. if (!NT_SUCCESS(NtStatus)) {
  715. goto UpdateTdoAttributesForCreationExit;
  716. }
  717. //
  718. // Need to realloc
  719. //
  720. pNewSDForAttr = midl_user_allocate(cbNewSD);
  721. if (NULL == pNewSDForAttr) {
  722. NtStatus = STATUS_NO_MEMORY;
  723. goto UpdateTdoAttributesForCreationExit;
  724. }
  725. RtlCopyMemory(pNewSDForAttr, pNewSD, cbNewSD);
  726. //
  727. // Add the new security descriptor
  728. //
  729. LsapDbInitializeAttributeDs(
  730. NextAttribute,
  731. SecDesc,
  732. pNewSDForAttr,
  733. cbNewSD,
  734. TRUE // to be freed
  735. );
  736. pNewSDForAttr = NULL;
  737. NextAttribute++;
  738. (*AttributeCount)++;
  739. //
  740. // Done
  741. //
  742. UpdateTdoAttributesForCreationExit:
  743. //
  744. // We shouldn't have added more attributes that are allocated
  745. //
  746. ASSERT((*AttributeCount) <= AttributesAllocated);
  747. if (TokenOwnerInformation) {
  748. LsapFreeLsaHeap( TokenOwnerInformation );
  749. }
  750. if (LocalDnsDomainInfo) {
  751. LsaIFree_LSAPR_POLICY_INFORMATION(PolicyDnsDomainInformation,
  752. (PLSAPR_POLICY_INFORMATION) LocalDnsDomainInfo);
  753. }
  754. if (DsName) {
  755. LsapDsFree(DsName);
  756. }
  757. if (pSD) {
  758. LsapFreeLsaHeap(pSD);
  759. }
  760. if (CreatorSid) {
  761. midl_user_free(CreatorSid);
  762. }
  763. if (pNewSD) {
  764. LsapFreeLsaHeap(pNewSD);
  765. }
  766. if (pNewSDForAttr) {
  767. midl_user_free(pNewSDForAttr);
  768. }
  769. return NtStatus;
  770. }
  771. NTSTATUS
  772. LsapCheckTDODeletionQuotas(
  773. IN LSAP_DB_HANDLE Handle
  774. )
  775. /*++
  776. Routine Description:
  777. This routine checks to make sure that the client has not exceeded the
  778. number of deleted trusts they are allowed.
  779. Arguments:
  780. Handle -- the handle to the trust object
  781. Return Values:
  782. STATUS_SUCCESS, a resource error otherwise
  783. STATUS_QUOTA_EXCEEDED
  784. --*/
  785. {
  786. NTSTATUS Status = STATUS_SUCCESS;
  787. PSID ClientSid = NULL;
  788. PSID CreatorSid = NULL;
  789. PTOKEN_OWNER TokenOwnerInformation = NULL;
  790. ULONG Quota = 0, ClientUsage = 0;
  791. LSAP_DB_ATTRIBUTE Attribute;
  792. //
  793. // Get the trust creator SID, if any
  794. //
  795. LsapDbInitializeAttributeDs(
  796. &Attribute,
  797. TrDmCrSid,
  798. NULL,
  799. 0,
  800. FALSE
  801. );
  802. Status = LsapDsReadAttributes(&Handle->PhysicalNameDs,
  803. LSAPDS_OP_NO_LOCK,
  804. &Attribute,
  805. 1);
  806. if (STATUS_NOT_FOUND == Status) {
  807. //
  808. // No creator? No quota
  809. //
  810. Status = STATUS_SUCCESS;
  811. goto CheckTDODeletionQuotasExit;
  812. }
  813. if (!NT_SUCCESS(Status)) {
  814. goto CheckTDODeletionQuotasExit;
  815. }
  816. CreatorSid = (PSID) Attribute.AttributeValue;
  817. //
  818. // Get the client SID
  819. //
  820. Status = LsapGetCurrentOwnerAndPrimaryGroup(&TokenOwnerInformation,
  821. NULL);
  822. if (!NT_SUCCESS(Status)) {
  823. goto CheckTDODeletionQuotasExit;
  824. }
  825. ClientSid = TokenOwnerInformation->Owner;
  826. //
  827. // Does it match the caller?
  828. //
  829. if (!RtlEqualSid(ClientSid, CreatorSid)) {
  830. //
  831. // No quota enforced
  832. //
  833. goto CheckTDODeletionQuotasExit;
  834. }
  835. //
  836. // Do the quota check
  837. //
  838. Status = LsapCheckDelegatedTDOQuotas(ClientSid,
  839. LSAP_CHECK_TDO_QUOTA_USER_DELETED);
  840. //
  841. // Fall through to exit
  842. //
  843. CheckTDODeletionQuotasExit:
  844. if (TokenOwnerInformation) {
  845. LsapFreeLsaHeap( TokenOwnerInformation );
  846. }
  847. if (CreatorSid) {
  848. MIDL_user_free( CreatorSid );
  849. }
  850. return Status;
  851. }
  852. NTSTATUS
  853. LsapGetDelegatedTDOQuotas(
  854. OUT ULONG *PerUserQuota OPTIONAL,
  855. OUT ULONG *GlobalQuota OPTIONAL,
  856. OUT ULONG *PerUserDeletedQuota OPTIONAL
  857. )
  858. /*++
  859. Routine Description:
  860. This routine returns the domain-wide delegatable TDO quotas.
  861. Arguments:
  862. PerUserQuota, GlobalQuota, PerUserDeletedQuota -- the quota to be filled in
  863. Return Values:
  864. STATUS_SUCCESS, a resource error otherwise
  865. --*/
  866. {
  867. NTSTATUS NtStatus = STATUS_SUCCESS;
  868. BOOLEAN ReleaseState = FALSE;
  869. ULONG LocalGlobalQuota = 0,
  870. LocalPerUserQuota = 0,
  871. LocalTombstoneQuota = 0;
  872. ATTRBLOCK ReadResAttrBlock = {0, NULL};
  873. ATTRBLOCK ReadAttrBlock = {0, NULL};
  874. ULONG i;
  875. //
  876. // Start a transaction, if necessary
  877. //
  878. NtStatus = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  879. LSAP_DB_DS_OP_TRANSACTION,
  880. NullObject,
  881. &ReleaseState );
  882. if ( !NT_SUCCESS( NtStatus ) ) {
  883. goto GetDelegatedTDOQuotasError;
  884. }
  885. //
  886. // Read the attributes
  887. //
  888. ReadAttrBlock.attrCount = LsapDsTDOQuotaAttributesCount;
  889. ReadAttrBlock.pAttr = LsapDsTDOQuotaAttributes;
  890. NtStatus = LsapDsReadByDsName(LsaDsStateInfo.DsRoot,
  891. 0,
  892. &ReadAttrBlock,
  893. &ReadResAttrBlock);
  894. if (NtStatus == STATUS_NOT_FOUND) {
  895. //
  896. // Attributes aren't present; that's ok
  897. //
  898. NtStatus = STATUS_SUCCESS;
  899. }
  900. if (!NT_SUCCESS(NtStatus)) {
  901. goto GetDelegatedTDOQuotasError;
  902. }
  903. //
  904. // Extract the attribute
  905. //
  906. for (i = 0; i < ReadResAttrBlock.attrCount; i++) {
  907. DWORD Value;
  908. ASSERT(ReadResAttrBlock.pAttr[i].AttrVal.valCount == 1);
  909. ASSERT(ReadResAttrBlock.pAttr[i].AttrVal.pAVal[0].valLen == sizeof(DWORD));
  910. Value = *((ULONG*)ReadResAttrBlock.pAttr[i].AttrVal.pAVal[0].pVal);
  911. switch (ReadResAttrBlock.pAttr[i].attrTyp) {
  912. case ATT_MS_DS_PER_USER_TRUST_QUOTA:
  913. LocalPerUserQuota = Value;
  914. break;
  915. case ATT_MS_DS_ALL_USERS_TRUST_QUOTA:
  916. LocalGlobalQuota = Value;
  917. break;
  918. case ATT_MS_DS_PER_USER_TRUST_TOMBSTONES_QUOTA:
  919. LocalTombstoneQuota = Value;
  920. break;
  921. }
  922. }
  923. if (PerUserQuota) {
  924. *PerUserQuota = LocalPerUserQuota;
  925. }
  926. if (GlobalQuota) {
  927. *GlobalQuota = LocalGlobalQuota;
  928. }
  929. if (PerUserDeletedQuota) {
  930. *PerUserDeletedQuota = LocalTombstoneQuota;
  931. }
  932. GetDelegatedTDOQuotasError:
  933. if (ReleaseState) {
  934. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  935. LSAP_DB_DS_OP_TRANSACTION,
  936. NullObject,
  937. ReleaseState );
  938. }
  939. return NtStatus;
  940. }
  941. NTSTATUS
  942. LsapGetDelegatedTDOCount(
  943. IN ULONG Flags,
  944. IN PSID CreatorSid OPTIONAL,
  945. OUT ULONG *Count
  946. )
  947. /*++
  948. Routine Description:
  949. This routine returns the number of TDO's that satisfy the input parameters.
  950. Arguments:
  951. Flags -- LSAP_GET_DELEGATED_TDO_DELETED_ONLY return only deleted objects
  952. CreatorSid -- if present, the TDO must have a msds-creator-sid attribute
  953. equal to this value
  954. Count -- the number of objects that match the request
  955. Return Values:
  956. STATUS_SUCCESS, a resource error otherwise
  957. --*/
  958. {
  959. NTSTATUS Status = STATUS_SUCCESS;
  960. SEARCHARG SearchArg;
  961. FILTER Filters[ 3 ], RootFilter;
  962. ENTINFSEL EntInfSel;
  963. ENTINFLIST *EntInfList;
  964. ULONG ClassId, FlagValue, i;
  965. SEARCHRES *SearchRes = NULL;
  966. BOOLEAN CloseTransaction = FALSE;
  967. ATTR AttrsToRead[] = {{ATT_OBJECT_GUID, {0, NULL}}};
  968. ULONG LocalCount = 0;
  969. USHORT FilterCount = 0;
  970. BOOL True = TRUE;
  971. RtlZeroMemory( &SearchArg, sizeof( SEARCHARG ) );
  972. //
  973. // See if we already have a transaction going
  974. //
  975. // If one already exists, we'll use the existing transaction and not
  976. // delete the thread state at the end.
  977. //
  978. Status = LsapDsInitAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  979. LSAP_DB_DS_OP_TRANSACTION,
  980. NullObject,
  981. &CloseTransaction );
  982. if (!NT_SUCCESS( Status)) {
  983. goto GetDelegatedTDOCountExit;
  984. }
  985. //
  986. // Build the filter.
  987. //
  988. ClassId = CLASS_TRUSTED_DOMAIN;
  989. RtlZeroMemory( Filters, sizeof (Filters) );
  990. RtlZeroMemory( &RootFilter, sizeof (RootFilter) );
  991. //
  992. // Match the msds-Creator-Sid
  993. //
  994. Filters[ 0 ].choice = FILTER_CHOICE_ITEM;
  995. if (CreatorSid) {
  996. Filters[ 0 ].FilterTypes.Item.choice = FI_CHOICE_EQUALITY;
  997. Filters[ 0 ].FilterTypes.Item.FilTypes.ava.type = ATT_MS_DS_CREATOR_SID;
  998. Filters[ 0 ].FilterTypes.Item.FilTypes.ava.Value.valLen = RtlLengthSid(CreatorSid);
  999. Filters[ 0 ].FilterTypes.Item.FilTypes.ava.Value.pVal = ( PUCHAR )CreatorSid;
  1000. } else {
  1001. Filters[ 0 ].FilterTypes.Item.choice = FI_CHOICE_PRESENT;
  1002. Filters[ 0 ].FilterTypes.Item.FilTypes.present = ATT_MS_DS_CREATOR_SID;
  1003. }
  1004. FilterCount++;
  1005. //
  1006. // Only TDO's
  1007. //
  1008. Filters[ 0 ].pNextFilter = &Filters[ 1 ];
  1009. Filters[ 1 ].choice = FILTER_CHOICE_ITEM;
  1010. Filters[ 1 ].FilterTypes.Item.choice = FI_CHOICE_EQUALITY;
  1011. Filters[ 1 ].FilterTypes.Item.FilTypes.ava.type = ATT_OBJECT_CLASS;
  1012. Filters[ 1 ].FilterTypes.Item.FilTypes.ava.Value.valLen = sizeof( ULONG );
  1013. Filters[ 1 ].FilterTypes.Item.FilTypes.ava.Value.pVal = ( PUCHAR )&ClassId;
  1014. FilterCount++;
  1015. if (Flags & LSAP_GET_DELEGATED_TDO_DELETED_ONLY) {
  1016. //
  1017. // Only deleted TDO's
  1018. //
  1019. Filters[ 1 ].pNextFilter = &Filters[ 2 ];
  1020. Filters[ 2 ].choice = FILTER_CHOICE_ITEM;
  1021. Filters[ 2 ].FilterTypes.Item.choice = FI_CHOICE_EQUALITY;
  1022. Filters[ 2 ].FilterTypes.Item.FilTypes.ava.type = ATT_IS_DELETED;
  1023. Filters[ 2 ].FilterTypes.Item.FilTypes.ava.Value.valLen = sizeof( BOOL );
  1024. Filters[ 2 ].FilterTypes.Item.FilTypes.ava.Value.pVal = ( PUCHAR )&True;
  1025. FilterCount++;
  1026. //
  1027. // Search the NC, since deleted objects are moved in to the
  1028. // deleted objects container
  1029. //
  1030. SearchArg.pObject = LsaDsStateInfo.DsRoot;
  1031. SearchArg.choice = SE_CHOICE_WHOLE_SUBTREE;
  1032. } else {
  1033. //
  1034. // Search just the system container
  1035. //
  1036. SearchArg.pObject = LsaDsStateInfo.DsSystemContainer;
  1037. SearchArg.choice = SE_CHOICE_IMMED_CHLDRN;
  1038. }
  1039. RootFilter.choice = FILTER_CHOICE_AND;
  1040. RootFilter.FilterTypes.And.count = FilterCount;
  1041. RootFilter.FilterTypes.And.pFirstFilter = Filters;
  1042. SearchArg.bOneNC = TRUE;
  1043. SearchArg.pFilter = &RootFilter;
  1044. SearchArg.searchAliases = FALSE;
  1045. SearchArg.pSelection = &EntInfSel;
  1046. //
  1047. // Build the list of attributes to return
  1048. //
  1049. EntInfSel.attSel = EN_ATTSET_LIST;
  1050. EntInfSel.AttrTypBlock.attrCount = 1;
  1051. EntInfSel.AttrTypBlock.pAttr = AttrsToRead;
  1052. EntInfSel.infoTypes = EN_INFOTYPES_TYPES_VALS;
  1053. //
  1054. // Build the Commarg structure
  1055. //
  1056. LsapDsInitializeStdCommArg( &( SearchArg.CommArg ), 0 );
  1057. if (Flags & LSAP_GET_DELEGATED_TDO_DELETED_ONLY) {
  1058. SearchArg.CommArg.Svccntl.makeDeletionsAvail = TRUE;
  1059. }
  1060. //
  1061. // There could be thousands of trusts; make a paged search
  1062. // to scale
  1063. //
  1064. SearchArg.CommArg.PagedResult.fPresent = TRUE;
  1065. SearchArg.CommArg.ulSizeLimit = 100;
  1066. LsapDsSetDsaFlags( TRUE );
  1067. while (NT_SUCCESS(Status)
  1068. && SearchArg.CommArg.PagedResult.fPresent) {
  1069. DirSearch( &SearchArg, &SearchRes );
  1070. LsapDsContinueTransaction();
  1071. if ( SearchRes ) {
  1072. Status = LsapDsMapDsReturnToStatusEx( &SearchRes->CommRes );
  1073. } else {
  1074. Status = STATUS_INSUFFICIENT_RESOURCES;
  1075. }
  1076. if ( NT_SUCCESS( Status ) ) {
  1077. //
  1078. // Increment the count
  1079. //
  1080. LocalCount += SearchRes->count;
  1081. //
  1082. // See if we have to search again
  1083. //
  1084. SearchArg.CommArg.PagedResult.fPresent =
  1085. SearchRes->PagedResult.fPresent;
  1086. SearchArg.CommArg.PagedResult.pRestart =
  1087. SearchRes->PagedResult.pRestart;
  1088. }
  1089. }
  1090. if (NT_SUCCESS(Status)) {
  1091. *Count = LocalCount;
  1092. }
  1093. GetDelegatedTDOCountExit:
  1094. if (CloseTransaction) {
  1095. LsapDsDeleteAllocAsNeededEx( LSAP_DB_READ_ONLY_TRANSACTION |
  1096. LSAP_DB_DS_OP_TRANSACTION,
  1097. NullObject,
  1098. CloseTransaction );
  1099. }
  1100. return( Status );
  1101. }