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.

10255 lines
295 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dbdomain.c
  5. Abstract:
  6. LSA Database - Trusted Domain Object Private API Workers
  7. NOTE: This module should remain as portable code that is independent
  8. of the implementation of the LSA Database. As such, it is
  9. permitted to use only the exported LSA Database interfaces
  10. contained in db.h and NOT the private implementation
  11. dependent functions in dbp.h.
  12. Author:
  13. Scott Birrell (ScottBi) January 13, 1992
  14. Environment:
  15. Revision History:
  16. --*/
  17. #include <lsapch2.h>
  18. #include "dbp.h"
  19. #include <dns.h>
  20. #include <dnsapi.h>
  21. #include <names.h>
  22. #include <malloc.h>
  23. #include "lsawmi.h"
  24. #include <logonmsv.h>
  25. LSAP_DB_TRUSTED_DOMAIN_LIST LsapDbTrustedDomainList;
  26. BOOLEAN LsapDbReturnAuthData;
  27. //
  28. // Local function prototypes
  29. //
  30. VOID
  31. LsapDbBuildTrustInfoExForTrustInfo(
  32. IN PLSAPR_UNICODE_STRING Domain,
  33. IN PLSAPR_SID Sid,
  34. IN OUT PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustInfoEx
  35. )
  36. /*++
  37. Routine Description:
  38. This takes the equivalent of a TRUST_INFORMATION structure and converts
  39. it to a TRUSTED_DOMAIN_INFORMATION_EX structure
  40. Arguments:
  41. Domain -- Domain name
  42. Sid -- Domain sid
  43. TrustInfoEx -- Pointer to a structure to initialize
  44. --*/
  45. {
  46. RtlCopyMemory( &TrustInfoEx->Name,
  47. Domain,
  48. sizeof( UNICODE_STRING ) );
  49. RtlCopyMemory( &TrustInfoEx->FlatName,
  50. Domain,
  51. sizeof( UNICODE_STRING ) );
  52. TrustInfoEx->Sid = Sid;
  53. TrustInfoEx->TrustDirection = TRUST_DIRECTION_OUTBOUND;
  54. TrustInfoEx->TrustType = TRUST_TYPE_DOWNLEVEL;
  55. TrustInfoEx->TrustAttributes = 0;
  56. }
  57. NTSTATUS
  58. LsapNotifyNetlogonOfTrustChange(
  59. IN PSID pChangeSid,
  60. IN SECURITY_DB_DELTA_TYPE ChangeType
  61. )
  62. /*++
  63. Routine Description:
  64. This function will notify netlogon when a trusted domain object comes or
  65. goes into or out of existence
  66. Arguments:
  67. pChangeSid - The sid of the trusted domain object that changed
  68. IsDeletion - Indicates whether the trusted domain was added or removed
  69. --*/
  70. {
  71. NTSTATUS Status;
  72. Status = I_NetNotifyTrustedDomain (
  73. NULL,
  74. pChangeSid,
  75. ( BOOLEAN )(ChangeType == SecurityDbDelete)
  76. );
  77. if ( LsapKerberosTrustNotificationFunction ) {
  78. LsaIRegisterNotification( ( SEC_THREAD_START )LsapKerberosTrustNotificationFunction,
  79. ( PVOID ) ChangeType,
  80. NOTIFIER_TYPE_IMMEDIATE,
  81. 0,
  82. NOTIFIER_FLAG_ONE_SHOT,
  83. 0,
  84. 0 );
  85. }
  86. return(Status);
  87. }
  88. NTSTATUS
  89. LsarCreateTrustedDomain(
  90. IN LSAPR_HANDLE PolicyHandle,
  91. IN PLSAPR_TRUST_INFORMATION TrustedDomainInformation,
  92. IN ACCESS_MASK DesiredAccess,
  93. OUT PLSAPR_HANDLE TrustedDomainHandle
  94. )
  95. /*++
  96. Routine Description:
  97. This function is the LSA server RPC worker routine for the
  98. LsaCreateTrustedDomain API.
  99. The LsaCreateTrustedDomain API creates a new TrustedDomain object. The
  100. caller must have POLICY_TRUST_ADMIN access to the Policy Object.
  101. Note that NO verification is done to check that the given domain name
  102. matches the given SID or that the SID or name represent an actual domain.
  103. Arguments:
  104. PolicyHandle - Handle from an LsaOpenPolicy call.
  105. TrustedDomainInformation - Pointer to structure containing the name and
  106. SID of the new Trusted Domain.
  107. DesiredAccess - Specifies the accesses to be granted for the newly
  108. created object.
  109. TrustedDomainHandle - receives a handle referencing the newly created
  110. object. This handle is used on subsequent accesses to the object.
  111. --*/
  112. {
  113. NTSTATUS Status = STATUS_SUCCESS;
  114. LSAPR_TRUSTED_DOMAIN_INFORMATION_EX ExInfo;
  115. LsarpReturnCheckSetup();
  116. LsapDbBuildTrustInfoExForTrustInfo( &TrustedDomainInformation->Name,
  117. TrustedDomainInformation->Sid,
  118. &ExInfo );
  119. Status = LsapCreateTrustedDomain2( PolicyHandle, &ExInfo, NULL,
  120. DesiredAccess,
  121. TrustedDomainHandle );
  122. LsarpReturnPrologue();
  123. return( Status );
  124. }
  125. NTSTATUS
  126. LsapDbVerifyTrustLocation(
  127. IN OUT PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation
  128. )
  129. /*++
  130. Routine Description:
  131. Verifies that a trust described by TrustedDomainInformation is pointing
  132. either entirely within, or entirely outside this forest
  133. If appropriate, sets the TRUST_ATTRIBUTE_WITHIN_FOREST attribute
  134. Arguments:
  135. TrustedDomainInformation trust attributes to examine
  136. Returns:
  137. STATUS_SUCCESS if happy
  138. STATUS_INVALID_PARAMETER if TrustedDomainInformation was inconsistent
  139. STATUS_INSUFFICIENT_RESOURCES not enough memory
  140. --*/
  141. {
  142. NTSTATUS Status;
  143. PSID MatchDnsName = NULL, MatchNetbiosName = NULL, MatchSid = NULL;
  144. BOOLEAN TrustInternal = FALSE, TrustExternal = FALSE;
  145. typedef enum {
  146. ExternalTrust,
  147. InternalTrust,
  148. UndeterminedTrust,
  149. } TRUST_LOCATION;
  150. TRUST_LOCATION SidLocation = UndeterminedTrust,
  151. DnsLocation = UndeterminedTrust,
  152. NbLocation = UndeterminedTrust;
  153. if ( TrustedDomainInformation->Sid ) {
  154. Status = LsapForestTrustFindMatch(
  155. RoutingMatchDomainSid,
  156. TrustedDomainInformation->Sid,
  157. TRUE,
  158. NULL,
  159. &MatchSid
  160. );
  161. if ( Status == STATUS_NO_MATCH ) {
  162. SidLocation = ExternalTrust;
  163. Status = STATUS_SUCCESS;
  164. } else if ( !NT_SUCCESS( Status )) {
  165. goto Cleanup;
  166. } else {
  167. SidLocation = InternalTrust;
  168. }
  169. }
  170. Status = LsapForestTrustFindMatch(
  171. RoutingMatchDomainName,
  172. &TrustedDomainInformation->Name,
  173. TRUE,
  174. NULL,
  175. &MatchDnsName
  176. );
  177. if ( Status == STATUS_NO_MATCH ) {
  178. DnsLocation = ExternalTrust;
  179. Status = STATUS_SUCCESS;
  180. } else if ( !NT_SUCCESS( Status )) {
  181. goto Cleanup;
  182. } else {
  183. DnsLocation = InternalTrust;
  184. }
  185. if ( TrustedDomainInformation->FlatName.Buffer != NULL ) {
  186. Status = LsapForestTrustFindMatch(
  187. RoutingMatchDomainName,
  188. &TrustedDomainInformation->FlatName,
  189. TRUE,
  190. NULL,
  191. &MatchNetbiosName
  192. );
  193. if ( Status == STATUS_NO_MATCH ) {
  194. NbLocation = ExternalTrust;
  195. Status = STATUS_SUCCESS;
  196. } else if ( !NT_SUCCESS( Status )) {
  197. goto Cleanup;
  198. } else {
  199. NbLocation = InternalTrust;
  200. }
  201. }
  202. if ( SidLocation == InternalTrust ||
  203. DnsLocation == InternalTrust ||
  204. NbLocation == InternalTrust ) {
  205. TrustInternal = TRUE;
  206. }
  207. if ( SidLocation == ExternalTrust ||
  208. DnsLocation == ExternalTrust ||
  209. NbLocation == ExternalTrust ) {
  210. TrustExternal = TRUE;
  211. }
  212. if ( TrustInternal && TrustExternal ) {
  213. //
  214. // Portions of the trust information point inside, portions - outside
  215. //
  216. Status = STATUS_INVALID_PARAMETER;
  217. goto Cleanup;
  218. }
  219. if ( TrustInternal ) {
  220. TrustedDomainInformation->TrustAttributes |= TRUST_ATTRIBUTE_WITHIN_FOREST;
  221. }
  222. //
  223. // For things that matched internally, perform pairwise SID comparisons
  224. // so that one trust points to one location only
  225. //
  226. if ( MatchDnsName &&
  227. MatchSid &&
  228. !RtlEqualSid( MatchDnsName, MatchSid )) {
  229. Status = STATUS_INVALID_PARAMETER;
  230. goto Cleanup;
  231. }
  232. if ( MatchDnsName &&
  233. MatchNetbiosName &&
  234. !RtlEqualSid( MatchDnsName, MatchNetbiosName )) {
  235. Status = STATUS_INVALID_PARAMETER;
  236. goto Cleanup;
  237. }
  238. if ( MatchSid &&
  239. MatchNetbiosName &&
  240. !RtlEqualSid( MatchSid, MatchNetbiosName )) {
  241. Status = STATUS_INVALID_PARAMETER;
  242. goto Cleanup;
  243. }
  244. Cleanup:
  245. MIDL_user_free( MatchNetbiosName );
  246. MIDL_user_free( MatchDnsName );
  247. MIDL_user_free( MatchSid );
  248. return Status;
  249. }
  250. NTSTATUS
  251. LsapCreateTrustedDomain2(
  252. IN LSAPR_HANDLE PolicyHandle,
  253. IN PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
  254. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation,
  255. IN ACCESS_MASK DesiredAccess,
  256. OUT PLSAPR_HANDLE TrustedDomainHandle
  257. )
  258. /*++
  259. Routine Description:
  260. This function is the LSA server RPC worker routine for the
  261. LsaCreateTrustedDomain API.
  262. The LsaCreateTrustedDomain API creates a new TrustedDomain object. The
  263. caller must have POLICY_TRUST_ADMIN access to the Policy Object.
  264. Note that NO verification is done to check that the given domain name
  265. matches the given SID or that the SID or name represent an actual domain.
  266. Arguments:
  267. PolicyHandle - Handle from an LsaOpenPolicy call.
  268. TrustedDomainInformation - Pointer to structure containing the name and
  269. SID of the new Trusted Domain.
  270. DesiredAccess - Specifies the accesses to be granted for the newly
  271. created object.
  272. TrustedDomainHandle - receives a handle referencing the newly created
  273. object. This handle is used on subsequent accesses to the object.
  274. The returned handle has a reference to the passed in PolicyHandle. So,
  275. when the TrustedDomainHandle is closed, either call LsapCloseHandle or at least
  276. call LsapDbDereferenceObject passing in LSAP_DB_DEREFERENCE_CONTR.
  277. Returns:
  278. STATUS_SUCCESS - Success
  279. STATUS_DIRECTORY_SERVICE_REQUIRED - An attempt was made to create a trusted domain
  280. object on a non-DC
  281. STATUS_INVALID_SID - An invalid sid was specified
  282. STATUS_UNSUCCESSFUL - Unable to obtain the product type
  283. STATUS_CURRENT_DOMAIN_NOT_ALLOWED - Can not add the current domain to the trusted domain list
  284. STATUS_INVALID_DOMAIN_STATE - Forest transitive bit can not be specified on this DC
  285. STATUS_ACCESS_DENIED - Do not have enough rights to create a trusted domain
  286. --*/
  287. {
  288. NTSTATUS Status = STATUS_SUCCESS, SecondaryStatus = STATUS_SUCCESS;
  289. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  290. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_DOMAIN];
  291. PLSAP_DB_ATTRIBUTE NextAttribute;
  292. UNICODE_STRING LogicalNameU;
  293. BOOLEAN AcquiredListWriteLock = FALSE;
  294. DNS_STATUS DnsStatus;
  295. BOOLEAN AllLocksLocked = FALSE;
  296. BOOLEAN ClientPolicyHandleReferenced = FALSE;
  297. PSID DomainSid;
  298. ULONG AttributeCount = 0;
  299. LSAP_DB_HANDLE InternalTrustedDomainHandle = NULL;
  300. PVOID TrustedDomainNameAttributeValue = NULL;
  301. ULONG TrustedDomainPosixOffset;
  302. BOOLEAN TrustCreated = FALSE;
  303. PLSAPR_TRUST_DOMAIN_AUTH_INFO_HALF AuthHalf;
  304. LSAPR_TRUST_INFORMATION InputTrustInformation;
  305. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  306. ULONG CriticalValue = 0;
  307. PPOLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo = NULL;
  308. LsarpReturnCheckSetup();
  309. LsapEnterFunc( "LsapCreateTrustedDomain2" );
  310. LogicalNameU.Length = 0;
  311. RtlZeroMemory(Attributes, sizeof(Attributes));
  312. if (LsapProductSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
  313. {
  314. Status = STATUS_NOT_SUPPORTED_ON_SBS;
  315. goto CreateTrustedDomainError;
  316. }
  317. if (!ARGUMENT_PRESENT( TrustedDomainInformation )) {
  318. Status = STATUS_INVALID_PARAMETER;
  319. goto CreateTrustedDomainError;
  320. }
  321. //
  322. // Creating a trust with the forest transitive bit set is not legal
  323. // outside of the root domain of the forest
  324. //
  325. if ( !LsapDbDcInRootDomain() &&
  326. ( TrustedDomainInformation->TrustAttributes & TRUST_ATTRIBUTE_FOREST_TRANSITIVE )) {
  327. Status = STATUS_INVALID_DOMAIN_STATE;
  328. goto CreateTrustedDomainError;
  329. }
  330. //
  331. // Creating a trust with the forest transitive bit set is not legal
  332. // until all domains are upgraded to Whistler
  333. //
  334. if ( FLAG_ON( TrustedDomainInformation->TrustAttributes,
  335. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  336. !LsapDbNoMoreWin2KForest()) {
  337. Status = STATUS_INVALID_DOMAIN_STATE;
  338. goto CreateTrustedDomainError;
  339. }
  340. //
  341. // Creating a trust with the cross-federation bit set is not legal
  342. // until this domain is upgraded to Whistler
  343. //
  344. if ( FLAG_ON( TrustedDomainInformation->TrustAttributes,
  345. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) &&
  346. !LsapDbNoMoreWin2KDomain()) {
  347. Status = STATUS_INVALID_DOMAIN_STATE;
  348. goto CreateTrustedDomainError;
  349. }
  350. //
  351. // If this is not a Dc, then return an error. Creating trust on a client is
  352. // not supported
  353. //
  354. //
  355. // We allow this API to be called before we're completely initialized
  356. // for installation reasons. However, it is the responsibility of the
  357. // installation program to not call it before the Product Type is
  358. // obtainable from the Registry.
  359. //
  360. if (!LsapDbIsServerInitialized()) {
  361. if ( !RtlGetNtProductType(&LsapProductType) ) {
  362. Status = STATUS_UNSUCCESSFUL;
  363. goto CreateTrustedDomainError;
  364. }
  365. }
  366. if ( !LsaDsStateInfo.UseDs ) {
  367. Status = STATUS_DIRECTORY_SERVICE_REQUIRED;
  368. goto CreateTrustedDomainError;
  369. }
  370. //
  371. // Validate the input argument formats
  372. //
  373. if ( !LsapValidateLsaUnicodeString( &TrustedDomainInformation->Name ) ||
  374. !LsapValidateLsaUnicodeString( &TrustedDomainInformation->FlatName ) ) {
  375. Status = STATUS_INVALID_PARAMETER;
  376. goto CreateTrustedDomainError;
  377. }
  378. //
  379. // Fix the name to ensure that it doesn't have a trailing period
  380. //
  381. if ( TrustedDomainInformation->TrustType == TRUST_TYPE_UPLEVEL ) {
  382. if ( TrustedDomainInformation->Name.Length == 0 ||
  383. TrustedDomainInformation->Name.Buffer == NULL ) {
  384. Status = STATUS_INVALID_PARAMETER;
  385. goto CreateTrustedDomainError;
  386. }
  387. if ( TrustedDomainInformation->Name.Buffer[
  388. (TrustedDomainInformation->Name.Length - 1) / sizeof(WCHAR)] == L'.' ) {
  389. TrustedDomainInformation->Name.Buffer[
  390. (TrustedDomainInformation->Name.Length - 1) / sizeof(WCHAR)] = UNICODE_NULL;
  391. TrustedDomainInformation->Name.Length -= sizeof(WCHAR);
  392. }
  393. }
  394. //
  395. // Check to make sure the NetBIOS name is actually valid
  396. //
  397. if ( TrustedDomainInformation->TrustType == TRUST_TYPE_DOWNLEVEL ||
  398. TrustedDomainInformation->TrustType == TRUST_TYPE_UPLEVEL ) {
  399. BOOLEAN Valid;
  400. Status = LsapValidateNetbiosName(
  401. ( UNICODE_STRING * )&TrustedDomainInformation->FlatName,
  402. &Valid
  403. );
  404. if ( NT_SUCCESS( Status ) && !Valid ) {
  405. Status = STATUS_OBJECT_NAME_INVALID;
  406. }
  407. if ( !NT_SUCCESS( Status )) {
  408. goto CreateTrustedDomainError;
  409. }
  410. }
  411. //
  412. // Now, do the same for the DNS name
  413. //
  414. if ( TrustedDomainInformation->TrustType == TRUST_TYPE_UPLEVEL ) {
  415. BOOLEAN Valid;
  416. Status = LsapValidateDnsName(
  417. ( UNICODE_STRING * )&TrustedDomainInformation->Name,
  418. &Valid
  419. );
  420. if ( NT_SUCCESS( Status ) && !Valid ) {
  421. Status = STATUS_OBJECT_NAME_INVALID;
  422. }
  423. if ( !NT_SUCCESS( Status )) {
  424. goto CreateTrustedDomainError;
  425. }
  426. }
  427. //
  428. // Validate the Trusted Domain Sid.
  429. //
  430. DomainSid = TrustedDomainInformation->Sid;
  431. if ( DomainSid ) {
  432. //
  433. // SIDs passed in should be valid domain SIDs
  434. //
  435. Status = LsapIsValidDomainSid( DomainSid );
  436. if ( !NT_SUCCESS( Status )) {
  437. goto CreateTrustedDomainError;
  438. }
  439. }
  440. if ( !((LSAP_DB_HANDLE)PolicyHandle)->Trusted && DomainSid == NULL &&
  441. ( TrustedDomainInformation->TrustType == TRUST_TYPE_DOWNLEVEL ||
  442. TrustedDomainInformation->TrustType == TRUST_TYPE_UPLEVEL ) ) {
  443. Status = STATUS_INVALID_SID;
  444. goto CreateTrustedDomainError;
  445. }
  446. //
  447. // Guard against adding self to the trusted domain list
  448. //
  449. Status = LsapDbQueryInformationPolicy(
  450. LsapPolicyHandle,
  451. PolicyDnsDomainInformation,
  452. ( PLSAPR_POLICY_INFORMATION *)&PolicyDnsDomainInfo );
  453. if ( !NT_SUCCESS( Status ) ) {
  454. goto CreateTrustedDomainError;
  455. }
  456. //
  457. // Catch attempts to create a TDO with the same SID as the SID of this domain
  458. //
  459. if ( DomainSid != NULL && PolicyDnsDomainInfo->Sid != NULL &&
  460. RtlEqualSid( DomainSid, PolicyDnsDomainInfo->Sid ) ) {
  461. Status = STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
  462. goto CreateTrustedDomainError;
  463. }
  464. //
  465. // Catch attempts to create a TDO with the same name as this domain
  466. //
  467. if ( TrustedDomainInformation->Name.Buffer != NULL ) {
  468. if ( PolicyDnsDomainInfo->Name.Buffer != NULL &&
  469. RtlEqualUnicodeString(
  470. ( PUNICODE_STRING )&TrustedDomainInformation->Name,
  471. ( PUNICODE_STRING )&PolicyDnsDomainInfo->Name, TRUE ) ) {
  472. Status = STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
  473. goto CreateTrustedDomainError;
  474. } else if ( PolicyDnsDomainInfo->DnsDomainName.Buffer != NULL &&
  475. RtlEqualUnicodeString(
  476. ( PUNICODE_STRING )&TrustedDomainInformation->Name,
  477. ( PUNICODE_STRING )&PolicyDnsDomainInfo->DnsDomainName, TRUE ) ) {
  478. Status = STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
  479. goto CreateTrustedDomainError;
  480. }
  481. }
  482. if ( TrustedDomainInformation->FlatName.Buffer != NULL ) {
  483. if ( PolicyDnsDomainInfo->Name.Buffer != NULL &&
  484. RtlEqualUnicodeString(
  485. ( PUNICODE_STRING )&TrustedDomainInformation->FlatName,
  486. ( PUNICODE_STRING )&PolicyDnsDomainInfo->Name, TRUE ) ) {
  487. Status = STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
  488. goto CreateTrustedDomainError;
  489. } else if ( PolicyDnsDomainInfo->DnsDomainName.Buffer != NULL &&
  490. RtlEqualUnicodeString(
  491. ( PUNICODE_STRING )&TrustedDomainInformation->FlatName,
  492. ( PUNICODE_STRING )&PolicyDnsDomainInfo->DnsDomainName, TRUE ) ) {
  493. Status = STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
  494. goto CreateTrustedDomainError;
  495. }
  496. }
  497. //
  498. // Almost done with the checks - see if this domain is within our forest
  499. // and if so, set the TRUST_ATTRIBUTE_WITHIN_FOREST bit
  500. //
  501. Status = LsapDbVerifyTrustLocation( TrustedDomainInformation );
  502. if ( !NT_SUCCESS( Status )) {
  503. goto CreateTrustedDomainError;
  504. }
  505. //
  506. // A trust can not be both "within forest" and either external or cross-org
  507. //
  508. if ( FLAG_ON( TrustedDomainInformation->TrustAttributes,
  509. TRUST_ATTRIBUTE_WITHIN_FOREST ) &&
  510. ( FLAG_ON( TrustedDomainInformation->TrustAttributes,
  511. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) ||
  512. FLAG_ON( TrustedDomainInformation->TrustAttributes,
  513. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ))) {
  514. Status = STATUS_INVALID_PARAMETER;
  515. goto CreateTrustedDomainError;
  516. }
  517. //
  518. // Grab all of the locks.
  519. //
  520. // There are code paths where we lock Policy, secret, trusted domain and
  521. // registry locks, there is no convenient order. So grab them all.
  522. //
  523. LsapDbAcquireLockEx( AllObject, 0 );
  524. AllLocksLocked = TRUE;
  525. //
  526. // Verify that the PolicyHandle is valid.
  527. // Reference the Policy Object handle (as container object).
  528. //
  529. Status = LsapDbReferenceObject(
  530. PolicyHandle,
  531. 0,
  532. PolicyObject,
  533. TrustedDomainObject,
  534. LSAP_DB_LOCK );
  535. if (!NT_SUCCESS(Status)) {
  536. goto CreateTrustedDomainError;
  537. }
  538. ClientPolicyHandleReferenced = TRUE;
  539. //
  540. // Validate whether the name/flat name is not already in use
  541. //
  542. Status = LsapDbAcquireReadLockTrustedDomainList();
  543. if (!NT_SUCCESS(Status)) {
  544. goto CreateTrustedDomainError;
  545. }
  546. RtlCopyMemory(&InputTrustInformation.Name,&TrustedDomainInformation->Name,sizeof(UNICODE_STRING));
  547. InputTrustInformation.Sid = NULL;
  548. Status = LsapDbLookupEntryTrustedDomainList(
  549. &InputTrustInformation,
  550. &TrustEntry
  551. );
  552. if (STATUS_SUCCESS==Status)
  553. {
  554. LsapDbReleaseLockTrustedDomainList();
  555. Status = STATUS_OBJECT_NAME_COLLISION;
  556. goto CreateTrustedDomainError;
  557. }
  558. RtlCopyMemory(&InputTrustInformation.Name,&TrustedDomainInformation->FlatName,sizeof(UNICODE_STRING));
  559. InputTrustInformation.Sid = NULL;
  560. Status = LsapDbLookupEntryTrustedDomainList(
  561. &InputTrustInformation,
  562. &TrustEntry
  563. );
  564. LsapDbReleaseLockTrustedDomainList();
  565. if (STATUS_SUCCESS==Status)
  566. {
  567. Status = STATUS_OBJECT_NAME_COLLISION;
  568. goto CreateTrustedDomainError;
  569. }
  570. //
  571. // Construct the Trusted Domain Name attribute info.
  572. //
  573. NextAttribute = Attributes;
  574. Status = LsapDbMakeUnicodeAttributeDs(
  575. (PUNICODE_STRING) &TrustedDomainInformation->Name,
  576. TrDmName,
  577. NextAttribute );
  578. if (!NT_SUCCESS(Status)) {
  579. goto CreateTrustedDomainError;
  580. }
  581. NextAttribute++;
  582. AttributeCount++;
  583. //
  584. // Construct the Trusted Domain Sid attribute info
  585. //
  586. if ( DomainSid ) {
  587. Status = LsapDbMakeSidAttributeDs(
  588. DomainSid,
  589. Sid,
  590. NextAttribute
  591. );
  592. if (!NT_SUCCESS(Status)) {
  593. goto CreateTrustedDomainError;
  594. }
  595. NextAttribute++;
  596. AttributeCount++;
  597. }
  598. //
  599. // Set critical system object for the trusted domain
  600. //
  601. CriticalValue = 1;
  602. LsapDbInitializeAttributeDs( NextAttribute,
  603. PseudoSystemCritical,
  604. &CriticalValue,
  605. sizeof( ULONG ),
  606. FALSE );
  607. NextAttribute++;
  608. AttributeCount++;
  609. //
  610. // Set the Posix Offset for this Trusted Domain.
  611. //
  612. // The rules are as follows:
  613. //
  614. // For a PDC, set the Posix Offset to the value.
  615. //
  616. // For a BDC, set the Posix Offset to the null Posix offset. It will be
  617. // set on the PDC when the TDO is replicated there.
  618. //
  619. TrustedDomainPosixOffset = SE_NULL_POSIX_OFFSET;
  620. if ( LsapNeedPosixOffset( TrustedDomainInformation->TrustDirection,
  621. TrustedDomainInformation->TrustType ) ) {
  622. DOMAIN_SERVER_ROLE ServerRole = DomainServerRolePrimary;
  623. //
  624. // Query the server role, PDC/BDC
  625. //
  626. Status = SamIQueryServerRole(
  627. LsapAccountDomainHandle,
  628. &ServerRole
  629. );
  630. if (!NT_SUCCESS(Status)) {
  631. goto CreateTrustedDomainError;
  632. }
  633. if ( ServerRole == DomainServerRolePrimary ) {
  634. //
  635. // Need to grab the TDL write lock while allocating a Posix Offset
  636. //
  637. Status = LsapDbAcquireWriteLockTrustedDomainList();
  638. if ( !NT_SUCCESS(Status)) {
  639. goto CreateTrustedDomainError;
  640. }
  641. AcquiredListWriteLock = TRUE;
  642. //
  643. // Allocate the next available Posix Offset.
  644. //
  645. Status = LsapDbAllocatePosixOffsetTrustedDomainList(
  646. &TrustedDomainPosixOffset );
  647. if ( !NT_SUCCESS(Status)) {
  648. goto CreateTrustedDomainError;
  649. }
  650. }
  651. }
  652. //
  653. // Add a transaction to write the Posix Offset to the Trusted Domain
  654. // object when it is created.
  655. //
  656. LsapDbInitializeAttributeDs(
  657. NextAttribute,
  658. TrDmPxOf,
  659. &TrustedDomainPosixOffset,
  660. sizeof(TrustedDomainPosixOffset),
  661. FALSE
  662. );
  663. NextAttribute++;
  664. AttributeCount++;
  665. //
  666. // Construct the Logical Name (Internal LSA Database Name) of the
  667. // Trusted Domain object.
  668. //
  669. if ( LsapDsWriteDs ) {
  670. //
  671. // Create the object name as the domain name. There will be another mechanism in
  672. // place to ensure that the object name is kept in synch with the Dns domain Name
  673. //
  674. RtlCopyMemory( &LogicalNameU,
  675. (PUNICODE_STRING) &TrustedDomainInformation->Name,
  676. sizeof( UNICODE_STRING ) );
  677. } else {
  678. // The Logical Name is constructed from the Domain Sid by converting it into
  679. // a Unicode Sstring
  680. Status = LsapDbSidToLogicalNameObject( DomainSid, &LogicalNameU );
  681. }
  682. if (!NT_SUCCESS(Status)) {
  683. goto CreateTrustedDomainError;
  684. }
  685. //
  686. // Fill in the ObjectInformation structure. Initialize the
  687. // embedded Object Attributes with the PolicyHandle as the
  688. // Root Directory (Container Object) handle and the Logical Name (Rid)
  689. // of the Trusted Domain. Store the types of the object and its container.
  690. //
  691. InitializeObjectAttributes(
  692. &ObjectInformation.ObjectAttributes,
  693. &LogicalNameU,
  694. OBJ_CASE_INSENSITIVE,
  695. PolicyHandle,
  696. NULL
  697. );
  698. ObjectInformation.ObjectTypeId = TrustedDomainObject;
  699. ObjectInformation.ContainerTypeId = PolicyObject;
  700. ObjectInformation.Sid = DomainSid;
  701. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  702. ObjectInformation.DesiredObjectAccess = DesiredAccess;
  703. if ( LsapDsWriteDs ) {
  704. ULONG TrustAttributesValue;
  705. PBYTE AuthBuffer;
  706. ULONG AuthSize;
  707. //
  708. // Set the Netbios domain name
  709. //
  710. Status = LsapDbMakeUnicodeAttributeDs(
  711. (PUNICODE_STRING) &TrustedDomainInformation->FlatName,
  712. TrDmTrPN,
  713. NextAttribute
  714. );
  715. if ( !NT_SUCCESS( Status ) ) {
  716. goto CreateTrustedDomainError;
  717. }
  718. NextAttribute++;
  719. AttributeCount++;
  720. //
  721. // Set the trust type and direction
  722. //
  723. LsapDbInitializeAttributeDs(
  724. NextAttribute,
  725. TrDmTrTy,
  726. &TrustedDomainInformation->TrustType,
  727. sizeof( TrustedDomainInformation->TrustType ),
  728. FALSE
  729. );
  730. NextAttribute++;
  731. AttributeCount++;
  732. LsapDbInitializeAttributeDs(
  733. NextAttribute,
  734. TrDmTrDi,
  735. &TrustedDomainInformation->TrustDirection,
  736. sizeof( TrustedDomainInformation->TrustDirection ),
  737. FALSE
  738. );
  739. NextAttribute++;
  740. AttributeCount++;
  741. //
  742. // When setting trust attributes, mask off all but the supported bits
  743. //
  744. TrustAttributesValue =
  745. TrustedDomainInformation->TrustAttributes & TRUST_ATTRIBUTES_VALID;
  746. LsapDbInitializeAttributeDs(
  747. NextAttribute,
  748. TrDmTrLA,
  749. &TrustAttributesValue,
  750. sizeof( TrustAttributesValue ),
  751. FALSE
  752. );
  753. NextAttribute++;
  754. AttributeCount++;
  755. //
  756. // Authentication data
  757. //
  758. AuthHalf = LsapDsAuthHalfFromAuthInfo( AuthenticationInformation, TRUE );
  759. Status = LsapDsBuildAuthInfoAttribute( PolicyHandle,
  760. AuthHalf,
  761. NULL,
  762. &AuthBuffer,
  763. &AuthSize );
  764. if ( NT_SUCCESS( Status ) ) {
  765. if ( AuthBuffer != NULL ) {
  766. LsapDbInitializeAttributeDs(
  767. NextAttribute,
  768. TrDmSAI,
  769. AuthBuffer,
  770. AuthSize,
  771. TRUE );
  772. NextAttribute++;
  773. AttributeCount++;
  774. }
  775. }
  776. if ( NT_SUCCESS( Status ) ) {
  777. AuthHalf = LsapDsAuthHalfFromAuthInfo( AuthenticationInformation, FALSE );
  778. Status = LsapDsBuildAuthInfoAttribute( PolicyHandle,
  779. AuthHalf,
  780. NULL,
  781. &AuthBuffer,
  782. &AuthSize );
  783. if ( NT_SUCCESS( Status ) ) {
  784. if ( AuthBuffer ) {
  785. LsapDbInitializeAttributeDs(
  786. NextAttribute,
  787. TrDmSAO,
  788. AuthBuffer,
  789. AuthSize,
  790. TRUE );
  791. NextAttribute++;
  792. AttributeCount++;
  793. }
  794. }
  795. }
  796. }
  797. if (!NT_SUCCESS(Status)) {
  798. goto CreateTrustedDomainError;
  799. }
  800. ASSERT( AttributeCount <= LSAP_DB_ATTRS_INFO_CLASS_DOMAIN );
  801. //
  802. // Save a copy of the trust direction for the fixup routines
  803. //
  804. // The DS does two fixup notifications. One for the DirAddEntry and
  805. // one for the DirModifyEntry. If the second one didn't exist (or was otherwise
  806. // distinguishable from a LsarSetInformationTrustedDomain), then we wouldn't
  807. // need to save the OldTrustDirection here.
  808. //
  809. {
  810. PLSADS_PER_THREAD_INFO CurrentThreadInfo;
  811. CurrentThreadInfo = TlsGetValue( LsapDsThreadState );
  812. ASSERT( CurrentThreadInfo != NULL );
  813. if ( CurrentThreadInfo != NULL ) {
  814. CurrentThreadInfo->OldTrustDirection = TrustedDomainInformation->TrustDirection;
  815. CurrentThreadInfo->OldTrustType = TrustedDomainInformation->TrustType;
  816. }
  817. }
  818. //
  819. // Create the Trusted Domain Object. We fail if the object already exists.
  820. // Note that the object create routine performs a Database transaction.
  821. //
  822. Status = LsapDbCreateObject(
  823. &ObjectInformation,
  824. DesiredAccess,
  825. LSAP_DB_OBJECT_CREATE,
  826. 0,
  827. Attributes,
  828. &AttributeCount,
  829. RTL_NUMBER_OF(Attributes),
  830. TrustedDomainHandle
  831. );
  832. InternalTrustedDomainHandle = (LSAP_DB_HANDLE) *TrustedDomainHandle;
  833. //
  834. // This approach must be changed later. Goto LsapDbOpenObject and search for
  835. // Bug #340164 for the cause.
  836. //
  837. // LsapDbCreateObject returns STATUS_OBJECT_NAME_NOT_FOUND for secrets
  838. // in case of anonymous access not to reveal secrets. We should correct the error
  839. //
  840. if (Status == STATUS_OBJECT_NAME_NOT_FOUND &&
  841. LsapGlobalRestrictAnonymous &&
  842. ((( LSAP_DB_HANDLE )PolicyHandle)->Options & LSAP_DB_OPENED_BY_ANONYMOUS )){
  843. Status = STATUS_ACCESS_DENIED;
  844. }
  845. //
  846. // If object creation failed, dereference the container object.
  847. //
  848. if (!NT_SUCCESS(Status)) {
  849. goto CreateTrustedDomainError;
  850. }
  851. TrustCreated = TRUE;
  852. //
  853. // Create the interdomain trust account, if required
  854. //
  855. if ( NT_SUCCESS( Status ) &&
  856. FLAG_ON( TrustedDomainInformation->TrustDirection, TRUST_DIRECTION_INBOUND ) &&
  857. ((TrustedDomainInformation->TrustType == TRUST_TYPE_UPLEVEL) ||
  858. (TrustedDomainInformation->TrustType == TRUST_TYPE_DOWNLEVEL)) &&
  859. !FLAG_ON( ( ( LSAP_DB_HANDLE )PolicyHandle )->Options, LSAP_DB_HANDLE_UPGRADE ) ) {
  860. Status = LsapDsCreateInterdomainTrustAccount( *TrustedDomainHandle );
  861. if ( !NT_SUCCESS( Status ) ) {
  862. goto CreateTrustedDomainError;
  863. }
  864. }
  865. //
  866. // Add the Trusted Domain to the Trusted Domain List, unless we're doing an upgrade
  867. //
  868. if ( !FLAG_ON( ( ( LSAP_DB_HANDLE )PolicyHandle )->Options, LSAP_DB_HANDLE_UPGRADE ) ) {
  869. LSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 TrustedDomainInformation2;
  870. RtlCopyMemory(
  871. &TrustedDomainInformation2,
  872. TrustedDomainInformation,
  873. sizeof( LSAPR_TRUSTED_DOMAIN_INFORMATION_EX )
  874. );
  875. //
  876. // New domains are always created without forest trust information
  877. //
  878. TrustedDomainInformation2.ForestTrustLength = 0;
  879. TrustedDomainInformation2.ForestTrustInfo = NULL;
  880. Status = LsapDbAcquireWriteLockTrustedDomainList();
  881. if ( NT_SUCCESS( Status )) {
  882. Status = LsapDbInsertTrustedDomainList(
  883. &TrustedDomainInformation2,
  884. TrustedDomainPosixOffset
  885. );
  886. LsapDbReleaseLockTrustedDomainList();
  887. }
  888. }
  889. if (!NT_SUCCESS(Status)) {
  890. goto CreateTrustedDomainError;
  891. }
  892. if (LsapAdtAuditingEnabledHint(
  893. AuditCategoryPolicyChange,
  894. EVENTLOG_AUDIT_SUCCESS
  895. )) {
  896. (void) LsapAdtTrustedDomainAdd(
  897. EVENTLOG_AUDIT_SUCCESS,
  898. (PUNICODE_STRING) &TrustedDomainInformation->Name,
  899. TrustedDomainInformation->Sid,
  900. TrustedDomainInformation->TrustType,
  901. TrustedDomainInformation->TrustDirection,
  902. TrustedDomainInformation->TrustAttributes
  903. );
  904. }
  905. //
  906. // If necessary, release the LSA Database lock. Note that we don't
  907. // call LsapDbDereferenceObject() because we want to leave the
  908. // reference count incremented by default in this success case.
  909. // In the error case, we call LsapDbDereferenceObject().
  910. //
  911. if (ClientPolicyHandleReferenced) {
  912. LsapDbApplyTransaction( PolicyHandle,
  913. LSAP_DB_READ_ONLY_TRANSACTION,
  914. (SECURITY_DB_DELTA_TYPE) 0 );
  915. LsapDbReleaseLockEx( TrustedDomainObject,
  916. 0 );
  917. ClientPolicyHandleReferenced = FALSE;
  918. }
  919. CreateTrustedDomainFinish:
  920. //
  921. // If necessary, free the Policy DNS Domain Information
  922. //
  923. if (PolicyDnsDomainInfo != NULL) {
  924. LsaIFree_LSAPR_POLICY_INFORMATION(
  925. PolicyDnsDomainInformation,
  926. (PLSAPR_POLICY_INFORMATION) PolicyDnsDomainInfo
  927. );
  928. PolicyDnsDomainInfo = NULL;
  929. }
  930. //
  931. // If we locked all of the locks,
  932. // drop them now.
  933. //
  934. if ( AllLocksLocked ) {
  935. LsapDbReleaseLockEx( AllObject, 0 );
  936. }
  937. //
  938. // Free any Attribute Value buffers allocated.
  939. //
  940. SecondaryStatus = LsapDbFreeAttributes( AttributeCount, Attributes );
  941. if (!NT_SUCCESS(SecondaryStatus)) {
  942. goto CreateTrustedDomainError;
  943. }
  944. //
  945. // If necessary, free the Unicode String buffer allocated for the
  946. // Logical Name.
  947. //
  948. if ( !LsapDsWriteDs && LogicalNameU.Length > 0 ) {
  949. RtlFreeUnicodeString(&LogicalNameU);
  950. LogicalNameU.Length = 0;
  951. }
  952. //
  953. // If necessary, release the Trusted Domain List Write Lock.
  954. //
  955. if (AcquiredListWriteLock) {
  956. LsapDbReleaseLockTrustedDomainList();
  957. AcquiredListWriteLock = FALSE;
  958. }
  959. LsapExitFunc( "LsapCreateTrustedDomain2", Status );
  960. LsarpReturnPrologue();
  961. return(Status);
  962. CreateTrustedDomainError:
  963. //
  964. // If necessary, dereference the client Policy Handle and release the
  965. // LSA Database lock.
  966. //
  967. LsapDbSetStatusFromSecondary( Status, SecondaryStatus );
  968. if (ClientPolicyHandleReferenced) {
  969. Status = LsapDbDereferenceObject(
  970. &PolicyHandle,
  971. PolicyObject,
  972. TrustedDomainObject,
  973. LSAP_DB_LOCK,
  974. (SECURITY_DB_DELTA_TYPE) 0,
  975. Status
  976. );
  977. ClientPolicyHandleReferenced = FALSE;
  978. }
  979. //
  980. // If necessary, delete the trusted domain object
  981. //
  982. if ( TrustCreated ) {
  983. //
  984. // We don't want to dereference the container handle. Because we already did!
  985. // Just delete it and replace it back.
  986. //
  987. LSAP_DB_HANDLE Container = InternalTrustedDomainHandle->ContainerHandle;
  988. InternalTrustedDomainHandle->ContainerHandle = NULL;
  989. LsarDeleteObject( TrustedDomainHandle );
  990. InternalTrustedDomainHandle->ContainerHandle = Container;
  991. }
  992. goto CreateTrustedDomainFinish;
  993. }
  994. NTSTATUS
  995. LsarOpenTrustedDomain(
  996. IN LSAPR_HANDLE PolicyHandle,
  997. IN PLSAPR_SID TrustedDomainSid,
  998. IN ACCESS_MASK DesiredAccess,
  999. OUT PLSAPR_HANDLE TrustedDomainHandle
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. The LsaOpenTrustedDomain API opens an existing TrustedDomain object
  1004. using the SID as the primary key value.
  1005. Arguments:
  1006. PolicyHandle - An open handle to a Policy object.
  1007. TrustedDomainSid - Pointer to the trust's Sid.
  1008. DesiredAccess - This is an access mask indicating accesses being
  1009. requested to the target object.
  1010. TrustedDomainHandle - Receives a handle to be used in future requests.
  1011. Return Values:
  1012. NTSTATUS - Standard Nt Result Code
  1013. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1014. to complete the operation.
  1015. STATUS_TRUSTED_DOMAIN_NOT_FOUND - There is no TrustedDomain object in the
  1016. target system's LSA Database having the specified AccountSid.
  1017. --*/
  1018. {
  1019. NTSTATUS Status;
  1020. LsarpReturnCheckSetup();
  1021. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_OpenTrustedDomain);
  1022. //
  1023. // Call the internal routine. Caller is not trusted and the Database
  1024. // lock needs to be acquired.
  1025. //
  1026. Status = LsapDbOpenTrustedDomain(
  1027. PolicyHandle,
  1028. (PSID) TrustedDomainSid,
  1029. DesiredAccess,
  1030. TrustedDomainHandle,
  1031. LSAP_DB_LOCK |
  1032. LSAP_DB_READ_ONLY_TRANSACTION |
  1033. LSAP_DB_DS_OP_TRANSACTION
  1034. );
  1035. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_OpenTrustedDomain);
  1036. LsarpReturnPrologue();
  1037. return(Status);
  1038. }
  1039. NTSTATUS
  1040. LsapDbOpenTrustedDomain(
  1041. IN LSAPR_HANDLE PolicyHandle,
  1042. IN PSID TrustedDomainSid,
  1043. IN ACCESS_MASK DesiredAccess,
  1044. OUT PLSAPR_HANDLE TrustedDomainHandle,
  1045. IN ULONG Options
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. This function opens a Trusted Domain Object, optionally with
  1050. trusted access.
  1051. Arguments:
  1052. PolicyHandle - An open handle to a Policy object.
  1053. TrustedDomainSid - Pointer to the account's Sid.
  1054. DesiredAccess - This is an access mask indicating accesses being
  1055. requested to the target object.
  1056. TrustedDomainHandle - Receives a handle to be used in future requests.
  1057. Options - Specifies option flags
  1058. LSAP_DB_LOCK - Acquire the Lsa Database lock for the
  1059. duration of the open operation.
  1060. LSAP_DB_TRUSTED - Always generate a Trusted Handle to the opened
  1061. object. If not specified, the trust status of the returned
  1062. handle is inherited from the PolicyHandle as container object.
  1063. Return Values:
  1064. NTSTATUS - Standard Nt Result Code
  1065. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1066. to complete the operation.
  1067. STATUS_TRUSTED_DOMAIN_NOT_FOUND - There is no TrustedDomain object in the
  1068. target system's LSA Database having the specified AccountSid.
  1069. --*/
  1070. {
  1071. NTSTATUS Status, SecondaryStatus;
  1072. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  1073. UNICODE_STRING LogicalNameU;
  1074. BOOLEAN ContainerReferenced = FALSE;
  1075. BOOLEAN AcquiredLock = FALSE;
  1076. ULONG DerefOptions = 0;
  1077. RtlZeroMemory(&LogicalNameU,sizeof(UNICODE_STRING));
  1078. //
  1079. // Validate that the Ds is up and running. If it isn't, there aren't any trusted domains
  1080. //
  1081. if ( !LsaDsStateInfo.UseDs &&
  1082. !FLAG_ON( ( ( LSAP_DB_HANDLE )PolicyHandle )->Options, LSAP_DB_HANDLE_UPGRADE ) ) {
  1083. Status = STATUS_DIRECTORY_SERVICE_REQUIRED;
  1084. goto OpenTrustedDomainError;
  1085. }
  1086. //
  1087. // Validate the Trusted Domain Sid.
  1088. //
  1089. if (!RtlValidSid( TrustedDomainSid )) {
  1090. Status = STATUS_INVALID_PARAMETER;
  1091. goto OpenTrustedDomainError;
  1092. }
  1093. //
  1094. // Acquire the Lsa Database lock. Verify that the connection handle
  1095. // (container object handle) is valid, and is of the expected type.
  1096. // Reference the container object handle. This reference remains in
  1097. // effect until the child object handle is closed.
  1098. //
  1099. DerefOptions |= Options;
  1100. Status = LsapDbReferenceObject(
  1101. PolicyHandle,
  1102. 0,
  1103. PolicyObject,
  1104. TrustedDomainObject,
  1105. Options
  1106. );
  1107. if (!NT_SUCCESS(Status)) {
  1108. goto OpenTrustedDomainError;
  1109. }
  1110. ContainerReferenced =TRUE;
  1111. if (Options & LSAP_DB_LOCK) {
  1112. DerefOptions |= LSAP_DB_LOCK;
  1113. AcquiredLock = TRUE;
  1114. }
  1115. //
  1116. // Setup Object Information prior to calling the Object
  1117. // Open routine. The Object Type, Container Object Type and
  1118. // Logical Name (derived from the Sid) need to be filled in.
  1119. //
  1120. ObjectInformation.ObjectTypeId = TrustedDomainObject;
  1121. ObjectInformation.ContainerTypeId = PolicyObject;
  1122. ObjectInformation.Sid = TrustedDomainSid;
  1123. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  1124. ObjectInformation.DesiredObjectAccess = DesiredAccess;
  1125. //
  1126. // Construct the Logical Name of the Trusted Domain object. The Logical
  1127. // Name is constructed from the Trusted Domain Sid by extracting the
  1128. // Relative Id (lowest subauthority) and converting it to an 8-digit
  1129. // numeric Unicode String in which leading zeros are added if needed.
  1130. //
  1131. if ( LsapDsWriteDs ) {
  1132. LSAPR_TRUST_INFORMATION InputTrustInformation;
  1133. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  1134. //
  1135. // Lookup the cache to find the domain
  1136. //
  1137. Status = LsapDbAcquireReadLockTrustedDomainList();
  1138. if (!NT_SUCCESS(Status)) {
  1139. goto OpenTrustedDomainError;
  1140. }
  1141. RtlZeroMemory(&InputTrustInformation.Name,sizeof(UNICODE_STRING));
  1142. InputTrustInformation.Sid = TrustedDomainSid;
  1143. Status = LsapDbLookupEntryTrustedDomainList(
  1144. &InputTrustInformation,
  1145. &TrustEntry
  1146. );
  1147. if (!NT_SUCCESS(Status))
  1148. {
  1149. LsapDbReleaseLockTrustedDomainList();
  1150. goto OpenTrustedDomainError;
  1151. }
  1152. LogicalNameU.Buffer = LsapAllocateLsaHeap(TrustEntry->TrustInfoEx.Name.MaximumLength);
  1153. if (NULL==LogicalNameU.Buffer)
  1154. {
  1155. LsapDbReleaseLockTrustedDomainList();
  1156. Status = STATUS_INSUFFICIENT_RESOURCES;
  1157. goto OpenTrustedDomainError;
  1158. }
  1159. LogicalNameU.Length = TrustEntry->TrustInfoEx.Name.Length;
  1160. LogicalNameU.MaximumLength = TrustEntry->TrustInfoEx.Name.MaximumLength;
  1161. RtlCopyMemory(LogicalNameU.Buffer,TrustEntry->TrustInfoEx.Name.Buffer,LogicalNameU.Length);
  1162. LsapDbReleaseLockTrustedDomainList();
  1163. } else {
  1164. Status = LsapDbSidToLogicalNameObject( TrustedDomainSid, &LogicalNameU );
  1165. }
  1166. if (!NT_SUCCESS(Status)) {
  1167. goto OpenTrustedDomainError;
  1168. }
  1169. //
  1170. // Initialize the Object Attributes. The Container Object Handle and
  1171. // Logical Name (Internal Name) of the object must be set up.
  1172. //
  1173. InitializeObjectAttributes(
  1174. &ObjectInformation.ObjectAttributes,
  1175. &LogicalNameU,
  1176. 0,
  1177. PolicyHandle,
  1178. NULL
  1179. );
  1180. //
  1181. // Open the specific Trusted Domain object. Note that the
  1182. // handle returned is an RPC Context Handle.
  1183. //
  1184. Status = LsapDbOpenObject(
  1185. &ObjectInformation,
  1186. DesiredAccess,
  1187. Options,
  1188. TrustedDomainHandle
  1189. );
  1190. RtlFreeUnicodeString( &LogicalNameU );
  1191. if (!NT_SUCCESS(Status)) {
  1192. goto OpenTrustedDomainError;
  1193. }
  1194. OpenTrustedDomainFinish:
  1195. //
  1196. // If necessary, release the LSA Database lock. Note that object
  1197. // remains referenced unless we came here via error.
  1198. //
  1199. if (AcquiredLock) {
  1200. LsapDbApplyTransaction( PolicyHandle,
  1201. LSAP_DB_DS_OP_TRANSACTION |
  1202. LSAP_DB_READ_ONLY_TRANSACTION,
  1203. (SECURITY_DB_DELTA_TYPE) 0 );
  1204. LsapDbReleaseLockEx( TrustedDomainObject,
  1205. DerefOptions );
  1206. }
  1207. return( Status );
  1208. OpenTrustedDomainError:
  1209. //
  1210. // If necessary, dereference the Container Object handle. Note that
  1211. // this is only done in the error case. In the non-error case, the
  1212. // Container handle stays referenced until the TrustedDomain object is
  1213. // closed.
  1214. //
  1215. if ( ContainerReferenced ) {
  1216. *TrustedDomainHandle = NULL;
  1217. SecondaryStatus = LsapDbDereferenceObject(
  1218. &PolicyHandle,
  1219. PolicyObject,
  1220. TrustedDomainObject,
  1221. DerefOptions,
  1222. (SECURITY_DB_DELTA_TYPE) 0,
  1223. Status
  1224. );
  1225. if ( FLAG_ON( Options, LSAP_DB_LOCK ) ) {
  1226. DerefOptions &= ~LSAP_DB_LOCK;
  1227. DerefOptions |= LSAP_DB_NO_LOCK;
  1228. }
  1229. LsapDbSetStatusFromSecondary( Status, SecondaryStatus );
  1230. }
  1231. goto OpenTrustedDomainFinish;
  1232. }
  1233. NTSTATUS
  1234. LsarQueryInfoTrustedDomain(
  1235. IN LSAPR_HANDLE TrustedDomainHandle,
  1236. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1237. OUT PLSAPR_TRUSTED_DOMAIN_INFO *Buffer
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. This function is the LSA server RPC worker routine for the
  1242. LsaQueryInfoTrustedDomain API.
  1243. The LsaQueryInfoTrustedDomain API obtains information from a
  1244. TrustedDomain object. The caller must have access appropriate to the
  1245. information being requested (see InformationClass parameter).
  1246. Arguments:
  1247. PolicyHandle - Handle from an LsaOpenPolicy call.
  1248. InformationClass - Specifies the information to be returned. The
  1249. Information Classes and accesses required are as follows:
  1250. Information Class Required Access Type
  1251. TrustedDomainNameInformation TRUSTED_QUERY_ACCOUNT_NAME
  1252. TrustedControllersInformation TRUSTED_QUERY_CONTROLLERS
  1253. TrustedPosixInformation TRUSTED_QUERY_POSIX
  1254. Buffer - Receives a pointer to the buffer returned comtaining the
  1255. requested information. This buffer is allocated by this service
  1256. and must be freed when no longer needed by passing the returned
  1257. value to LsaFreeMemory().
  1258. Return Value:
  1259. NTSTATUS - Standard Nt Result Code
  1260. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1261. access to complete the operation.
  1262. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  1263. such as memory, to complete the call.
  1264. --*/
  1265. {
  1266. NTSTATUS Status, ReadAttributesStatus;
  1267. PTRUSTED_DOMAIN_NAME_INFO TrustedDomainNameInfo;
  1268. PTRUSTED_POSIX_OFFSET_INFO TrustedPosixOffsetInfo;
  1269. PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInfoEx;
  1270. PTRUSTED_DOMAIN_AUTH_INFORMATION TrustedDomainAuthInfo;
  1271. PTRUSTED_DOMAIN_FULL_INFORMATION TrustedDomainFullInfo;
  1272. PTRUSTED_DOMAIN_FULL_INFORMATION2 TrustedDomainFullInfo2;
  1273. LSAPR_TRUST_DOMAIN_AUTH_INFO_HALF AuthInfoHalf;
  1274. BOOLEAN ObjectReferenced = FALSE;
  1275. ACCESS_MASK DesiredAccess;
  1276. ULONG AttributeCount = 0;
  1277. ULONG AttributeNumber = 0;
  1278. PVOID InformationBuffer = NULL;
  1279. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_INFO_CLASS_DOMAIN];
  1280. PLSAP_DB_ATTRIBUTE NextAttribute;
  1281. BOOLEAN InfoBufferInAttributeArray = TRUE;
  1282. ULONG TrustedPosixOffset = 0, TrustDirection = 0, TrustType = 0, TrustAttributes = 0;
  1283. LsarpReturnCheckSetup();
  1284. LsapEnterFunc( "LsarQueryInfoTrustedDomain\n" );
  1285. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_QueryInfoTrustedDomain);
  1286. //
  1287. // Validate the Information Class and determine the access required to
  1288. // query this Trusted Domain Information Class.
  1289. //
  1290. Status = LsapDbVerifyInfoQueryTrustedDomain(
  1291. InformationClass,
  1292. FALSE,
  1293. &DesiredAccess
  1294. );
  1295. if (!NT_SUCCESS(Status)) {
  1296. goto QueryInfoTrustedDomainError;
  1297. }
  1298. //
  1299. // We don't currently allow querying of the auth data, so there's no need
  1300. // to support returning encrypted auth data.
  1301. //
  1302. if ( InformationClass == TrustedDomainAuthInformationInternal ||
  1303. InformationClass == TrustedDomainFullInformationInternal ) {
  1304. Status = STATUS_INVALID_INFO_CLASS;
  1305. goto QueryInfoTrustedDomainError;
  1306. }
  1307. //
  1308. // Acquire the Lsa Database lock. Verify that the handle is a valid
  1309. // handle to a TrustedDomain object and has the necessary access granted.
  1310. // Reference the handle.
  1311. //
  1312. //
  1313. // If this is the open handle to a trusted domain object being treated as a secret object,
  1314. // we already have a transaction going, so don't start one here.
  1315. //
  1316. if ( !FLAG_ON( ((LSAP_DB_HANDLE)TrustedDomainHandle)->Options,
  1317. LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET )) {
  1318. Status = LsapDbReferenceObject(
  1319. TrustedDomainHandle,
  1320. DesiredAccess,
  1321. TrustedDomainObject,
  1322. TrustedDomainObject,
  1323. LSAP_DB_LOCK |
  1324. LSAP_DB_READ_ONLY_TRANSACTION |
  1325. LSAP_DB_DS_OP_TRANSACTION );
  1326. if (!NT_SUCCESS(Status)) {
  1327. goto QueryInfoTrustedDomainError;
  1328. }
  1329. ObjectReferenced = TRUE;
  1330. }
  1331. //
  1332. // Compile a list of the attributes that hold the Trusted Domain Information of
  1333. // the specified class.
  1334. //
  1335. NextAttribute = Attributes;
  1336. switch (InformationClass) {
  1337. case TrustedDomainNameInformation:
  1338. //
  1339. // Request read of the Trusted Account Name Information.
  1340. //
  1341. LsapDbInitializeAttributeDs(
  1342. NextAttribute,
  1343. TrDmTrPN,
  1344. NULL,
  1345. 0,
  1346. FALSE
  1347. );
  1348. AttributeCount++;
  1349. break;
  1350. case TrustedPosixOffsetInformation:
  1351. //
  1352. // Request read of the Trusted Posix Offset Information.
  1353. //
  1354. LsapDbInitializeAttributeDs(
  1355. NextAttribute,
  1356. TrDmPxOf,
  1357. &TrustedPosixOffset,
  1358. sizeof(ULONG),
  1359. FALSE
  1360. );
  1361. AttributeCount++;
  1362. break;
  1363. case TrustedDomainInformationEx:
  1364. //
  1365. // Request just about everything...
  1366. //
  1367. LsapDbInitializeAttributeDs(
  1368. NextAttribute,
  1369. TrDmName,
  1370. NULL,
  1371. 0,
  1372. FALSE
  1373. );
  1374. AttributeCount++;
  1375. NextAttribute++;
  1376. LsapDbInitializeAttributeDs(
  1377. NextAttribute,
  1378. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmTrPN : TrDmName,
  1379. NULL,
  1380. 0,
  1381. FALSE
  1382. );
  1383. AttributeCount++;
  1384. NextAttribute++;
  1385. LsapDbInitializeAttributeDs(
  1386. NextAttribute,
  1387. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmSid : Sid,
  1388. NULL,
  1389. 0,
  1390. FALSE
  1391. );
  1392. //
  1393. // In the DS, it is possible to have an entry with a NULL sid. If FULL info is
  1394. // being collected, make sure to allow the read to happen if a NULL is encountered
  1395. //
  1396. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1397. NextAttribute->CanDefaultToZero = TRUE;
  1398. }
  1399. AttributeCount++;
  1400. NextAttribute++;
  1401. LsapDbInitializeAttributeDs(
  1402. NextAttribute,
  1403. TrDmPxOf,
  1404. &TrustedPosixOffset,
  1405. sizeof(ULONG),
  1406. FALSE
  1407. );
  1408. AttributeCount++;
  1409. NextAttribute++;
  1410. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1411. LsapDbInitializeAttributeDs(
  1412. NextAttribute,
  1413. TrDmTrTy,
  1414. &TrustType,
  1415. sizeof( TrustType ),
  1416. FALSE
  1417. );
  1418. NextAttribute++;
  1419. AttributeCount++;
  1420. LsapDbInitializeAttributeDs(
  1421. NextAttribute,
  1422. TrDmTrDi,
  1423. &TrustDirection,
  1424. sizeof( TrustDirection ),
  1425. FALSE
  1426. );
  1427. NextAttribute++;
  1428. AttributeCount++;
  1429. LsapDbInitializeAttributeDs(
  1430. NextAttribute,
  1431. TrDmTrLA,
  1432. &TrustAttributes,
  1433. sizeof( TrustAttributes ),
  1434. FALSE
  1435. );
  1436. LsapDbAttributeCanNotExist( NextAttribute );
  1437. NextAttribute++;
  1438. AttributeCount++;
  1439. }
  1440. break;
  1441. case TrustedDomainAuthInformation:
  1442. //
  1443. // Only allow query of AuthInformation by trusted client.
  1444. //
  1445. // (And global not set for debugging purposes.)
  1446. //
  1447. if ( !((LSAP_DB_HANDLE)TrustedDomainHandle)->Trusted &&
  1448. !LsapDbReturnAuthData ) {
  1449. Status = STATUS_INVALID_INFO_CLASS;
  1450. goto QueryInfoTrustedDomainError;
  1451. }
  1452. //
  1453. // Get the auth info...
  1454. //
  1455. LsapDbInitializeAttributeDs(
  1456. NextAttribute,
  1457. TrDmSAI,
  1458. NULL,
  1459. 0,
  1460. FALSE
  1461. );
  1462. LsapDbAttributeCanNotExist( NextAttribute );
  1463. AttributeCount++;
  1464. NextAttribute++;
  1465. LsapDbInitializeAttributeDs(
  1466. NextAttribute,
  1467. TrDmSAO,
  1468. NULL,
  1469. 0,
  1470. FALSE
  1471. );
  1472. LsapDbAttributeCanNotExist( NextAttribute );
  1473. AttributeCount++;
  1474. NextAttribute++;
  1475. break;
  1476. case TrustedDomainFullInformation:
  1477. //
  1478. // Request read of the Trusted Posix Offset Information.
  1479. //
  1480. LsapDbInitializeAttributeDs(
  1481. NextAttribute,
  1482. TrDmPxOf,
  1483. &TrustedPosixOffset,
  1484. sizeof(ULONG),
  1485. FALSE
  1486. );
  1487. NextAttribute++;
  1488. AttributeCount++;
  1489. //
  1490. // Request just about everything...
  1491. //
  1492. LsapDbInitializeAttributeDs(
  1493. NextAttribute,
  1494. TrDmName,
  1495. NULL,
  1496. 0,
  1497. FALSE
  1498. );
  1499. AttributeCount++;
  1500. NextAttribute++;
  1501. LsapDbInitializeAttributeDs(
  1502. NextAttribute,
  1503. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmTrPN : TrDmName,
  1504. NULL,
  1505. 0,
  1506. FALSE
  1507. );
  1508. AttributeCount++;
  1509. NextAttribute++;
  1510. LsapDbInitializeAttributeDs(
  1511. NextAttribute,
  1512. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmSid : Sid,
  1513. NULL,
  1514. 0,
  1515. FALSE
  1516. );
  1517. //
  1518. // In the DS, it is possible to have an entry with a NULL sid. If FULL info is
  1519. // being collected, make sure to allow the read to happen if a NULL is encountered
  1520. //
  1521. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1522. NextAttribute->CanDefaultToZero = TRUE;
  1523. }
  1524. AttributeCount++;
  1525. NextAttribute++;
  1526. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1527. LsapDbInitializeAttributeDs(
  1528. NextAttribute,
  1529. TrDmTrTy,
  1530. &TrustType,
  1531. sizeof( TrustType ),
  1532. FALSE
  1533. );
  1534. NextAttribute++;
  1535. AttributeCount++;
  1536. LsapDbInitializeAttributeDs(
  1537. NextAttribute,
  1538. TrDmTrDi,
  1539. &TrustDirection,
  1540. sizeof( TrustDirection ),
  1541. FALSE
  1542. );
  1543. NextAttribute++;
  1544. AttributeCount++;
  1545. LsapDbInitializeAttributeDs(
  1546. NextAttribute,
  1547. TrDmTrLA,
  1548. &TrustAttributes,
  1549. sizeof( TrustAttributes ),
  1550. FALSE
  1551. );
  1552. LsapDbAttributeCanNotExist( NextAttribute );
  1553. NextAttribute++;
  1554. AttributeCount++;
  1555. }
  1556. //
  1557. // Get the auth info...
  1558. //
  1559. LsapDbInitializeAttributeDs(
  1560. NextAttribute,
  1561. TrDmSAI,
  1562. NULL,
  1563. 0,
  1564. FALSE
  1565. );
  1566. LsapDbAttributeCanNotExist( NextAttribute );
  1567. AttributeCount++;
  1568. NextAttribute++;
  1569. LsapDbInitializeAttributeDs(
  1570. NextAttribute,
  1571. TrDmSAO,
  1572. NULL,
  1573. 0,
  1574. FALSE
  1575. );
  1576. LsapDbAttributeCanNotExist( NextAttribute );
  1577. AttributeCount++;
  1578. NextAttribute++;
  1579. break;
  1580. case TrustedDomainFullInformation2Internal:
  1581. //
  1582. // Request read of the Trusted Posix Offset Information.
  1583. //
  1584. LsapDbInitializeAttributeDs(
  1585. NextAttribute,
  1586. TrDmPxOf,
  1587. &TrustedPosixOffset,
  1588. sizeof(ULONG),
  1589. FALSE
  1590. );
  1591. NextAttribute++;
  1592. AttributeCount++;
  1593. //
  1594. // Request just about everything...
  1595. //
  1596. LsapDbInitializeAttributeDs(
  1597. NextAttribute,
  1598. TrDmName,
  1599. NULL,
  1600. 0,
  1601. FALSE
  1602. );
  1603. AttributeCount++;
  1604. NextAttribute++;
  1605. LsapDbInitializeAttributeDs(
  1606. NextAttribute,
  1607. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmTrPN : TrDmName,
  1608. NULL,
  1609. 0,
  1610. FALSE
  1611. );
  1612. AttributeCount++;
  1613. NextAttribute++;
  1614. LsapDbInitializeAttributeDs(
  1615. NextAttribute,
  1616. LsapDsIsWriteDs( TrustedDomainHandle ) ? TrDmSid : Sid,
  1617. NULL,
  1618. 0,
  1619. FALSE
  1620. );
  1621. //
  1622. // In the DS, it is possible to have an entry with a NULL sid. If FULL info is
  1623. // being collected, make sure to allow the read to happen if a NULL is encountered
  1624. //
  1625. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1626. NextAttribute->CanDefaultToZero = TRUE;
  1627. }
  1628. AttributeCount++;
  1629. NextAttribute++;
  1630. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1631. LsapDbInitializeAttributeDs(
  1632. NextAttribute,
  1633. TrDmTrTy,
  1634. &TrustType,
  1635. sizeof( TrustType ),
  1636. FALSE
  1637. );
  1638. NextAttribute++;
  1639. AttributeCount++;
  1640. LsapDbInitializeAttributeDs(
  1641. NextAttribute,
  1642. TrDmTrDi,
  1643. &TrustDirection,
  1644. sizeof( TrustDirection ),
  1645. FALSE
  1646. );
  1647. NextAttribute++;
  1648. AttributeCount++;
  1649. LsapDbInitializeAttributeDs(
  1650. NextAttribute,
  1651. TrDmTrLA,
  1652. &TrustAttributes,
  1653. sizeof( TrustAttributes ),
  1654. FALSE
  1655. );
  1656. LsapDbAttributeCanNotExist( NextAttribute );
  1657. NextAttribute++;
  1658. AttributeCount++;
  1659. LsapDbInitializeAttributeDs(
  1660. NextAttribute,
  1661. TrDmForT,
  1662. NULL,
  1663. 0,
  1664. FALSE
  1665. );
  1666. LsapDbAttributeCanNotExist( NextAttribute );
  1667. AttributeCount++;
  1668. NextAttribute++;
  1669. }
  1670. //
  1671. // Get the auth info...
  1672. //
  1673. LsapDbInitializeAttributeDs(
  1674. NextAttribute,
  1675. TrDmSAI,
  1676. NULL,
  1677. 0,
  1678. FALSE
  1679. );
  1680. LsapDbAttributeCanNotExist( NextAttribute );
  1681. AttributeCount++;
  1682. NextAttribute++;
  1683. LsapDbInitializeAttributeDs(
  1684. NextAttribute,
  1685. TrDmSAO,
  1686. NULL,
  1687. 0,
  1688. FALSE
  1689. );
  1690. LsapDbAttributeCanNotExist( NextAttribute );
  1691. AttributeCount++;
  1692. NextAttribute++;
  1693. break;
  1694. default:
  1695. Status = STATUS_INVALID_PARAMETER;
  1696. break;
  1697. }
  1698. if (!NT_SUCCESS(Status)) {
  1699. goto QueryInfoTrustedDomainError;
  1700. }
  1701. ASSERT( AttributeCount <= LSAP_DB_ATTRS_INFO_CLASS_DOMAIN );
  1702. //
  1703. //
  1704. // Read the attributes corresponding to the given Policy Information
  1705. // Class. Memory will be allocated where required via MIDL_user_allocate
  1706. // for attribute values.
  1707. //
  1708. Status = LsapDbReadAttributesObject(
  1709. TrustedDomainHandle,
  1710. 0,
  1711. Attributes,
  1712. AttributeCount
  1713. );
  1714. ReadAttributesStatus = Status;
  1715. if (!NT_SUCCESS(Status)) {
  1716. //
  1717. // If the error was that one or more of the attributes holding
  1718. // the information of the given class was not found, continue.
  1719. // Otherwise, return an error.
  1720. //
  1721. goto QueryInfoTrustedDomainError;
  1722. }
  1723. //
  1724. // If we are not in .NET forest mode, behave as if the forest transitive
  1725. // bit did not exist
  1726. //
  1727. if ( !LsapDbNoMoreWin2KForest()) {
  1728. TrustAttributes &= ~TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
  1729. }
  1730. //
  1731. // Now copy the information read to the output. For certain information
  1732. // classes where the information is stored as the value of a single
  1733. // attribute of the Policy object and is in the form required by the
  1734. // caller, we can just return the pointer to this buffer. For all
  1735. // other cases, an output buffer structure tree of the form desired
  1736. // must be allocated via MIDL_user_allocate() and the information read from the attribute(s) of
  1737. // the Policy object must be copied in. These buffers must then be freed
  1738. // by this routine before exit. The array of attribute information
  1739. // filled in by LsapDbReadAttributes() has MemoryAllocated = TRUE
  1740. // in all cases. We reset this flag to FALSE in the simple cases where
  1741. // we can use the buffer as is. The Finish section of the routine
  1742. // will free up any buffers referenced by the AttributeValue pointer
  1743. // in the attribute array where MemoryAllocated is still TRUE. If
  1744. // we go to error, the error processing is responsible for freeing
  1745. // those buffers which would be passed to the calling RPC server stub
  1746. // in the non-error case.
  1747. //
  1748. NextAttribute = Attributes;
  1749. switch (InformationClass) {
  1750. case TrustedDomainNameInformation:
  1751. //
  1752. // Allocate memory for output buffer top-level structure.
  1753. //
  1754. TrustedDomainNameInfo =
  1755. MIDL_user_allocate(sizeof(TRUSTED_DOMAIN_NAME_INFO));
  1756. if (TrustedDomainNameInfo == NULL) {
  1757. Status = STATUS_NO_MEMORY;
  1758. goto QueryInfoTrustedDomainError;
  1759. }
  1760. InfoBufferInAttributeArray = FALSE;
  1761. InformationBuffer = TrustedDomainNameInfo;
  1762. //
  1763. // Copy the Unicode Name field to the output. Original buffer will
  1764. // be freed in Finish section.
  1765. //
  1766. Status = LsapDbCopyUnicodeAttribute(
  1767. &TrustedDomainNameInfo->Name,
  1768. NextAttribute,
  1769. TRUE
  1770. );
  1771. if (!NT_SUCCESS(Status)) {
  1772. goto QueryInfoTrustedDomainError;
  1773. }
  1774. NextAttribute++;
  1775. break;
  1776. case TrustedPosixOffsetInformation:
  1777. //
  1778. // Allocate memory for top-level output buffer.
  1779. //
  1780. InformationBuffer = NextAttribute->AttributeValue;
  1781. TrustedPosixOffsetInfo = MIDL_user_allocate(sizeof(TRUSTED_POSIX_OFFSET_INFO));
  1782. if (TrustedPosixOffsetInfo == NULL) {
  1783. Status = STATUS_INSUFFICIENT_RESOURCES;
  1784. break;
  1785. }
  1786. InfoBufferInAttributeArray = FALSE;
  1787. //
  1788. // Copy Posix Offset value to output.
  1789. //
  1790. TrustedPosixOffsetInfo->Offset = TrustedPosixOffset;
  1791. InformationBuffer = TrustedPosixOffsetInfo;
  1792. break;
  1793. case TrustedDomainInformationEx:
  1794. //
  1795. // Allocate memory for output buffer top-level structure.
  1796. //
  1797. TrustedDomainInfoEx =
  1798. MIDL_user_allocate( sizeof( TRUSTED_DOMAIN_INFORMATION_EX ) );
  1799. if (TrustedDomainInfoEx == NULL) {
  1800. Status = STATUS_INSUFFICIENT_RESOURCES;
  1801. goto QueryInfoTrustedDomainError;
  1802. }
  1803. InfoBufferInAttributeArray = FALSE;
  1804. //
  1805. // Copy the Unicode Name field to the output. Original buffer will
  1806. // be freed in Finish section.
  1807. //
  1808. Status = LsapDbCopyUnicodeAttribute(
  1809. &TrustedDomainInfoEx->Name,
  1810. NextAttribute,
  1811. TRUE
  1812. );
  1813. if (!NT_SUCCESS(Status)) {
  1814. MIDL_user_free( TrustedDomainInfoEx );
  1815. goto QueryInfoTrustedDomainError;
  1816. }
  1817. NextAttribute++;
  1818. //
  1819. // Netbios name
  1820. //
  1821. Status = LsapDbCopyUnicodeAttribute(
  1822. &TrustedDomainInfoEx->FlatName,
  1823. NextAttribute,
  1824. TRUE
  1825. );
  1826. if (!NT_SUCCESS(Status)) {
  1827. MIDL_user_free( TrustedDomainInfoEx->Name.Buffer );
  1828. MIDL_user_free( TrustedDomainInfoEx );
  1829. goto QueryInfoTrustedDomainError;
  1830. }
  1831. NextAttribute++;
  1832. if ( NextAttribute->AttributeValueLength != 0 ) {
  1833. TrustedDomainInfoEx->Sid = MIDL_user_allocate( NextAttribute->AttributeValueLength );
  1834. if ( TrustedDomainInfoEx->Sid == NULL ) {
  1835. MIDL_user_free( TrustedDomainInfoEx->Name.Buffer );
  1836. MIDL_user_free( TrustedDomainInfoEx->FlatName.Buffer );
  1837. MIDL_user_free( TrustedDomainInfoEx );
  1838. Status = STATUS_INSUFFICIENT_RESOURCES;
  1839. goto QueryInfoTrustedDomainError;
  1840. }
  1841. RtlCopyMemory( TrustedDomainInfoEx->Sid, NextAttribute->AttributeValue,
  1842. NextAttribute->AttributeValueLength );
  1843. } else {
  1844. TrustedDomainInfoEx->Sid = NULL;
  1845. }
  1846. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1847. TrustedDomainInfoEx->TrustDirection = TrustDirection;
  1848. TrustedDomainInfoEx->TrustType = TrustType;
  1849. TrustedDomainInfoEx->TrustAttributes = TrustAttributes;
  1850. } else {
  1851. TrustedDomainInfoEx->TrustDirection = TRUST_DIRECTION_OUTBOUND;
  1852. TrustedDomainInfoEx->TrustType = TRUST_TYPE_DOWNLEVEL;
  1853. TrustedDomainInfoEx->TrustAttributes = 0;
  1854. }
  1855. InformationBuffer = TrustedDomainInfoEx;
  1856. NextAttribute++;
  1857. break;
  1858. case TrustedDomainAuthInformation:
  1859. TrustedDomainAuthInfo = (PTRUSTED_DOMAIN_AUTH_INFORMATION)
  1860. MIDL_user_allocate( sizeof( TRUSTED_DOMAIN_AUTH_INFORMATION ) );
  1861. if ( TrustedDomainAuthInfo == NULL ) {
  1862. Status = STATUS_INSUFFICIENT_RESOURCES;
  1863. goto QueryInfoTrustedDomainError;
  1864. }
  1865. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  1866. NextAttribute->AttributeValue,
  1867. NextAttribute->AttributeValueLength,
  1868. &AuthInfoHalf );
  1869. if ( NT_SUCCESS( Status ) ) {
  1870. RtlCopyMemory( TrustedDomainAuthInfo, &AuthInfoHalf, sizeof( AuthInfoHalf ) );
  1871. NextAttribute++;
  1872. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  1873. NextAttribute->AttributeValue,
  1874. NextAttribute->AttributeValueLength,
  1875. &AuthInfoHalf );
  1876. if ( NT_SUCCESS( Status ) ) {
  1877. TrustedDomainAuthInfo->OutgoingAuthInfos = AuthInfoHalf.AuthInfos;
  1878. TrustedDomainAuthInfo->OutgoingAuthenticationInformation =
  1879. (PLSA_AUTH_INFORMATION)AuthInfoHalf.AuthenticationInformation;
  1880. TrustedDomainAuthInfo->OutgoingPreviousAuthenticationInformation =
  1881. (PLSA_AUTH_INFORMATION)AuthInfoHalf.PreviousAuthenticationInformation;
  1882. } else {
  1883. LsapDsFreeUnmarshaledAuthInfo(
  1884. TrustedDomainAuthInfo->IncomingAuthInfos,
  1885. (PLSAPR_AUTH_INFORMATION)TrustedDomainAuthInfo->
  1886. IncomingAuthenticationInformation );
  1887. }
  1888. }
  1889. if ( !NT_SUCCESS( Status ) ) {
  1890. MIDL_user_free( TrustedDomainAuthInfo );
  1891. goto QueryInfoTrustedDomainError;
  1892. }
  1893. InformationBuffer = TrustedDomainAuthInfo;
  1894. break;
  1895. case TrustedDomainFullInformation:
  1896. //
  1897. // Allocate memory for top-level output buffer.
  1898. //
  1899. InformationBuffer = NextAttribute->AttributeValue;
  1900. TrustedDomainFullInfo = MIDL_user_allocate(sizeof( TRUSTED_DOMAIN_FULL_INFORMATION ));
  1901. if (TrustedDomainFullInfo == NULL) {
  1902. Status = STATUS_INSUFFICIENT_RESOURCES;
  1903. goto QueryInfoTrustedDomainError;
  1904. }
  1905. InfoBufferInAttributeArray = FALSE;
  1906. //
  1907. // Copy Posix Offset value to output.
  1908. //
  1909. TrustedDomainFullInfo->PosixOffset.Offset = TrustedPosixOffset;
  1910. NextAttribute++;
  1911. InformationBuffer = TrustedDomainFullInfo;
  1912. //
  1913. // Copy the Unicode Name field to the output. Original buffer will
  1914. // be freed in Finish section.
  1915. //
  1916. Status = LsapDbCopyUnicodeAttribute(
  1917. &TrustedDomainFullInfo->Information.Name,
  1918. NextAttribute,
  1919. TRUE
  1920. );
  1921. if (!NT_SUCCESS(Status)) {
  1922. goto QueryInfoTrustedDomainError;
  1923. }
  1924. NextAttribute++;
  1925. //
  1926. // Netbios name
  1927. //
  1928. Status = LsapDbCopyUnicodeAttribute(
  1929. &TrustedDomainFullInfo->Information.FlatName,
  1930. NextAttribute,
  1931. TRUE
  1932. );
  1933. if (!NT_SUCCESS(Status)) {
  1934. MIDL_user_free( TrustedDomainFullInfo->Information.Name.Buffer );
  1935. goto QueryInfoTrustedDomainError;
  1936. }
  1937. NextAttribute++;
  1938. if ( NextAttribute->AttributeValueLength != 0 ) {
  1939. TrustedDomainFullInfo->Information.Sid =
  1940. MIDL_user_allocate( NextAttribute->AttributeValueLength );
  1941. if ( TrustedDomainFullInfo->Information.Sid == NULL ) {
  1942. MIDL_user_free( TrustedDomainFullInfo->Information.Name.Buffer );
  1943. MIDL_user_free( TrustedDomainFullInfo->Information.FlatName.Buffer );
  1944. Status = STATUS_INSUFFICIENT_RESOURCES;
  1945. goto QueryInfoTrustedDomainError;
  1946. }
  1947. RtlCopyMemory( TrustedDomainFullInfo->Information.Sid, NextAttribute->AttributeValue,
  1948. NextAttribute->AttributeValueLength );
  1949. } else {
  1950. TrustedDomainFullInfo->Information.Sid = NULL;
  1951. }
  1952. NextAttribute++;
  1953. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  1954. TrustedDomainFullInfo->Information.TrustDirection = TrustDirection;
  1955. NextAttribute++;
  1956. TrustedDomainFullInfo->Information.TrustType = TrustType;
  1957. NextAttribute++;
  1958. TrustedDomainFullInfo->Information.TrustAttributes = TrustAttributes;
  1959. NextAttribute++;
  1960. } else {
  1961. TrustedDomainFullInfo->Information.TrustDirection = TRUST_DIRECTION_OUTBOUND;
  1962. TrustedDomainFullInfo->Information.TrustType = TRUST_TYPE_DOWNLEVEL;
  1963. TrustedDomainFullInfo->Information.TrustAttributes = 0;
  1964. }
  1965. //
  1966. // Only return Auth data to trusted client.
  1967. // (or if we're debugging auth data)
  1968. //
  1969. if ( !((LSAP_DB_HANDLE)TrustedDomainHandle)->Trusted &&
  1970. !LsapDbReturnAuthData ) {
  1971. RtlZeroMemory( &TrustedDomainFullInfo->AuthInformation,
  1972. sizeof( TrustedDomainFullInfo->AuthInformation ) );
  1973. } else {
  1974. //
  1975. // Finally, the AuthInfo...
  1976. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  1977. NextAttribute->AttributeValue,
  1978. NextAttribute->AttributeValueLength,
  1979. &AuthInfoHalf );
  1980. if ( NT_SUCCESS( Status ) ) {
  1981. RtlCopyMemory( &TrustedDomainFullInfo->AuthInformation, &AuthInfoHalf, sizeof( AuthInfoHalf ) );
  1982. NextAttribute++;
  1983. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  1984. NextAttribute->AttributeValue,
  1985. NextAttribute->AttributeValueLength,
  1986. &AuthInfoHalf );
  1987. if ( NT_SUCCESS( Status ) ) {
  1988. TrustedDomainFullInfo->AuthInformation.OutgoingAuthInfos = AuthInfoHalf.AuthInfos;
  1989. TrustedDomainFullInfo->AuthInformation.OutgoingAuthenticationInformation =
  1990. (PLSA_AUTH_INFORMATION)AuthInfoHalf.AuthenticationInformation;
  1991. TrustedDomainFullInfo->AuthInformation.OutgoingPreviousAuthenticationInformation =
  1992. (PLSA_AUTH_INFORMATION)AuthInfoHalf.PreviousAuthenticationInformation;
  1993. } else {
  1994. LsapDsFreeUnmarshaledAuthInfo(
  1995. TrustedDomainFullInfo->AuthInformation.IncomingAuthInfos,
  1996. (PLSAPR_AUTH_INFORMATION)TrustedDomainFullInfo->AuthInformation.
  1997. IncomingAuthenticationInformation );
  1998. }
  1999. }
  2000. if ( !NT_SUCCESS ( Status ) ) {
  2001. MIDL_user_free( TrustedDomainFullInfo->Information.Name.Buffer );
  2002. MIDL_user_free( TrustedDomainFullInfo->Information.FlatName.Buffer );
  2003. MIDL_user_free( TrustedDomainFullInfo->Information.Sid );
  2004. }
  2005. }
  2006. break;
  2007. case TrustedDomainFullInformation2Internal:
  2008. //
  2009. // Allocate memory for top-level output buffer.
  2010. //
  2011. InformationBuffer = NextAttribute->AttributeValue;
  2012. TrustedDomainFullInfo2 = MIDL_user_allocate(sizeof( TRUSTED_DOMAIN_FULL_INFORMATION2 ));
  2013. if ( TrustedDomainFullInfo2 == NULL ) {
  2014. Status = STATUS_INSUFFICIENT_RESOURCES;
  2015. goto QueryInfoTrustedDomainError;
  2016. }
  2017. InfoBufferInAttributeArray = FALSE;
  2018. //
  2019. // Copy Posix Offset value to output.
  2020. //
  2021. TrustedDomainFullInfo2->PosixOffset.Offset = TrustedPosixOffset;
  2022. NextAttribute++;
  2023. InformationBuffer = TrustedDomainFullInfo2;
  2024. //
  2025. // Copy the Unicode Name field to the output. Original buffer will
  2026. // be freed in Finish section.
  2027. //
  2028. Status = LsapDbCopyUnicodeAttribute(
  2029. &TrustedDomainFullInfo2->Information.Name,
  2030. NextAttribute,
  2031. TRUE
  2032. );
  2033. if (!NT_SUCCESS(Status)) {
  2034. goto QueryInfoTrustedDomainError;
  2035. }
  2036. NextAttribute++;
  2037. //
  2038. // Netbios name
  2039. //
  2040. Status = LsapDbCopyUnicodeAttribute(
  2041. &TrustedDomainFullInfo2->Information.FlatName,
  2042. NextAttribute,
  2043. TRUE
  2044. );
  2045. if (!NT_SUCCESS(Status)) {
  2046. MIDL_user_free( TrustedDomainFullInfo2->Information.Name.Buffer );
  2047. goto QueryInfoTrustedDomainError;
  2048. }
  2049. NextAttribute++;
  2050. if ( NextAttribute->AttributeValueLength != 0 ) {
  2051. TrustedDomainFullInfo2->Information.Sid =
  2052. MIDL_user_allocate( NextAttribute->AttributeValueLength );
  2053. if ( TrustedDomainFullInfo2->Information.Sid == NULL ) {
  2054. MIDL_user_free( TrustedDomainFullInfo2->Information.Name.Buffer );
  2055. MIDL_user_free( TrustedDomainFullInfo2->Information.FlatName.Buffer );
  2056. Status = STATUS_INSUFFICIENT_RESOURCES;
  2057. goto QueryInfoTrustedDomainError;
  2058. }
  2059. RtlCopyMemory( TrustedDomainFullInfo2->Information.Sid, NextAttribute->AttributeValue,
  2060. NextAttribute->AttributeValueLength );
  2061. } else {
  2062. TrustedDomainFullInfo2->Information.Sid = NULL;
  2063. }
  2064. NextAttribute++;
  2065. if ( LsapDsIsWriteDs( TrustedDomainHandle ) ) {
  2066. TrustedDomainFullInfo2->Information.TrustDirection = TrustDirection;
  2067. NextAttribute++;
  2068. TrustedDomainFullInfo2->Information.TrustType = TrustType;
  2069. NextAttribute++;
  2070. TrustedDomainFullInfo2->Information.TrustAttributes = TrustAttributes;
  2071. NextAttribute++;
  2072. if ( NextAttribute->AttributeValueLength != 0 ) {
  2073. TrustedDomainFullInfo2->Information.ForestTrustLength = NextAttribute->AttributeValueLength;
  2074. TrustedDomainFullInfo2->Information.ForestTrustInfo =
  2075. MIDL_user_allocate( NextAttribute->AttributeValueLength );
  2076. if ( TrustedDomainFullInfo2->Information.ForestTrustInfo == NULL ) {
  2077. MIDL_user_free( TrustedDomainFullInfo2->Information.Name.Buffer );
  2078. MIDL_user_free( TrustedDomainFullInfo2->Information.FlatName.Buffer );
  2079. MIDL_user_free( TrustedDomainFullInfo2->Information.Sid );
  2080. Status = STATUS_INSUFFICIENT_RESOURCES;
  2081. goto QueryInfoTrustedDomainError;
  2082. }
  2083. RtlCopyMemory(
  2084. TrustedDomainFullInfo2->Information.ForestTrustInfo,
  2085. NextAttribute->AttributeValue,
  2086. NextAttribute->AttributeValueLength
  2087. );
  2088. } else {
  2089. TrustedDomainFullInfo2->Information.ForestTrustLength = 0;
  2090. TrustedDomainFullInfo2->Information.ForestTrustInfo = NULL;
  2091. }
  2092. NextAttribute++;
  2093. } else {
  2094. TrustedDomainFullInfo2->Information.TrustDirection = TRUST_DIRECTION_OUTBOUND;
  2095. TrustedDomainFullInfo2->Information.TrustType = TRUST_TYPE_DOWNLEVEL;
  2096. TrustedDomainFullInfo2->Information.TrustAttributes = 0;
  2097. TrustedDomainFullInfo2->Information.ForestTrustLength = 0;
  2098. TrustedDomainFullInfo2->Information.ForestTrustInfo = NULL;
  2099. }
  2100. //
  2101. // Only return Auth data to trusted client.
  2102. // (or if we're debugging auth data)
  2103. //
  2104. if ( !((LSAP_DB_HANDLE)TrustedDomainHandle)->Trusted &&
  2105. !LsapDbReturnAuthData ) {
  2106. RtlZeroMemory( &TrustedDomainFullInfo2->AuthInformation,
  2107. sizeof( TrustedDomainFullInfo2->AuthInformation ) );
  2108. } else {
  2109. //
  2110. // Finally, the AuthInfo...
  2111. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  2112. NextAttribute->AttributeValue,
  2113. NextAttribute->AttributeValueLength,
  2114. &AuthInfoHalf );
  2115. if ( NT_SUCCESS( Status ) ) {
  2116. RtlCopyMemory( &TrustedDomainFullInfo2->AuthInformation, &AuthInfoHalf, sizeof( AuthInfoHalf ) );
  2117. NextAttribute++;
  2118. Status = LsapDsBuildAuthInfoFromAttribute( TrustedDomainHandle,
  2119. NextAttribute->AttributeValue,
  2120. NextAttribute->AttributeValueLength,
  2121. &AuthInfoHalf );
  2122. if ( NT_SUCCESS( Status ) ) {
  2123. TrustedDomainFullInfo2->AuthInformation.OutgoingAuthInfos = AuthInfoHalf.AuthInfos;
  2124. TrustedDomainFullInfo2->AuthInformation.OutgoingAuthenticationInformation =
  2125. (PLSA_AUTH_INFORMATION)AuthInfoHalf.AuthenticationInformation;
  2126. TrustedDomainFullInfo2->AuthInformation.OutgoingPreviousAuthenticationInformation =
  2127. (PLSA_AUTH_INFORMATION)AuthInfoHalf.PreviousAuthenticationInformation;
  2128. } else {
  2129. LsapDsFreeUnmarshaledAuthInfo(
  2130. TrustedDomainFullInfo2->AuthInformation.IncomingAuthInfos,
  2131. (PLSAPR_AUTH_INFORMATION)TrustedDomainFullInfo2->AuthInformation.
  2132. IncomingAuthenticationInformation );
  2133. }
  2134. }
  2135. if ( !NT_SUCCESS ( Status ) ) {
  2136. MIDL_user_free( TrustedDomainFullInfo2->Information.ForestTrustInfo );
  2137. MIDL_user_free( TrustedDomainFullInfo2->Information.Name.Buffer );
  2138. MIDL_user_free( TrustedDomainFullInfo2->Information.FlatName.Buffer );
  2139. MIDL_user_free( TrustedDomainFullInfo2->Information.Sid );
  2140. }
  2141. }
  2142. break;
  2143. default:
  2144. Status = STATUS_INVALID_PARAMETER;
  2145. break;
  2146. }
  2147. if (!NT_SUCCESS(Status)) {
  2148. goto QueryInfoTrustedDomainError;
  2149. }
  2150. //
  2151. // Verify that the returned Trusted Domain Information is valid. If not,
  2152. // the Policy Database is corrupt.
  2153. //
  2154. if (!LsapDbValidInfoTrustedDomain(InformationClass, InformationBuffer)) {
  2155. Status = STATUS_INTERNAL_DB_CORRUPTION;
  2156. }
  2157. //
  2158. // Return a pointer to the output buffer to the caller
  2159. //
  2160. *Buffer = (PLSAPR_TRUSTED_DOMAIN_INFO) InformationBuffer;
  2161. QueryInfoTrustedDomainFinish:
  2162. //
  2163. // Free any unwanted buffers that were allocated by
  2164. // LsapDbReadAttributesObject() and that are not being returned to the
  2165. // caller server stub. The server stub will free the buffers that we
  2166. // do return after copying them to the return RPC transmit buffer.
  2167. //
  2168. for (NextAttribute = Attributes, AttributeNumber = 0;
  2169. AttributeNumber < AttributeCount;
  2170. NextAttribute++, AttributeNumber++) {
  2171. //
  2172. // If buffer holding attribute is marked as allocated, it is
  2173. // to be freed here.
  2174. //
  2175. if (NextAttribute->MemoryAllocated) {
  2176. if (NextAttribute->AttributeValue != NULL) {
  2177. MIDL_user_free(NextAttribute->AttributeValue);
  2178. NextAttribute->AttributeValue = NULL;
  2179. NextAttribute->MemoryAllocated = FALSE;
  2180. }
  2181. }
  2182. }
  2183. //
  2184. // If necessary, dereference the Trusted Domain Object, release the LSA Database lock and
  2185. // return.
  2186. //
  2187. if (ObjectReferenced) {
  2188. Status = LsapDbDereferenceObject(
  2189. &TrustedDomainHandle,
  2190. TrustedDomainObject,
  2191. TrustedDomainObject,
  2192. LSAP_DB_LOCK |
  2193. LSAP_DB_READ_ONLY_TRANSACTION |
  2194. LSAP_DB_DS_OP_TRANSACTION |
  2195. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION,
  2196. (SECURITY_DB_DELTA_TYPE) 0,
  2197. Status
  2198. );
  2199. }
  2200. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_QueryInfoTrustedDomain);
  2201. LsapExitFunc( "LsarQueryInfoTrustedDomain", Status );
  2202. LsarpReturnPrologue();
  2203. return(Status);
  2204. QueryInfoTrustedDomainError:
  2205. //
  2206. // If necessary, free the memory allocated for the output buffer.
  2207. // We only do this free if the buffer is not referenced by the
  2208. // attribute array, since all buffers so referenced will be freed
  2209. // here or in the Finish section.
  2210. //
  2211. if ((InformationBuffer != NULL) && !InfoBufferInAttributeArray) {
  2212. MIDL_user_free(InformationBuffer);
  2213. InformationBuffer = NULL;
  2214. }
  2215. goto QueryInfoTrustedDomainFinish;
  2216. }
  2217. NTSTATUS
  2218. LsarSetInformationTrustedDomain(
  2219. IN LSAPR_HANDLE TrustedDomainHandle,
  2220. IN TRUSTED_INFORMATION_CLASS InformationClass,
  2221. IN PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation
  2222. )
  2223. /*++
  2224. Routine Description:
  2225. This function is the LSA server RPC worker routine for the
  2226. LsaSetInfoTrustedDomain API.
  2227. The LsaSetInformationTrustedDomain API modifies information in the Trusted
  2228. Domain Object. The caller must have access appropriate to the
  2229. information to be changed in the Policy Object, see the InformationClass
  2230. parameter.
  2231. Arguments:
  2232. PolicyHandle - Handle from an LsaOpenPolicy call.
  2233. InformationClass - Specifies the type of information being changed.
  2234. The information types and accesses required to change them are as
  2235. follows:
  2236. TrustedDomainNameInformation ( Cannot be set )
  2237. TrustedControllersInformation TRUSTED_SET_CONTROLLERS
  2238. TrustedPosixOffsetInformation TRUSTED_POSIX_INFORMATION
  2239. Buffer - Points to a structure containing the information appropriate
  2240. to the InformationClass parameter.
  2241. Return Value:
  2242. NTSTATUS - Standard Nt Result Code
  2243. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2244. to complete the operation.
  2245. Others TBS
  2246. --*/
  2247. {
  2248. NTSTATUS Status;
  2249. ACCESS_MASK DesiredAccess;
  2250. BOOLEAN ObjectReferenced = FALSE;
  2251. BOOLEAN AcquiredListWriteLock = FALSE;
  2252. PTRUSTED_POSIX_OFFSET_INFO TrustedPosixOffsetInfo;
  2253. PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInfoEx = NULL;
  2254. PTRUSTED_DOMAIN_AUTH_INFORMATION TrustedDomainAuthInfo;
  2255. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL TrustedDomainAuthInfoInternal;
  2256. PTRUSTED_DOMAIN_FULL_INFORMATION TrustedDomainFullInfo;
  2257. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL TrustedDomainFullInfoInternal;
  2258. PTRUSTED_DOMAIN_FULL_INFORMATION2 CurrentTrustedDomainFullInfo2 = NULL;
  2259. TRUSTED_DOMAIN_INFORMATION_EX2 UpdateInfoEx2 = { 0 };
  2260. TRUSTED_DOMAIN_AUTH_INFORMATION DecryptedTrustedDomainAuthInfo;
  2261. TRUSTED_DOMAIN_FULL_INFORMATION DecryptedTrustedDomainFullInfo;
  2262. LSAP_DB_ATTRIBUTE Attributes[LSAP_DB_ATTRS_INFO_CLASS_DOMAIN];
  2263. PLSAP_DB_ATTRIBUTE NextAttribute;
  2264. ULONG AttributeCount = 0;
  2265. ULONG AttributeNumber;
  2266. BOOLEAN CreateInterdomainTrustAccount = FALSE;
  2267. BOOLEAN UpdateTrustedDomainList = FALSE;
  2268. PULONG UpdatePosixOffset = NULL;
  2269. ULONG TrustedDomainPosixOffset = 0;
  2270. PBYTE IncomingAuth = NULL, OutgoingAuth = NULL;
  2271. ULONG IncomingSize = 0, OutgoingSize = 0;
  2272. ULONG ReferenceOptions = LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION;
  2273. ULONG DereferenceOptions = LSAP_DB_LOCK | LSAP_DB_FINISH_TRANSACTION;
  2274. BOOLEAN HandleReferenced = FALSE;
  2275. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  2276. ULONG TrustAttributesValue;
  2277. BOOLEAN SavedTrusted;
  2278. LSAP_DB_HANDLE InternalTdoHandle = (LSAP_DB_HANDLE) TrustedDomainHandle;
  2279. LsarpReturnCheckSetup();
  2280. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_SetInformationTrustedDomain);
  2281. //
  2282. // Initialization
  2283. //
  2284. RtlZeroMemory( &DecryptedTrustedDomainAuthInfo, sizeof(DecryptedTrustedDomainAuthInfo) );
  2285. RtlZeroMemory( &DecryptedTrustedDomainFullInfo, sizeof(DecryptedTrustedDomainFullInfo) );
  2286. //
  2287. // Validate the Information Class and Trusted Domain Information provided and
  2288. // if valid, return the mask of accesses required to update this
  2289. // class of Trusted Domain information.
  2290. //
  2291. Status = LsapDbVerifyInfoSetTrustedDomain(
  2292. InformationClass,
  2293. TrustedDomainInformation,
  2294. FALSE,
  2295. &DesiredAccess
  2296. );
  2297. if (!NT_SUCCESS(Status)) {
  2298. goto Cleanup;
  2299. }
  2300. //
  2301. // Verify the handle before using it.
  2302. //
  2303. Status = LsapDbVerifyHandle( TrustedDomainHandle, 0, TrustedDomainObject, TRUE );
  2304. if (!NT_SUCCESS(Status)) {
  2305. goto Cleanup;
  2306. }
  2307. HandleReferenced = TRUE;
  2308. //
  2309. // If this is the open handle to a trusted domain object being treated as a secret object,
  2310. // we already have a transaction going, so don't start one here.
  2311. //
  2312. if ( FLAG_ON( ((LSAP_DB_HANDLE)TrustedDomainHandle)->Options,
  2313. LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET )) {
  2314. ReferenceOptions &= ~LSAP_DB_START_TRANSACTION;
  2315. DereferenceOptions &= ~LSAP_DB_FINISH_TRANSACTION;
  2316. }
  2317. //
  2318. // Get the session key.
  2319. //
  2320. // Do this before grabbing any locks. Getting the session key is a kernel call.
  2321. // The kernel will call back up to the LSA in another thread to get the key.
  2322. // That thread may need locks this thread has locked.
  2323. //
  2324. if ( InformationClass == TrustedDomainAuthInformationInternal ||
  2325. InformationClass == TrustedDomainFullInformationInternal ) {
  2326. Status = LsapCrServerGetSessionKeySafe(
  2327. LsapDbContainerFromHandle( TrustedDomainHandle ),
  2328. PolicyObject,
  2329. &SessionKey );
  2330. if (!NT_SUCCESS(Status)) {
  2331. goto Cleanup;
  2332. }
  2333. }
  2334. //
  2335. // Acquire the Lsa Database lock. Verify that the handle is
  2336. // valid, is a handle to a TrustedDomain Object and has the necessary accesses
  2337. // granted. Reference the handle and start an Lsa Database transaction.
  2338. //
  2339. //
  2340. // If this is the open handle to a trusted domain object being treated as a secret object,
  2341. // we already have a transaction going, so don't start one here.
  2342. //
  2343. if ( !FLAG_ON( ((LSAP_DB_HANDLE)TrustedDomainHandle)->Options,
  2344. LSAP_DB_DS_TRUSTED_DOMAIN_AS_SECRET )) {
  2345. Status = LsapDbReferenceObject(
  2346. TrustedDomainHandle,
  2347. DesiredAccess,
  2348. TrustedDomainObject,
  2349. TrustedDomainObject,
  2350. ReferenceOptions
  2351. );
  2352. if (!NT_SUCCESS(Status)) {
  2353. goto Cleanup;
  2354. }
  2355. ObjectReferenced = TRUE;
  2356. }
  2357. //
  2358. // Update the specified information in the Policy Object.
  2359. //
  2360. NextAttribute = Attributes;
  2361. //
  2362. // Grab a copy of the current information on the object.
  2363. //
  2364. SavedTrusted = ((LSAP_DB_HANDLE) TrustedDomainHandle)->Trusted;
  2365. ((LSAP_DB_HANDLE) TrustedDomainHandle)->Trusted = TRUE;
  2366. Status = LsarQueryInfoTrustedDomain( TrustedDomainHandle,
  2367. TrustedDomainFullInformation2Internal,
  2368. (PLSAPR_TRUSTED_DOMAIN_INFO *)
  2369. &CurrentTrustedDomainFullInfo2 );
  2370. ((LSAP_DB_HANDLE) TrustedDomainHandle)->Trusted = SavedTrusted;
  2371. if ( !NT_SUCCESS( Status ) ) {
  2372. goto Cleanup;
  2373. }
  2374. RtlCopyMemory( &UpdateInfoEx2, &CurrentTrustedDomainFullInfo2->Information, sizeof( TRUSTED_DOMAIN_INFORMATION_EX2 ) );
  2375. //
  2376. // Save a copy of the trust direction for the fixup routines
  2377. //
  2378. {
  2379. PLSADS_PER_THREAD_INFO CurrentThreadInfo;
  2380. CurrentThreadInfo = TlsGetValue( LsapDsThreadState );
  2381. ASSERT( CurrentThreadInfo != NULL );
  2382. if ( CurrentThreadInfo != NULL ) {
  2383. CurrentThreadInfo->OldTrustDirection = CurrentTrustedDomainFullInfo2->Information.TrustDirection;
  2384. CurrentThreadInfo->OldTrustType = CurrentTrustedDomainFullInfo2->Information.TrustType;
  2385. }
  2386. }
  2387. //
  2388. // If we have a Ds object, we might be coming from the *ByName functions, which have a
  2389. // cobbled handle that doesn't include the sid. As such, we'll go ahead and read it here.
  2390. //
  2391. if ( LsapDsWriteDs ) {
  2392. if ( ((LSAP_DB_HANDLE) TrustedDomainHandle)->Sid == NULL ) {
  2393. if ( CurrentTrustedDomainFullInfo2->Information.Sid ) {
  2394. ULONG SidLength;
  2395. SidLength = RtlLengthSid( CurrentTrustedDomainFullInfo2->Information.Sid );
  2396. ((LSAP_DB_HANDLE)TrustedDomainHandle)->Sid = LsapAllocateLsaHeap( SidLength );
  2397. if (((LSAP_DB_HANDLE)TrustedDomainHandle)->Sid == NULL) {
  2398. Status = STATUS_INSUFFICIENT_RESOURCES;
  2399. goto Cleanup;
  2400. }
  2401. RtlCopySid( SidLength,
  2402. ((LSAP_DB_HANDLE)TrustedDomainHandle)->Sid,
  2403. CurrentTrustedDomainFullInfo2->Information.Sid );
  2404. }
  2405. }
  2406. }
  2407. switch (InformationClass) {
  2408. case TrustedDomainNameInformation:
  2409. Status = STATUS_INVALID_PARAMETER;
  2410. goto Cleanup;
  2411. case TrustedControllersInformation:
  2412. //
  2413. // Obsolete info level. Do nothing
  2414. //
  2415. break;
  2416. case TrustedPosixOffsetInformation:
  2417. TrustedPosixOffsetInfo = (PTRUSTED_POSIX_OFFSET_INFO) TrustedDomainInformation;
  2418. LsapDbInitializeAttributeDs(
  2419. NextAttribute,
  2420. TrDmPxOf,
  2421. &TrustedPosixOffsetInfo->Offset,
  2422. sizeof(ULONG),
  2423. FALSE
  2424. );
  2425. NextAttribute++;
  2426. AttributeCount++;
  2427. //
  2428. // Update the cache, too.
  2429. //
  2430. UpdatePosixOffset = &TrustedPosixOffsetInfo->Offset;
  2431. break;
  2432. case TrustedDomainInformationBasic:
  2433. Status = STATUS_INVALID_INFO_CLASS;
  2434. goto Cleanup;
  2435. case TrustedDomainInformationEx:
  2436. TrustedDomainInfoEx = (PTRUSTED_DOMAIN_INFORMATION_EX)TrustedDomainInformation;
  2437. RtlCopyMemory( &UpdateInfoEx2,
  2438. TrustedDomainInfoEx,
  2439. sizeof( TRUSTED_DOMAIN_INFORMATION_EX ) );
  2440. UpdateInfoEx2.ForestTrustLength = CurrentTrustedDomainFullInfo2->Information.ForestTrustLength;
  2441. UpdateInfoEx2.ForestTrustInfo = CurrentTrustedDomainFullInfo2->Information.ForestTrustInfo;
  2442. //
  2443. // If the client attempts to set the forest transitive bit,
  2444. // verify that this is a domain in the root DC and that all
  2445. // domains have been upgraded to Whistler before allowing the operation
  2446. //
  2447. if ( !FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2448. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2449. FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2450. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2451. ( !LsapDbDcInRootDomain() ||
  2452. !LsapDbNoMoreWin2KForest())) {
  2453. Status = STATUS_INVALID_DOMAIN_STATE;
  2454. goto Cleanup;
  2455. }
  2456. //
  2457. // If the client attempts to set the cross-federation bit,
  2458. // verify that this domain is in Whistler mode before allowing the operation
  2459. //
  2460. if ( !FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2461. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) &&
  2462. FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2463. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) &&
  2464. !LsapDbNoMoreWin2KDomain()) {
  2465. Status = STATUS_INVALID_DOMAIN_STATE;
  2466. goto Cleanup;
  2467. }
  2468. //
  2469. // Verify that trust points to the right place
  2470. //
  2471. Status = LsapDbVerifyTrustLocation(( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )TrustedDomainInfoEx );
  2472. if ( !NT_SUCCESS( Status )) {
  2473. goto Cleanup;
  2474. }
  2475. //
  2476. // A trust can not be both "within forest" and either external or cross-org
  2477. //
  2478. if ( FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2479. TRUST_ATTRIBUTE_WITHIN_FOREST ) &&
  2480. ( FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2481. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) ||
  2482. FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2483. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ))) {
  2484. Status = STATUS_INVALID_PARAMETER;
  2485. goto Cleanup;
  2486. }
  2487. UpdateTrustedDomainList = TRUE;
  2488. //
  2489. // Can't set domain names via this interface
  2490. //
  2491. //
  2492. // Set the trust type and direction
  2493. //
  2494. LsapDbInitializeAttributeDs(
  2495. NextAttribute,
  2496. TrDmTrTy,
  2497. &TrustedDomainInfoEx->TrustType,
  2498. sizeof( TrustedDomainInfoEx->TrustType ),
  2499. FALSE
  2500. );
  2501. NextAttribute++;
  2502. AttributeCount++;
  2503. LsapDbInitializeAttributeDs(
  2504. NextAttribute,
  2505. TrDmTrDi,
  2506. &TrustedDomainInfoEx->TrustDirection,
  2507. sizeof( TrustedDomainInfoEx->TrustDirection ),
  2508. FALSE
  2509. );
  2510. NextAttribute++;
  2511. AttributeCount++;
  2512. //
  2513. // For outbound up- and down-level TDO's, only allow the operation if either
  2514. // -- either a SID is specified as part of TrustedDomainInfoEx or
  2515. // -- a SID is specified as part of
  2516. //
  2517. if ( ( TrustedDomainInfoEx->TrustType == TRUST_TYPE_DOWNLEVEL ||
  2518. TrustedDomainInfoEx->TrustType == TRUST_TYPE_UPLEVEL ) &&
  2519. FLAG_ON( TrustedDomainInfoEx->TrustDirection, TRUST_DIRECTION_OUTBOUND ) &&
  2520. TrustedDomainInfoEx->Sid == NULL &&
  2521. CurrentTrustedDomainFullInfo2->Information.Sid == NULL ) {
  2522. Status = STATUS_INVALID_SID;
  2523. goto Cleanup;
  2524. }
  2525. //
  2526. // If a SID was provided as part of TrustedDomainInfoEx, use it
  2527. // but first verify that it is a valid domain SID
  2528. //
  2529. if ( TrustedDomainInfoEx->Sid != NULL ) {
  2530. //
  2531. // Trusted domain SIDs passsed in my be valid domain SIDs
  2532. //
  2533. Status = LsapIsValidDomainSid(
  2534. TrustedDomainInfoEx->Sid
  2535. );
  2536. if ( !NT_SUCCESS( Status )) {
  2537. goto Cleanup;
  2538. }
  2539. Status = LsapDbMakeSidAttributeDs(
  2540. TrustedDomainInfoEx->Sid,
  2541. TrDmSid,
  2542. NextAttribute );
  2543. if ( !NT_SUCCESS( Status )) {
  2544. goto Cleanup;
  2545. }
  2546. NextAttribute++;
  2547. AttributeCount++;
  2548. }
  2549. //
  2550. // Create the interdomain trust account for inbound TDOs
  2551. //
  2552. if ( FLAG_ON( TrustedDomainInfoEx->TrustDirection, TRUST_DIRECTION_INBOUND )) {
  2553. CreateInterdomainTrustAccount = TRUE;
  2554. }
  2555. //
  2556. // When setting trust attributes, mask off all but the supported bits
  2557. //
  2558. TrustAttributesValue =
  2559. TrustedDomainInfoEx->TrustAttributes & TRUST_ATTRIBUTES_VALID;
  2560. LsapDbInitializeAttributeDs(
  2561. NextAttribute,
  2562. TrDmTrLA,
  2563. &TrustAttributesValue,
  2564. sizeof( TrustAttributesValue ),
  2565. FALSE
  2566. );
  2567. NextAttribute++;
  2568. AttributeCount++;
  2569. //
  2570. // If the forest trust bit is being cleared,
  2571. // remove forest trust information from the TDO
  2572. //
  2573. if ( FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2574. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2575. !FLAG_ON( TrustedDomainInfoEx->TrustAttributes,
  2576. TRUST_ATTRIBUTE_FOREST_TRANSITIVE )) {
  2577. LsapDbInitializeAttributeDs(
  2578. NextAttribute,
  2579. TrDmForT,
  2580. NULL,
  2581. 0,
  2582. FALSE
  2583. );
  2584. NextAttribute++;
  2585. AttributeCount++;
  2586. UpdateInfoEx2.ForestTrustLength = 0;
  2587. UpdateInfoEx2.ForestTrustInfo = NULL;
  2588. LsapDsDebugOut(( DEB_FTINFO, "Removing forest trust information because forest trust bit is being cleared\n" ));
  2589. }
  2590. break;
  2591. case TrustedDomainAuthInformationInternal:
  2592. TrustedDomainAuthInfoInternal = (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL)TrustedDomainInformation;
  2593. //
  2594. // Build a decrypted Auth Info structure.
  2595. //
  2596. Status = LsapDecryptAuthDataWithSessionKey(
  2597. SessionKey,
  2598. TrustedDomainAuthInfoInternal,
  2599. &DecryptedTrustedDomainAuthInfo );
  2600. if ( !NT_SUCCESS(Status) ) {
  2601. goto Cleanup;
  2602. }
  2603. //
  2604. // Use the decrypted information as though cleartext was passed from the caller.
  2605. //
  2606. TrustedDomainInformation = (PLSAPR_TRUSTED_DOMAIN_INFO) &DecryptedTrustedDomainAuthInfo;
  2607. /* Drop through */
  2608. case TrustedDomainAuthInformation:
  2609. TrustedDomainAuthInfo = (PTRUSTED_DOMAIN_AUTH_INFORMATION)TrustedDomainInformation;
  2610. //
  2611. // Incoming...
  2612. // Use zero AuthInfos as our hint to not change the auth info.
  2613. //
  2614. if ( TrustedDomainAuthInfo->IncomingAuthInfos != 0 ) {
  2615. //
  2616. // There's a bug in the idl definition LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION where
  2617. // it doesn't allow more than one auth info to be passed over the wire.
  2618. // So, short circuit it here.
  2619. //
  2620. if ( InformationClass == TrustedDomainAuthInformation &&
  2621. !InternalTdoHandle->Trusted &&
  2622. TrustedDomainAuthInfo->IncomingAuthInfos > 1 ) {
  2623. Status = STATUS_INVALID_PARAMETER;
  2624. goto Cleanup;
  2625. }
  2626. Status = LsapDsBuildAuthInfoAttribute( TrustedDomainHandle,
  2627. LsapDsAuthHalfFromAuthInfo(
  2628. TrustedDomainAuthInfo, TRUE ),
  2629. LsapDsAuthHalfFromAuthInfo(
  2630. &CurrentTrustedDomainFullInfo2->AuthInformation, TRUE ),
  2631. &IncomingAuth,
  2632. &IncomingSize );
  2633. if ( !NT_SUCCESS( Status ) ) {
  2634. goto Cleanup;
  2635. }
  2636. }
  2637. //
  2638. // Same thing with the outgoing
  2639. //
  2640. if ( TrustedDomainAuthInfo->OutgoingAuthInfos != 0 ) {
  2641. //
  2642. // There's a bug in the idl definition LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION where
  2643. // it doesn't allow more than one auth info to be passed over the wire.
  2644. // So, short circuit it here.
  2645. //
  2646. if ( !InternalTdoHandle->Trusted &&
  2647. TrustedDomainAuthInfo->OutgoingAuthInfos > 1 ) {
  2648. Status = STATUS_INVALID_PARAMETER;
  2649. goto Cleanup;
  2650. }
  2651. Status = LsapDsBuildAuthInfoAttribute( TrustedDomainHandle,
  2652. LsapDsAuthHalfFromAuthInfo(
  2653. TrustedDomainAuthInfo, FALSE ),
  2654. LsapDsAuthHalfFromAuthInfo(
  2655. &CurrentTrustedDomainFullInfo2->AuthInformation, FALSE ),
  2656. &OutgoingAuth,
  2657. &OutgoingSize );
  2658. if ( !NT_SUCCESS( Status ) ) {
  2659. goto Cleanup;
  2660. }
  2661. }
  2662. if ( TrustedDomainAuthInfo->IncomingAuthInfos != 0 ) {
  2663. LsapDbInitializeAttributeDs(
  2664. NextAttribute,
  2665. TrDmSAI,
  2666. IncomingAuth,
  2667. IncomingSize,
  2668. FALSE);
  2669. NextAttribute++;
  2670. AttributeCount++;
  2671. }
  2672. if ( TrustedDomainAuthInfo->OutgoingAuthInfos != 0 ) {
  2673. LsapDbInitializeAttributeDs(
  2674. NextAttribute,
  2675. TrDmSAO,
  2676. OutgoingAuth,
  2677. OutgoingSize,
  2678. FALSE);
  2679. NextAttribute++;
  2680. AttributeCount++;
  2681. }
  2682. if ( FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustDirection, TRUST_DIRECTION_INBOUND ) ) {
  2683. CreateInterdomainTrustAccount = TRUE;
  2684. }
  2685. break;
  2686. case TrustedDomainFullInformationInternal:
  2687. TrustedDomainFullInfoInternal = (PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL)TrustedDomainInformation;
  2688. //
  2689. // Build a decrypted Auth Info structure.
  2690. //
  2691. Status = LsapDecryptAuthDataWithSessionKey(
  2692. SessionKey,
  2693. &TrustedDomainFullInfoInternal->AuthInformation,
  2694. &DecryptedTrustedDomainFullInfo.AuthInformation );
  2695. if ( !NT_SUCCESS(Status) ) {
  2696. goto Cleanup;
  2697. }
  2698. //
  2699. // Copy over the other fields into a single structure
  2700. //
  2701. DecryptedTrustedDomainFullInfo.Information = *((PTRUSTED_DOMAIN_INFORMATION_EX)&(TrustedDomainFullInfoInternal->Information));
  2702. DecryptedTrustedDomainFullInfo.PosixOffset = TrustedDomainFullInfoInternal->PosixOffset;
  2703. //
  2704. // Use the decrypted information as though cleartext was passed from the caller.
  2705. //
  2706. TrustedDomainInformation = (PLSAPR_TRUSTED_DOMAIN_INFO) &DecryptedTrustedDomainFullInfo;
  2707. /* Drop through */
  2708. case TrustedDomainFullInformation:
  2709. TrustedDomainFullInfo = ( PTRUSTED_DOMAIN_FULL_INFORMATION )TrustedDomainInformation;
  2710. RtlCopyMemory( &UpdateInfoEx2,
  2711. &TrustedDomainFullInfo->Information,
  2712. sizeof( TRUSTED_DOMAIN_INFORMATION_EX ) );
  2713. UpdateInfoEx2.ForestTrustLength = CurrentTrustedDomainFullInfo2->Information.ForestTrustLength;
  2714. UpdateInfoEx2.ForestTrustInfo = CurrentTrustedDomainFullInfo2->Information.ForestTrustInfo;
  2715. //
  2716. // If the client attempts to set the forest transitive bit,
  2717. // verify that this is a domain in the root DC and that all
  2718. // domains have been upgraded to Whistler before allowing the operation
  2719. //
  2720. if ( !FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2721. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2722. FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2723. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2724. ( !LsapDbDcInRootDomain() ||
  2725. !LsapDbNoMoreWin2KForest())) {
  2726. Status = STATUS_INVALID_DOMAIN_STATE;
  2727. goto Cleanup;
  2728. }
  2729. //
  2730. // If the client attempts to set the cross-federation bit,
  2731. // verify that this domain is in Whistler mode before allowing the operation
  2732. //
  2733. if ( !FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2734. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) &&
  2735. FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2736. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) &&
  2737. !LsapDbNoMoreWin2KDomain()) {
  2738. Status = STATUS_INVALID_DOMAIN_STATE;
  2739. goto Cleanup;
  2740. }
  2741. //
  2742. // Verify that trust points to the right place
  2743. //
  2744. Status = LsapDbVerifyTrustLocation(
  2745. ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )&TrustedDomainFullInfo->Information );
  2746. if ( !NT_SUCCESS( Status )) {
  2747. goto Cleanup;
  2748. }
  2749. //
  2750. // A trust can not be both "within forest" and either external or cross-org
  2751. //
  2752. if ( FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2753. TRUST_ATTRIBUTE_WITHIN_FOREST ) &&
  2754. ( FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2755. TRUST_ATTRIBUTE_CROSS_ORGANIZATION ) ||
  2756. FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2757. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ))) {
  2758. Status = STATUS_INVALID_PARAMETER;
  2759. goto Cleanup;
  2760. }
  2761. UpdateTrustedDomainList = TRUE;
  2762. //
  2763. // Update the Posix Offset in the cache, too.
  2764. //
  2765. UpdatePosixOffset = &TrustedDomainFullInfo->PosixOffset.Offset;
  2766. LsapDbInitializeAttributeDs(
  2767. NextAttribute,
  2768. TrDmPxOf,
  2769. &TrustedDomainFullInfo->PosixOffset.Offset,
  2770. sizeof(ULONG),
  2771. FALSE
  2772. );
  2773. NextAttribute++;
  2774. AttributeCount++;
  2775. //
  2776. // Can't set domain names via this interface
  2777. //
  2778. //
  2779. // Set the trust type and direction
  2780. //
  2781. LsapDbInitializeAttributeDs(
  2782. NextAttribute,
  2783. TrDmTrTy,
  2784. &TrustedDomainFullInfo->Information.TrustType,
  2785. sizeof( TrustedDomainFullInfo->Information.TrustType ),
  2786. FALSE
  2787. );
  2788. NextAttribute++;
  2789. AttributeCount++;
  2790. LsapDbInitializeAttributeDs(
  2791. NextAttribute,
  2792. TrDmTrDi,
  2793. &TrustedDomainFullInfo->Information.TrustDirection,
  2794. sizeof( TrustedDomainFullInfo->Information.TrustDirection ),
  2795. FALSE
  2796. );
  2797. NextAttribute++;
  2798. AttributeCount++;
  2799. //
  2800. // For outbound up- and down-level TDO's, only allow the operation if either
  2801. // -- either a SID is specified as part of TrustedDomainInfoEx or
  2802. // -- a SID is specified as part of
  2803. //
  2804. if ( ( TrustedDomainFullInfo->Information.TrustType == TRUST_TYPE_DOWNLEVEL ||
  2805. TrustedDomainFullInfo->Information.TrustType == TRUST_TYPE_UPLEVEL ) &&
  2806. FLAG_ON( TrustedDomainFullInfo->Information.TrustDirection, TRUST_DIRECTION_OUTBOUND ) &&
  2807. TrustedDomainFullInfo->Information.Sid == NULL &&
  2808. CurrentTrustedDomainFullInfo2->Information.Sid == NULL ) {
  2809. Status = STATUS_INVALID_SID;
  2810. goto Cleanup;
  2811. }
  2812. //
  2813. // If a SID was provided as part of TrustedDomainFullInfo->Information, use it
  2814. //
  2815. if ( TrustedDomainFullInfo->Information.Sid != NULL ) {
  2816. Status = LsapDbMakeSidAttributeDs(
  2817. TrustedDomainFullInfo->Information.Sid,
  2818. TrDmSid,
  2819. NextAttribute );
  2820. if ( !NT_SUCCESS( Status )) {
  2821. goto Cleanup;
  2822. }
  2823. NextAttribute++;
  2824. AttributeCount++;
  2825. }
  2826. //
  2827. // Create the interdomain trust account for inbound TDOs
  2828. //
  2829. if ( FLAG_ON( TrustedDomainFullInfo->Information.TrustDirection, TRUST_DIRECTION_INBOUND )) {
  2830. CreateInterdomainTrustAccount = TRUE;
  2831. }
  2832. //
  2833. // When setting trust attributes, mask off all but the supported bits
  2834. //
  2835. TrustAttributesValue =
  2836. TrustedDomainFullInfo->Information.TrustAttributes & TRUST_ATTRIBUTES_VALID;
  2837. LsapDbInitializeAttributeDs(
  2838. NextAttribute,
  2839. TrDmTrLA,
  2840. &TrustAttributesValue,
  2841. sizeof( TrustAttributesValue ),
  2842. FALSE
  2843. );
  2844. NextAttribute++;
  2845. AttributeCount++;
  2846. //
  2847. // Incoming...
  2848. // Use zero AuthInfos as our hint to not change the auth info.
  2849. //
  2850. if ( TrustedDomainFullInfo->AuthInformation.IncomingAuthInfos != 0 ) {
  2851. //
  2852. // There's a bug in the idl definition LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION where
  2853. // it doesn't allow more than one auth info to be passed over the wire.
  2854. // So, short circuit it here.
  2855. //
  2856. if ( InformationClass == TrustedDomainFullInformation &&
  2857. !InternalTdoHandle->Trusted &&
  2858. TrustedDomainFullInfo->AuthInformation.IncomingAuthInfos > 1 ) {
  2859. Status = STATUS_INVALID_PARAMETER;
  2860. goto Cleanup;
  2861. }
  2862. Status = LsapDsBuildAuthInfoAttribute( TrustedDomainHandle,
  2863. LsapDsAuthHalfFromAuthInfo(
  2864. &TrustedDomainFullInfo->AuthInformation, TRUE ),
  2865. LsapDsAuthHalfFromAuthInfo(
  2866. &CurrentTrustedDomainFullInfo2->AuthInformation, TRUE ),
  2867. &IncomingAuth,
  2868. &IncomingSize );
  2869. if ( !NT_SUCCESS(Status) ) {
  2870. goto Cleanup;
  2871. }
  2872. }
  2873. //
  2874. // Same thing with the outgoing
  2875. //
  2876. if ( TrustedDomainFullInfo->AuthInformation.OutgoingAuthInfos != 0 ) {
  2877. //
  2878. // There's a bug in the idl definition LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION where
  2879. // it doesn't allow more than one auth info to be passed over the wire.
  2880. // So, short circuit it here.
  2881. //
  2882. if ( !InternalTdoHandle->Trusted &&
  2883. TrustedDomainFullInfo->AuthInformation.OutgoingAuthInfos > 1 ) {
  2884. Status = STATUS_INVALID_PARAMETER;
  2885. goto Cleanup;
  2886. }
  2887. Status = LsapDsBuildAuthInfoAttribute( TrustedDomainHandle,
  2888. LsapDsAuthHalfFromAuthInfo(
  2889. &TrustedDomainFullInfo->AuthInformation, FALSE ),
  2890. LsapDsAuthHalfFromAuthInfo(
  2891. &CurrentTrustedDomainFullInfo2->AuthInformation, FALSE ),
  2892. &OutgoingAuth,
  2893. &OutgoingSize );
  2894. if ( !NT_SUCCESS(Status) ) {
  2895. goto Cleanup;
  2896. }
  2897. }
  2898. if ( TrustedDomainFullInfo->AuthInformation.IncomingAuthInfos != 0 ) {
  2899. LsapDbInitializeAttributeDs(
  2900. NextAttribute,
  2901. TrDmSAI,
  2902. IncomingAuth,
  2903. IncomingSize,
  2904. FALSE);
  2905. NextAttribute++;
  2906. AttributeCount++;
  2907. }
  2908. if ( TrustedDomainFullInfo->AuthInformation.OutgoingAuthInfos != 0 ) {
  2909. LsapDbInitializeAttributeDs(
  2910. NextAttribute,
  2911. TrDmSAO,
  2912. OutgoingAuth,
  2913. OutgoingSize,
  2914. FALSE);
  2915. NextAttribute++;
  2916. AttributeCount++;
  2917. }
  2918. //
  2919. // If the forest trust bit is being cleared,
  2920. // remove forest trust information from the TDO
  2921. //
  2922. if ( FLAG_ON( CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  2923. TRUST_ATTRIBUTE_FOREST_TRANSITIVE ) &&
  2924. !FLAG_ON( TrustedDomainFullInfo->Information.TrustAttributes,
  2925. TRUST_ATTRIBUTE_FOREST_TRANSITIVE )) {
  2926. LsapDbInitializeAttributeDs(
  2927. NextAttribute,
  2928. TrDmForT,
  2929. NULL,
  2930. 0,
  2931. FALSE
  2932. );
  2933. NextAttribute++;
  2934. AttributeCount++;
  2935. UpdateInfoEx2.ForestTrustLength = 0;
  2936. UpdateInfoEx2.ForestTrustInfo = NULL;
  2937. LsapDsDebugOut(( DEB_FTINFO, "Removing forest trust information because forest trust bit is being cleared\n" ));
  2938. }
  2939. break;
  2940. default:
  2941. Status = STATUS_INVALID_PARAMETER;
  2942. goto Cleanup;
  2943. }
  2944. ASSERT( AttributeCount <= LSAP_DB_ATTRS_INFO_CLASS_DOMAIN );
  2945. //
  2946. // Update the TrustedDomain Object attributes
  2947. //
  2948. if ( AttributeCount > 0 ) {
  2949. //
  2950. // If we're might be changing trust direction or type,
  2951. // or we're changing the Posix Offset,
  2952. // check if we need to compute the Posix Offset.
  2953. //
  2954. if ( UpdateTrustedDomainList || UpdatePosixOffset != NULL ) {
  2955. DOMAIN_SERVER_ROLE ServerRole;
  2956. //
  2957. // Only change the Posix Offset on the PDC.
  2958. // (Changes made on BDCs will have their Posix offset updated
  2959. // when the change is replicated onto the PDC.)
  2960. //
  2961. Status = SamIQueryServerRole(
  2962. LsapAccountDomainHandle,
  2963. &ServerRole
  2964. );
  2965. if (!NT_SUCCESS(Status)) {
  2966. goto Cleanup;
  2967. }
  2968. //
  2969. // Only allocate a Posix offset on the PDC.
  2970. //
  2971. if ( ServerRole == DomainServerRolePrimary ) {
  2972. ULONG CurrentPosixOffset;
  2973. BOOLEAN PosixOffsetChanged = FALSE;
  2974. //
  2975. // Get the current PosixOffset
  2976. //
  2977. if ( UpdatePosixOffset == NULL ) {
  2978. CurrentPosixOffset = CurrentTrustedDomainFullInfo2->PosixOffset.Offset;
  2979. } else {
  2980. CurrentPosixOffset = *UpdatePosixOffset;
  2981. }
  2982. //
  2983. // If we should have a Posix Offset,
  2984. // ensure we have one.
  2985. //
  2986. if ( LsapNeedPosixOffset( UpdateInfoEx2.TrustDirection,
  2987. UpdateInfoEx2.TrustType ) ) {
  2988. if ( CurrentPosixOffset == 0 ) {
  2989. //
  2990. // Need to grab the TDL write lock while allocating a Posix Offset
  2991. //
  2992. Status = LsapDbAcquireWriteLockTrustedDomainList();
  2993. if ( !NT_SUCCESS(Status)) {
  2994. goto Cleanup;
  2995. }
  2996. AcquiredListWriteLock = TRUE;
  2997. //
  2998. // Allocate the next available Posix Offset.
  2999. //
  3000. Status = LsapDbAllocatePosixOffsetTrustedDomainList(
  3001. &TrustedDomainPosixOffset );
  3002. if ( !NT_SUCCESS(Status)) {
  3003. goto Cleanup;
  3004. }
  3005. PosixOffsetChanged = TRUE;
  3006. }
  3007. //
  3008. // If we shouldn't have a Posix Offset,
  3009. // ensure we don't have one.
  3010. //
  3011. } else {
  3012. if ( CurrentPosixOffset != 0 ) {
  3013. TrustedDomainPosixOffset = 0;
  3014. PosixOffsetChanged = TRUE;
  3015. }
  3016. }
  3017. //
  3018. // If we're forcing the Posix Offset to change,
  3019. // do it now.
  3020. //
  3021. if ( PosixOffsetChanged ) {
  3022. //
  3023. // If we're already writing the Posix Offset to the DS,
  3024. // simply put the new value in that location.
  3025. //
  3026. if ( UpdatePosixOffset != NULL ) {
  3027. *UpdatePosixOffset = TrustedDomainPosixOffset;
  3028. //
  3029. // Otherwise, add it to the list of attributes to write.
  3030. //
  3031. } else {
  3032. UpdatePosixOffset = &TrustedDomainPosixOffset;
  3033. LsapDbInitializeAttributeDs(
  3034. NextAttribute,
  3035. TrDmPxOf,
  3036. UpdatePosixOffset,
  3037. sizeof(ULONG),
  3038. FALSE
  3039. );
  3040. NextAttribute++;
  3041. AttributeCount++;
  3042. }
  3043. }
  3044. }
  3045. }
  3046. //
  3047. // Write the attributes to the DS.
  3048. //
  3049. Status = LsapDbWriteAttributesObject(
  3050. TrustedDomainHandle,
  3051. Attributes,
  3052. AttributeCount
  3053. );
  3054. if (!NT_SUCCESS(Status)) {
  3055. goto Cleanup;
  3056. }
  3057. //
  3058. // If we need it, create the interdomain trust account
  3059. //
  3060. if ( CreateInterdomainTrustAccount ) {
  3061. Status = LsapDsCreateInterdomainTrustAccount( TrustedDomainHandle );
  3062. if ( !NT_SUCCESS(Status)) {
  3063. goto Cleanup;
  3064. }
  3065. }
  3066. //
  3067. // Finally, update the trust info in the trusted domain list
  3068. //
  3069. if ( UpdateTrustedDomainList ) {
  3070. Status = LsapDbFixupTrustedDomainListEntry(
  3071. CurrentTrustedDomainFullInfo2->Information.Sid,
  3072. ( PLSAPR_UNICODE_STRING )&CurrentTrustedDomainFullInfo2->Information.Name,
  3073. ( PLSAPR_UNICODE_STRING )&CurrentTrustedDomainFullInfo2->Information.FlatName,
  3074. ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 )&UpdateInfoEx2,
  3075. UpdatePosixOffset );
  3076. if ( !NT_SUCCESS(Status)) {
  3077. goto Cleanup;
  3078. }
  3079. } else if ( UpdatePosixOffset != NULL ) {
  3080. Status = LsapDbFixupTrustedDomainListEntry(
  3081. ((LSAP_DB_HANDLE)TrustedDomainHandle)->Sid,
  3082. NULL,
  3083. NULL,
  3084. NULL, // No other trust info to update
  3085. UpdatePosixOffset );
  3086. if ( !NT_SUCCESS(Status)) {
  3087. goto Cleanup;
  3088. }
  3089. }
  3090. }
  3091. Status = STATUS_SUCCESS;
  3092. Cleanup:
  3093. if (NT_SUCCESS(Status) && LsapAdtAuditingEnabledHint(AuditCategoryPolicyChange, EVENTLOG_AUDIT_SUCCESS)) {
  3094. (void) LsapAdtTrustedDomainMod(
  3095. EVENTLOG_AUDIT_SUCCESS,
  3096. CurrentTrustedDomainFullInfo2->Information.Sid,
  3097. &CurrentTrustedDomainFullInfo2->Information.Name,
  3098. CurrentTrustedDomainFullInfo2->Information.TrustType,
  3099. CurrentTrustedDomainFullInfo2->Information.TrustDirection,
  3100. CurrentTrustedDomainFullInfo2->Information.TrustAttributes,
  3101. &UpdateInfoEx2.Name,
  3102. UpdateInfoEx2.TrustType,
  3103. UpdateInfoEx2.TrustDirection,
  3104. UpdateInfoEx2.TrustAttributes
  3105. );
  3106. }
  3107. if ( HandleReferenced ) {
  3108. LsapDbDereferenceHandle( TrustedDomainHandle, NT_SUCCESS( Status ) );
  3109. }
  3110. if ( SessionKey != NULL ) {
  3111. MIDL_user_free( SessionKey );
  3112. }
  3113. //
  3114. // Free memory allocated by this routine for attribute buffers.
  3115. // These have MemoryAllocated = TRUE in their attribute information.
  3116. // Leave alone buffers allocated by calling RPC stub.
  3117. //
  3118. for( NextAttribute = Attributes, AttributeNumber = 0;
  3119. AttributeNumber < AttributeCount;
  3120. NextAttribute++, AttributeNumber++) {
  3121. if (NextAttribute->MemoryAllocated) {
  3122. ASSERT(NextAttribute->AttributeValue != NULL);
  3123. MIDL_user_free(NextAttribute->AttributeValue);
  3124. }
  3125. }
  3126. //
  3127. // If necessary, dereference the Trusted Domain Object, release the LSA Database lock and
  3128. // return.
  3129. //
  3130. if (ObjectReferenced) {
  3131. Status = LsapDbDereferenceObject(
  3132. &TrustedDomainHandle,
  3133. TrustedDomainObject,
  3134. TrustedDomainObject,
  3135. DereferenceOptions,
  3136. SecurityDbChange,
  3137. Status
  3138. );
  3139. }
  3140. if ( CurrentTrustedDomainFullInfo2 != NULL ) {
  3141. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO(
  3142. TrustedDomainFullInformation2Internal,
  3143. (PLSAPR_TRUSTED_DOMAIN_INFO) CurrentTrustedDomainFullInfo2 );
  3144. }
  3145. //
  3146. // If necessary, release the Trusted Domain List Write Lock.
  3147. //
  3148. if (AcquiredListWriteLock) {
  3149. LsapDbReleaseLockTrustedDomainList();
  3150. AcquiredListWriteLock = FALSE;
  3151. }
  3152. //
  3153. // Free the auth info we might have allocated
  3154. //
  3155. if ( IncomingAuth ) {
  3156. LsapFreeLsaHeap( IncomingAuth );
  3157. }
  3158. if ( OutgoingAuth ) {
  3159. LsapFreeLsaHeap( OutgoingAuth );
  3160. }
  3161. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainAuthInfo, TRUE ) );
  3162. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainAuthInfo, FALSE ) );
  3163. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainFullInfo.AuthInformation, TRUE ) );
  3164. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainFullInfo.AuthInformation, FALSE ) );
  3165. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_SetInformationTrustedDomain);
  3166. LsarpReturnPrologue();
  3167. return(Status);
  3168. }
  3169. NTSTATUS
  3170. LsarEnumerateTrustedDomains(
  3171. IN LSAPR_HANDLE PolicyHandle,
  3172. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  3173. OUT PLSAPR_TRUSTED_ENUM_BUFFER EnumerationBuffer,
  3174. IN ULONG PreferedMaximumLength
  3175. )
  3176. /*++
  3177. Routine Description:
  3178. This function is the LSA server RPC worker routine for the
  3179. LsaEnumerateTrustedDomains API.
  3180. The LsaEnumerateTrustedDomains API returns information about
  3181. TrustedDomain objects. This call requires POLICY_VIEW_LOCAL_INFORMATION
  3182. access to the Policy object. Since there may be more information than
  3183. can be returned in a single call of the routine, multiple calls can be
  3184. made to get all of the information. To support this feature, the caller
  3185. is provided with a handle that can be used across calls to the API. On
  3186. the initial call, EnumerationContext should point to a variable that has
  3187. been initialized to 0. On each subsequent call, the value returned by
  3188. the preceding call should be passed in unchanged. The enumeration is
  3189. complete when the warning STATUS_NO_MORE_ENTRIES is returned.
  3190. Arguments:
  3191. PolicyHandle - Handle from an LsaOpenPolicy call.
  3192. EnumerationContext - API-specific handle to allow multiple calls
  3193. (see Routine Description above).
  3194. EnumerationBuffer - Pointer to an enumeration structure that will receive
  3195. a count of the Trusted Domains enumerated on this call and a pointer to
  3196. an array of entries containing information for each enumerated
  3197. Trusted Domain.
  3198. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  3199. bytes). This is not a hard upper limit, but serves as a guide. Due to
  3200. data conversion between systems with different natural data sizes, the
  3201. actual amount of data returned may be greater than this value.
  3202. Return Values:
  3203. NTSTATUS - Standard Nt Result Code
  3204. STATUS_SUCCESS - The call completed successfully.
  3205. Some entries may have been returned.
  3206. The caller need not call again.
  3207. STATUS_MORE_ENTRIES - The call completed successfully.
  3208. Some entries have been returned. The caller should call again to
  3209. get additional entries.
  3210. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3211. to complete the operation.
  3212. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  3213. is returned if no objects have been enumerated because the
  3214. EnumerationContext value is too high.
  3215. --*/
  3216. {
  3217. NTSTATUS Status;
  3218. PLSA_TRUST_INFORMATION XrefDomainTrustList = NULL;
  3219. ULONG XrefEntriesReturned;
  3220. ULONG XrefDomainTrustListLength;
  3221. ULONG XrefDomainTrustCount = 0;
  3222. PLSAPR_POLICY_INFORMATION PolicyAccountDomainInfo = NULL;
  3223. // PSID *Sids = NULL;
  3224. // LSAPR_HANDLE TrustedDomainHandle = NULL;
  3225. // ULONG MaxLength;
  3226. ULONG XrefIndex;
  3227. ULONG CurrentIndex;
  3228. LIST_ENTRY RootList, TrustList;
  3229. PLIST_ENTRY ListEntry;
  3230. PLIST_ENTRY NextEntry;
  3231. BOOLEAN TdosEnumerated = FALSE;
  3232. // BOOLEAN SomeTdosReturned = FALSE;
  3233. PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC FullTrustedDomainList = NULL;
  3234. ULONG FullTrustedDomainCount = 0 ;
  3235. ULONG i;
  3236. #define LSAP_XREF_ENUMERATION_CONTEXT 0x80000000
  3237. LsarpReturnCheckSetup();
  3238. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_EnumerateTrustedDomains);
  3239. //
  3240. // If no Enumeration Structure is provided, return an error.
  3241. //
  3242. if (!ARGUMENT_PRESENT(EnumerationBuffer)) {
  3243. Status = STATUS_INVALID_PARAMETER;
  3244. goto FunctionReturn;
  3245. }
  3246. EnumerationBuffer->EntriesRead = 0;
  3247. EnumerationBuffer->Information = NULL;
  3248. InitializeListHead( &RootList );
  3249. InitializeListHead( &TrustList );
  3250. if ( PreferedMaximumLength == 0 ) {
  3251. PreferedMaximumLength = 1;
  3252. }
  3253. //
  3254. // If the enumeration context indicates we've already progress past the TDOs,
  3255. // skip them
  3256. //
  3257. if ( (*EnumerationContext & LSAP_XREF_ENUMERATION_CONTEXT) == 0 ) {
  3258. //
  3259. // Call the worker routine that's shared with the Ex version.
  3260. //
  3261. Status = LsapEnumerateTrustedDomainsEx(
  3262. PolicyHandle,
  3263. EnumerationContext,
  3264. TrustedDomainInformationBasic,
  3265. (PLSAPR_TRUSTED_DOMAIN_INFO *)&(EnumerationBuffer->Information),
  3266. PreferedMaximumLength,
  3267. &EnumerationBuffer->EntriesRead,
  3268. LSAP_DB_ENUMERATE_AS_NT4 );
  3269. //
  3270. // If we're not done with the TDOs,
  3271. // return to the caller.
  3272. //
  3273. if ( Status != STATUS_SUCCESS && Status != STATUS_NO_MORE_ENTRIES ) {
  3274. goto Cleanup;
  3275. }
  3276. //
  3277. // Indicate that we're just starting to enumerate the XREF objects.
  3278. //
  3279. *EnumerationContext = LSAP_XREF_ENUMERATION_CONTEXT;
  3280. } else {
  3281. Status = STATUS_NO_MORE_ENTRIES;
  3282. }
  3283. //
  3284. // On native mode domains,
  3285. // return all of the domains in the forest.
  3286. //
  3287. // This ensures that downlevel clients see the indirectly trusted domains.
  3288. // The downlevel client can then authenticate using accounts in such domains
  3289. // using NTLM transitive trust.
  3290. //
  3291. //
  3292. // If we're not hosting a DS,
  3293. // or this is a mixed domain,
  3294. // we're done enumerating.
  3295. //
  3296. // The only trusted called of this is replication to an NT 4 BDC.
  3297. // It only wants the directly trusted domains.
  3298. //
  3299. if ( !LsapDsWriteDs ||
  3300. ((LSAP_DB_HANDLE)PolicyHandle)->Trusted ||
  3301. SamIMixedDomain( LsapAccountDomainHandle ) ) {
  3302. *EnumerationContext = 0xFFFFFFFF;
  3303. // Status is already set.
  3304. goto Cleanup;
  3305. }
  3306. //
  3307. // Enumerate the XREF objects
  3308. //
  3309. Status = LsapBuildForestTrustInfoLists(
  3310. NULL, // Use global policy handle
  3311. &TrustList );
  3312. if ( !NT_SUCCESS(Status) ) {
  3313. goto Cleanup;
  3314. }
  3315. //
  3316. // Loop through the XREFS determining how many we should return to the caller.
  3317. //
  3318. // Assert: at this point RootList is empty and TrustList contains all XREFs
  3319. //
  3320. // This loop will move a subset of the XREFs to the RootList. Those XREFs
  3321. // represent the ones to be returned to the caller.
  3322. //
  3323. XrefIndex = (*EnumerationContext) & ~LSAP_XREF_ENUMERATION_CONTEXT;
  3324. CurrentIndex = 0;
  3325. XrefEntriesReturned = 0;
  3326. for ( ListEntry = TrustList.Flink ;
  3327. ListEntry != &TrustList ;
  3328. ListEntry = NextEntry ) {
  3329. PLSAPDS_FOREST_TRUST_BLOB TrustBlob;
  3330. NextEntry = ListEntry->Flink;
  3331. TrustBlob = CONTAINING_RECORD( ListEntry,
  3332. LSAPDS_FOREST_TRUST_BLOB,
  3333. Next );
  3334. //
  3335. // Only consider entries greater or equal to our current enumeration context.
  3336. //
  3337. if ( CurrentIndex >= XrefIndex ) {
  3338. //
  3339. // Ignore entries without a DomainSid.
  3340. //
  3341. if ( TrustBlob->DomainSid != NULL &&
  3342. TrustBlob->FlatName.Length != 0 ) {
  3343. BOOLEAN AlreadyDone;
  3344. //
  3345. // If we haven't yet read a complete list of all the TDOs we've
  3346. // returned to the caller in the past,
  3347. // do so now.
  3348. //
  3349. if ( !TdosEnumerated ) {
  3350. LSA_ENUMERATION_HANDLE LocalEnumHandle = 0;
  3351. //
  3352. // Get to complete trusted domain list.
  3353. // Use global handle to avoid list length limitations.
  3354. //
  3355. Status = LsapEnumerateTrustedDomainsEx(
  3356. LsapPolicyHandle,
  3357. &LocalEnumHandle,
  3358. TrustedDomainInformationBasic,
  3359. (PLSAPR_TRUSTED_DOMAIN_INFO *)&FullTrustedDomainList,
  3360. 0xFFFFFFFF,
  3361. &FullTrustedDomainCount,
  3362. LSAP_DB_ENUMERATE_AS_NT4 );
  3363. // Handle the zero trusted domain case
  3364. if ( Status == STATUS_NO_MORE_ENTRIES ) {
  3365. Status = STATUS_SUCCESS;
  3366. FullTrustedDomainCount = 0;
  3367. FullTrustedDomainList = NULL;
  3368. }
  3369. if ( Status != STATUS_SUCCESS ) {
  3370. if ( Status == STATUS_MORE_ENTRIES ) {
  3371. Status = STATUS_INTERNAL_DB_CORRUPTION;
  3372. }
  3373. goto Cleanup;
  3374. }
  3375. //
  3376. // Get the Sid of this domain, too
  3377. //
  3378. Status = LsapDbQueryInformationPolicy(
  3379. LsapPolicyHandle,
  3380. PolicyAccountDomainInformation,
  3381. &PolicyAccountDomainInfo );
  3382. if ( !NT_SUCCESS(Status) ) {
  3383. goto Cleanup;
  3384. }
  3385. TdosEnumerated = TRUE;
  3386. }
  3387. //
  3388. // Check if this is the XREF for this domain.
  3389. //
  3390. AlreadyDone = FALSE;
  3391. if ( RtlEqualSid( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid,
  3392. TrustBlob->DomainSid ) ) {
  3393. AlreadyDone = TRUE;
  3394. }
  3395. //
  3396. // Determine if the XREF object matches one of the TDOs.
  3397. //
  3398. if ( !AlreadyDone ) {
  3399. for ( i=0; i<FullTrustedDomainCount; i++ ) {
  3400. if ( FullTrustedDomainList[i].Sid != NULL &&
  3401. RtlEqualSid( FullTrustedDomainList[i].Sid,
  3402. TrustBlob->DomainSid ) ) {
  3403. AlreadyDone = TRUE;
  3404. break;
  3405. }
  3406. }
  3407. }
  3408. //
  3409. // If the XREF object doesn't match any of the TDOs,
  3410. // return it to the caller.
  3411. //
  3412. if ( !AlreadyDone ) {
  3413. //
  3414. // Add the entry to the list of entries to return to the caller
  3415. //
  3416. RemoveEntryList( ListEntry );
  3417. InsertTailList( &RootList, ListEntry );
  3418. XrefEntriesReturned++;
  3419. }
  3420. }
  3421. }
  3422. //
  3423. // Account for the entry
  3424. //
  3425. CurrentIndex++;
  3426. }
  3427. XrefIndex = CurrentIndex | LSAP_XREF_ENUMERATION_CONTEXT;
  3428. //
  3429. // If the passed in enumeration context was too large,
  3430. // tell the caller.
  3431. //
  3432. XrefDomainTrustListLength = (XrefEntriesReturned + EnumerationBuffer->EntriesRead) * sizeof(LSA_TRUST_INFORMATION);
  3433. if ( XrefDomainTrustListLength == 0 ) {
  3434. if ( *EnumerationContext == 0 ) {
  3435. Status = STATUS_SUCCESS;
  3436. } else {
  3437. Status = STATUS_NO_MORE_ENTRIES;
  3438. }
  3439. goto Cleanup;
  3440. }
  3441. //
  3442. // Allocate a buffer to returned to the caller.
  3443. //
  3444. XrefDomainTrustList = MIDL_user_allocate( XrefDomainTrustListLength );
  3445. if ( XrefDomainTrustList == NULL ) {
  3446. Status = STATUS_INSUFFICIENT_RESOURCES;
  3447. goto Cleanup;
  3448. }
  3449. RtlZeroMemory ( XrefDomainTrustList, XrefDomainTrustListLength );
  3450. //
  3451. // If there were any TDOs returned on this call,
  3452. // copy them over now.
  3453. //
  3454. XrefDomainTrustCount = 0;
  3455. if ( EnumerationBuffer->EntriesRead != 0 ) {
  3456. //
  3457. // Indicate where the first XREF will be returned.
  3458. //
  3459. XrefDomainTrustCount = EnumerationBuffer->EntriesRead;
  3460. RtlCopyMemory( XrefDomainTrustList,
  3461. EnumerationBuffer->Information,
  3462. EnumerationBuffer->EntriesRead * sizeof(LSA_TRUST_INFORMATION) );
  3463. //
  3464. // Free the old buffer since it is no longer needed.
  3465. //
  3466. MIDL_user_free( EnumerationBuffer->Information );
  3467. EnumerationBuffer->Information = NULL;
  3468. EnumerationBuffer->EntriesRead = 0;
  3469. }
  3470. //
  3471. // Loop through the XREFS returning them
  3472. //
  3473. // Assert: at this point RootList contains the entries to return and
  3474. // TrustList contain the other XREFs
  3475. //
  3476. // XrefEntriesReturned = 0;
  3477. for ( ListEntry = RootList.Flink ;
  3478. ListEntry != &RootList ;
  3479. ListEntry = ListEntry->Flink ) {
  3480. PLSAPDS_FOREST_TRUST_BLOB TrustBlob;
  3481. TrustBlob = CONTAINING_RECORD( ListEntry,
  3482. LSAPDS_FOREST_TRUST_BLOB,
  3483. Next );
  3484. //
  3485. // Copy the Name.
  3486. //
  3487. Status = LsapRpcCopyUnicodeString(
  3488. NULL,
  3489. (PUNICODE_STRING) &XrefDomainTrustList[XrefDomainTrustCount].Name,
  3490. &TrustBlob->FlatName );
  3491. if (!NT_SUCCESS(Status)) {
  3492. goto Cleanup;
  3493. }
  3494. //
  3495. // Copy the Sid.
  3496. //
  3497. Status = LsapRpcCopySid(
  3498. NULL,
  3499. (PSID) &XrefDomainTrustList[XrefDomainTrustCount].Sid,
  3500. TrustBlob->DomainSid );
  3501. if (!NT_SUCCESS(Status)) {
  3502. goto Cleanup;
  3503. }
  3504. XrefDomainTrustCount ++;
  3505. }
  3506. *EnumerationContext = XrefIndex;
  3507. EnumerationBuffer->Information = (PLSAPR_TRUST_INFORMATION)XrefDomainTrustList;
  3508. EnumerationBuffer->EntriesRead = XrefDomainTrustCount;
  3509. XrefDomainTrustList = NULL;
  3510. Status = STATUS_SUCCESS;
  3511. Cleanup:
  3512. //
  3513. // Delete the trust lists
  3514. //
  3515. LsapDsForestFreeTrustBlobList( &TrustList );
  3516. LsapDsForestFreeTrustBlobList( &RootList );
  3517. if ( PolicyAccountDomainInfo != NULL ) {
  3518. LsaIFree_LSAPR_POLICY_INFORMATION ( PolicyAccountDomainInformation,
  3519. PolicyAccountDomainInfo );
  3520. }
  3521. if ( FullTrustedDomainList != NULL ) {
  3522. LsapFreeTrustedDomainsEx( TrustedDomainInformationBasic,
  3523. (PLSAPR_TRUSTED_DOMAIN_INFO)FullTrustedDomainList,
  3524. FullTrustedDomainCount );
  3525. }
  3526. if ( XrefDomainTrustList != NULL ) {
  3527. LsapFreeTrustedDomainsEx( TrustedDomainInformationBasic,
  3528. (PLSAPR_TRUSTED_DOMAIN_INFO)XrefDomainTrustList,
  3529. XrefDomainTrustCount );
  3530. }
  3531. FunctionReturn:
  3532. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_EnumerateTrustedDomains);
  3533. LsarpReturnPrologue();
  3534. return(Status);
  3535. }
  3536. NTSTATUS
  3537. LsapDbSlowEnumerateTrustedDomains(
  3538. IN LSAPR_HANDLE PolicyHandle,
  3539. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  3540. IN TRUSTED_INFORMATION_CLASS InfoClass,
  3541. OUT PLSAPR_TRUSTED_ENUM_BUFFER EnumerationBuffer,
  3542. IN ULONG PreferedMaximumLength
  3543. )
  3544. /*++
  3545. Routine Description:
  3546. This function performs the same actions as LsarEnumerateTrustedDomains()
  3547. except that the Trusted Domain List is not used.
  3548. This routine is called internally by the LSA only. Since there
  3549. may be more information than can be returned in a single call of the
  3550. routine, multiple calls can be made to get all of the information. To
  3551. support this feature, the caller is provided with a handle that can
  3552. be used across calls to the API. On the initial call, EnumerationContext
  3553. should point to a variable that has been initialized to 0.
  3554. Arguments:
  3555. PolicyHandle - Handle from an LsaOpenPolicy call.
  3556. EnumerationContext - API-specific handle to allow multiple calls
  3557. (see Routine Description above).
  3558. InfoClass - The class of information to return
  3559. Must be TrustedDomainInformationEx, TrustedDomainInformatinBasic or
  3560. TrustedDomainInformationEx2Internal
  3561. EnumerationBuffer - Pointer to an enumeration structure that will receive
  3562. a count of the Trusted Domains enumerated on this call and a pointer to
  3563. an array of entries containing information for each enumerated
  3564. Trusted Domain.
  3565. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  3566. bytes). This is not a hard upper limit, but serves as a guide. Due to
  3567. data conversion between systems with different natural data sizes, the
  3568. actual amount of data returned may be greater than this value.
  3569. Return Values:
  3570. NTSTATUS - Standard Nt Result Code
  3571. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3572. to complete the operation.
  3573. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  3574. is returned if there are no more objects to enumerate. Note that
  3575. one or more objects may be enumerated on a call that returns this
  3576. reply.
  3577. --*/
  3578. {
  3579. NTSTATUS Status;
  3580. LSAP_DB_SID_ENUMERATION_BUFFER DbEnumerationBuffer;
  3581. PVOID AllocatedBuffer = NULL;
  3582. //PLSA_TRUST_INFORMATION DomainTrustInfo = NULL;
  3583. LSAP_DB_ATTRIBUTE DomainNameAttribute;
  3584. ULONG DomainTrustInfoLength;
  3585. LSAPR_HANDLE TrustedDomainHandle = NULL;
  3586. ULONG EntriesRead = 0;
  3587. ULONG Index;
  3588. ASSERT( InfoClass == TrustedDomainInformationEx ||
  3589. InfoClass == TrustedDomainInformationEx2Internal ||
  3590. InfoClass == TrustedDomainInformationBasic );
  3591. //
  3592. // Initialization.
  3593. //
  3594. DbEnumerationBuffer.EntriesRead = 0;
  3595. DbEnumerationBuffer.Sids = NULL;
  3596. EnumerationBuffer->EntriesRead = 0;
  3597. EnumerationBuffer->Information = NULL;
  3598. DomainNameAttribute.AttributeValue = NULL;
  3599. //
  3600. // If no Enumeration Structure is provided, return an error.
  3601. //
  3602. if (!ARGUMENT_PRESENT(EnumerationBuffer)) {
  3603. Status = STATUS_INVALID_PARAMETER;
  3604. goto Cleanup;
  3605. }
  3606. //
  3607. // Call general Sid enumeration routine. This will return an array
  3608. // of pointers to Sids of Trusted Domains referenced from the
  3609. // Enumeration Buffer.
  3610. //
  3611. Status = LsapDbEnumerateSids(
  3612. PolicyHandle,
  3613. TrustedDomainObject,
  3614. EnumerationContext,
  3615. &DbEnumerationBuffer,
  3616. PreferedMaximumLength
  3617. );
  3618. if ((Status != STATUS_NO_MORE_ENTRIES) && !NT_SUCCESS(Status)) {
  3619. goto Cleanup;
  3620. }
  3621. //
  3622. // Return the number of entries read. Note that the Enumeration Buffer
  3623. // returned from LsapDbEnumerateSids is expected to be non-null
  3624. // in all non-error cases.
  3625. //
  3626. EntriesRead = DbEnumerationBuffer.EntriesRead;
  3627. if (EntriesRead == 0) {
  3628. goto Cleanup;
  3629. }
  3630. //
  3631. // Allocate a buffer to return to our caller
  3632. //
  3633. switch (InfoClass ) {
  3634. case TrustedDomainInformationBasic:
  3635. DomainTrustInfoLength = EntriesRead * sizeof(LSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC);
  3636. break;
  3637. case TrustedDomainInformationEx:
  3638. DomainTrustInfoLength = EntriesRead * sizeof(LSAPR_TRUSTED_DOMAIN_INFORMATION_EX);
  3639. break;
  3640. case TrustedDomainInformationEx2Internal:
  3641. DomainTrustInfoLength = EntriesRead * sizeof(LSAPR_TRUSTED_DOMAIN_INFORMATION_EX2);
  3642. break;
  3643. default:
  3644. Status = STATUS_INVALID_PARAMETER;
  3645. goto Cleanup;
  3646. }
  3647. AllocatedBuffer = MIDL_user_allocate( DomainTrustInfoLength );
  3648. if ( AllocatedBuffer == NULL ) {
  3649. Status = STATUS_INSUFFICIENT_RESOURCES;
  3650. goto Cleanup;
  3651. }
  3652. //
  3653. // Initialize all pointers to Sids and Unicode buffers in the
  3654. // DomainTrustInfo array to zero. The error path of this routine
  3655. // assumes that a non-zero value of a Sid or Unicode buffer indicates
  3656. // that memory is to be freed.
  3657. //
  3658. RtlZeroMemory( AllocatedBuffer, DomainTrustInfoLength );
  3659. //
  3660. // Loop through the trusted domains returning the information the caller
  3661. // requested.
  3662. //
  3663. for ( Index=0; Index<EntriesRead; Index++ ) {
  3664. //
  3665. // Grab the Sid of the trusted domain.
  3666. //
  3667. //
  3668. // Open the Trusted Domain object. This call is trusted, i.e.
  3669. // no access validation or impersonation is required. Also,
  3670. // the Lsa Database is already locked so we do not need to
  3671. // lock it again.
  3672. //
  3673. Status = LsapDbOpenTrustedDomain(
  3674. PolicyHandle,
  3675. DbEnumerationBuffer.Sids[Index],
  3676. (ACCESS_MASK) 0,
  3677. &TrustedDomainHandle,
  3678. LSAP_DB_TRUSTED );
  3679. if (!NT_SUCCESS(Status)) {
  3680. goto Cleanup;
  3681. }
  3682. //
  3683. // Read the Domain Name
  3684. //
  3685. LsapDbInitializeAttributeDs(
  3686. &DomainNameAttribute,
  3687. TrDmName,
  3688. NULL,
  3689. 0L,
  3690. FALSE
  3691. );
  3692. Status = LsapDbReadAttribute(TrustedDomainHandle, &DomainNameAttribute);
  3693. (VOID) LsapDbCloseObject(
  3694. &TrustedDomainHandle,
  3695. LSAP_DB_DEREFERENCE_CONTR,
  3696. Status
  3697. );
  3698. if (!NT_SUCCESS(Status)) {
  3699. #if DBG
  3700. DbgPrint( "LsarEnumerateTrustedDomains - Reading Domain Name\n" );
  3701. DbgPrint( " failed. Error 0x%lx reading Trusted Domain Name attribute\n",
  3702. Status);
  3703. #endif //DBG
  3704. goto Cleanup;
  3705. }
  3706. //
  3707. // Return the information to the caller.
  3708. //
  3709. switch (InfoClass ) {
  3710. case TrustedDomainInformationBasic:
  3711. {
  3712. PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC DomainTrust;
  3713. DomainTrust = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC)AllocatedBuffer)[Index];
  3714. // Grab the Sid
  3715. DomainTrust->Sid = DbEnumerationBuffer.Sids[Index];
  3716. DbEnumerationBuffer.Sids[Index] = NULL;
  3717. // Grab the Domain Name
  3718. Status = LsapDbCopyUnicodeAttribute(
  3719. (PUNICODE_STRING)&DomainTrust->Name,
  3720. &DomainNameAttribute,
  3721. TRUE );
  3722. if ( !NT_SUCCESS(Status)) {
  3723. goto Cleanup;
  3724. }
  3725. break;
  3726. }
  3727. case TrustedDomainInformationEx2Internal:
  3728. {
  3729. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 TrustInfoEx2;
  3730. TrustInfoEx2 = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2)AllocatedBuffer)[Index];
  3731. // Grab the Sid
  3732. TrustInfoEx2->Sid = DbEnumerationBuffer.Sids[Index];
  3733. DbEnumerationBuffer.Sids[Index] = NULL;
  3734. // Grab the Domain Name
  3735. Status = LsapDbCopyUnicodeAttribute(
  3736. (PUNICODE_STRING)&TrustInfoEx2->Name,
  3737. &DomainNameAttribute,
  3738. TRUE );
  3739. if ( !NT_SUCCESS(Status)) {
  3740. goto Cleanup;
  3741. }
  3742. // Grab the Flat Domain Name
  3743. Status = LsapDbCopyUnicodeAttribute(
  3744. (PUNICODE_STRING)&TrustInfoEx2->FlatName,
  3745. &DomainNameAttribute,
  3746. TRUE );
  3747. if ( !NT_SUCCESS(Status)) {
  3748. goto Cleanup;
  3749. }
  3750. // Fill in the constant info
  3751. TrustInfoEx2->TrustDirection = TRUST_DIRECTION_OUTBOUND;
  3752. TrustInfoEx2->TrustType = TRUST_TYPE_DOWNLEVEL;
  3753. TrustInfoEx2->TrustAttributes = 0;
  3754. TrustInfoEx2->ForestTrustLength = 0;
  3755. TrustInfoEx2->ForestTrustInfo = NULL;
  3756. break;
  3757. }
  3758. case TrustedDomainInformationEx:
  3759. {
  3760. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustInfoEx;
  3761. TrustInfoEx = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX)AllocatedBuffer)[Index];
  3762. // Grab the Sid
  3763. TrustInfoEx->Sid = DbEnumerationBuffer.Sids[Index];
  3764. DbEnumerationBuffer.Sids[Index] = NULL;
  3765. // Grab the Domain Name
  3766. Status = LsapDbCopyUnicodeAttribute(
  3767. (PUNICODE_STRING)&TrustInfoEx->Name,
  3768. &DomainNameAttribute,
  3769. TRUE );
  3770. if ( !NT_SUCCESS(Status)) {
  3771. goto Cleanup;
  3772. }
  3773. // Grab the Flat Domain Name
  3774. Status = LsapDbCopyUnicodeAttribute(
  3775. (PUNICODE_STRING)&TrustInfoEx->FlatName,
  3776. &DomainNameAttribute,
  3777. TRUE );
  3778. if ( !NT_SUCCESS(Status)) {
  3779. goto Cleanup;
  3780. }
  3781. // Fill in the constant info
  3782. TrustInfoEx->TrustDirection = TRUST_DIRECTION_OUTBOUND;
  3783. TrustInfoEx->TrustType = TRUST_TYPE_DOWNLEVEL;
  3784. TrustInfoEx->TrustAttributes = 0;
  3785. break;
  3786. }
  3787. }
  3788. }
  3789. Status = STATUS_SUCCESS;
  3790. Cleanup:
  3791. //
  3792. // On error,
  3793. // free any buffer we allocated.
  3794. //
  3795. if ( !NT_SUCCESS(Status) ) {
  3796. if (AllocatedBuffer != NULL) {
  3797. for ( Index=0; Index<EntriesRead; Index++ ) {
  3798. switch (InfoClass ) {
  3799. case TrustedDomainInformationBasic:
  3800. {
  3801. PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC DomainTrust;
  3802. DomainTrust = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC)AllocatedBuffer)[Index];
  3803. if ( DomainTrust->Sid != NULL ) {
  3804. MIDL_user_free( DomainTrust->Sid );
  3805. }
  3806. if ( DomainTrust->Name.Buffer != NULL ) {
  3807. MIDL_user_free( DomainTrust->Name.Buffer );
  3808. }
  3809. break;
  3810. }
  3811. case TrustedDomainInformationEx:
  3812. {
  3813. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustInfoEx;
  3814. TrustInfoEx = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX)AllocatedBuffer)[Index];
  3815. if ( TrustInfoEx->Sid != NULL ) {
  3816. MIDL_user_free( TrustInfoEx->Sid );
  3817. }
  3818. if ( TrustInfoEx->Name.Buffer != NULL ) {
  3819. MIDL_user_free( TrustInfoEx->Name.Buffer );
  3820. }
  3821. if ( TrustInfoEx->FlatName.Buffer != NULL ) {
  3822. MIDL_user_free( TrustInfoEx->FlatName.Buffer );
  3823. }
  3824. break;
  3825. }
  3826. case TrustedDomainInformationEx2Internal:
  3827. {
  3828. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 TrustInfoEx2;
  3829. TrustInfoEx2 = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2)AllocatedBuffer)[Index];
  3830. if ( TrustInfoEx2->Sid != NULL ) {
  3831. MIDL_user_free( TrustInfoEx2->Sid );
  3832. }
  3833. if ( TrustInfoEx2->Name.Buffer != NULL ) {
  3834. MIDL_user_free( TrustInfoEx2->Name.Buffer );
  3835. }
  3836. if ( TrustInfoEx2->FlatName.Buffer != NULL ) {
  3837. MIDL_user_free( TrustInfoEx2->FlatName.Buffer );
  3838. }
  3839. break;
  3840. }
  3841. }
  3842. }
  3843. MIDL_user_free( AllocatedBuffer );
  3844. AllocatedBuffer = NULL;
  3845. DbEnumerationBuffer.EntriesRead = 0;
  3846. }
  3847. }
  3848. //
  3849. // Fill in returned Enumeration Structure, returning 0 or NULL for
  3850. // fields in the error case.
  3851. //
  3852. EnumerationBuffer->Information = (PLSAPR_TRUST_INFORMATION) AllocatedBuffer;
  3853. EnumerationBuffer->EntriesRead = DbEnumerationBuffer.EntriesRead;
  3854. //
  3855. // If necessary, free the Domain Name Attribute Value buffer which
  3856. // holds a self relative Unicode String.
  3857. //
  3858. if (DomainNameAttribute.AttributeValue != NULL) {
  3859. MIDL_user_free( DomainNameAttribute.AttributeValue );
  3860. DomainNameAttribute.AttributeValue = NULL;
  3861. }
  3862. //
  3863. // Free the SID enumeration buffer.
  3864. //
  3865. if ( DbEnumerationBuffer.Sids != NULL ) {
  3866. for ( Index=0; Index<EntriesRead; Index++ ) {
  3867. if ( DbEnumerationBuffer.Sids[Index] != NULL ) {
  3868. MIDL_user_free( DbEnumerationBuffer.Sids[Index] );
  3869. }
  3870. }
  3871. MIDL_user_free( DbEnumerationBuffer.Sids );
  3872. }
  3873. return(Status);
  3874. }
  3875. NTSTATUS
  3876. LsapDbVerifyInfoQueryTrustedDomain(
  3877. IN TRUSTED_INFORMATION_CLASS InformationClass,
  3878. IN BOOLEAN Trusted,
  3879. OUT PACCESS_MASK RequiredAccess
  3880. )
  3881. /*++
  3882. Routine Description:
  3883. This function validates a TrustedDomain Information Class. If valid, a mask
  3884. of the accesses required to set the TrustedDomain Information of the class is
  3885. returned.
  3886. Arguments:
  3887. InformationClass - Specifies a TrustedDomain Information Class.
  3888. Trusted - TRUE if client is trusted, else FALSE. A trusted client
  3889. is allowed to query TrustedDomain for all Information Classes, whereas
  3890. a non-trusted client is restricted.
  3891. RequiredAccess - Points to variable that will receive a mask of the
  3892. accesses required to query the given class of TrustedDomain Information.
  3893. If an error is returned, this value is cleared to 0.
  3894. Return Values:
  3895. NTSTATUS - Standard Nt Result Code
  3896. STATUS_SUCCESS - The TrustedDomain Information Class provided is
  3897. valid and the information provided is consistent with this
  3898. class.
  3899. STATUS_INVALID_PARAMETER - Invalid parameter:
  3900. Information Class is invalid
  3901. TrustedDomain Information not valid for the class
  3902. --*/
  3903. {
  3904. if (LsapDbValidInfoTrustedDomain( InformationClass, NULL)) {
  3905. *RequiredAccess = LsapDbRequiredAccessQueryTrustedDomain[InformationClass];
  3906. return(STATUS_SUCCESS);
  3907. }
  3908. return(STATUS_INVALID_PARAMETER);
  3909. //
  3910. // Currently, all TrustedDomain information classes may be queried
  3911. // by non-trusted callers, so the Trusted parameter is not accessed.
  3912. //
  3913. UNREFERENCED_PARAMETER(Trusted);
  3914. }
  3915. NTSTATUS
  3916. LsapDbVerifyInfoSetTrustedDomain(
  3917. IN TRUSTED_INFORMATION_CLASS InformationClass,
  3918. IN PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation,
  3919. IN BOOLEAN Trusted,
  3920. OUT PACCESS_MASK RequiredAccess
  3921. )
  3922. /*++
  3923. Routine Description:
  3924. This function validates a TrustedDomain Information Class and verifies
  3925. that the provided TrustedDomain Information is valid for the class.
  3926. If valid, a mask of the accesses required to set the TrustedDomain
  3927. Information of the class is returned.
  3928. Arguments:
  3929. InformationClass - Specifies a TrustedDomain Information Class.
  3930. TrustedDomainInformation - Points to TrustedDomain Information to be set.
  3931. Trusted - TRUE if client is trusted, else FALSE. A trusted client
  3932. is allowed to set TrustedDomain for all Information Classes, whereas
  3933. a non-trusted client is restricted.
  3934. RequiredAccess - Points to variable that will receive a mask of the
  3935. accesses required to set the given class of TrustedDomain Information.
  3936. If an error is returned, this value is cleared to 0.
  3937. Return Values:
  3938. NTSTATUS - Standard Nt Result Code
  3939. STATUS_SUCCESS - The TrustedDomain Information Class provided is
  3940. valid and the information provided is consistent with this
  3941. class.
  3942. STATUS_INVALID_PARAMETER - Invalid parameter:
  3943. Information Class is invalid
  3944. Information Class is invalid for non-trusted clients
  3945. TrustedDomain Information not valid for the class
  3946. --*/
  3947. {
  3948. //
  3949. // Verify that the information class is valid and that the TrustedDomain
  3950. // Information provided is valid for the class.
  3951. //
  3952. if (LsapDbValidInfoTrustedDomain( InformationClass, TrustedDomainInformation)) {
  3953. //
  3954. // Non-trusted callers are not allowed to set the
  3955. // TrustedDomainNameInformation information class.
  3956. //
  3957. if (!Trusted) {
  3958. if (InformationClass == TrustedDomainNameInformation) {
  3959. return(STATUS_INVALID_PARAMETER);
  3960. }
  3961. }
  3962. // ASSERT( InformationClass <=
  3963. // sizeof( LsapDbRequiredAccessSetTrustedDomain ) / sizeof( ACCESS_MASK ) + 1);
  3964. *RequiredAccess = LsapDbRequiredAccessSetTrustedDomain[InformationClass];
  3965. return(STATUS_SUCCESS);
  3966. }
  3967. return(STATUS_INVALID_PARAMETER);
  3968. }
  3969. BOOLEAN
  3970. LsapDbValidInfoTrustedDomain(
  3971. IN TRUSTED_INFORMATION_CLASS InformationClass,
  3972. IN OPTIONAL PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation
  3973. )
  3974. /*++
  3975. Routine Description:
  3976. This function validates a TrustedDomain Information Class and optionally verifies
  3977. that provided TrustedDomain Information is valid for the class.
  3978. Arguments:
  3979. InformationClass - Specifies a TrustedDomain Information Class.
  3980. TrustedDomainInformation - Optionally points to TrustedDomain Information. If
  3981. NULL is specified, no TrustedDomain Information checking takes place.
  3982. Return Values:
  3983. BOOLEAN - TRUE if the TrustedDomain information class provided is
  3984. valid, else FALSE.
  3985. --*/
  3986. {
  3987. BOOLEAN BooleanStatus = FALSE;
  3988. //
  3989. // Validate the Information Class
  3990. //
  3991. if ((InformationClass >= TrustedDomainNameInformation) &&
  3992. (InformationClass <= TrustedDomainFullInformation2Internal)) {
  3993. if (TrustedDomainInformation == NULL) {
  3994. return(TRUE);
  3995. }
  3996. switch (InformationClass) {
  3997. case TrustedDomainNameInformation: {
  3998. PTRUSTED_DOMAIN_NAME_INFO TrustedDomainNameInfo = (PTRUSTED_DOMAIN_NAME_INFO) TrustedDomainInformation;
  3999. if ( !LsapValidateLsaUnicodeString( &TrustedDomainNameInfo->Name )) {
  4000. break;
  4001. }
  4002. BooleanStatus = TRUE;
  4003. break;
  4004. }
  4005. case TrustedPosixOffsetInformation: {
  4006. PTRUSTED_POSIX_OFFSET_INFO TrustedPosixOffsetInfo = (PTRUSTED_POSIX_OFFSET_INFO) TrustedDomainInformation;
  4007. BooleanStatus = TRUE;
  4008. break;
  4009. }
  4010. case TrustedPasswordInformation: {
  4011. PLSAPR_TRUSTED_PASSWORD_INFO TrustedPasswordInfo = (PLSAPR_TRUSTED_PASSWORD_INFO) TrustedDomainInformation; TrustedPasswordInfo;
  4012. if ( TrustedPasswordInfo->Password != NULL &&
  4013. !LsapValidateLsaCipherValue( TrustedPasswordInfo->Password )) {
  4014. break;
  4015. }
  4016. if ( TrustedPasswordInfo->OldPassword != NULL &&
  4017. !LsapValidateLsaCipherValue( TrustedPasswordInfo->OldPassword )) {
  4018. break;
  4019. }
  4020. BooleanStatus = TRUE;
  4021. break;
  4022. }
  4023. case TrustedDomainInformationBasic: {
  4024. PTRUSTED_DOMAIN_INFORMATION_BASIC TrustedDomainBasicInfo = (PTRUSTED_DOMAIN_INFORMATION_BASIC) TrustedDomainInformation;
  4025. if ( !LsapValidateLsaUnicodeString( &TrustedDomainBasicInfo->Name )) {
  4026. break;
  4027. }
  4028. BooleanStatus = TRUE;
  4029. break;
  4030. }
  4031. case TrustedDomainInformationEx: {
  4032. PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainExInfo = (PTRUSTED_DOMAIN_INFORMATION_EX) TrustedDomainInformation;
  4033. if ( !LsapValidateLsaUnicodeString( &TrustedDomainExInfo->Name )) {
  4034. break;
  4035. }
  4036. if ( !LsapValidateLsaUnicodeString( &TrustedDomainExInfo->FlatName )) {
  4037. break;
  4038. }
  4039. BooleanStatus = TRUE;
  4040. break;
  4041. }
  4042. case TrustedDomainAuthInformation: {
  4043. PTRUSTED_DOMAIN_AUTH_INFORMATION TrustedDomainAuthInfo = (PTRUSTED_DOMAIN_AUTH_INFORMATION) TrustedDomainInformation;
  4044. if ( TrustedDomainAuthInfo->IncomingAuthInfos != 0 &&
  4045. TrustedDomainAuthInfo->IncomingAuthenticationInformation == NULL ) {
  4046. break;
  4047. }
  4048. if ( TrustedDomainAuthInfo->OutgoingAuthInfos != 0 &&
  4049. TrustedDomainAuthInfo->OutgoingAuthenticationInformation == NULL ) {
  4050. break;
  4051. }
  4052. BooleanStatus = TRUE;
  4053. break;
  4054. }
  4055. case TrustedDomainFullInformation: {
  4056. PTRUSTED_DOMAIN_FULL_INFORMATION TrustedDomainFullInfo = (PTRUSTED_DOMAIN_FULL_INFORMATION) TrustedDomainInformation;
  4057. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo->Information.Name )) {
  4058. break;
  4059. }
  4060. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo->Information.FlatName )) {
  4061. break;
  4062. }
  4063. if ( TrustedDomainFullInfo->AuthInformation.IncomingAuthInfos != 0 &&
  4064. TrustedDomainFullInfo->AuthInformation.IncomingAuthenticationInformation == NULL ) {
  4065. break;
  4066. }
  4067. if ( TrustedDomainFullInfo->AuthInformation.OutgoingAuthInfos != 0 &&
  4068. TrustedDomainFullInfo->AuthInformation.OutgoingAuthenticationInformation == NULL ) {
  4069. break;
  4070. }
  4071. BooleanStatus = TRUE;
  4072. break;
  4073. }
  4074. case TrustedDomainAuthInformationInternal: {
  4075. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL TrustedDomainAuthInfo = (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL) TrustedDomainInformation;
  4076. if ( TrustedDomainAuthInfo->AuthBlob.AuthSize != 0 &&
  4077. TrustedDomainAuthInfo->AuthBlob.AuthBlob == NULL ) {
  4078. break;
  4079. }
  4080. BooleanStatus = TRUE;
  4081. break;
  4082. }
  4083. case TrustedDomainFullInformationInternal: {
  4084. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL TrustedDomainFullInfo = (PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL) TrustedDomainInformation;
  4085. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo->Information.Name )) {
  4086. break;
  4087. }
  4088. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo->Information.FlatName )) {
  4089. break;
  4090. }
  4091. if ( TrustedDomainFullInfo->AuthInformation.AuthBlob.AuthSize != 0 &&
  4092. TrustedDomainFullInfo->AuthInformation.AuthBlob.AuthBlob == NULL ) {
  4093. break;
  4094. }
  4095. BooleanStatus = TRUE;
  4096. break;
  4097. }
  4098. case TrustedDomainInformationEx2Internal: {
  4099. PTRUSTED_DOMAIN_INFORMATION_EX2 TrustedDomainExInfo2 = (PTRUSTED_DOMAIN_INFORMATION_EX2) TrustedDomainInformation;
  4100. if ( !LsapValidateLsaUnicodeString( &TrustedDomainExInfo2->Name )) {
  4101. break;
  4102. }
  4103. if ( !LsapValidateLsaUnicodeString( &TrustedDomainExInfo2->FlatName )) {
  4104. break;
  4105. }
  4106. if ( TrustedDomainExInfo2->ForestTrustLength == 0 ||
  4107. TrustedDomainExInfo2->ForestTrustInfo == NULL ) {
  4108. if ( TrustedDomainExInfo2->ForestTrustLength != 0 ||
  4109. TrustedDomainExInfo2->ForestTrustInfo != NULL ) {
  4110. break;
  4111. }
  4112. }
  4113. BooleanStatus = TRUE;
  4114. break;
  4115. }
  4116. case TrustedDomainFullInformation2Internal: {
  4117. PTRUSTED_DOMAIN_FULL_INFORMATION2 TrustedDomainFullInfo2 = (PTRUSTED_DOMAIN_FULL_INFORMATION2) TrustedDomainInformation;
  4118. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo2->Information.Name )) {
  4119. break;
  4120. }
  4121. if ( !LsapValidateLsaUnicodeString( &TrustedDomainFullInfo2->Information.FlatName )) {
  4122. break;
  4123. }
  4124. if ( TrustedDomainFullInfo2->AuthInformation.IncomingAuthInfos != 0 &&
  4125. TrustedDomainFullInfo2->AuthInformation.IncomingAuthenticationInformation == NULL ) {
  4126. break;
  4127. }
  4128. if ( TrustedDomainFullInfo2->AuthInformation.OutgoingAuthInfos != 0 &&
  4129. TrustedDomainFullInfo2->AuthInformation.OutgoingAuthenticationInformation == NULL ) {
  4130. break;
  4131. }
  4132. if ( TrustedDomainFullInfo2->Information.ForestTrustLength == 0 ||
  4133. TrustedDomainFullInfo2->Information.ForestTrustInfo == NULL ) {
  4134. if ( TrustedDomainFullInfo2->Information.ForestTrustLength != 0 ||
  4135. TrustedDomainFullInfo2->Information.ForestTrustInfo != NULL ) {
  4136. break;
  4137. }
  4138. }
  4139. BooleanStatus = TRUE;
  4140. break;
  4141. }
  4142. case TrustedControllersInformation: // No longer supported
  4143. default:
  4144. BooleanStatus = FALSE;
  4145. break;
  4146. }
  4147. }
  4148. return(BooleanStatus);
  4149. }
  4150. NTSTATUS
  4151. LsapDbLookupSidTrustedDomainList(
  4152. IN PLSAPR_SID DomainSid,
  4153. OUT PLSAPR_TRUST_INFORMATION *TrustInformation
  4154. )
  4155. /*++
  4156. Routine Description:
  4157. This function looks up a given Trusted Domain Sid in the Trusted
  4158. Domain List and returns Trust Information consisting of its
  4159. Sid and Name.
  4160. Arguments:
  4161. DomainSid - Pointer to a Sid that will be compared with the list of
  4162. Sids of Trusted Domains.
  4163. TrustInformation - Receives the a pointer to the Trust Information
  4164. (Sid and Name) of the Trusted Domain specified by DomainSid
  4165. within the Trusted Domain List.
  4166. NOTE: The trust information returned will always be the trusted
  4167. domain objects domain name. Not the flat name. That means that
  4168. for uplevel trusts, a DNS domain name will be returned.
  4169. NOTE: This routine assumes that the Trusted Domain List
  4170. will not be updated while any Lookup operations are pending.
  4171. Thus, the pointer returned for TrustInformation will remain
  4172. valid.
  4173. Return Value:
  4174. NTSTATUS - Standard Nt Result Code
  4175. STATUS_SUCCESS - The domain was found.
  4176. STATUS_NO_SUCH_DOMAIN - The domain was not found.
  4177. --*/
  4178. {
  4179. NTSTATUS Status = STATUS_SUCCESS;
  4180. ULONG SectionIndex;
  4181. LSAPR_TRUST_INFORMATION InputTrustInformation;
  4182. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  4183. //
  4184. // Don't try to lookup by sid if we don't have a sid
  4185. //
  4186. if ( DomainSid == NULL ) {
  4187. Status = STATUS_NO_SUCH_DOMAIN;
  4188. goto LookupSidTrustedDomainListError;
  4189. }
  4190. ASSERT( LsapDbIsLockedTrustedDomainList());
  4191. if ( !LsapDbIsValidTrustedDomainList()) {
  4192. LsapDbConvertReadLockTrustedDomainListToExclusive();
  4193. Status = LsapDbBuildTrustedDomainCache();
  4194. if ( !NT_SUCCESS( Status )) {
  4195. goto LookupSidTrustedDomainListError;
  4196. }
  4197. }
  4198. InputTrustInformation.Sid = DomainSid;
  4199. InputTrustInformation.Name.Buffer = NULL;
  4200. InputTrustInformation.Name.Length = 0;
  4201. InputTrustInformation.Name.MaximumLength = 0;
  4202. Status = LsapDbLookupEntryTrustedDomainList(
  4203. &InputTrustInformation,
  4204. &TrustEntry
  4205. );
  4206. if (!NT_SUCCESS(Status)) {
  4207. goto LookupSidTrustedDomainListError;
  4208. }
  4209. //
  4210. // Return pointer to Trust Information
  4211. //
  4212. *TrustInformation = &TrustEntry->ConstructedTrustInfo;
  4213. LookupSidTrustedDomainListFinish:
  4214. return(Status);
  4215. LookupSidTrustedDomainListError:
  4216. *TrustInformation = NULL;
  4217. goto LookupSidTrustedDomainListFinish;
  4218. }
  4219. NTSTATUS
  4220. LsapDbLookupNameTrustedDomainList(
  4221. IN PLSAPR_UNICODE_STRING DomainName,
  4222. OUT PLSAPR_TRUST_INFORMATION *TrustInformation
  4223. )
  4224. /*++
  4225. Routine Description:
  4226. This function looks up a given Trusted Domain Name in the Trusted
  4227. Domain List and returns Trust Information consisting of its
  4228. Sid and Name.
  4229. Arguments:
  4230. DomainName - Pointer to a Unicode Name that will be compared with the
  4231. list of Names of Trusted Domains.
  4232. TrustInformation - Receives the a pointer to the Trust Information
  4233. (Sid and Name) of the Trusted Domain described by DomainName
  4234. within the Trusted Domain List.
  4235. NOTE: This name will be looked up as both the trusted domain objects
  4236. domain name and the flat name
  4237. NOTE: This routine assumes that the Trusted Domain List
  4238. will not be updated while any Lookup operations are pending.
  4239. Thus, the pointer returned for TrustInformation will remain
  4240. valid.
  4241. Return Value:
  4242. NTSTATUS - Standard Nt Result Code
  4243. STATUS_SUCCESS - The domain was found.
  4244. STATUS_NO_SUCH_DOMAIN - The domain was not found.
  4245. --*/
  4246. {
  4247. NTSTATUS Status = STATUS_SUCCESS;
  4248. ULONG SectionIndex;
  4249. LSAPR_TRUST_INFORMATION InputTrustInformation;
  4250. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  4251. ASSERT( LsapDbIsLockedTrustedDomainList());
  4252. if ( !LsapDbIsValidTrustedDomainList()) {
  4253. LsapDbConvertReadLockTrustedDomainListToExclusive();
  4254. Status = LsapDbBuildTrustedDomainCache();
  4255. if ( !NT_SUCCESS( Status )) {
  4256. goto LookupNameTrustedDomainListError;
  4257. }
  4258. }
  4259. InputTrustInformation.Sid = NULL;
  4260. InputTrustInformation.Name = *DomainName;
  4261. Status = LsapDbLookupEntryTrustedDomainList(
  4262. &InputTrustInformation,
  4263. &TrustEntry
  4264. );
  4265. if (!NT_SUCCESS(Status)) {
  4266. goto LookupNameTrustedDomainListError;
  4267. }
  4268. //
  4269. // Return pointer to Trust Information
  4270. //
  4271. *TrustInformation = &TrustEntry->ConstructedTrustInfo;
  4272. LookupNameTrustedDomainListFinish:
  4273. return(Status);
  4274. LookupNameTrustedDomainListError:
  4275. *TrustInformation = NULL;
  4276. goto LookupNameTrustedDomainListFinish;
  4277. }
  4278. NTSTATUS
  4279. LsapDbLookupSidTrustedDomainListEx(
  4280. IN PSID DomainSid,
  4281. OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *TrustedDomainListEntry
  4282. )
  4283. /*++
  4284. Routine Description:
  4285. This function looks up a given Trusted Domain Name in the Trusted
  4286. Domain List and returns Trust Information consisting of its
  4287. Sid and Name.
  4288. Arguments:
  4289. DomainSid - sid of the domain to lookup
  4290. TrustInformation - Receives the a pointer to the Trust Information
  4291. (Sid and Name) of the Trusted Domain described by DomainName
  4292. within the Trusted Domain List.
  4293. NOTE: This name will be looked up as both the trusted domain objects
  4294. domain name and the flat name
  4295. NOTE: This routine assumes that the Trusted Domain List
  4296. will not be updated while any Lookup operations are pending.
  4297. Thus, the pointer returned for TrustInformation will remain
  4298. valid.
  4299. Return Value:
  4300. NTSTATUS - Standard Nt Result Code
  4301. STATUS_SUCCESS - The domain was found.
  4302. STATUS_NO_SUCH_DOMAIN - The domain was not found.
  4303. --*/
  4304. {
  4305. NTSTATUS Status = STATUS_SUCCESS;
  4306. ULONG SectionIndex;
  4307. LSAPR_TRUST_INFORMATION InputTrustInformation;
  4308. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  4309. ASSERT( LsapDbIsLockedTrustedDomainList());
  4310. if ( !LsapDbIsValidTrustedDomainList()) {
  4311. LsapDbConvertReadLockTrustedDomainListToExclusive();
  4312. Status = LsapDbBuildTrustedDomainCache();
  4313. if ( !NT_SUCCESS( Status )) {
  4314. goto LookupSidTrustedDomainListError;
  4315. }
  4316. }
  4317. InputTrustInformation.Sid = DomainSid;
  4318. RtlInitUnicodeString( (UNICODE_STRING*)&InputTrustInformation.Name, NULL );
  4319. Status = LsapDbLookupEntryTrustedDomainList(
  4320. &InputTrustInformation,
  4321. &TrustEntry );
  4322. if (!NT_SUCCESS(Status)) {
  4323. goto LookupSidTrustedDomainListError;
  4324. }
  4325. //
  4326. // Return pointer to Trust Information
  4327. //
  4328. *TrustedDomainListEntry = TrustEntry;
  4329. LookupSidTrustedDomainListFinish:
  4330. return(Status);
  4331. LookupSidTrustedDomainListError:
  4332. *TrustedDomainListEntry = NULL;
  4333. goto LookupSidTrustedDomainListFinish;
  4334. }
  4335. NTSTATUS
  4336. LsapDbLookupNameTrustedDomainListEx(
  4337. IN PLSAPR_UNICODE_STRING DomainName,
  4338. OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *TrustedDomainListEntry
  4339. )
  4340. /*++
  4341. Routine Description:
  4342. This function looks up a given Trusted Domain Name in the Trusted
  4343. Domain List and returns Trust Information consisting of its
  4344. Sid and Name.
  4345. Arguments:
  4346. DomainName - Pointer to a Unicode Name that will be compared with the
  4347. list of Names of Trusted Domains.
  4348. TrustInformation - Receives the a pointer to the Trust Information
  4349. (Sid and Name) of the Trusted Domain described by DomainName
  4350. within the Trusted Domain List.
  4351. NOTE: This name will be looked up as both the trusted domain objects
  4352. domain name and the flat name
  4353. NOTE: This routine assumes that the Trusted Domain List
  4354. will not be updated while any Lookup operations are pending.
  4355. Thus, the pointer returned for TrustInformation will remain
  4356. valid.
  4357. Return Value:
  4358. NTSTATUS - Standard Nt Result Code
  4359. STATUS_SUCCESS - The domain was found.
  4360. STATUS_NO_SUCH_DOMAIN - The domain was not found.
  4361. --*/
  4362. {
  4363. NTSTATUS Status = STATUS_SUCCESS;
  4364. ULONG SectionIndex;
  4365. LSAPR_TRUST_INFORMATION InputTrustInformation;
  4366. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  4367. ASSERT( LsapDbIsLockedTrustedDomainList());
  4368. if ( !LsapDbIsValidTrustedDomainList()) {
  4369. LsapDbConvertReadLockTrustedDomainListToExclusive();
  4370. Status = LsapDbBuildTrustedDomainCache();
  4371. if ( !NT_SUCCESS( Status )) {
  4372. goto LookupNameTrustedDomainListError;
  4373. }
  4374. }
  4375. InputTrustInformation.Sid = NULL;
  4376. InputTrustInformation.Name = *DomainName;
  4377. Status = LsapDbLookupEntryTrustedDomainList(
  4378. &InputTrustInformation,
  4379. &TrustEntry );
  4380. if (!NT_SUCCESS(Status)) {
  4381. goto LookupNameTrustedDomainListError;
  4382. }
  4383. //
  4384. // Return pointer to Trust Information
  4385. //
  4386. *TrustedDomainListEntry = TrustEntry;
  4387. LookupNameTrustedDomainListFinish:
  4388. return(Status);
  4389. LookupNameTrustedDomainListError:
  4390. *TrustedDomainListEntry = NULL;
  4391. goto LookupNameTrustedDomainListFinish;
  4392. }
  4393. NTSTATUS
  4394. LsapDbLookupEntryTrustedDomainList(
  4395. IN PLSAPR_TRUST_INFORMATION TrustInformation,
  4396. OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *TrustedDomainListEntry
  4397. )
  4398. /*++
  4399. Routine Decsription:
  4400. This function locates an entry for a Trusted Domain in the Trusted
  4401. Domain List, given Trust Information containing either a Domain Sid
  4402. or a Domain Name.
  4403. Arguments:
  4404. TrustInformation - Points to the Sid and Name of a Trusted Domain.
  4405. TrustedDomainListEntry - Receives pointer to the trusted domain list
  4406. entry that statisfies the request
  4407. Return Value:
  4408. NTSTATUS - Standard Nt Result Code
  4409. STATUS_SUCCESS - The domain was found.
  4410. STATUS_NO_SUCH_DOMAIN - The domain was not found.
  4411. --*/
  4412. {
  4413. NTSTATUS Status = STATUS_SUCCESS;
  4414. PLIST_ENTRY ListEntry;
  4415. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY PossibleMatch = NULL, BestMatch = NULL, Current;
  4416. ULONG ScanSectionIndex;
  4417. BOOLEAN LookupSid = TRUE;
  4418. ASSERT( LsapDbIsLockedTrustedDomainList());
  4419. if ( !LsapDbIsValidTrustedDomainList()) {
  4420. LsapDbConvertReadLockTrustedDomainListToExclusive();
  4421. Status = LsapDbBuildTrustedDomainCache();
  4422. if ( !NT_SUCCESS( Status )) {
  4423. *TrustedDomainListEntry = NULL;
  4424. goto Cleanup;
  4425. }
  4426. }
  4427. //
  4428. // Decide if we're to lookup a Domain Sid or a Domain Name.
  4429. //
  4430. if (TrustInformation->Sid == NULL) {
  4431. LookupSid = FALSE;
  4432. }
  4433. for ( ListEntry = LsapDbTrustedDomainList.ListHead.Flink;
  4434. ListEntry != &LsapDbTrustedDomainList.ListHead;
  4435. ListEntry = ListEntry->Flink ) {
  4436. Current = CONTAINING_RECORD( ListEntry, LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  4437. //
  4438. // Find the best match. Note that if we find an entry without a SID, we'll mark it
  4439. // as a possible match, but see if we can do better.
  4440. if (LookupSid) {
  4441. if ( Current->TrustInfoEx.Sid &&
  4442. RtlEqualSid( ( PSID )TrustInformation->Sid,
  4443. ( PSID )Current->TrustInfoEx.Sid ) ) {
  4444. BestMatch = Current;
  4445. break;
  4446. }
  4447. } else {
  4448. //
  4449. // Check domain name first
  4450. //
  4451. if ( LsapCompareDomainNames(
  4452. (PUNICODE_STRING) &(TrustInformation->Name),
  4453. (PUNICODE_STRING) &(Current->TrustInfoEx.Name),
  4454. (PUNICODE_STRING) &(Current->TrustInfoEx.FlatName))
  4455. ) {
  4456. //
  4457. // If we have a full domain object, just return the info. Otherwise,
  4458. // we'll see if we don't have a better match down the line
  4459. //
  4460. if ( Current->TrustInfoEx.Sid ) {
  4461. BestMatch = Current;
  4462. break;
  4463. } else {
  4464. //
  4465. // There might be duplicate objects in the DS
  4466. // The best we can do is pick one
  4467. //
  4468. PossibleMatch = Current;
  4469. }
  4470. }
  4471. }
  4472. }
  4473. //
  4474. // Now, see what to return
  4475. //
  4476. if ( BestMatch == NULL ) {
  4477. BestMatch = PossibleMatch;
  4478. }
  4479. if ( BestMatch ) {
  4480. *TrustedDomainListEntry = BestMatch;
  4481. } else {
  4482. *TrustedDomainListEntry = NULL;
  4483. Status = STATUS_NO_SUCH_DOMAIN;
  4484. }
  4485. Cleanup:
  4486. return(Status);
  4487. }
  4488. NTSTATUS
  4489. LsapDbInitializeTrustedDomainListEntry(
  4490. IN PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustListEntry,
  4491. IN PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 DomainInfo,
  4492. IN ULONG PosixOffset
  4493. )
  4494. /*++
  4495. Routine Description:
  4496. This function will initialize a trusted domain list entry to the
  4497. information contained in the TRUSTED_DOMAIN_INFORMATION_EX structure
  4498. Arguments:
  4499. TrustListEntry - The TRUSTED_DOMAIN_LIST_ENTRY node to initialize
  4500. DomainInfo - Points to a LSAPR_TRUSTED_DOMAIN_INFORMATION_EX
  4501. structure which contains information on the trusted domain.
  4502. PosixOffset - Posix offset for this trusted domain
  4503. Return Value:
  4504. NTSTATUS - Standard Nt Result Code
  4505. --*/
  4506. {
  4507. NTSTATUS Status = STATUS_SUCCESS;
  4508. //
  4509. // Intialize the Trust List entry first to all 0's
  4510. //
  4511. RtlZeroMemory(TrustListEntry,sizeof(LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY));
  4512. //
  4513. // Copy the information over
  4514. //
  4515. Status = LsapRpcCopyUnicodeString( NULL,
  4516. ( PUNICODE_STRING )&TrustListEntry->TrustInfoEx.Name,
  4517. ( PUNICODE_STRING )&DomainInfo->Name );
  4518. if ( NT_SUCCESS( Status ) ) {
  4519. Status = LsapRpcCopyUnicodeString( NULL,
  4520. ( PUNICODE_STRING )&TrustListEntry->TrustInfoEx.FlatName,
  4521. ( PUNICODE_STRING )&DomainInfo->FlatName );
  4522. if ( NT_SUCCESS( Status ) && DomainInfo->Sid ) {
  4523. Status = LsapRpcCopySid( NULL,
  4524. ( PSID )&TrustListEntry->TrustInfoEx.Sid,
  4525. ( PSID )DomainInfo->Sid );
  4526. } else {
  4527. TrustListEntry->TrustInfoEx.Sid = NULL;
  4528. }
  4529. }
  4530. //
  4531. // See if this entry contains forest trust information, and if so, insert it
  4532. //
  4533. if ( NT_SUCCESS( Status ) &&
  4534. LsapHavingForestTrustMakesSense(
  4535. DomainInfo->TrustDirection,
  4536. DomainInfo->TrustType,
  4537. DomainInfo->TrustAttributes
  4538. ) &&
  4539. DomainInfo->ForestTrustInfo != NULL &&
  4540. DomainInfo->ForestTrustLength > 0 ) {
  4541. LSA_FOREST_TRUST_INFORMATION ForestTrustInfo;
  4542. Status = LsapForestTrustUnmarshalBlob(
  4543. DomainInfo->ForestTrustLength,
  4544. DomainInfo->ForestTrustInfo,
  4545. ForestTrustRecordTypeLast,
  4546. &ForestTrustInfo
  4547. );
  4548. if ( NT_SUCCESS( Status )) {
  4549. Status = LsapForestTrustCacheInsert(
  4550. ( PUNICODE_STRING )&DomainInfo->Name,
  4551. ( PSID )DomainInfo->Sid,
  4552. &ForestTrustInfo,
  4553. FALSE
  4554. );
  4555. LsapFreeForestTrustInfo( &ForestTrustInfo );
  4556. }
  4557. }
  4558. if ( NT_SUCCESS( Status ) ) {
  4559. TrustListEntry->TrustInfoEx.TrustAttributes = DomainInfo->TrustAttributes;
  4560. TrustListEntry->TrustInfoEx.TrustDirection = DomainInfo->TrustDirection;
  4561. TrustListEntry->TrustInfoEx.TrustType = DomainInfo->TrustType;
  4562. TrustListEntry->PosixOffset = PosixOffset;
  4563. //
  4564. // Construct the TRUST_INFO that most of the lookup routines return
  4565. //
  4566. TrustListEntry->ConstructedTrustInfo.Sid = TrustListEntry->TrustInfoEx.Sid;
  4567. RtlCopyMemory( &TrustListEntry->ConstructedTrustInfo.Name,
  4568. &TrustListEntry->TrustInfoEx.FlatName,
  4569. sizeof( UNICODE_STRING ) );
  4570. } else {
  4571. //
  4572. // Something failed... clean up
  4573. //
  4574. MIDL_user_free( TrustListEntry->TrustInfoEx.Sid );
  4575. MIDL_user_free( TrustListEntry->TrustInfoEx.Name.Buffer );
  4576. MIDL_user_free( TrustListEntry->TrustInfoEx.FlatName.Buffer );
  4577. RtlZeroMemory(TrustListEntry,sizeof(LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY));
  4578. }
  4579. return( Status );
  4580. }
  4581. NTSTATUS
  4582. LsapDbReconcileDuplicateTrusts(
  4583. IN PUNICODE_STRING Name,
  4584. OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *WinningEntry
  4585. )
  4586. /*++
  4587. Routine Description
  4588. This function searches the DS for the occurance of any duplicates
  4589. and using appropriate criteria chooses a winner. The object guid
  4590. of the winner is stamped on the winning entry
  4591. Arguments:
  4592. ExistingEntry
  4593. NewEntry
  4594. Return Values
  4595. STATUS_SUCCESS
  4596. Other error codes to indicate resource failures
  4597. --*/
  4598. {
  4599. NTSTATUS Status = STATUS_SUCCESS;
  4600. ATTRVAL SearchAttrVal;
  4601. ATTR AttrToMatch = {ATT_TRUST_PARTNER, {1,&SearchAttrVal}};
  4602. DSNAME *WinningObject = NULL;
  4603. WCHAR szRDN[MAX_RDN_SIZE+1];
  4604. ULONG Rdnlength = MAX_RDN_SIZE;
  4605. ATTRTYP RDNtype;
  4606. ULONG i,j;
  4607. BOOLEAN CloseTransaction = FALSE;
  4608. BOOLEAN ActiveThreadState = FALSE;
  4609. PDSNAME * FoundNames = NULL;
  4610. ULONG cFoundNames=0;
  4611. //
  4612. // Duplicates can occur legally in DS mode only
  4613. //
  4614. *WinningEntry = NULL;
  4615. if (!LsaDsStateInfo.UseDs)
  4616. {
  4617. ASSERT(FALSE && "Duplicate Trust in Registry Mode");
  4618. return(STATUS_SUCCESS);
  4619. }
  4620. //
  4621. // At this point we cannot say whether we are in a transaction
  4622. // therefore handle both cases
  4623. //
  4624. if (!SampExistsDsTransaction())
  4625. {
  4626. //
  4627. // Begin a Transaction
  4628. //
  4629. Status = LsapDsInitAllocAsNeededEx(
  4630. LSAP_DB_NO_LOCK,
  4631. TrustedDomainObject,
  4632. &CloseTransaction
  4633. );
  4634. if (!NT_SUCCESS(Status))
  4635. goto Error;
  4636. ActiveThreadState = TRUE;
  4637. }
  4638. SearchAttrVal.valLen = Name->Length;
  4639. SearchAttrVal.pVal = (PVOID) Name->Buffer;
  4640. Status = LsapDsSearchNonUnique(
  4641. 0,
  4642. LsaDsStateInfo.DsSystemContainer,
  4643. &AttrToMatch,
  4644. 1, // num attrs to match
  4645. &FoundNames,
  4646. &cFoundNames
  4647. );
  4648. if(!NT_SUCCESS(Status))
  4649. {
  4650. goto Error;
  4651. }
  4652. for (i=0;i<cFoundNames;i++)
  4653. {
  4654. //
  4655. // Get the RDN
  4656. //
  4657. if (0!=GetRDNInfoExternal(
  4658. FoundNames[i],
  4659. szRDN,
  4660. &Rdnlength,
  4661. &RDNtype
  4662. ))
  4663. {
  4664. Status = STATUS_OBJECT_NAME_INVALID;
  4665. goto Error;
  4666. }
  4667. //
  4668. // Test if mangled
  4669. //
  4670. if (!IsMangledRDNExternal(szRDN,Rdnlength,NULL))
  4671. {
  4672. WinningObject = FoundNames[i];
  4673. break;
  4674. }
  4675. }
  4676. if (NULL!=WinningObject)
  4677. {
  4678. ATTRBLOCK Read, Results;
  4679. UNICODE_STRING FlatName;
  4680. ULONG TrustType = 0,TrustDirection=0,TrustAttributes = 0;
  4681. ULONG ForestTrustLength = 0;
  4682. PBYTE ForestTrustInfo = NULL;
  4683. ULONG PosixOffset = 0;
  4684. PSID TrustedDomainSid = NULL;
  4685. LSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 NewTrustInfo;
  4686. //
  4687. // Winning object can legally be null here as the above logic is not necessarily in
  4688. // the same transaction
  4689. //
  4690. RtlZeroMemory(&FlatName,sizeof(UNICODE_STRING));
  4691. RtlZeroMemory(&NewTrustInfo, sizeof(NewTrustInfo));
  4692. Read.attrCount = LsapDsTrustedDomainFixupAttributeCount;
  4693. Read.pAttr = LsapDsTrustedDomainFixupAttributes;
  4694. Status = LsapDsReadByDsName( WinningObject,
  4695. 0,
  4696. &Read,
  4697. &Results );
  4698. if (!NT_SUCCESS(Status))
  4699. {
  4700. goto Error;
  4701. }
  4702. //
  4703. // Walk the results
  4704. //
  4705. for ( j = 0; j < Results.attrCount; j++ ) {
  4706. switch ( Results.pAttr[ j ].attrTyp ) {
  4707. case ATT_TRUST_TYPE:
  4708. TrustType = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &Results.pAttr[ j ] );
  4709. break;
  4710. case ATT_TRUST_DIRECTION:
  4711. TrustDirection = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &Results.pAttr[ j ] );
  4712. break;
  4713. case ATT_TRUST_ATTRIBUTES:
  4714. TrustAttributes = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &Results.pAttr[ j ] );
  4715. break;
  4716. case ATT_TRUST_POSIX_OFFSET:
  4717. PosixOffset = LSAP_DS_GET_DS_ATTRIBUTE_AS_ULONG( &Results.pAttr[j] );
  4718. break;
  4719. case ATT_FLAT_NAME:
  4720. FlatName.Length = ( USHORT) LSAP_DS_GET_DS_ATTRIBUTE_LENGTH( &Results.pAttr[ j ] );
  4721. FlatName.MaximumLength = FlatName.Length;
  4722. FlatName.Buffer = LSAP_DS_GET_DS_ATTRIBUTE_AS_PWSTR( &Results.pAttr[ j ] );
  4723. break;
  4724. case ATT_SECURITY_IDENTIFIER:
  4725. TrustedDomainSid = (PSID)LSAP_DS_GET_DS_ATTRIBUTE_AS_PWSTR(&Results.pAttr[j]);
  4726. break;
  4727. case ATT_MS_DS_TRUST_FOREST_TRUST_INFO:
  4728. ForestTrustLength = ( ULONG )LSAP_DS_GET_DS_ATTRIBUTE_LENGTH( &Results.pAttr[ j ] );
  4729. ForestTrustInfo = LSAP_DS_GET_DS_ATTRIBUTE_AS_PBYTE( &Results.pAttr[ j ] );
  4730. break;
  4731. }
  4732. }
  4733. RtlCopyMemory(&NewTrustInfo.Name,Name, sizeof(UNICODE_STRING));
  4734. RtlCopyMemory(&NewTrustInfo.FlatName,&FlatName,sizeof(UNICODE_STRING));
  4735. NewTrustInfo.Sid = TrustedDomainSid;
  4736. NewTrustInfo.TrustType = TrustType;
  4737. NewTrustInfo.TrustDirection = TrustDirection;
  4738. NewTrustInfo.TrustAttributes = TrustAttributes;
  4739. NewTrustInfo.ForestTrustLength = ForestTrustLength;
  4740. NewTrustInfo.ForestTrustInfo = ForestTrustInfo;
  4741. *WinningEntry = MIDL_user_allocate( sizeof( LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY ) );
  4742. if ( *WinningEntry == NULL ) {
  4743. Status = STATUS_INSUFFICIENT_RESOURCES;
  4744. goto Error;
  4745. }
  4746. RtlZeroMemory(*WinningEntry,sizeof( LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY));
  4747. Status = LsapDbInitializeTrustedDomainListEntry( *WinningEntry,
  4748. &NewTrustInfo,
  4749. PosixOffset );
  4750. if (!NT_SUCCESS(Status))
  4751. {
  4752. goto Error;
  4753. }
  4754. //
  4755. // Set the GUID on the object
  4756. //
  4757. RtlCopyMemory(&(*WinningEntry)->ObjectGuidInDs,&WinningObject->Guid,sizeof(GUID));
  4758. }
  4759. else
  4760. {
  4761. //
  4762. // Its O.K to find no entry for the name
  4763. //
  4764. Status = STATUS_SUCCESS;
  4765. }
  4766. Error:
  4767. if (ActiveThreadState)
  4768. {
  4769. LsapDsDeleteAllocAsNeededEx2(
  4770. LSAP_DB_NO_LOCK,
  4771. TrustedDomainObject,
  4772. CloseTransaction,
  4773. FALSE // rollback transaction
  4774. );
  4775. ASSERT(!SampExistsDsTransaction());
  4776. }
  4777. if (!NT_SUCCESS(Status))
  4778. {
  4779. if (NULL!=*WinningEntry)
  4780. {
  4781. _fgu__LSAPR_TRUSTED_DOMAIN_INFO (
  4782. ( PLSAPR_TRUSTED_DOMAIN_INFO )&(*WinningEntry)->TrustInfoEx,
  4783. TrustedDomainInformationEx
  4784. );
  4785. MIDL_user_free( *WinningEntry );
  4786. *WinningEntry = NULL;
  4787. }
  4788. }
  4789. if(NULL!=FoundNames)
  4790. {
  4791. //
  4792. // Search non unique allocates only one big chunk,
  4793. // so no need to free individual members
  4794. //
  4795. LsapFreeLsaHeap(FoundNames);
  4796. }
  4797. return(Status);
  4798. }
  4799. NTSTATUS
  4800. LsapDbInsertTrustedDomainList(
  4801. IN PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 DomainInfo,
  4802. IN ULONG PosixOffset
  4803. )
  4804. /*++
  4805. Routine Description:
  4806. This function inserts a Trusted Domain in the Trusted Domain List.
  4807. It is called when a Trusted Domain object is created in the Lsa
  4808. Policy Database. The List will not be altered while it is active.
  4809. Arguments:
  4810. DomainInfo - Points to a LSAPR_TRUSTED_DOMAIN_INFORMATION_EX
  4811. structure which contains information on the trusted domain.
  4812. ObjectGuidInDs - Indicates the ObjectGuid in the DS.
  4813. Return Value:
  4814. NTSTATUS - Standard Nt Result Code
  4815. --*/
  4816. {
  4817. NTSTATUS Status = STATUS_SUCCESS;
  4818. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY NewEntry = NULL;
  4819. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY ExistingEntry = NULL;
  4820. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY EntryToFree = NULL;
  4821. //
  4822. // If we are actually upgrading from NT4, do not touch any in memory structures
  4823. //
  4824. if ( LsaDsStateInfo.Nt4UpgradeInProgress ) {
  4825. return STATUS_SUCCESS;
  4826. }
  4827. if ( DomainInfo == NULL ) {
  4828. return STATUS_SUCCESS;
  4829. }
  4830. ASSERT( LsapDbIsLockedTrustedDomainList());
  4831. //
  4832. // If the Trusted Domain List is not valid, attempt to rebuild the cache
  4833. // One exception: the cache is being built just now, then no need to rebuild
  4834. //
  4835. if ( !LsapDbIsValidTrustedDomainList()) {
  4836. Status = LsapDbBuildTrustedDomainCache();
  4837. if ( !NT_SUCCESS( Status )) {
  4838. goto InsertTrustedDomainListError;
  4839. }
  4840. }
  4841. //
  4842. // Check for Duplicates. Duplicates can legally occur in a multi master system
  4843. //
  4844. Status = LsapDbLookupNameTrustedDomainListEx(
  4845. &DomainInfo->Name,
  4846. &ExistingEntry
  4847. );
  4848. if ( STATUS_NO_SUCH_DOMAIN == Status ) {
  4849. //
  4850. // Good ! There are no duplicates. Simply insert into the list
  4851. //
  4852. //
  4853. // The Trusted Domain List is referenced by us, but otherwise inactive
  4854. // so we can update it. Create a new Trusted Domain List section for
  4855. // all of the Trusted Domains to be added to the list.
  4856. //
  4857. NewEntry = MIDL_user_allocate( sizeof( LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY ));
  4858. if ( NewEntry == NULL ) {
  4859. Status = STATUS_INSUFFICIENT_RESOURCES;
  4860. goto InsertTrustedDomainListError;
  4861. }
  4862. Status = LsapDbInitializeTrustedDomainListEntry(
  4863. NewEntry,
  4864. DomainInfo,
  4865. PosixOffset
  4866. );
  4867. if ( Status == STATUS_INVALID_PARAMETER ) {
  4868. SpmpReportEventU(
  4869. EVENTLOG_ERROR_TYPE,
  4870. LSA_TRUST_INSERT_ERROR,
  4871. 0,
  4872. sizeof( ULONG ),
  4873. &Status,
  4874. 1,
  4875. &NewEntry->TrustInfoEx.Name
  4876. );
  4877. _fgu__LSAPR_TRUSTED_DOMAIN_INFO (
  4878. ( PLSAPR_TRUSTED_DOMAIN_INFO )&NewEntry->TrustInfoEx,
  4879. TrustedDomainInformationEx
  4880. );
  4881. MIDL_user_free( NewEntry );
  4882. NewEntry = NULL;
  4883. } else if ( !NT_SUCCESS( Status )) {
  4884. EntryToFree = NewEntry;
  4885. goto InsertTrustedDomainListError;
  4886. } else {
  4887. //
  4888. // Remember a sequence number for this trusted domain
  4889. //
  4890. LsapDbTrustedDomainList.TrustedDomainCount++;
  4891. LsapDbTrustedDomainList.CurrentSequenceNumber++;
  4892. NewEntry->SequenceNumber = LsapDbTrustedDomainList.CurrentSequenceNumber;
  4893. InsertTailList(
  4894. &LsapDbTrustedDomainList.ListHead,
  4895. &NewEntry->NextEntry
  4896. );
  4897. }
  4898. Status = STATUS_SUCCESS;
  4899. } else if ( STATUS_SUCCESS == Status ) {
  4900. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY WinningEntry = NULL;
  4901. //
  4902. // We found an entry already in the trusted domain list
  4903. // we now need to reconcile and make only one of the 2 entries win.
  4904. // Our reconciliation logic is very simple
  4905. //
  4906. // 1. We handle only duplicates via name.
  4907. // 2. We assume that both duplicates are identical in terms of domain
  4908. // SID, trust type, trust attributes etc. This covers us for the case
  4909. // where a duplicate has been created inverdantly by an admin who ended
  4910. // up creating the same trust on different DC's
  4911. //
  4912. Status = LsapDbReconcileDuplicateTrusts(
  4913. ( PUNICODE_STRING )&DomainInfo->Name,
  4914. &WinningEntry
  4915. );
  4916. if ( !NT_SUCCESS( Status )) {
  4917. goto InsertTrustedDomainListError;
  4918. }
  4919. RemoveEntryList( &ExistingEntry->NextEntry );
  4920. LsapDbTrustedDomainList.TrustedDomainCount--;
  4921. EntryToFree = ExistingEntry;
  4922. if ( NULL != WinningEntry ) {
  4923. //
  4924. // It is legal to expect WinningEntry to be NULL, this
  4925. // can occur if out of band all duplicates were deleted
  4926. //
  4927. //
  4928. // Remember a sequence number for this trusted domain
  4929. //
  4930. LsapDbTrustedDomainList.TrustedDomainCount++;
  4931. LsapDbTrustedDomainList.CurrentSequenceNumber++;
  4932. WinningEntry->SequenceNumber = LsapDbTrustedDomainList.CurrentSequenceNumber;
  4933. InsertTailList(
  4934. &LsapDbTrustedDomainList.ListHead,
  4935. &WinningEntry->NextEntry
  4936. );
  4937. }
  4938. }
  4939. InsertTrustedDomainListFinish:
  4940. if ( NULL != EntryToFree ) {
  4941. NTSTATUS Ignore;
  4942. //
  4943. // We will remove the entry from the cache iff we are in the root domain. If not,
  4944. // we don't want to touch the FT Cache.
  4945. //
  4946. if( LsapDbDcInRootDomain() ) {
  4947. Ignore = LsapForestTrustCacheRemove(( UNICODE_STRING * )&EntryToFree->TrustInfoEx.Name );
  4948. ASSERT( Ignore == STATUS_SUCCESS ||
  4949. Ignore == STATUS_NOT_FOUND );
  4950. }
  4951. _fgu__LSAPR_TRUSTED_DOMAIN_INFO (
  4952. ( PLSAPR_TRUSTED_DOMAIN_INFO )&EntryToFree->TrustInfoEx,
  4953. TrustedDomainInformationEx
  4954. );
  4955. MIDL_user_free( EntryToFree );
  4956. }
  4957. return Status;
  4958. InsertTrustedDomainListError:
  4959. LsapDbMakeCacheInvalid( TrustedDomainObject );
  4960. goto InsertTrustedDomainListFinish;
  4961. }
  4962. NTSTATUS
  4963. LsapDbDeleteTrustedDomainList(
  4964. IN PLSAPR_TRUST_INFORMATION TrustInformation
  4965. )
  4966. /*++
  4967. Routine Description:
  4968. This function deletes a Trusted Domain from the Trusted Domain List
  4969. if that list is marked as valid. The Trusted Domain List will not
  4970. be altered while there are Lookup operations pending.
  4971. Arguments:
  4972. TrustInformation - Points to the Sid and Name of a Trusted Domain.
  4973. Return Value:
  4974. NTSTATUS - Standard Nt Result Code
  4975. --*/
  4976. {
  4977. NTSTATUS Status = STATUS_SUCCESS;
  4978. NTSTATUS Ignore;
  4979. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry;
  4980. ASSERT( LsapDbIsLockedTrustedDomainList());
  4981. //
  4982. // If the Trusted Domain List is not valid, quit and do nothing.
  4983. //
  4984. if (!LsapDbIsValidTrustedDomainList()) {
  4985. goto DeleteTrustedDomainListFinish;
  4986. }
  4987. //
  4988. // The Trusted Domain List is referenced by us, but otherwise inactive.
  4989. // Update the List. First, we need to locate the entry to be deleted.
  4990. //
  4991. Status = LsapDbLookupEntryTrustedDomainList(
  4992. TrustInformation,
  4993. &TrustEntry );
  4994. if (!NT_SUCCESS(Status)) {
  4995. goto DeleteTrustedDomainListError;
  4996. }
  4997. RemoveEntryList( &TrustEntry->NextEntry );
  4998. LsapDbTrustedDomainList.TrustedDomainCount--;
  4999. //
  5000. // We will remove the entry from the cache iff we are in the root domain. If not,
  5001. // we don't want to touch the FT Cache.
  5002. //
  5003. if( LsapDbDcInRootDomain() ) {
  5004. Ignore = LsapForestTrustCacheRemove(( UNICODE_STRING * )&TrustEntry->TrustInfoEx.Name );
  5005. ASSERT( Ignore == STATUS_SUCCESS ||
  5006. Ignore == STATUS_NOT_FOUND );
  5007. }
  5008. _fgu__LSAPR_TRUSTED_DOMAIN_INFO ( ( PLSAPR_TRUSTED_DOMAIN_INFO )&TrustEntry->TrustInfoEx,
  5009. TrustedDomainInformationEx );
  5010. MIDL_user_free( TrustEntry );
  5011. DeleteTrustedDomainListFinish:
  5012. return(Status);
  5013. DeleteTrustedDomainListError:
  5014. LsapDbMakeCacheInvalid( TrustedDomainObject );
  5015. goto DeleteTrustedDomainListFinish;
  5016. }
  5017. NTSTATUS
  5018. LsapDbFixupTrustedDomainListEntry(
  5019. IN OPTIONAL PSID TrustedDomainSid,
  5020. IN OPTIONAL PLSAPR_UNICODE_STRING Name,
  5021. IN OPTIONAL PLSAPR_UNICODE_STRING FlatName,
  5022. IN OPTIONAL PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 NewTrustInfo,
  5023. IN OPTIONAL PULONG PosixOffset
  5024. )
  5025. /*++
  5026. Routine Description:
  5027. This function will update the information in the trusted domain list that
  5028. corresponds to the given trust item. This is mostly useful for SetTrustedDomainInformation
  5029. calls
  5030. Arguments:
  5031. TrustedDomainSid - If specified, is used to identify which TDL entry to update.
  5032. In not specified, NewTrustInfo is used.
  5033. NewTrustInfo - Points to the full information regarding the trusted domain
  5034. If specified, TDL entry is updated to reflect this information.
  5035. PosixOffset - Points to the Posix Offset to set on the entry
  5036. If not specified, the Posix Offset will not be changed.
  5037. Return Value:
  5038. NTSTATUS - Standard Nt Result Code
  5039. --*/
  5040. {
  5041. NTSTATUS Status;
  5042. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry = NULL;
  5043. LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TempTrustEntry;
  5044. BOOLEAN AcquiredListWriteLock = FALSE;
  5045. LSAPR_TRUST_INFORMATION TrustInformation;
  5046. //
  5047. // If we are upgrading from NT4, then do nothing
  5048. //
  5049. if (LsaDsStateInfo.Nt4UpgradeInProgress)
  5050. {
  5051. return ( STATUS_SUCCESS);
  5052. }
  5053. //
  5054. // Acquire exclusive write lock for the Trusted Domain List.
  5055. //
  5056. Status = LsapDbAcquireWriteLockTrustedDomainList();
  5057. if (!NT_SUCCESS(Status)) {
  5058. return Status;
  5059. }
  5060. //
  5061. // If the Trusted Domain List is not marked
  5062. // as a valid cache, do nothing.
  5063. //
  5064. if (!LsapDbIsCacheValid(TrustedDomainObject)) {
  5065. Status = STATUS_SUCCESS;
  5066. goto Cleanup;
  5067. }
  5068. //
  5069. // If the Trusted Domain List is not valid, quit and do nothing.
  5070. //
  5071. if (!LsapDbIsValidTrustedDomainList()) {
  5072. Status = STATUS_SUCCESS;
  5073. goto Cleanup;
  5074. }
  5075. //
  5076. // Find the TDL entry using trusted domain sid.
  5077. //
  5078. if ( TrustedDomainSid != NULL || Name != NULL || FlatName != NULL ) {
  5079. RtlZeroMemory( &TrustInformation, sizeof( TrustInformation ));
  5080. TrustInformation.Sid = TrustedDomainSid;
  5081. if ( Name != NULL ) {
  5082. TrustInformation.Name = *Name;
  5083. }
  5084. Status = LsapDbLookupEntryTrustedDomainList( &TrustInformation,
  5085. &TrustEntry );
  5086. if ( Status == STATUS_NO_SUCH_DOMAIN &&
  5087. FlatName != NULL ) {
  5088. TrustInformation.Name = *FlatName;
  5089. Status = LsapDbLookupEntryTrustedDomainList( &TrustInformation,
  5090. &TrustEntry );
  5091. }
  5092. if ( !NT_SUCCESS( Status )) {
  5093. goto Cleanup;
  5094. }
  5095. } else {
  5096. Status = STATUS_INVALID_PARAMETER;
  5097. goto Cleanup;
  5098. }
  5099. ASSERT( TrustEntry );
  5100. //
  5101. // If new trust info is to be updated,
  5102. // update it.
  5103. //
  5104. if ( NewTrustInfo != NULL ) {
  5105. UNICODE_STRING * RemovingFtInfo = NULL;
  5106. if ( NewTrustInfo->ForestTrustInfo == NULL ) {
  5107. //
  5108. // We will remove the entry from the cache iff we are in the root domain. If not,
  5109. // we don't want to touch the FT Cache.
  5110. //
  5111. if( LsapDbDcInRootDomain() ) {
  5112. RemovingFtInfo = ( UNICODE_STRING * )&TrustEntry->TrustInfoEx.Name;
  5113. }
  5114. }
  5115. //
  5116. // Use a temp variable for the entry (so if we fail to initialize it,
  5117. // we won't have trashed our current data)
  5118. //
  5119. Status = LsapDbInitializeTrustedDomainListEntry( &TempTrustEntry,
  5120. NewTrustInfo,
  5121. 0 ); // Ignore Posix Offset
  5122. if ( NT_SUCCESS( Status ) ) {
  5123. if ( RemovingFtInfo ) {
  5124. NTSTATUS Ignore;
  5125. Ignore = LsapForestTrustCacheRemove( RemovingFtInfo );
  5126. ASSERT( Ignore == STATUS_SUCCESS ||
  5127. Ignore == STATUS_NOT_FOUND );
  5128. }
  5129. //
  5130. // Delete the contents of the current item...
  5131. //
  5132. _fgu__LSAPR_TRUSTED_DOMAIN_INFO ( ( PLSAPR_TRUSTED_DOMAIN_INFO )&TrustEntry->TrustInfoEx,
  5133. TrustedDomainInformationEx );
  5134. //
  5135. // Copy in the fields that need updating
  5136. //
  5137. RtlCopyMemory( &TrustEntry->TrustInfoEx, &TempTrustEntry.TrustInfoEx, sizeof(LSAPR_TRUSTED_DOMAIN_INFORMATION_EX) );
  5138. RtlCopyMemory(&TrustEntry->ConstructedTrustInfo, &TempTrustEntry.ConstructedTrustInfo,sizeof(LSAPR_TRUST_INFORMATION));
  5139. }
  5140. }
  5141. //
  5142. // If Posix offset is to be updated,
  5143. // update it.
  5144. //
  5145. if ( PosixOffset != NULL ) {
  5146. TrustEntry->PosixOffset = *PosixOffset;
  5147. }
  5148. Cleanup:
  5149. if( !NT_SUCCESS( Status ) ) {
  5150. LsapDbMakeCacheInvalid( TrustedDomainObject );
  5151. }
  5152. LsapDbReleaseLockTrustedDomainList();
  5153. return(Status);
  5154. }
  5155. NTSTATUS
  5156. LsapDbTraverseTrustedDomainList(
  5157. IN OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *TrustedDomainEntry,
  5158. OUT OPTIONAL PLSAPR_TRUST_INFORMATION *TrustInformation
  5159. )
  5160. /*++
  5161. Routine Description:
  5162. This function is used to traverse the Trusted Domain List. Each call
  5163. yields a pointer to the Trust Information for the next Trusted Domain
  5164. on the list.
  5165. Arguments:
  5166. TrustedDomainEntry - A pointer to the relevant trusted domain entry. Prior to the
  5167. first call to the routine, this location must be initialized to
  5168. NULL.
  5169. TrustInformation - If specified, receives a pointer to the Trust
  5170. Information for the next Trusted Domain, or NULL if there are no more.
  5171. Return Values:
  5172. NTSTATUS - Standard Nt Result Code
  5173. STATUS_SUCCESS - This is returned when the final entry is being
  5174. returned.
  5175. STATUS_MORE_ENTRIES - There are more entries in the list, so call
  5176. again.
  5177. STATUS_NO_MORE_ENTRIES - There are no more entries after the
  5178. one returned.
  5179. STATUS_INVALID_PARAMETER -- An invalid TrustedDomainEntry pointer was given
  5180. --*/
  5181. {
  5182. NTSTATUS Status = STATUS_SUCCESS;
  5183. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustEntry = NULL;
  5184. ASSERT( TrustedDomainEntry );
  5185. if ( TrustedDomainEntry == NULL ) {
  5186. return( STATUS_INVALID_PARAMETER );
  5187. }
  5188. ASSERT( LsapDbIsLockedTrustedDomainList());
  5189. //
  5190. // If there is a present section selected, examine it.
  5191. //
  5192. if ( *TrustedDomainEntry == NULL ) {
  5193. //
  5194. // Handle the empty list case first...
  5195. //
  5196. if ( IsListEmpty( &LsapDbTrustedDomainList.ListHead ) ) {
  5197. Status = STATUS_NO_MORE_ENTRIES;
  5198. TrustEntry = NULL;
  5199. } else {
  5200. TrustEntry = CONTAINING_RECORD( LsapDbTrustedDomainList.ListHead.Flink,
  5201. LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  5202. ASSERT( TrustEntry );
  5203. }
  5204. } else {
  5205. TrustEntry = *TrustedDomainEntry;
  5206. if ( TrustEntry->NextEntry.Flink == &LsapDbTrustedDomainList.ListHead ) {
  5207. Status = STATUS_NO_MORE_ENTRIES;
  5208. TrustEntry = NULL;
  5209. } else {
  5210. TrustEntry = CONTAINING_RECORD( TrustEntry->NextEntry.Flink,
  5211. LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  5212. ASSERT( TrustEntry );
  5213. }
  5214. }
  5215. //
  5216. // Set our return status
  5217. //
  5218. if ( Status == STATUS_SUCCESS ) {
  5219. ASSERT( TrustEntry );
  5220. if ( TrustEntry->NextEntry.Flink == &LsapDbTrustedDomainList.ListHead ) {
  5221. Status = STATUS_SUCCESS;
  5222. } else {
  5223. Status = STATUS_MORE_ENTRIES;
  5224. }
  5225. }
  5226. //
  5227. // Return the trust information
  5228. //
  5229. if ( TrustEntry != NULL && TrustInformation != NULL ) {
  5230. *TrustInformation = &TrustEntry->ConstructedTrustInfo;
  5231. }
  5232. *TrustedDomainEntry = TrustEntry;
  5233. return(Status);
  5234. }
  5235. NTSTATUS
  5236. LsapDbEnumerateTrustedDomainList(
  5237. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  5238. OUT PLSAPR_TRUSTED_ENUM_BUFFER EnumerationBuffer,
  5239. IN ULONG PreferedMaximumLength,
  5240. IN ULONG InfoLevel,
  5241. IN BOOLEAN AllowNullSids
  5242. )
  5243. /*++
  5244. Routine Description:
  5245. This function enumerates zero or more Trusted Domains on the
  5246. Trusted Domain List. Since there may be more information than can be
  5247. returned in a single call of the routine, multiple calls can be made to
  5248. get all of the information. To support this feature, the caller is
  5249. provided with a handle that can be used across calls to the API. On the
  5250. initial call, EnumerationContext should point to a variable that has
  5251. been initialized to 0.
  5252. Arguments:
  5253. EnumerationContext - API-specific handle to allow multiple calls
  5254. (see Routine Description above).
  5255. EnumerationBuffer - Pointer to an enumeration structure that will receive
  5256. a count of the Trusted Domains enumerated on this call and a pointer to
  5257. an array of entries containing information for each enumerated
  5258. Trusted Domain.
  5259. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  5260. bytes). This is not a hard upper limit, but serves as a guide. Due to
  5261. data conversion between systems with different natural data sizes, the
  5262. actual amount of data returned may be greater than this value.
  5263. Return Values:
  5264. NTSTATUS - Standard Nt Result Code
  5265. STATUS_SUCCESS - The call completed successfully.
  5266. STATUS_MORE_ENTRIES - The call completed successfully. There
  5267. are more entries so call again. This is a success status.
  5268. STATUS_NO_MORE_ENTRIES - No entries have been returned because there
  5269. are no more entries in the list.
  5270. --*/
  5271. {
  5272. NTSTATUS Status = STATUS_SUCCESS, EnumerationStatus = STATUS_SUCCESS;
  5273. NTSTATUS InitialEnumerationStatus = STATUS_SUCCESS;
  5274. ULONG LengthEnumeratedInfo = 0;
  5275. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustedDomainEntry;
  5276. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY StartingEntry;
  5277. BOOLEAN AcquiredTrustedDomainListReadLock = FALSE;
  5278. ULONG EntriesRead, DomainTrustInfoLength, ValidEntries, ValidInserted;
  5279. PLSAPR_TRUST_INFORMATION TrustInformation = NULL;
  5280. PLSAPR_TRUST_INFORMATION StartingTrustInformation = NULL;
  5281. PLSAPR_TRUST_INFORMATION DomainTrustInfo = NULL;
  5282. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX DomainTrustInfoEx = NULL;
  5283. LsapEnterFunc( "LsapDbEnumerateTrustedDomainList" );
  5284. EntriesRead = 0;
  5285. ValidEntries = 0;
  5286. //
  5287. // Always allow us to return at least one object.
  5288. //
  5289. if ( PreferedMaximumLength == 0 ) {
  5290. PreferedMaximumLength = 1;
  5291. }
  5292. //
  5293. // Acquire the Read Lock for the Trusted Domain List
  5294. //
  5295. Status = LsapDbAcquireReadLockTrustedDomainList();
  5296. if (!NT_SUCCESS(Status)) {
  5297. return Status;
  5298. }
  5299. if ( !LsapDbIsValidTrustedDomainList()) {
  5300. LsapDbConvertReadLockTrustedDomainListToExclusive();
  5301. Status = LsapDbBuildTrustedDomainCache();
  5302. if ( !NT_SUCCESS( Status )) {
  5303. goto EnumerateTrustedDomainListError;
  5304. }
  5305. }
  5306. //
  5307. // Find the starting point using the Enumeration Context Variable.
  5308. // This variable specifies an unsigned integer, which is the
  5309. // number of the entry in the list at which to begin the enumeration.
  5310. //
  5311. Status = LsapDbLocateEntryNumberTrustedDomainList(
  5312. *EnumerationContext,
  5313. &StartingEntry,
  5314. &StartingTrustInformation
  5315. );
  5316. if (!NT_SUCCESS(Status)) {
  5317. goto EnumerateTrustedDomainListError;
  5318. }
  5319. InitialEnumerationStatus = Status;
  5320. //
  5321. // Now scan the Trusted Domain List to calculate how many
  5322. // entries we can return and the length of the buffer required.
  5323. // We use the PreferedMaximumLength value as a guide by accumulating
  5324. // the actual length of Trust Information structures and their
  5325. // contents until we either reach the end of the Trusted Domain List
  5326. // or until we first exceed the PreferedMaximumLength value. Thus,
  5327. // the amount of information returned typically exceeds the
  5328. // PreferedmaximumLength value by a smail amount, namely the
  5329. // size of the Trust Information for a single domain.
  5330. //
  5331. TrustedDomainEntry = StartingEntry;
  5332. TrustInformation = StartingTrustInformation;
  5333. EnumerationStatus = InitialEnumerationStatus;
  5334. for (;;) {
  5335. //
  5336. // Add in the length of the data to be returned for this
  5337. // Domain's Trust Information. We count the length of the
  5338. // Trust Information structure plus the length of the unicode
  5339. // Domain Name and Sid within it.
  5340. //
  5341. if ( InfoLevel == TrustedDomainInformationEx ) {
  5342. if ( TrustedDomainEntry->TrustInfoEx.Sid ) {
  5343. LengthEnumeratedInfo += sizeof( TRUSTED_DOMAIN_INFORMATION_EX ) +
  5344. RtlLengthSid(( PSID )TrustedDomainEntry->TrustInfoEx.Sid ) +
  5345. TrustedDomainEntry->TrustInfoEx.Name.MaximumLength +
  5346. TrustedDomainEntry->TrustInfoEx.FlatName.MaximumLength;
  5347. ValidEntries++;
  5348. } else if ( AllowNullSids ) {
  5349. LengthEnumeratedInfo += sizeof( TRUSTED_DOMAIN_INFORMATION_EX ) +
  5350. TrustedDomainEntry->TrustInfoEx.Name.MaximumLength +
  5351. TrustedDomainEntry->TrustInfoEx.FlatName.MaximumLength;
  5352. ValidEntries++;
  5353. }
  5354. } else {
  5355. //
  5356. // If it's an incoming only trust, don't return it...
  5357. //
  5358. if ( FLAG_ON( TrustedDomainEntry->TrustInfoEx.TrustDirection,
  5359. TRUST_DIRECTION_OUTBOUND ) &&
  5360. NULL != TrustInformation->Sid ) {
  5361. LengthEnumeratedInfo += sizeof(LSA_TRUST_INFORMATION) +
  5362. RtlLengthSid(( PSID )TrustInformation->Sid ) +
  5363. TrustInformation->Name.MaximumLength;
  5364. ValidEntries++;
  5365. }
  5366. }
  5367. EntriesRead++;
  5368. //
  5369. // If we've returned all of the entries the caller wants,
  5370. // quit.
  5371. //
  5372. if (LengthEnumeratedInfo >= PreferedMaximumLength) {
  5373. break;
  5374. }
  5375. //
  5376. // If there are no more entries to enumerate, quit.
  5377. //
  5378. if (EnumerationStatus != STATUS_MORE_ENTRIES) {
  5379. break;
  5380. }
  5381. //
  5382. // Point at the next entry in the Trusted Domain List
  5383. //
  5384. Status = LsapDbTraverseTrustedDomainList(
  5385. &TrustedDomainEntry,
  5386. &TrustInformation
  5387. );
  5388. EnumerationStatus = Status;
  5389. if (!NT_SUCCESS(Status)) {
  5390. goto EnumerateTrustedDomainListError;
  5391. }
  5392. }
  5393. //
  5394. // Allocate memory for the array of TrustInformation entries to be
  5395. // returned.
  5396. //
  5397. if ( InfoLevel == TrustedDomainInformationEx ) {
  5398. DomainTrustInfoLength = ValidEntries * sizeof(LSAPR_TRUSTED_DOMAIN_INFORMATION_EX);
  5399. } else {
  5400. DomainTrustInfoLength = ValidEntries * sizeof(LSA_TRUST_INFORMATION);
  5401. }
  5402. //
  5403. // Now construct the information to be returned to the caller. We
  5404. // first need to allocate an array of structures of type
  5405. // LSA_TRUST_INFORMATION each entry of which will be filled in with
  5406. // the Sid of the domain and its Unicode Name.
  5407. //
  5408. DomainTrustInfo = (( DomainTrustInfoLength > 0 ) ? MIDL_user_allocate( DomainTrustInfoLength ) : 0);
  5409. if ( DomainTrustInfo == NULL && DomainTrustInfoLength > 0 ) {
  5410. Status = STATUS_INSUFFICIENT_RESOURCES;
  5411. goto EnumerateTrustedDomainListError;
  5412. } else if ( DomainTrustInfo != NULL ) {
  5413. RtlZeroMemory ( DomainTrustInfo, DomainTrustInfoLength );
  5414. }
  5415. DomainTrustInfoEx = ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )DomainTrustInfo;
  5416. //
  5417. // Now read through the Trusted Domains again to copy the output
  5418. // information.
  5419. //
  5420. TrustedDomainEntry = StartingEntry;
  5421. TrustInformation = StartingTrustInformation;
  5422. EnumerationStatus = InitialEnumerationStatus;
  5423. ValidInserted = 0;
  5424. for (;;) {
  5425. //
  5426. // Copy in the Trust Information.
  5427. //
  5428. if ( InfoLevel == TrustedDomainInformationEx ) {
  5429. if ( TrustedDomainEntry->TrustInfoEx.Sid || AllowNullSids ) {
  5430. if (ValidInserted == ValidEntries) {
  5431. //
  5432. // We'd like to return more, but it won't fit
  5433. //
  5434. EnumerationStatus = STATUS_MORE_ENTRIES;
  5435. break;
  5436. } else {
  5437. Status = LsapRpcCopyTrustInformationEx(
  5438. NULL,
  5439. ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )&DomainTrustInfoEx[ ValidInserted ],
  5440. &TrustedDomainEntry->TrustInfoEx );
  5441. if (!NT_SUCCESS(Status)) {
  5442. goto EnumerateTrustedDomainListError;
  5443. }
  5444. ValidInserted++;
  5445. *EnumerationContext = TrustedDomainEntry->SequenceNumber;
  5446. }
  5447. }
  5448. } else {
  5449. //
  5450. // If it's an incoming only trust, don't return it...
  5451. //
  5452. if ( FLAG_ON( TrustedDomainEntry->TrustInfoEx.TrustDirection,
  5453. TRUST_DIRECTION_OUTBOUND ) &&
  5454. NULL != TrustInformation->Sid ) {
  5455. if (ValidInserted == ValidEntries) {
  5456. //
  5457. // We'd like to return more, but it won't fit
  5458. //
  5459. EnumerationStatus = STATUS_MORE_ENTRIES;
  5460. break;
  5461. } else {
  5462. Status = LsapRpcCopyTrustInformation( NULL,
  5463. &DomainTrustInfo[ ValidInserted ],
  5464. TrustInformation );
  5465. if (!NT_SUCCESS(Status)) {
  5466. goto EnumerateTrustedDomainListError;
  5467. }
  5468. ValidInserted++;
  5469. *EnumerationContext = TrustedDomainEntry->SequenceNumber;
  5470. }
  5471. }
  5472. }
  5473. //
  5474. // If there are no more entries to enumerate, quit.
  5475. //
  5476. if (EnumerationStatus != STATUS_MORE_ENTRIES) {
  5477. break;
  5478. }
  5479. //
  5480. // Point at the next entry in the Trusted Domain List
  5481. //
  5482. Status = LsapDbTraverseTrustedDomainList(
  5483. &TrustedDomainEntry,
  5484. &TrustInformation );
  5485. EnumerationStatus = Status;
  5486. if (!NT_SUCCESS(Status)) {
  5487. goto EnumerateTrustedDomainListError;
  5488. }
  5489. }
  5490. //
  5491. // Make sure that we are actually returning something...
  5492. //
  5493. if ( EntriesRead == 0 || ValidEntries == 0 ) {
  5494. Status = STATUS_NO_MORE_ENTRIES;
  5495. goto EnumerateTrustedDomainListError;
  5496. } else {
  5497. Status = EnumerationStatus;
  5498. }
  5499. EnumerateTrustedDomainListFinish:
  5500. LsapDbReleaseLockTrustedDomainList();
  5501. //
  5502. // Fill in returned Enumeration Structure, returning 0 or NULL for
  5503. // fields in the error case.
  5504. //
  5505. EnumerationBuffer->Information = (PLSAPR_TRUST_INFORMATION) DomainTrustInfo;
  5506. EnumerationBuffer->EntriesRead = ValidEntries;
  5507. LsapExitFunc( "LsapDbEnumerateTrustedDomainList", Status );
  5508. return(Status);
  5509. EnumerateTrustedDomainListError:
  5510. //
  5511. // If necessary, free the DomainTrustInfo array and all of its entries.
  5512. //
  5513. if (DomainTrustInfo != NULL) {
  5514. if ( InfoLevel == TrustedDomainInformationEx ) {
  5515. LSAPR_TRUSTED_ENUM_BUFFER_EX FreeEnum;
  5516. FreeEnum.EnumerationBuffer = ( PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX )DomainTrustInfo;
  5517. FreeEnum.EntriesRead = ValidEntries;
  5518. LsaIFree_LSAPR_TRUSTED_ENUM_BUFFER_EX ( &FreeEnum );
  5519. } else {
  5520. LSAPR_TRUSTED_ENUM_BUFFER FreeEnum;
  5521. FreeEnum.Information = ( PLSAPR_TRUST_INFORMATION )DomainTrustInfo;
  5522. FreeEnum.EntriesRead = ValidEntries;
  5523. LsaIFree_LSAPR_TRUSTED_ENUM_BUFFER ( &FreeEnum );
  5524. }
  5525. DomainTrustInfo = NULL;
  5526. EntriesRead = (ULONG) 0;
  5527. }
  5528. goto EnumerateTrustedDomainListFinish;
  5529. }
  5530. NTSTATUS
  5531. LsapDbLocateEntryNumberTrustedDomainList(
  5532. IN ULONG EntryNumber,
  5533. OUT PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY *TrustedDomainEntry,
  5534. OUT PLSAPR_TRUST_INFORMATION *TrustInformation
  5535. )
  5536. /*++
  5537. Routine Description:
  5538. Given an Entry Number n, this function obtains the pointer to the nth
  5539. entry (if any) in a Trusted Domain List. The first entry in the
  5540. list is entry number 0.
  5541. Given an Entry Number n, this function obtains a pointer to the
  5542. first entry with a sequence number greater than n.
  5543. 0: returns the first entry.
  5544. WARNING: The caller of this function must hold a lock for the
  5545. Trusted Domain List. The valditiy of the returned pointers
  5546. is guaranteed only while that lock is held.
  5547. Arguments:
  5548. EntryNumber - Specifies the sequence number. The returned entry will
  5549. be the first entry with a sequence number greater than this.
  5550. 0: returns the first entry.
  5551. TrustedDomainEntry - Receives a pointer to the Trusted
  5552. Domain entry. If no such entry exists, NULL is returned.
  5553. TrustInformation - Receives a pointer to the Trust
  5554. Information for the entry being returned.
  5555. Return Values:
  5556. NTSTATUS - Standard Nt Result Code
  5557. STATUS_SUCCESS - Call completed successfully and there are no
  5558. entries beyond the entry returned.
  5559. STATUS_MORE_ENTRIES - Call completed successfully and there are
  5560. more entries beyond the entry returned.
  5561. STATUS_NO_MORE_ENTRIES - There is no entry to return.
  5562. --*/
  5563. {
  5564. NTSTATUS Status;
  5565. PLIST_ENTRY ListEntry;
  5566. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY Current = NULL;
  5567. //
  5568. // Initialization
  5569. //
  5570. *TrustInformation = NULL;
  5571. *TrustedDomainEntry = NULL;
  5572. ASSERT( LsapDbIsLockedTrustedDomainList());
  5573. if ( !LsapDbIsValidTrustedDomainList()) {
  5574. LsapDbConvertReadLockTrustedDomainListToExclusive();
  5575. Status = LsapDbBuildTrustedDomainCache();
  5576. if ( !NT_SUCCESS( Status )) {
  5577. return Status;
  5578. }
  5579. }
  5580. //
  5581. // Find the first entry with a sequence number greater than the
  5582. // specified number.
  5583. //
  5584. for ( ListEntry = LsapDbTrustedDomainList.ListHead.Flink;
  5585. ListEntry != &LsapDbTrustedDomainList.ListHead;
  5586. ListEntry = ListEntry->Flink ) {
  5587. Current = CONTAINING_RECORD( ListEntry, LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  5588. //
  5589. // See if we have the entry we require
  5590. //
  5591. if ( EntryNumber < Current->SequenceNumber ) {
  5592. if ( ListEntry->Flink != &LsapDbTrustedDomainList.ListHead ) {
  5593. Status = STATUS_MORE_ENTRIES;
  5594. } else {
  5595. Status = STATUS_SUCCESS;
  5596. }
  5597. *TrustInformation = &Current->ConstructedTrustInfo;
  5598. *TrustedDomainEntry = Current;
  5599. return Status;
  5600. }
  5601. }
  5602. //
  5603. // If no entry was found,
  5604. // return an error to the caller.
  5605. //
  5606. return STATUS_NO_MORE_ENTRIES;
  5607. }
  5608. BYTE LdapSwapBitTable[256] = {
  5609. 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  5610. 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  5611. 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  5612. 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  5613. 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  5614. 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  5615. 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  5616. 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  5617. 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  5618. 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  5619. 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  5620. 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  5621. 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  5622. 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  5623. 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  5624. 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  5625. 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  5626. 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  5627. 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  5628. 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  5629. 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  5630. 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  5631. 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  5632. 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  5633. 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  5634. 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  5635. 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  5636. 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  5637. 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  5638. 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  5639. 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  5640. 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
  5641. };
  5642. ULONG
  5643. LdapSwapBits(
  5644. ULONG Bits
  5645. )
  5646. /*++
  5647. Routine Description:
  5648. Swaps the bits of a ULONG end to end.
  5649. That is, the LSB becomes the MSB, etc.
  5650. Arguments:
  5651. Bits - bits to swap
  5652. Return Value:
  5653. ULONG with bits swapped.
  5654. --*/
  5655. {
  5656. ULONG ReturnBits = 0;
  5657. LPBYTE BitPtr = (LPBYTE)&Bits;
  5658. return (LdapSwapBitTable[BitPtr[3]] << 0) |
  5659. (LdapSwapBitTable[BitPtr[2]] << 8) |
  5660. (LdapSwapBitTable[BitPtr[1]] << 16) |
  5661. (LdapSwapBitTable[BitPtr[0]] << 24);
  5662. }
  5663. ULONG
  5664. __cdecl
  5665. CompareUlongs(
  5666. const void * Param1,
  5667. const void * Param2
  5668. )
  5669. /*++
  5670. Routine Description:
  5671. Qsort comparison routine for sorting ULONGs
  5672. --*/
  5673. {
  5674. return *((PULONG)Param1) - *((PULONG)Param2);
  5675. }
  5676. NTSTATUS
  5677. LsapDbAllocatePosixOffsetTrustedDomainList(
  5678. OUT PULONG PosixOffset
  5679. )
  5680. /*++
  5681. Routine Description:
  5682. This function return the next available PosixOffset based on the
  5683. current Posix Offsets in the trusted domain list.
  5684. Posix offsets are allocated on the PDC. Each outbound trust has one. A TDO
  5685. is given a Posix Offset as it becomes an outbound trust. If that happens on a
  5686. BDC, the TDO is given a Posix Offset when the TDO is replicated to the PDC.
  5687. This routine must be entered with the trusted domain list write locked.
  5688. Arguments:
  5689. PosixOffset - On STATUS_SUCCESS, returns the next available Posix Offset
  5690. Return Value:
  5691. NTSTATUS - Standard Nt Result Code
  5692. --*/
  5693. {
  5694. NTSTATUS Status;
  5695. PULONG SwappedPosixOffsets = NULL;
  5696. ULONG SwappedPosixOffsetCount;
  5697. ULONG TargetSwappedPosixOffset;
  5698. PLIST_ENTRY ListEntry;
  5699. ULONG i;
  5700. //
  5701. // If the Trusted Domain List is not valid, rebuild it before continuing
  5702. //
  5703. ASSERT( LsapDbIsLockedTrustedDomainList());
  5704. if ( !LsapDbIsValidTrustedDomainList()) {
  5705. LsapDbConvertReadLockTrustedDomainListToExclusive();
  5706. Status = LsapDbBuildTrustedDomainCache();
  5707. if ( !NT_SUCCESS( Status )) {
  5708. goto Cleanup;
  5709. }
  5710. }
  5711. //
  5712. // Build an array of all the existing Posix Offsets.
  5713. //
  5714. SwappedPosixOffsets = LsapAllocateLsaHeap( LsapDbTrustedDomainList.TrustedDomainCount * sizeof(ULONG) );
  5715. if ( SwappedPosixOffsets == NULL ) {
  5716. Status = STATUS_NO_MEMORY;
  5717. goto Cleanup;
  5718. }
  5719. //
  5720. // Walk the list filling in the array.
  5721. //
  5722. SwappedPosixOffsetCount = 0;
  5723. for ( ListEntry = LsapDbTrustedDomainList.ListHead.Flink;
  5724. ListEntry != &LsapDbTrustedDomainList.ListHead;
  5725. ListEntry = ListEntry->Flink ) {
  5726. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY Current;
  5727. Current = CONTAINING_RECORD( ListEntry, LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  5728. //
  5729. // Only grab the Posix Offset from those TDOs that need one.
  5730. //
  5731. if ( LsapNeedPosixOffset( Current->TrustInfoEx.TrustDirection, Current->TrustInfoEx.TrustType ) ) {
  5732. SwappedPosixOffsets[SwappedPosixOffsetCount] = LdapSwapBits( Current->PosixOffset );
  5733. SwappedPosixOffsetCount++;
  5734. }
  5735. }
  5736. //
  5737. // Sort the list.
  5738. //
  5739. qsort( SwappedPosixOffsets,
  5740. SwappedPosixOffsetCount,
  5741. sizeof(ULONG),
  5742. CompareUlongs );
  5743. //
  5744. // Walk the list finding the first free entry.
  5745. //
  5746. #define SE_BUILT_IN_DOMAIN_SWAPPED_POSIX_OFFSET ((ULONG) 0x4000)
  5747. #define SE_ACCOUNT_DOMAIN_SWAPPED_POSIX_OFFSET ((ULONG) 0xC000)
  5748. #define SE_PRIMARY_DOMAIN_SWAPPED_POSIX_OFFSET ((ULONG) 0x0800)
  5749. ASSERT( SE_BUILT_IN_DOMAIN_SWAPPED_POSIX_OFFSET == LdapSwapBits( SE_BUILT_IN_DOMAIN_POSIX_OFFSET ) );
  5750. ASSERT( SE_ACCOUNT_DOMAIN_SWAPPED_POSIX_OFFSET == LdapSwapBits( SE_ACCOUNT_DOMAIN_POSIX_OFFSET ) );
  5751. ASSERT( SE_PRIMARY_DOMAIN_SWAPPED_POSIX_OFFSET == LdapSwapBits( SE_PRIMARY_DOMAIN_POSIX_OFFSET ) );
  5752. TargetSwappedPosixOffset = 1;
  5753. for ( i=0; i<SwappedPosixOffsetCount; i++ ) {
  5754. //
  5755. // If the target is free,
  5756. // we've found the free Posix Offset.
  5757. //
  5758. if ( SwappedPosixOffsets[i] > TargetSwappedPosixOffset ) {
  5759. break;
  5760. //
  5761. // If the current entry is the target,
  5762. // move the target.
  5763. //
  5764. } else if ( SwappedPosixOffsets[i] == TargetSwappedPosixOffset ) {
  5765. //
  5766. // Loop avoiding well known Posix Offsets.
  5767. //
  5768. while ( TRUE ) {
  5769. TargetSwappedPosixOffset++;
  5770. if ( TargetSwappedPosixOffset != SE_PRIMARY_DOMAIN_SWAPPED_POSIX_OFFSET &&
  5771. TargetSwappedPosixOffset != SE_ACCOUNT_DOMAIN_SWAPPED_POSIX_OFFSET &&
  5772. TargetSwappedPosixOffset != SE_BUILT_IN_DOMAIN_SWAPPED_POSIX_OFFSET ) {
  5773. break;
  5774. }
  5775. }
  5776. }
  5777. }
  5778. //
  5779. // Return the first free Posix Offset to the caller.
  5780. //
  5781. *PosixOffset = LdapSwapBits( TargetSwappedPosixOffset );
  5782. Status = STATUS_SUCCESS;
  5783. Cleanup:
  5784. if ( SwappedPosixOffsets != NULL ) {
  5785. LsapFreeLsaHeap( SwappedPosixOffsets );
  5786. }
  5787. return Status;
  5788. }
  5789. NTSTATUS
  5790. LsapDbBuildTrustedDomainCache(
  5791. )
  5792. /*++
  5793. Routine Description:
  5794. This function initializes a Trusted Domain List by enumerating all
  5795. of the Trusted Domain objects in the specified target system's
  5796. Policy Database. For a Windows Nt system (Workstation) the list
  5797. contains only the Primary Domain. For a LanManNt system (DC), the
  5798. list contains zero or more Trusted Domain objects. Note that the
  5799. list contains only those domains for which Trusted Domain objects
  5800. exist in the local LSA Policy Database. If for example, a DC
  5801. trusted Domain A which in turn trusts Domain B, the list will not
  5802. contain an entry for Domain B unless there is a direct relationship.
  5803. Arguments:
  5804. None
  5805. Return Value:
  5806. NTSTATUS - Standard Nt Result Code
  5807. STATUS_SUCCESS - The call completed successfully.
  5808. --*/
  5809. {
  5810. NTSTATUS Status = STATUS_SUCCESS;
  5811. NTSTATUS EnumerationStatus = STATUS_SUCCESS;
  5812. LSAPR_TRUSTED_ENUM_BUFFER TrustedDomains;
  5813. ULONG EnumerationContext = 0, i;
  5814. BOOLEAN LookupDs = LsapDsWriteDs;
  5815. BOOLEAN CloseTransaction = FALSE;
  5816. LsapEnterFunc( "LsapDbBuildTrustedDomainCache" );
  5817. ASSERT( LsapDbIsLockedTrustedDomainList());
  5818. ASSERT( !LsapDbIsValidTrustedDomainList());
  5819. //
  5820. // Verify input parameters
  5821. //
  5822. if ( LsapDsWriteDs ) {
  5823. Status = LsapDsInitAllocAsNeededEx(
  5824. LSAP_DB_DS_OP_TRANSACTION |
  5825. LSAP_DB_NO_LOCK,
  5826. TrustedDomainObject,
  5827. &CloseTransaction
  5828. );
  5829. if ( !NT_SUCCESS( Status ) ) {
  5830. return Status;
  5831. }
  5832. }
  5833. LsapDbMakeCacheBuilding( TrustedDomainObject );
  5834. //
  5835. // Initialize the Trusted Domain List to the empty state.
  5836. //
  5837. LsapDbPurgeTrustedDomainCache();
  5838. //
  5839. // Register for UPN list notifications first (only on DCs)
  5840. //
  5841. if ( LsaDsStateInfo.DsInitializedAndRunning ) {
  5842. Status = LsapRegisterForUpnListNotifications();
  5843. if ( !NT_SUCCESS( Status )) {
  5844. goto BuildTrustedDomainListError;
  5845. }
  5846. //
  5847. // Continue the transaction
  5848. //
  5849. LsapDsContinueTransaction();
  5850. }
  5851. //
  5852. // DCs in the root domain must not allow other forests to claim SIDs
  5853. // and namespaces that conflict with their own forest
  5854. // For that, the information about the current forest is inserted
  5855. // into the forest trust cache as just another (though special) entry
  5856. //
  5857. Status = LsapForestTrustInsertLocalInfo();
  5858. if ( !NT_SUCCESS( Status )) {
  5859. goto BuildTrustedDomainListError;
  5860. }
  5861. //
  5862. // Loop round, enumerating groups of Trusted Domain objects.
  5863. //
  5864. do {
  5865. //
  5866. // Enumerate the next group of Trusted Domains
  5867. //
  5868. if ( LookupDs ) {
  5869. EnumerationStatus = Status = LsapDsEnumerateTrustedDomainsEx(
  5870. &EnumerationContext,
  5871. TrustedDomainFullInformation2Internal,
  5872. (PLSAPR_TRUSTED_DOMAIN_INFO *)&(TrustedDomains.Information),
  5873. LSAP_DB_ENUM_DOMAIN_LENGTH * 100,
  5874. &TrustedDomains.EntriesRead,
  5875. LSAP_DB_ENUMERATE_NO_OPTIONS
  5876. );
  5877. } else {
  5878. EnumerationStatus = Status = LsapDbSlowEnumerateTrustedDomains(
  5879. LsapPolicyHandle,
  5880. &EnumerationContext,
  5881. TrustedDomainInformationEx2Internal,
  5882. &TrustedDomains,
  5883. LSAP_DB_ENUM_DOMAIN_LENGTH
  5884. );
  5885. }
  5886. if (!NT_SUCCESS(Status)) {
  5887. if (Status != STATUS_NO_MORE_ENTRIES) {
  5888. break;
  5889. }
  5890. Status = STATUS_SUCCESS;
  5891. }
  5892. //
  5893. // If the number of entries returned was zero, quit.
  5894. //
  5895. if (TrustedDomains.EntriesRead == (ULONG) 0) {
  5896. break;
  5897. }
  5898. //
  5899. // Otherwise, add them to our list
  5900. //
  5901. for ( i = 0; i < TrustedDomains.EntriesRead && NT_SUCCESS( Status ); i++ ) {
  5902. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2 TrustInfoEx2;
  5903. ULONG PosixOffset;
  5904. if ( LookupDs ) {
  5905. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2 TrustFullInfo2;
  5906. TrustFullInfo2 = &((PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION2)TrustedDomains.Information)[i];
  5907. TrustInfoEx2 = &TrustFullInfo2->Information;
  5908. PosixOffset = TrustFullInfo2->PosixOffset.Offset;
  5909. } else {
  5910. TrustInfoEx2 = &((PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX2)TrustedDomains.Information)[i];
  5911. //
  5912. // This is only used during upgrade. This Posix Offset will be recomputed.
  5913. PosixOffset = 0;
  5914. }
  5915. //
  5916. // Now, add it to the list
  5917. //
  5918. Status = LsapDbInsertTrustedDomainList(
  5919. TrustInfoEx2,
  5920. PosixOffset
  5921. );
  5922. }
  5923. } while ( NT_SUCCESS( Status ) && EnumerationStatus != STATUS_NO_MORE_ENTRIES );
  5924. if (!NT_SUCCESS(Status)) {
  5925. //
  5926. // If STATUS_NO_MORE_ENTRIES was returned, there are no more
  5927. // trusted domains. Discard this status.
  5928. //
  5929. if (Status != STATUS_NO_MORE_ENTRIES) {
  5930. goto BuildTrustedDomainListError;
  5931. }
  5932. Status = STATUS_SUCCESS;
  5933. }
  5934. //
  5935. // The forest trust cache is only marked "external valid" for
  5936. // DCs in root domain and GCs outside of the root domain
  5937. //
  5938. if ( LsapDbDcInRootDomain()) {
  5939. LsapForestTrustCacheSetExternalValid();
  5940. } else if ( SamIAmIGC()) {
  5941. Status = LsapRebuildFtCacheGC();
  5942. if ( !NT_SUCCESS( Status )) {
  5943. goto BuildTrustedDomainListError;
  5944. }
  5945. // LsapRebuildFtCacheGC will set the cache "external valid"
  5946. }
  5947. //
  5948. // Mark the Trusted Domain List as valid.
  5949. //
  5950. LsapDbMakeCacheValid( TrustedDomainObject );
  5951. BuildTrustedDomainListFinish:
  5952. if ( LsapDsWriteDs ) {
  5953. LsapDsDeleteAllocAsNeededEx(
  5954. LSAP_DB_DS_OP_TRANSACTION |
  5955. LSAP_DB_NO_LOCK,
  5956. TrustedDomainObject,
  5957. CloseTransaction
  5958. );
  5959. }
  5960. LsapExitFunc( "LsapEnumerateTrustedDomainsEx", Status );
  5961. return(Status);
  5962. BuildTrustedDomainListError:
  5963. LsapDbMakeCacheInvalid( TrustedDomainObject );
  5964. LsapDbPurgeTrustedDomainCache();
  5965. goto BuildTrustedDomainListFinish;
  5966. }
  5967. VOID
  5968. LsapDbPurgeTrustedDomainCache(
  5969. )
  5970. /*++
  5971. Routine Description:
  5972. This function is the opposite of LsapDbBuildTrustedDomainCache().
  5973. Arguments:
  5974. None
  5975. Return Value:
  5976. NTSTATUS - Standard Nt Result Code
  5977. STATUS_SUCCESS - The call completed successfully.
  5978. --*/
  5979. {
  5980. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY Current;
  5981. //
  5982. // Caller must already have the trusted domain list locked
  5983. // Convert the read lock to exclusive to be sure
  5984. //
  5985. ASSERT( LsapDbIsLockedTrustedDomainList());
  5986. //
  5987. // Purge the forest trust cache
  5988. //
  5989. LsapForestTrustCacheSetInvalid();
  5990. while( !IsListEmpty( &LsapDbTrustedDomainList.ListHead ) ) {
  5991. Current = CONTAINING_RECORD( LsapDbTrustedDomainList.ListHead.Flink,
  5992. LSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY, NextEntry );
  5993. RemoveEntryList( &Current->NextEntry );
  5994. LsapDbTrustedDomainList.TrustedDomainCount--;
  5995. _fgu__LSAPR_TRUSTED_DOMAIN_INFO( ( PLSAPR_TRUSTED_DOMAIN_INFO )&Current->TrustInfoEx,
  5996. TrustedDomainInformationEx );
  5997. MIDL_user_free( Current );
  5998. }
  5999. //
  6000. // Initialize the Trusted Domain List to the empty state.
  6001. //
  6002. InitializeListHead( &LsapDbTrustedDomainList.ListHead );
  6003. LsapDbTrustedDomainList.TrustedDomainCount = 0;
  6004. LsapDbTrustedDomainList.CurrentSequenceNumber = 0;
  6005. if ( !LsapDbIsCacheBuilding( TrustedDomainObject )) {
  6006. LsapDbMakeCacheInvalid( TrustedDomainObject );
  6007. }
  6008. return;
  6009. }
  6010. #ifdef DBG // this is a macro in FRE builds
  6011. BOOLEAN
  6012. LsapDbIsValidTrustedDomainList(
  6013. )
  6014. /*++
  6015. Routine Description:
  6016. This function checks if the Trusted Domain List is valid.
  6017. Arguments:
  6018. None
  6019. Return Values:
  6020. BOOLEAN - TRUE if the list is valid, else FALSE
  6021. --*/
  6022. {
  6023. ASSERT( LsapDbIsLockedTrustedDomainList());
  6024. return( LsapDbIsCacheValid( TrustedDomainObject ) ||
  6025. LsapDbIsCacheBuilding( TrustedDomainObject ));
  6026. }
  6027. #endif
  6028. NTSTATUS
  6029. LsarEnumerateTrustedDomainsEx(
  6030. IN LSAPR_HANDLE PolicyHandle,
  6031. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  6032. OUT PLSAPR_TRUSTED_ENUM_BUFFER_EX TrustedDomainInformation,
  6033. IN ULONG PreferedMaximumLength
  6034. )
  6035. /*++
  6036. Routine Description:
  6037. This function is the LSA server RPC worker routine for the
  6038. LsaEnumerateTrustedDomains API.
  6039. The LsaEnumerateTrustedDomains API returns information about
  6040. TrustedDomain objects. This call requires POLICY_VIEW_LOCAL_INFORMATION
  6041. access to the Policy object. Since there may be more information than
  6042. can be returned in a single call of the routine, multiple calls can be
  6043. made to get all of the information. To support this feature, the caller
  6044. is provided with a handle that can be used across calls to the API. On
  6045. the initial call, EnumerationContext should point to a variable that has
  6046. been initialized to 0. On each subsequent call, the value returned by
  6047. the preceding call should be passed in unchanged. The enumeration is
  6048. complete when the warning STATUS_NO_MORE_ENTRIES is returned.
  6049. Arguments:
  6050. PolicyHandle - Handle from an LsaOpenPolicy call.
  6051. EnumerationContext - API-specific handle to allow multiple calls
  6052. (see Routine Description above).
  6053. EnumerationBuffer - Pointer to an enumeration structure that will receive
  6054. a count of the Trusted Domains enumerated on this call and a pointer to
  6055. an array of entries containing information for each enumerated
  6056. Trusted Domain.
  6057. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  6058. bytes). This is not a hard upper limit, but serves as a guide. Due to
  6059. data conversion between systems with different natural data sizes, the
  6060. actual amount of data returned may be greater than this value.
  6061. Return Values:
  6062. NTSTATUS - Standard Nt Result Code
  6063. STATUS_SUCCESS - The call completed successfully.
  6064. Some entries may have been returned.
  6065. The caller need not call again.
  6066. STATUS_MORE_ENTRIES - The call completed successfully.
  6067. Some entries have been returned. The caller should call again to
  6068. get additional entries.
  6069. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  6070. to complete the operation.
  6071. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  6072. is returned if no objects have been enumerated because the
  6073. EnumerationContext value is too high.
  6074. --*/
  6075. {
  6076. NTSTATUS Status;
  6077. ULONG Items = 0;
  6078. PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomInfo;
  6079. LsarpReturnCheckSetup();
  6080. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_EnumerateTrustedDomainsEx);
  6081. Status = LsapEnumerateTrustedDomainsEx( PolicyHandle,
  6082. EnumerationContext,
  6083. TrustedDomainInformationEx,
  6084. &TrustedDomInfo,
  6085. PreferedMaximumLength,
  6086. &Items,
  6087. LSAP_DB_ENUMERATE_NO_OPTIONS |
  6088. LSAP_DB_ENUMERATE_NULL_SIDS );
  6089. if ( NT_SUCCESS( Status ) || Status == STATUS_NO_MORE_ENTRIES ) {
  6090. TrustedDomainInformation->EntriesRead = Items;
  6091. TrustedDomainInformation->EnumerationBuffer =
  6092. (PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX)TrustedDomInfo;
  6093. }
  6094. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_EnumerateTrustedDomainsEx);
  6095. LsarpReturnPrologue();
  6096. return( Status );
  6097. }
  6098. NTSTATUS
  6099. LsapEnumerateTrustedDomainsEx(
  6100. IN LSAPR_HANDLE PolicyHandle,
  6101. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  6102. IN TRUSTED_INFORMATION_CLASS InfoClass,
  6103. OUT PLSAPR_TRUSTED_DOMAIN_INFO *TrustedDomainInformation,
  6104. IN ULONG PreferedMaximumLength,
  6105. OUT PULONG CountReturned,
  6106. IN ULONG EnumerationFlags
  6107. )
  6108. /*++
  6109. Routine Description:
  6110. This function is the LSA server RPC worker routine for the
  6111. LsaEnumerateTrustedDomains API.
  6112. The LsaEnumerateTrustedDomains API returns information about
  6113. TrustedDomain objects. This call requires POLICY_VIEW_LOCAL_INFORMATION
  6114. access to the Policy object. Since there may be more information than
  6115. can be returned in a single call of the routine, multiple calls can be
  6116. made to get all of the information. To support this feature, the caller
  6117. is provided with a handle that can be used across calls to the API. On
  6118. the initial call, EnumerationContext should point to a variable that has
  6119. been initialized to 0. On each subsequent call, the value returned by
  6120. the preceding call should be passed in unchanged. The enumeration is
  6121. complete when the warning STATUS_NO_MORE_ENTRIES is returned.
  6122. Arguments:
  6123. PolicyHandle - Handle from an LsaOpenPolicy call.
  6124. EnumerationContext - API-specific handle to allow multiple calls
  6125. (see Routine Description above).
  6126. InfoClass - The class of information to return
  6127. Must be TrustedDomainInformationEx or TrustedDomainInformatinBasic
  6128. TrustedDomainInformation - Returns a pointer to an array of entries
  6129. containing information for each enumerated Trusted Domain.
  6130. Free using LsapFreeTrustedDomainsEx()
  6131. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  6132. bytes). This is not a hard upper limit, but serves as a guide. Due to
  6133. data conversion between systems with different natural data sizes, the
  6134. actual amount of data returned may be greater than this value.
  6135. CountReturned - Number of elements returned in TrustedDomainInformation
  6136. EnumerationFlags -- Controls how the enumeration is done.
  6137. Return Values:
  6138. NTSTATUS - Standard Nt Result Code
  6139. STATUS_SUCCESS - The call completed successfully.
  6140. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  6141. to complete the operation.
  6142. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  6143. is returned if no objects have been enumerated because the
  6144. EnumerationContext value is too high.
  6145. --*/
  6146. {
  6147. NTSTATUS Status, SecondaryStatus;
  6148. ULONG MaxLength, i;
  6149. BOOLEAN ObjectReferenced = FALSE, CloseTransaction = FALSE;
  6150. LsapEnterFunc( "LsapEnumerateTrustedDomainsEx" );
  6151. ASSERT( InfoClass == TrustedDomainInformationEx ||
  6152. InfoClass == TrustedDomainInformationBasic );
  6153. *TrustedDomainInformation = NULL;
  6154. *CountReturned = 0;
  6155. //
  6156. // If no Enumeration Structure is provided, return an error.
  6157. //
  6158. if ( !ARGUMENT_PRESENT(TrustedDomainInformation) ||
  6159. !ARGUMENT_PRESENT( EnumerationContext ) ) {
  6160. LsapExitFunc( "LsapEnumerateTrustedDomainsEx", STATUS_INVALID_PARAMETER );
  6161. return( STATUS_INVALID_PARAMETER );
  6162. }
  6163. //
  6164. // Acquire the Lsa Database lock. Verify that the connection handle is
  6165. // valid, is of the expected type and has all of the desired accesses
  6166. // granted. Reference the handle.
  6167. //
  6168. Status = LsapDbReferenceObject(
  6169. PolicyHandle,
  6170. POLICY_VIEW_LOCAL_INFORMATION,
  6171. PolicyObject,
  6172. TrustedDomainObject,
  6173. LSAP_DB_LOCK |
  6174. LSAP_DB_READ_ONLY_TRANSACTION |
  6175. LSAP_DB_NO_DS_OP_TRANSACTION );
  6176. if ( NT_SUCCESS( Status ) ) {
  6177. ObjectReferenced = TRUE;
  6178. //
  6179. // Limit the enumeration length except for trusted callers
  6180. //
  6181. if ( !((LSAP_DB_HANDLE)PolicyHandle)->Trusted &&
  6182. (PreferedMaximumLength > LSA_MAXIMUM_ENUMERATION_LENGTH) ) {
  6183. MaxLength = LSA_MAXIMUM_ENUMERATION_LENGTH;
  6184. } else {
  6185. MaxLength = PreferedMaximumLength;
  6186. }
  6187. //
  6188. // If the data is cached,
  6189. // use the cache.
  6190. //
  6191. if (LsapDbIsCacheValid(TrustedDomainObject)) {
  6192. LSAPR_TRUSTED_ENUM_BUFFER CacheEnum;
  6193. Status = LsapDbEnumerateTrustedDomainList(
  6194. EnumerationContext,
  6195. &CacheEnum,
  6196. PreferedMaximumLength,
  6197. InfoClass,
  6198. (BOOLEAN)(FLAG_ON( EnumerationFlags, LSAP_DB_ENUMERATE_NULL_SIDS ) ?
  6199. TRUE :
  6200. FALSE) );
  6201. if ( NT_SUCCESS( Status ) ) {
  6202. *CountReturned = CacheEnum.EntriesRead;
  6203. *TrustedDomainInformation = ( PLSAPR_TRUSTED_DOMAIN_INFO )CacheEnum.Information;
  6204. }
  6205. //
  6206. // If the data is in the registry,
  6207. // enumerate it from there.
  6208. //
  6209. } else if ( !LsapDsWriteDs ) {
  6210. LSAPR_TRUSTED_ENUM_BUFFER RegEnum;
  6211. //
  6212. // Use slow method of enumeration, by accessing backing storage.
  6213. // Later, we'll implement rebuilding of the cache.
  6214. Status = LsapDbSlowEnumerateTrustedDomains(
  6215. PolicyHandle,
  6216. EnumerationContext,
  6217. InfoClass,
  6218. &RegEnum,
  6219. PreferedMaximumLength );
  6220. if ( NT_SUCCESS( Status ) ) {
  6221. *CountReturned = RegEnum.EntriesRead;
  6222. *TrustedDomainInformation = ( PLSAPR_TRUSTED_DOMAIN_INFO )RegEnum.Information;
  6223. }
  6224. //
  6225. // If the data is in the DS,
  6226. // enumerate it from there.
  6227. //
  6228. } else {
  6229. BOOLEAN Reset = FALSE;
  6230. Status = LsapDsInitAllocAsNeededEx(
  6231. LSAP_DB_LOCK |
  6232. LSAP_DB_READ_ONLY_TRANSACTION |
  6233. LSAP_DB_DS_OP_TRANSACTION,
  6234. TrustedDomainObject,
  6235. &Reset);
  6236. if ( NT_SUCCESS( Status )) {
  6237. //
  6238. // LsapDsEnumerateTrustedDomainsEx increments the EnumerationContext as necessary
  6239. //
  6240. Status = LsapDsEnumerateTrustedDomainsEx(
  6241. EnumerationContext,
  6242. InfoClass,
  6243. TrustedDomainInformation,
  6244. MaxLength,
  6245. CountReturned,
  6246. EnumerationFlags
  6247. );
  6248. LsapDsDeleteAllocAsNeededEx(
  6249. LSAP_DB_LOCK |
  6250. LSAP_DB_READ_ONLY_TRANSACTION |
  6251. LSAP_DB_DS_OP_TRANSACTION,
  6252. TrustedDomainObject,
  6253. Reset
  6254. );
  6255. }
  6256. }
  6257. }
  6258. if ( ObjectReferenced == TRUE ) {
  6259. //
  6260. // Don't lose the results of the Enumeration
  6261. //
  6262. SecondaryStatus = LsapDbDereferenceObject(
  6263. &PolicyHandle,
  6264. PolicyObject,
  6265. TrustedDomainObject,
  6266. LSAP_DB_LOCK |
  6267. LSAP_DB_READ_ONLY_TRANSACTION |
  6268. LSAP_DB_NO_DS_OP_TRANSACTION,
  6269. (SECURITY_DB_DELTA_TYPE) 0,
  6270. Status
  6271. );
  6272. LsapDbSetStatusFromSecondary( Status, SecondaryStatus );
  6273. }
  6274. //
  6275. // Deallocate any memory if we failed
  6276. //
  6277. if ( !NT_SUCCESS( Status ) && Status != STATUS_NO_MORE_ENTRIES ) {
  6278. //
  6279. // Free it up.
  6280. //
  6281. LsapFreeTrustedDomainsEx( InfoClass,
  6282. *TrustedDomainInformation,
  6283. *CountReturned );
  6284. *TrustedDomainInformation = NULL;
  6285. *CountReturned = 0;
  6286. }
  6287. //
  6288. // Map the status into what LsarEnumerateTrustedDomains normally returns...
  6289. //
  6290. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  6291. Status = STATUS_NO_MORE_ENTRIES;
  6292. }
  6293. LsapExitFunc( "LsapEnumerateTrustedDomainsEx", Status );
  6294. return( Status );
  6295. }
  6296. VOID
  6297. LsapFreeTrustedDomainsEx(
  6298. IN TRUSTED_INFORMATION_CLASS InfoClass,
  6299. IN PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation,
  6300. IN ULONG TrustedDomainCount
  6301. )
  6302. /*++
  6303. Routine Description:
  6304. This function frees a buffer returned from LsapEnumerateTrustedDomainsEx
  6305. Arguments:
  6306. InfoClass - The class of information in the buffer.
  6307. Must be TrustedDomainInformationEx or TrustedDomainInformatinBasic
  6308. TrustedDomainInformation - A pointer to an array of entries
  6309. containing information for each enumerated Trusted Domain.
  6310. TrustedDomainCount - Number of elements in TrustedDomainInformation
  6311. Return Values:
  6312. None.
  6313. --*/
  6314. {
  6315. switch ( InfoClass ) {
  6316. case TrustedDomainInformationEx:
  6317. {
  6318. LSAPR_TRUSTED_ENUM_BUFFER_EX TrustedDomainInfoEx;
  6319. TrustedDomainInfoEx.EntriesRead = TrustedDomainCount;
  6320. TrustedDomainInfoEx.EnumerationBuffer =
  6321. (PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX) TrustedDomainInformation;
  6322. _fgs__LSAPR_TRUSTED_ENUM_BUFFER_EX( &TrustedDomainInfoEx );
  6323. break;
  6324. }
  6325. case TrustedDomainInformationBasic:
  6326. {
  6327. LSAPR_TRUSTED_ENUM_BUFFER TrustedDomainInfoBasic;
  6328. TrustedDomainInfoBasic.EntriesRead = TrustedDomainCount;
  6329. TrustedDomainInfoBasic.Information =
  6330. (PLSAPR_TRUSTED_DOMAIN_INFORMATION_BASIC) TrustedDomainInformation;
  6331. _fgs__LSAPR_TRUSTED_ENUM_BUFFER( &TrustedDomainInfoBasic );
  6332. break;
  6333. }
  6334. default:
  6335. ASSERT( FALSE );
  6336. break;
  6337. }
  6338. }
  6339. NTSTATUS
  6340. LsarQueryTrustedDomainInfoByName(
  6341. IN LSAPR_HANDLE PolicyHandle,
  6342. IN PLSAPR_UNICODE_STRING TrustedDomainName,
  6343. IN TRUSTED_INFORMATION_CLASS InformationClass,
  6344. OUT PLSAPR_TRUSTED_DOMAIN_INFO *TrustedDomainInformation
  6345. )
  6346. /*++
  6347. Routine Description:
  6348. This function is the LSA server RPC worker routine for the
  6349. LsaQueryInfoTrustedDomain API.
  6350. The LsaQueryInfoTrustedDomain API obtains information from a
  6351. TrustedDomain object. The caller must have access appropriate to the
  6352. information being requested (see InformationClass parameter).
  6353. Arguments:
  6354. PolicyHandle - Handle from an LsaOpenPolicy call.
  6355. InformationClass - Specifies the information to be returned. The
  6356. Information Classes and accesses required are as follows:
  6357. Information Class Required Access Type
  6358. TrustedDomainNameInformation TRUSTED_QUERY_DOMAIN_NAME
  6359. TrustedControllersInformation TRUSTED_QUERY_CONTROLLERS
  6360. TrustedPosixOffsetInformation TRUSTED_QUERY_POSIX
  6361. Buffer - Receives a pointer to the buffer returned comtaining the
  6362. requested information. This buffer is allocated by this service
  6363. and must be freed when no longer needed by passing the returned
  6364. value to LsaFreeMemory().
  6365. Return Value:
  6366. NTSTATUS - Standard Nt Result Code
  6367. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  6368. access to complete the operation.
  6369. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  6370. such as memory, to complete the call.
  6371. --*/
  6372. {
  6373. NTSTATUS Status, SecondaryStatus;
  6374. LSAP_DB_OBJECT_INFORMATION ObjInfo;
  6375. LSAPR_HANDLE TrustedDomainHandle;
  6376. BOOLEAN ObjectReferenced = FALSE;
  6377. PLSAP_DB_TRUSTED_DOMAIN_LIST_ENTRY TrustInfoForName;
  6378. PUNICODE_STRING ActualTDName = ( PUNICODE_STRING )TrustedDomainName;
  6379. ACCESS_MASK DesiredAccess;
  6380. BOOLEAN AcquiredTrustedDomainListReadLock = FALSE;
  6381. LsarpReturnCheckSetup();
  6382. LsapEnterFunc( "LsarQueryTrustedDomainInfoByName" );
  6383. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_QueryTrustedDomainInfoByName);
  6384. //
  6385. // Validate the input buffer
  6386. //
  6387. if ( !LsapValidateLsaUnicodeString( TrustedDomainName ) ) {
  6388. Status = STATUS_INVALID_PARAMETER;
  6389. goto GetInfoByNameError;
  6390. }
  6391. //
  6392. // Validate the Information Class and determine the access required to
  6393. // query this Trusted Domain Information Class.
  6394. //
  6395. Status = LsapDbVerifyInfoQueryTrustedDomain(
  6396. InformationClass,
  6397. (BOOLEAN)(((LSAP_DB_HANDLE)PolicyHandle)->Options & LSAP_DB_TRUSTED),
  6398. &DesiredAccess );
  6399. if (!NT_SUCCESS(Status)) {
  6400. goto GetInfoByNameError;
  6401. }
  6402. Status = LsapDbReferenceObject( PolicyHandle,
  6403. 0,
  6404. PolicyObject,
  6405. TrustedDomainObject,
  6406. LSAP_DB_LOCK |
  6407. LSAP_DB_READ_ONLY_TRANSACTION |
  6408. LSAP_DB_DS_OP_TRANSACTION );
  6409. if ( NT_SUCCESS( Status ) ) {
  6410. ObjectReferenced = TRUE;
  6411. //
  6412. // Acquire the Read Lock for the Trusted Domain List
  6413. //
  6414. Status = LsapDbAcquireReadLockTrustedDomainList();
  6415. if (!NT_SUCCESS(Status)) {
  6416. goto GetInfoByNameError;
  6417. }
  6418. AcquiredTrustedDomainListReadLock = TRUE;
  6419. //
  6420. // Get the right name
  6421. //
  6422. Status = LsapDbLookupNameTrustedDomainListEx( TrustedDomainName,
  6423. &TrustInfoForName );
  6424. if ( NT_SUCCESS( Status ) ) {
  6425. ActualTDName = ( PUNICODE_STRING )&TrustInfoForName->TrustInfoEx.Name;
  6426. } else {
  6427. LsapDsDebugOut(( DEB_ERROR,
  6428. "No trust entry found for %wZ: 0x%lx\n",
  6429. ( PUNICODE_STRING )TrustedDomainName,
  6430. Status ));
  6431. Status = STATUS_SUCCESS;
  6432. }
  6433. //
  6434. // Build a temporary handle
  6435. //
  6436. RtlZeroMemory( &ObjInfo, sizeof( ObjInfo ) );
  6437. ObjInfo.ObjectTypeId = TrustedDomainObject;
  6438. ObjInfo.ContainerTypeId = 0;
  6439. ObjInfo.Sid = NULL;
  6440. ObjInfo.DesiredObjectAccess = DesiredAccess;
  6441. InitializeObjectAttributes( &ObjInfo.ObjectAttributes,
  6442. ActualTDName,
  6443. 0L,
  6444. PolicyHandle,
  6445. NULL );
  6446. //
  6447. // Get a handle to the TDO
  6448. //
  6449. Status = LsapDbOpenObject( &ObjInfo,
  6450. DesiredAccess,
  6451. 0,
  6452. &TrustedDomainHandle );
  6453. if ( AcquiredTrustedDomainListReadLock ) {
  6454. LsapDbReleaseLockTrustedDomainList();
  6455. AcquiredTrustedDomainListReadLock = FALSE;
  6456. }
  6457. if ( NT_SUCCESS( Status ) ) {
  6458. Status = LsarQueryInfoTrustedDomain( TrustedDomainHandle,
  6459. InformationClass,
  6460. TrustedDomainInformation );
  6461. LsapDbCloseObject( &TrustedDomainHandle,
  6462. 0,
  6463. Status );
  6464. }
  6465. }
  6466. //
  6467. // If we got a DNS name to lookup and it wasn't found and it was an absolute DNS name
  6468. // try hacking off the trailing period and trying it again...
  6469. //
  6470. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  6471. if ( TrustedDomainName->Length == 0 || TrustedDomainName->Buffer == NULL ) {
  6472. goto GetInfoByNameError;
  6473. }
  6474. if ( TrustedDomainName->Buffer[ (TrustedDomainName->Length - 1) / sizeof(WCHAR)] == L'.' ) {
  6475. TrustedDomainName->Buffer[ (TrustedDomainName->Length - 1) / sizeof(WCHAR)] =
  6476. UNICODE_NULL;
  6477. TrustedDomainName->Length -= sizeof(WCHAR);
  6478. if ( TrustedDomainName->Length > 0 &&
  6479. TrustedDomainName->Buffer[ ( TrustedDomainName->Length - 1) / sizeof(WCHAR)] !=
  6480. L'.') {
  6481. LsapDsDebugOut(( DEB_WARN,
  6482. "GetTrustedDomainInfoByName tried with absolute DNS name. "
  6483. "Retrying with %wZ\n",
  6484. TrustedDomainName ));
  6485. Status = LsarQueryTrustedDomainInfoByName( PolicyHandle,
  6486. TrustedDomainName,
  6487. InformationClass,
  6488. TrustedDomainInformation );
  6489. }
  6490. }
  6491. }
  6492. GetInfoByNameError:
  6493. if ( AcquiredTrustedDomainListReadLock ) {
  6494. LsapDbReleaseLockTrustedDomainList();
  6495. }
  6496. //
  6497. // Dereference the object
  6498. //
  6499. if ( ObjectReferenced ) {
  6500. SecondaryStatus = LsapDbDereferenceObject(
  6501. &PolicyHandle,
  6502. PolicyObject,
  6503. TrustedDomainObject,
  6504. LSAP_DB_LOCK |
  6505. LSAP_DB_READ_ONLY_TRANSACTION |
  6506. LSAP_DB_DS_OP_TRANSACTION,
  6507. (SECURITY_DB_DELTA_TYPE) 0,
  6508. Status );
  6509. }
  6510. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_QueryTrustedDomainInfoByName);
  6511. LsapExitFunc( "LsarQueryTrustedDomainInfoByName", Status );
  6512. LsarpReturnPrologue();
  6513. return( Status );
  6514. }
  6515. NTSTATUS
  6516. LsarSetTrustedDomainInfoByName(
  6517. IN LSAPR_HANDLE PolicyHandle,
  6518. IN PLSAPR_UNICODE_STRING TrustedDomainName,
  6519. IN TRUSTED_INFORMATION_CLASS InformationClass,
  6520. IN PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation)
  6521. {
  6522. NTSTATUS Status, SecondaryStatus;
  6523. LSAP_DB_OBJECT_INFORMATION ObjInfo;
  6524. LSAPR_HANDLE TrustedDomainHandle;
  6525. ACCESS_MASK DesiredAccess;
  6526. LsarpReturnCheckSetup();
  6527. LsapEnterFunc( "LsarSetTrustedDomainInfoByName" );
  6528. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_SetTrustedDomainInfoByName);
  6529. //
  6530. // Validate the input buffer
  6531. //
  6532. if ( !LsapValidateLsaUnicodeString( TrustedDomainName ) ) {
  6533. Status = STATUS_INVALID_PARAMETER;
  6534. goto SetInfoByNameError;
  6535. }
  6536. //
  6537. // Validate the Information Class and Trusted Domain Information provided and
  6538. // if valid, return the mask of accesses required to update this
  6539. // class of Trusted Domain information.
  6540. //
  6541. Status = LsapDbVerifyInfoSetTrustedDomain(
  6542. InformationClass,
  6543. TrustedDomainInformation,
  6544. (BOOLEAN)(((LSAP_DB_HANDLE)PolicyHandle)->Options & LSAP_DB_TRUSTED),
  6545. &DesiredAccess );
  6546. if (!NT_SUCCESS(Status)) {
  6547. goto SetInfoByNameError;
  6548. }
  6549. //
  6550. // Build a temporary handle
  6551. //
  6552. RtlZeroMemory( &ObjInfo, sizeof( ObjInfo ) );
  6553. ObjInfo.ObjectTypeId = TrustedDomainObject;
  6554. ObjInfo.ContainerTypeId = 0;
  6555. ObjInfo.Sid = NULL;
  6556. ObjInfo.DesiredObjectAccess = DesiredAccess;
  6557. InitializeObjectAttributes(
  6558. &ObjInfo.ObjectAttributes,
  6559. (UNICODE_STRING *)TrustedDomainName,
  6560. 0L,
  6561. PolicyHandle,
  6562. NULL
  6563. );
  6564. Status = LsapDbReferenceObject(
  6565. PolicyHandle,
  6566. 0,
  6567. PolicyObject,
  6568. TrustedDomainObject,
  6569. LSAP_DB_LOCK
  6570. );
  6571. if ( NT_SUCCESS( Status ) ) {
  6572. //
  6573. // Get a handle to the TDO
  6574. //
  6575. Status = LsapDbOpenObject( &ObjInfo,
  6576. DesiredAccess,
  6577. 0,
  6578. &TrustedDomainHandle );
  6579. //
  6580. // Unlock the lock.
  6581. //
  6582. // We can't enter LsarSetInformationTrustedDomain with any locks locked since
  6583. // it goes out of process to get the session key.
  6584. //
  6585. // We can't dereference the PolicyHandle since this reference also
  6586. // serves as the ContainerHandle reference.
  6587. //
  6588. LsapDbReleaseLockEx( TrustedDomainObject,
  6589. 0 );
  6590. //
  6591. // Set the info on the TDO.
  6592. //
  6593. if ( NT_SUCCESS( Status ) ) {
  6594. Status = LsarSetInformationTrustedDomain(
  6595. TrustedDomainHandle,
  6596. InformationClass,
  6597. TrustedDomainInformation );
  6598. LsapDbCloseObject( &TrustedDomainHandle,
  6599. 0,
  6600. Status );
  6601. }
  6602. //
  6603. // Dereference the object.
  6604. //
  6605. SecondaryStatus = LsapDbDereferenceObject(
  6606. &PolicyHandle,
  6607. PolicyObject,
  6608. TrustedDomainObject,
  6609. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION,
  6610. (SECURITY_DB_DELTA_TYPE) 0,
  6611. Status
  6612. );
  6613. LsapDbSetStatusFromSecondary( Status, SecondaryStatus );
  6614. }
  6615. //
  6616. // If we got a DNS name to lookup and it wasn't found and it was an absolute DNS name
  6617. // try hacking off the trailing period and trying it again...
  6618. //
  6619. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  6620. if ( TrustedDomainName->Length == 0 || TrustedDomainName->Buffer == NULL ) {
  6621. goto SetInfoByNameError;
  6622. }
  6623. if ( TrustedDomainName->Buffer[ (TrustedDomainName->Length - 1) / sizeof(WCHAR)] == L'.' ) {
  6624. TrustedDomainName->Buffer[ (TrustedDomainName->Length - 1) / sizeof(WCHAR)] =
  6625. UNICODE_NULL;
  6626. TrustedDomainName->Length -= sizeof(WCHAR);
  6627. if ( TrustedDomainName->Length > 0 &&
  6628. TrustedDomainName->Buffer[ ( TrustedDomainName->Length - 1) / sizeof(WCHAR)] !=
  6629. L'.') {
  6630. LsapDsDebugOut(( DEB_WARN,
  6631. "SetTrustedDomainInfoByName tried with absolute DNS name. "
  6632. "Retrying with %wZ\n",
  6633. TrustedDomainName ));
  6634. Status = LsarSetTrustedDomainInfoByName( PolicyHandle,
  6635. TrustedDomainName,
  6636. InformationClass,
  6637. TrustedDomainInformation );
  6638. }
  6639. }
  6640. }
  6641. SetInfoByNameError:
  6642. LsapExitFunc( "LsarSetTrustedDomainInfoByName", Status );
  6643. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_SetTrustedDomainInfoByName);
  6644. LsarpReturnPrologue();
  6645. return( Status );
  6646. }
  6647. NTSTATUS
  6648. LsarCreateTrustedDomainEx(
  6649. IN LSAPR_HANDLE PolicyHandle,
  6650. IN PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
  6651. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation,
  6652. IN ACCESS_MASK DesiredAccess,
  6653. OUT LSAPR_HANDLE *TrustedDomainHandle
  6654. )
  6655. /*++
  6656. Routine Description:
  6657. The LsaCreateTrustedDomainEx function creates a new TrustedDomain object.
  6658. Arguments:
  6659. PolicyHandle - Handle from an LsaOpenPolicy call.
  6660. TrustedDomainInformation - Pointer to a TRUSTED_DOMAIN_INFORMATION_EX structure
  6661. containing the name and SID of the new trusted domain.
  6662. AuthenticationInformation - Pointer to a TRUSTED_DOMAIN_AUTH_INFORMATION
  6663. structure containing authentication information for the new trusted domain.
  6664. DesiredAccess - An ACCESS_MASK structure that specifies the accesses to
  6665. be granted for the new trusted domain.
  6666. TrustedDomainHandle - Receives the LSA policy handle of the remote
  6667. trusted domain. You can use pass this handle into LSA function calls
  6668. in order to query and/or manage the LSA policy of the remote machine.
  6669. When your application no longer needs this handle, it should call
  6670. LsaClose to delete the handle.
  6671. Return Value:
  6672. NTSTATUS - Standard Nt Result Code
  6673. --*/
  6674. {
  6675. NTSTATUS Status;
  6676. LsarpReturnCheckSetup();
  6677. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_CreateTrustedDomainEx);
  6678. //
  6679. // Former LSA implementations didn't enforce TRUSTED_SET_AUTH.
  6680. // So some callers were lured into a false sense of security and didn't
  6681. // ask for it. Ask here.
  6682. //
  6683. DesiredAccess |= TRUSTED_SET_AUTH;
  6684. //
  6685. // There's a bug in the definition LSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION where
  6686. // it doesn't allow more than one auth info to be passed over the wire.
  6687. // So, short circuit it here.
  6688. //
  6689. // We could let trusted callers thru, but we haven't validated the handle yet.
  6690. //
  6691. if ( AuthenticationInformation->IncomingAuthInfos > 1 ||
  6692. AuthenticationInformation->OutgoingAuthInfos > 1 ) {
  6693. return STATUS_INVALID_PARAMETER;
  6694. }
  6695. //
  6696. // Call the worker routine to do the job.
  6697. //
  6698. Status = LsapCreateTrustedDomain2( PolicyHandle,
  6699. TrustedDomainInformation,
  6700. AuthenticationInformation,
  6701. DesiredAccess,
  6702. TrustedDomainHandle );
  6703. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_CreateTrustedDomainEx);
  6704. LsarpReturnPrologue();
  6705. return( Status );
  6706. }
  6707. NTSTATUS
  6708. LsarCreateTrustedDomainEx2(
  6709. IN LSAPR_HANDLE PolicyHandle,
  6710. IN PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
  6711. IN PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL AuthenticationInformation,
  6712. IN ACCESS_MASK DesiredAccess,
  6713. OUT LSAPR_HANDLE *TrustedDomainHandle
  6714. )
  6715. /*++
  6716. Routine Description:
  6717. Same as LsarCreateTrustedDomainEx except the AuthenticationInformation is
  6718. encrypted on the wire.
  6719. Arguments:
  6720. Same as LsarCreateTrustedDomainEx except the AuthenticationInformation is
  6721. encrypted on the wire.
  6722. Return Value:
  6723. NTSTATUS - Standard Nt Result Code
  6724. --*/
  6725. {
  6726. NTSTATUS Status;
  6727. TRUSTED_DOMAIN_AUTH_INFORMATION DecryptedTrustedDomainAuthInfo;
  6728. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  6729. LsarpReturnCheckSetup();
  6730. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_CreateTrustedDomainEx);
  6731. RtlZeroMemory( &DecryptedTrustedDomainAuthInfo, sizeof(DecryptedTrustedDomainAuthInfo) );
  6732. //
  6733. // Check the parameters
  6734. // (AuthenticationInformation->AuthBlob.AuthBlob is a unique pointer therefore needs to be
  6735. // checked for null before reference)
  6736. //
  6737. if( ( AuthenticationInformation->AuthBlob.AuthBlob == NULL &&
  6738. AuthenticationInformation->AuthBlob.AuthSize != 0 ) ||
  6739. ( AuthenticationInformation->AuthBlob.AuthBlob != NULL &&
  6740. AuthenticationInformation->AuthBlob.AuthSize == 0 ) ) {
  6741. Status = STATUS_INVALID_PARAMETER;
  6742. goto Cleanup;
  6743. }
  6744. //
  6745. // Get the session key.
  6746. //
  6747. Status = LsapCrServerGetSessionKeySafe( PolicyHandle,
  6748. PolicyObject,
  6749. &SessionKey );
  6750. if (!NT_SUCCESS(Status)) {
  6751. goto Cleanup;
  6752. }
  6753. //
  6754. // Build a decrypted Auth Info structure.
  6755. //
  6756. Status = LsapDecryptAuthDataWithSessionKey(
  6757. SessionKey,
  6758. AuthenticationInformation,
  6759. &DecryptedTrustedDomainAuthInfo );
  6760. if ( !NT_SUCCESS(Status) ) {
  6761. goto Cleanup;
  6762. }
  6763. //
  6764. // Former LSA implementations didn't enforce TRUSTED_SET_AUTH.
  6765. // So some callers were lured into a false sense of security and didn't
  6766. // ask for it. Ask here.
  6767. //
  6768. DesiredAccess |= TRUSTED_SET_AUTH;
  6769. //
  6770. // Call the worker routine to do the job.
  6771. //
  6772. Status = LsapCreateTrustedDomain2( PolicyHandle,
  6773. TrustedDomainInformation,
  6774. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION)&DecryptedTrustedDomainAuthInfo,
  6775. DesiredAccess,
  6776. TrustedDomainHandle );
  6777. Cleanup:
  6778. if ( SessionKey != NULL ) {
  6779. MIDL_user_free( SessionKey );
  6780. }
  6781. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainAuthInfo, TRUE ) );
  6782. LsapDsFreeUnmarshalAuthInfoHalf( LsapDsAuthHalfFromAuthInfo( &DecryptedTrustedDomainAuthInfo, FALSE ) );
  6783. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_CreateTrustedDomainEx);
  6784. LsarpReturnPrologue();
  6785. return( Status );
  6786. }
  6787. NTSTATUS
  6788. LsapDbOpenTrustedDomainByName(
  6789. IN OPTIONAL LSAPR_HANDLE PolicyHandle,
  6790. IN PUNICODE_STRING TrustedDomainName,
  6791. OUT PLSAPR_HANDLE TrustedDomainHandle,
  6792. IN ULONG AccessMask,
  6793. IN ULONG Options,
  6794. IN BOOLEAN Trusted
  6795. )
  6796. /*++
  6797. Routine Description:
  6798. This function opens a Trusted Domain Object by the name. This name can be either the
  6799. DomainName or FlatName
  6800. Arguments:
  6801. PolicyHandle - Policy handle.
  6802. If NULL, the LSA's global policy handle will be used.
  6803. TrustedDomainName - Pointer to the domains name
  6804. TrustedDomainHandle - Receives a handle to be used in future requests.
  6805. AccessMask - Access mask to open the object with
  6806. Options - Specifies option flags
  6807. LSAP_DB_LOCK - Acquire the Lsa Database lock for the
  6808. duration of the open operation.
  6809. LSAP_DB_START_TRANSACTION -- Begin a transaction before access the database
  6810. Ignored if LSAP_DB_LOCK isn't specified.
  6811. Trusted - If TRUE, the open request is coming from a trusted client
  6812. Return Values:
  6813. NTSTATUS - Standard Nt Result Code
  6814. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  6815. to complete the operation.
  6816. STATUS_OBJECT_NAME_NOT_FOUND - There is no TrustedDomain object in the
  6817. target system's LSA Database having the specified Name.
  6818. --*/
  6819. {
  6820. NTSTATUS Status = STATUS_SUCCESS;
  6821. PDSNAME FoundTrustObject = NULL;
  6822. LSAP_DB_OBJECT_INFORMATION ObjInfo;
  6823. UNICODE_STRING ObjectName;
  6824. BOOLEAN DbLocked = FALSE;
  6825. BOOLEAN HandleReferenced = FALSE;
  6826. ULONG DereferenceOptions = 0, ReferenceOptions = 0, i;
  6827. LSAPR_HANDLE PolicyHandleToUse;
  6828. LsapEnterFunc( "LsapDbOpenTrustedDomainByName" );
  6829. if ((NULL==TrustedDomainName) || (NULL==TrustedDomainName->Buffer))
  6830. {
  6831. return(STATUS_INVALID_PARAMETER);
  6832. }
  6833. //
  6834. // Validate the Policy Handle
  6835. //
  6836. // Don't both verifying the global handle (it's fine).
  6837. // Increment the reference count. We'll be using this reference as the ContainerHandle on
  6838. // the open trusted domain handle.
  6839. //
  6840. // This mechanism for ref counting the ContainerHandle is bogus throughout the code.
  6841. // The code that does the reference (LsapDbCreateHandle) to the ContainerHandle should
  6842. // increment the ref count. The code that removes the reference (???) should decrement
  6843. // the ref count.
  6844. //
  6845. if ( PolicyHandle == NULL ) {
  6846. PolicyHandleToUse = LsapPolicyHandle;
  6847. } else {
  6848. PolicyHandleToUse = PolicyHandle;
  6849. Status = LsapDbVerifyHandle( PolicyHandle, 0, PolicyObject, TRUE );
  6850. if (!NT_SUCCESS(Status)) {
  6851. goto Cleanup;
  6852. }
  6853. HandleReferenced = TRUE;
  6854. }
  6855. //
  6856. // Do our opens as needed
  6857. //
  6858. if ( FLAG_ON( Options, LSAP_DB_LOCK ) ) {
  6859. ReferenceOptions |= LSAP_DB_LOCK;
  6860. DereferenceOptions |= LSAP_DB_LOCK;
  6861. if ( FLAG_ON( Options, LSAP_DB_START_TRANSACTION ) ) {
  6862. ReferenceOptions |= LSAP_DB_START_TRANSACTION;
  6863. DereferenceOptions |= LSAP_DB_FINISH_TRANSACTION;
  6864. }
  6865. Status = LsapDbReferenceObject( PolicyHandleToUse,
  6866. (ACCESS_MASK) 0,
  6867. PolicyObject,
  6868. TrustedDomainObject,
  6869. Trusted ? ReferenceOptions | LSAP_DB_TRUSTED :
  6870. ReferenceOptions );
  6871. if ( !NT_SUCCESS( Status ) ) {
  6872. goto Cleanup;
  6873. }
  6874. DbLocked = TRUE;
  6875. }
  6876. RtlZeroMemory( &ObjInfo, sizeof( ObjInfo ) );
  6877. ObjInfo.ObjectTypeId = TrustedDomainObject;
  6878. ObjInfo.ContainerTypeId = PolicyObject;
  6879. ObjInfo.Sid = NULL;
  6880. ObjInfo.DesiredObjectAccess = AccessMask;
  6881. InitializeObjectAttributes(
  6882. &ObjInfo.ObjectAttributes,
  6883. TrustedDomainName,
  6884. OBJ_CASE_INSENSITIVE,
  6885. PolicyHandle, // If NULL, we simply won't have a container handle.
  6886. NULL
  6887. );
  6888. Status = LsapDbOpenObject( &ObjInfo,
  6889. AccessMask,
  6890. Trusted ? LSAP_DB_TRUSTED : 0,
  6891. TrustedDomainHandle );
  6892. Cleanup:
  6893. if (DbLocked) {
  6894. Status = LsapDbDereferenceObject(
  6895. &PolicyHandleToUse,
  6896. PolicyObject,
  6897. TrustedDomainObject,
  6898. DereferenceOptions,
  6899. (SECURITY_DB_DELTA_TYPE) 0,
  6900. Status
  6901. );
  6902. }
  6903. if ( !NT_SUCCESS(Status) ) {
  6904. //
  6905. // On Success, the reference to the Policy object is used as the ContainerHandle reference.
  6906. //
  6907. if ( HandleReferenced ) {
  6908. LsapDbDereferenceHandle( PolicyHandle, FALSE );
  6909. }
  6910. }
  6911. LsapExitFunc( "LsapDbOpenTrustedDomainByName", Status );
  6912. return( Status );
  6913. }
  6914. NTSTATUS
  6915. LsarOpenTrustedDomainByName(
  6916. IN LSAPR_HANDLE PolicyHandle,
  6917. IN PLSAPR_UNICODE_STRING TrustedDomainName,
  6918. IN ACCESS_MASK DesiredAccess,
  6919. OUT PLSAPR_HANDLE TrustedDomainHandle
  6920. )
  6921. /*++
  6922. Routine Description:
  6923. The LsaOpenTrustedDomain API opens an existing TrustedDomain object
  6924. using the SID as the primary key value.
  6925. Arguments:
  6926. PolicyHandle - An open handle to a Policy object.
  6927. TrustedDomainName - Name of the trusted domain object
  6928. DesiredAccess - This is an access mask indicating accesses being
  6929. requested to the target object.
  6930. TrustedDomainHandle - Receives a handle to be used in future requests.
  6931. Return Values:
  6932. NTSTATUS - Standard Nt Result Code
  6933. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  6934. to complete the operation.
  6935. STATUS_TRUSTED_DOMAIN_NOT_FOUND - There is no TrustedDomain object in the
  6936. target system's LSA Database having the specified TrustedDomainName
  6937. --*/
  6938. {
  6939. NTSTATUS Status;
  6940. LsarpReturnCheckSetup();
  6941. LsapEnterFunc( "LsarOpenTrustedDomainByName" );
  6942. LsapTraceEvent(EVENT_TRACE_TYPE_START, LsaTraceEvent_OpenTrustedDomainByName);
  6943. //
  6944. // Call the internal routine. Caller is not trusted and the Database
  6945. // lock needs to be acquired.
  6946. //
  6947. Status = LsapDbOpenTrustedDomainByName( PolicyHandle,
  6948. (PUNICODE_STRING)TrustedDomainName,
  6949. TrustedDomainHandle,
  6950. DesiredAccess,
  6951. LSAP_DB_LOCK,
  6952. FALSE ); // Untrusted
  6953. LsapTraceEvent(EVENT_TRACE_TYPE_END, LsaTraceEvent_OpenTrustedDomainByName);
  6954. LsapExitFunc( "LsarOpenTrustedDomainByName", Status );
  6955. LsarpReturnPrologue();
  6956. return(Status);
  6957. }
  6958. NTSTATUS
  6959. LsapSidOnFtInfo(
  6960. IN PUNICODE_STRING TrustedDomainName,
  6961. IN PSID Sid
  6962. )
  6963. /*++
  6964. Routine description:
  6965. Determines whether the specified SID is on the FTINFO structure for the specified
  6966. TDO.
  6967. Arguments:
  6968. TrustedDomainName - Netbios name or DNS name of the trusted domain.
  6969. Sid - SID to test
  6970. Return values:
  6971. STATUS_SUCCESS Match was found - SID is on the FTINFO
  6972. STATUS_NO_MATCH Match was not found - SID is not on the FTINFO
  6973. STATUS_INVALID_DOMAIN_STATE Machine must be a GC or a DC in the root domain
  6974. STATUS_INVALID_PARAMETER Check the inputs
  6975. STATUS_INTERNAL_ERROR Cache is internally inconsistent
  6976. STATUS_INSUFFICIENT_RESOURCES Out of memory
  6977. --*/
  6978. {
  6979. NTSTATUS Status;
  6980. UNICODE_STRING MatchingDomain;
  6981. //
  6982. // Find the TDO that maps to this SID.
  6983. //
  6984. RtlInitUnicodeString( &MatchingDomain, NULL );
  6985. Status = LsaIForestTrustFindMatch(
  6986. RoutingMatchDomainSid,
  6987. Sid,
  6988. &MatchingDomain );
  6989. if ( Status != STATUS_SUCCESS ) {
  6990. return Status;
  6991. }
  6992. //
  6993. // If that TDO is not the named TDO,
  6994. // indicate that there was no match.
  6995. //
  6996. if ( !RtlEqualUnicodeString( TrustedDomainName,
  6997. &MatchingDomain,
  6998. TRUE ) ) {
  6999. Status = STATUS_NO_MATCH;
  7000. }
  7001. LsaIFree_LSAPR_UNICODE_STRING_BUFFER( (PLSAPR_UNICODE_STRING) &MatchingDomain );
  7002. return Status;
  7003. }
  7004. #ifdef TESTING_MATCHING_ROUTINE
  7005. #include <sddl.h> // ConvertStringSidToSidW
  7006. NTSTATUS
  7007. LsarForestTrustFindMatch(
  7008. IN LSA_HANDLE PolicyHandle,
  7009. IN ULONG Type,
  7010. IN PLSA_UNICODE_STRING Name,
  7011. OUT PLSA_UNICODE_STRING * Match
  7012. )
  7013. {
  7014. NTSTATUS Status;
  7015. PLSA_UNICODE_STRING _Match = MIDL_user_allocate( sizeof( LSA_UNICODE_STRING ));
  7016. PVOID Data;
  7017. UNREFERENCED_PARAMETER( PolicyHandle );
  7018. if ( _Match == NULL ) {
  7019. return STATUS_INSUFFICIENT_RESOURCES;
  7020. }
  7021. if ( Type == RoutingMatchDomainSid ) {
  7022. if ( FALSE == ConvertStringSidToSidW(
  7023. Name->Buffer,
  7024. &Data )) {
  7025. Data = NULL;
  7026. }
  7027. } else {
  7028. Data = Name;
  7029. }
  7030. if ( Data != NULL ) {
  7031. Status = LsaIForestTrustFindMatch(
  7032. ( LSA_ROUTING_MATCH_TYPE )Type,
  7033. Data,
  7034. _Match
  7035. );
  7036. if ( NT_SUCCESS( Status )) {
  7037. *Match = _Match;
  7038. } else {
  7039. *Match = NULL;
  7040. }
  7041. } else {
  7042. Status = STATUS_INVALID_PARAMETER;
  7043. }
  7044. if ( Type == RoutingMatchDomainSid ) {
  7045. LocalFree( Data );
  7046. }
  7047. return Status;
  7048. }
  7049. #endif
  7050. VOID
  7051. LsaIFree_LSA_FOREST_TRUST_INFORMATION(
  7052. IN PLSA_FOREST_TRUST_INFORMATION * ForestTrustInfo
  7053. )
  7054. /*++
  7055. Routine Description:
  7056. Frees up a structure pointed to by ForestTrustInfo
  7057. Arguments:
  7058. ForestTrustInfo structure to free
  7059. Returns:
  7060. Nothing
  7061. --*/
  7062. {
  7063. if ( ForestTrustInfo ) {
  7064. LsapFreeForestTrustInfo( *ForestTrustInfo );
  7065. MIDL_user_free( *ForestTrustInfo );
  7066. *ForestTrustInfo = NULL;
  7067. }
  7068. }
  7069. VOID
  7070. LsaIFree_LSA_FOREST_TRUST_COLLISION_INFORMATION(
  7071. IN PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo
  7072. )
  7073. /*++
  7074. Routine Description:
  7075. Frees up a structure pointed to by CollisionInfo
  7076. Arguments:
  7077. CollisionInfo structure to free
  7078. Returns:
  7079. Nothing
  7080. --*/
  7081. {
  7082. if ( CollisionInfo ) {
  7083. LsapFreeCollisionInfo( CollisionInfo );
  7084. }
  7085. }
  7086. BOOLEAN
  7087. LsapDbDcInRootDomain()
  7088. /*++
  7089. Routine Description:
  7090. Tells if the system is running as a domain controller
  7091. in the root domain of the forest
  7092. Arguments:
  7093. None
  7094. Returns:
  7095. TRUE or FALSE
  7096. --*/
  7097. {
  7098. //
  7099. // The determination is done at startup time and
  7100. // the results are assumed to remain constant for
  7101. // as long as the server stays up.
  7102. //
  7103. return DcInRootDomain;
  7104. }
  7105. BOOLEAN
  7106. LsapDbNoMoreWin2KForest()
  7107. /*++
  7108. Routine Description:
  7109. Determines whether all domain controllers in the forest have been upgraded
  7110. to Whistler (a requirement for forest trust operation) by querying
  7111. the msDS-Behavior-Version attribute from the Partitions container in the DS
  7112. Arguments:
  7113. None
  7114. Returns:
  7115. TRUE or FALSE
  7116. --*/
  7117. {
  7118. LONG ForestBehaviorVersion;
  7119. DWORD Size = sizeof( ForestBehaviorVersion );
  7120. static BOOLEAN Result = FALSE;
  7121. NTSTATUS Status;
  7122. //
  7123. // Make sure the DS is installed
  7124. //
  7125. if ( !LsaDsStateInfo.UseDs ) {
  7126. return FALSE;
  7127. }
  7128. //
  7129. // Once true - always true
  7130. //
  7131. if ( !Result ) {
  7132. Status = GetConfigurationInfo(
  7133. DSCONFIGINFO_FORESTVERSION,
  7134. &Size,
  7135. &ForestBehaviorVersion
  7136. );
  7137. ASSERT( NT_SUCCESS( Status ));
  7138. Result = ( ForestBehaviorVersion >= DS_BEHAVIOR_WIN2003 );
  7139. }
  7140. return Result;
  7141. }
  7142. BOOLEAN
  7143. LsaINoMoreWin2KDomain()
  7144. {
  7145. return LsapDbNoMoreWin2KDomain();
  7146. }
  7147. BOOLEAN
  7148. LsapDbNoMoreWin2KDomain()
  7149. /*++
  7150. Routine Description:
  7151. Determines whether all domain controllers in the current domain have been
  7152. upgraded to Whistler by querying the msDS-Behavior-Version attribute from
  7153. the root domain object in the DS
  7154. Arguments:
  7155. None
  7156. Returns:
  7157. TRUE or FALSE
  7158. --*/
  7159. {
  7160. LONG DomainBehaviorVersion;
  7161. DWORD Size = sizeof( DomainBehaviorVersion );
  7162. static BOOLEAN Result = FALSE;
  7163. NTSTATUS Status;
  7164. //
  7165. // Make sure the DS is installed
  7166. //
  7167. if ( !LsaDsStateInfo.UseDs ) {
  7168. return FALSE;
  7169. }
  7170. //
  7171. // Once true - always true
  7172. //
  7173. if ( !Result ) {
  7174. Status = GetConfigurationInfo(
  7175. DSCONFIGINFO_DOMAINVERSION,
  7176. &Size,
  7177. &DomainBehaviorVersion
  7178. );
  7179. ASSERT( NT_SUCCESS( Status ));
  7180. Result = ( DomainBehaviorVersion >= DS_BEHAVIOR_WIN2003 );
  7181. }
  7182. return Result;
  7183. }
  7184. NTSTATUS
  7185. LsaIIsDomainWithinForest(
  7186. IN UNICODE_STRING * TrustedDomainName,
  7187. OUT BOOL * WithinForest,
  7188. OUT OPTIONAL BOOL * ThisDomain,
  7189. OUT OPTIONAL PSID * TrustedDomainSid,
  7190. OUT OPTIONAL ULONG * TrustDirection,
  7191. OUT OPTIONAL ULONG * TrustType,
  7192. OUT OPTIONAL ULONG * TrustAttributes
  7193. )
  7194. /*++
  7195. Routine Description:
  7196. Figures out whether a given domain name is within our forest
  7197. Arguments:
  7198. TrustedDomainName DNS or Netbios domain name
  7199. WithinForest used to return TRUE if this domain is within forest
  7200. ThisDomain used to return TRUE if TrustedDomainName refers to
  7201. the name of this domain and not some other domain
  7202. in the forest
  7203. TrustedDomainSid used to return SID of the trusted domain
  7204. The following return values are returned if the caller asked for them _and_
  7205. there exists a direct trust relationship with the domain in question.
  7206. The routine will be faster if the caller does not ask for the following parameters
  7207. TrustDirection Direction of the trust
  7208. TrustType Type of the trust
  7209. TrustAttributes Attributes of the trust
  7210. Returns:
  7211. STATUS_SUCCESS was able to determine the result
  7212. STATUS_ error code some error has occurred
  7213. --*/
  7214. {
  7215. NTSTATUS Status;
  7216. PPOLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo = NULL;
  7217. PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation = NULL;
  7218. PSID Sid = NULL;
  7219. PSID MatchSid = NULL;
  7220. ULONG Direction = 0, Type = 0, Attributes = 0;
  7221. *WithinForest = FALSE;
  7222. if ( ThisDomain ) {
  7223. *ThisDomain = FALSE;
  7224. }
  7225. //
  7226. // First quickly check whether the caller specified the name of this domain
  7227. //
  7228. Status = LsapDbQueryInformationPolicy(
  7229. LsapPolicyHandle,
  7230. PolicyDnsDomainInformation,
  7231. ( PLSAPR_POLICY_INFORMATION *)&PolicyDnsDomainInfo
  7232. );
  7233. if ( !NT_SUCCESS( Status )) {
  7234. goto Cleanup;
  7235. }
  7236. if ( LsapCompareDomainNames(
  7237. TrustedDomainName,
  7238. (PUNICODE_STRING)&PolicyDnsDomainInfo->DnsDomainName,
  7239. (PUNICODE_STRING)&PolicyDnsDomainInfo->Name )) {
  7240. *WithinForest = TRUE;
  7241. if ( ThisDomain ) {
  7242. *ThisDomain = TRUE;
  7243. }
  7244. Sid = PolicyDnsDomainInfo->Sid;
  7245. goto Cleanup;
  7246. }
  7247. //
  7248. // First find out if the domain is within our forest. As a side effect,
  7249. // retrieve the SID of the domain
  7250. //
  7251. Status = LsapForestTrustFindMatch(
  7252. RoutingMatchDomainName,
  7253. TrustedDomainName,
  7254. TRUE,
  7255. NULL,
  7256. TrustedDomainSid ? &MatchSid : NULL
  7257. );
  7258. if ( NT_SUCCESS( Status )) {
  7259. *WithinForest = TRUE;
  7260. Sid = MatchSid;
  7261. } else if ( Status == STATUS_NO_MATCH ) {
  7262. *WithinForest = FALSE;
  7263. Status = STATUS_SUCCESS;
  7264. }
  7265. if ( !NT_SUCCESS( Status ) ||
  7266. !*WithinForest ) {
  7267. goto Cleanup;
  7268. }
  7269. //
  7270. // If the caller also asked for the attributes of the trust, look up the
  7271. // domain in the list of directly trusted domains
  7272. //
  7273. if ( TrustDirection ||
  7274. TrustType ||
  7275. TrustAttributes ) {
  7276. Status = LsarQueryTrustedDomainInfoByName(
  7277. LsapPolicyHandle,
  7278. (PLSAPR_UNICODE_STRING)TrustedDomainName,
  7279. TrustedDomainInformationEx,
  7280. (PLSAPR_TRUSTED_DOMAIN_INFO *)&TrustedDomainInformation
  7281. );
  7282. if ( NT_SUCCESS( Status )) {
  7283. Type = TrustedDomainInformation->TrustType;
  7284. Direction = TrustedDomainInformation->TrustDirection;
  7285. Attributes = TrustedDomainInformation->TrustAttributes;
  7286. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  7287. Status = STATUS_SUCCESS;
  7288. }
  7289. }
  7290. Cleanup:
  7291. if ( NT_SUCCESS( Status ) &&
  7292. *WithinForest ) {
  7293. if ( TrustDirection ) {
  7294. *TrustDirection = Direction;
  7295. }
  7296. if ( TrustType ) {
  7297. *TrustType = Type;
  7298. }
  7299. if ( TrustAttributes ) {
  7300. *TrustAttributes = Attributes;
  7301. }
  7302. if ( TrustedDomainSid && Sid ) {
  7303. Status = LsapDuplicateSid(
  7304. TrustedDomainSid,
  7305. Sid
  7306. );
  7307. }
  7308. } else {
  7309. if ( TrustedDomainSid ) {
  7310. *TrustedDomainSid = NULL;
  7311. }
  7312. if ( TrustDirection ) {
  7313. *TrustDirection = 0;
  7314. }
  7315. if ( TrustType ) {
  7316. *TrustType = 0;
  7317. }
  7318. if ( TrustAttributes ) {
  7319. *TrustAttributes = 0;
  7320. }
  7321. }
  7322. MIDL_user_free( MatchSid );
  7323. LsaIFree_LSAPR_POLICY_INFORMATION(
  7324. PolicyDnsDomainInformation,
  7325. ( PLSAPR_POLICY_INFORMATION )PolicyDnsDomainInfo
  7326. );
  7327. LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO(
  7328. TrustedDomainInformationEx,
  7329. (PLSAPR_TRUSTED_DOMAIN_INFO)TrustedDomainInformation
  7330. );
  7331. return Status;
  7332. }
  7333. NTSTATUS
  7334. LsapIsValidDomainSid(
  7335. IN PSID DomainSid
  7336. )
  7337. {
  7338. NTSTATUS Status = STATUS_SUCCESS;
  7339. BYTE TempDomainSid[ SECURITY_MAX_SID_SIZE ];
  7340. DWORD SidLength = sizeof( TempDomainSid );
  7341. if( !RtlValidSid( DomainSid ) ) {
  7342. Status = STATUS_INVALID_SID;
  7343. goto Error;
  7344. }
  7345. if ( FALSE == GetWindowsAccountDomainSid(
  7346. DomainSid,
  7347. ( PSID ) TempDomainSid,
  7348. &SidLength )) {
  7349. DWORD ErrorCode = GetLastError();
  7350. switch( ErrorCode ) {
  7351. case ERROR_INVALID_SID:
  7352. //
  7353. // We have already checked the SID for validity
  7354. //
  7355. ASSERT( FALSE );
  7356. //
  7357. // fall through
  7358. //
  7359. case ERROR_NON_ACCOUNT_SID:
  7360. case ERROR_NON_DOMAIN_SID:
  7361. Status = STATUS_INVALID_SID;
  7362. break;
  7363. case ERROR_INVALID_PARAMETER:
  7364. //
  7365. // What invalid parameter?
  7366. //
  7367. ASSERT( FALSE );
  7368. Status = STATUS_INVALID_PARAMETER;
  7369. break;
  7370. case ERROR_INSUFFICIENT_BUFFER:
  7371. //
  7372. // The buffer we supplied must be enough
  7373. //
  7374. ASSERT( FALSE );
  7375. Status = STATUS_BUFFER_OVERFLOW;
  7376. break;
  7377. default:
  7378. //
  7379. // map the error
  7380. //
  7381. ASSERT( FALSE );
  7382. Status = STATUS_INTERNAL_ERROR;
  7383. break;
  7384. }
  7385. goto Error;
  7386. } else {
  7387. //
  7388. // For domain SIDs, GetWindowsAccountDomainSid returns a SID equal to the one passed in.
  7389. // If the two SIDs are not equal, the SID passed in is not a true domain SID
  7390. //
  7391. if ( !RtlEqualSid(
  7392. ( PSID )DomainSid,
  7393. ( PSID )TempDomainSid )) {
  7394. Status = STATUS_INVALID_SID;
  7395. goto Error;
  7396. }
  7397. }
  7398. Cleanup:
  7399. return Status;
  7400. Error:
  7401. ASSERT( !NT_SUCCESS( Status ));
  7402. goto Cleanup;
  7403. }