Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1233 lines
35 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. trustdom.c
  5. Abstract:
  6. Implementation of the functions to manage the trust link between 2 servers
  7. Author:
  8. Mac McLain (MacM) Feb 10, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include <lsarpc.h>
  16. #include <samrpc.h>
  17. #include <db.h>
  18. #include <lsads.h>
  19. #include <lsasrvmm.h>
  20. #include <lsaisrv.h>
  21. #include <lmcons.h>
  22. #include <cryptdll.h>
  23. #include "trustdom.h"
  24. DWORD
  25. DsRolepSetLsaDnsInformationNoParent(
  26. IN LPWSTR DnsDomainName
  27. )
  28. /*++
  29. Routine Description:
  30. In the case where we are installing as a standalong or root Dc, set the Lsa
  31. POLICY_DNS_DOMAIN_INFORMATION DnsForestName value to point to ourselves.
  32. Arguments:
  33. DnsDomainName - Dns domain path to set
  34. Returns:
  35. ERROR_SUCCESS - Success
  36. --*/
  37. {
  38. NTSTATUS Status = STATUS_SUCCESS;
  39. PPOLICY_DNS_DOMAIN_INFO CurrentDnsInfo;
  40. PLSAPR_POLICY_INFORMATION LsaPolicy;
  41. OBJECT_ATTRIBUTES ObjectAttributes;
  42. HANDLE Policy;
  43. //
  44. // Open our local policy
  45. //
  46. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  47. Status = LsaOpenPolicy( NULL,
  48. &ObjectAttributes,
  49. POLICY_WRITE,
  50. &Policy );
  51. if ( NT_SUCCESS( Status ) ) {
  52. //
  53. // Get the current information
  54. //
  55. Status = LsaQueryInformationPolicy( Policy,
  56. PolicyDnsDomainInformation,
  57. ( PVOID * )&LsaPolicy );
  58. if ( NT_SUCCESS( Status ) ) {
  59. //
  60. // Add in the new...
  61. //
  62. CurrentDnsInfo = (PPOLICY_DNS_DOMAIN_INFO)LsaPolicy;
  63. RtlInitUnicodeString( &CurrentDnsInfo->DnsForestName, DnsDomainName );
  64. DsRolepLogPrint(( DEB_TRACE, "Configuring DnsForestName to %ws\n",
  65. DnsDomainName ));
  66. //
  67. // And write it out..
  68. //
  69. Status = LsaSetInformationPolicy( Policy,
  70. PolicyDnsDomainInformation,
  71. LsaPolicy );
  72. //
  73. // Don't want to actually free the passed in buffer
  74. //
  75. RtlZeroMemory( &CurrentDnsInfo->DnsForestName, sizeof( UNICODE_STRING ) );
  76. LsaIFree_LSAPR_POLICY_INFORMATION( PolicyDnsDomainInformation, LsaPolicy );
  77. }
  78. LsaClose( Policy );
  79. }
  80. DsRolepLogOnFailure( Status,
  81. DsRolepLogPrint(( DEB_TRACE,
  82. "DsRolepSetLsaDnsInformationNoParent failed with 0x%lx\n",
  83. Status )) );
  84. return( RtlNtStatusToDosError( Status ) );
  85. }
  86. DWORD
  87. DsRolepCreateTrustedDomainObjects(
  88. IN HANDLE CallerToken,
  89. IN LPWSTR ParentDc,
  90. IN LPWSTR DnsDomainName,
  91. IN PPOLICY_DNS_DOMAIN_INFO ParentDnsDomainInfo,
  92. IN ULONG Options
  93. )
  94. /*++
  95. Routine Description:
  96. Creates the trusted domain object on the domains if they should exist and sets the
  97. Lsa POLICY_DNS_DOMAIN_INFORMATION DnsTree value to either the value of our parent in
  98. a parent/child install, or as the root otherwise.
  99. Arguments:
  100. ParentDc - Optional. Name of the parent Dc
  101. DnsDomainName - Dns name of the domain we're installing into
  102. ParentDnsDomainInfo - DNS domain information obtained from the parent
  103. Options - Options that dictate what steps are taken
  104. Returns:
  105. ERROR_SUCCESS - Success
  106. ERROR_INVALID_PARAMETER - A bad results pointer was given
  107. --*/
  108. {
  109. DWORD Win32Err = ERROR_SUCCESS;
  110. NTSTATUS Status = STATUS_SUCCESS;
  111. UNICODE_STRING ParentServer;
  112. HANDLE LocalPolicy = NULL , ParentPolicy = NULL;
  113. PPOLICY_DNS_DOMAIN_INFO LocalDnsInfo = NULL;
  114. OBJECT_ATTRIBUTES ObjectAttributes;
  115. LSA_HANDLE ParentTrustedDomain = NULL;
  116. WCHAR GeneratedPassword[ PWLEN + 1 ];
  117. ULONG Length = PWLEN;
  118. LSA_AUTH_INFORMATION AuthData;
  119. TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx;
  120. DSROLEP_CURRENT_OP1( DSROLEEVT_SET_LSA_FROM, ParentDc );
  121. //
  122. // Make the Lsa think that we're initialized
  123. //
  124. Status = LsapDsInitializeDsStateInfo( LsapDsDsSetup );
  125. if ( !NT_SUCCESS( Status ) ) {
  126. DsRolepLogPrint(( DEB_TRACE,
  127. "Failed to convince Lsa to reinitialize: 0x%lx\n",
  128. Status ));
  129. return( RtlNtStatusToDosError( Status ) );
  130. }
  131. //
  132. // Prepare the Auth Info
  133. //
  134. RtlZeroMemory( &AuthInfoEx, sizeof(AuthInfoEx) );
  135. RtlZeroMemory( &AuthData, sizeof(AuthData) );
  136. RtlZeroMemory( &GeneratedPassword, sizeof(GeneratedPassword) );
  137. Win32Err = DsRolepGenerateRandomPassword( Length,
  138. GeneratedPassword );
  139. if ( ERROR_SUCCESS == Win32Err ) {
  140. Status = NtQuerySystemTime( &AuthData.LastUpdateTime );
  141. if ( NT_SUCCESS( Status ) ) {
  142. AuthData.AuthType = TRUST_AUTH_TYPE_CLEAR;
  143. AuthData.AuthInfoLength = Length;
  144. AuthData.AuthInfo = (PUCHAR)GeneratedPassword;
  145. AuthInfoEx.IncomingAuthInfos = 1;
  146. AuthInfoEx.IncomingAuthenticationInformation = &AuthData;
  147. AuthInfoEx.IncomingPreviousAuthenticationInformation = NULL;
  148. AuthInfoEx.OutgoingAuthInfos = 1;
  149. AuthInfoEx.OutgoingAuthenticationInformation = &AuthData;
  150. AuthInfoEx.OutgoingPreviousAuthenticationInformation = NULL;
  151. }
  152. } else {
  153. DsRolepLogPrint(( DEB_ERROR,
  154. "Failed to generate a trust password: %lu\n",
  155. Win32Err ));
  156. Status = STATUS_UNSUCCESSFUL;
  157. }
  158. if ( NT_SUCCESS( Status ) ) {
  159. //
  160. // Open both lsas
  161. //
  162. RtlInitUnicodeString( &ParentServer, ParentDc );
  163. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  164. Status = ImpLsaOpenPolicy( CallerToken,
  165. &ParentServer,
  166. &ObjectAttributes,
  167. POLICY_TRUST_ADMIN | POLICY_VIEW_LOCAL_INFORMATION,
  168. &ParentPolicy
  169. );
  170. if ( NT_SUCCESS( Status ) ) {
  171. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  172. Status = LsaOpenPolicy( NULL,
  173. &ObjectAttributes,
  174. POLICY_TRUST_ADMIN | POLICY_VIEW_LOCAL_INFORMATION,
  175. &LocalPolicy );
  176. } else {
  177. DsRolepLogPrint(( DEB_TRACE,
  178. "OpenPolicy on %ws failed with 0x%lx\n",
  179. ParentDc,
  180. Status ));
  181. }
  182. }
  183. //
  184. // Get our local dns domain information
  185. //
  186. if ( NT_SUCCESS( Status ) ) {
  187. Status = LsaQueryInformationPolicy( LocalPolicy,
  188. PolicyDnsDomainInformation,
  189. &LocalDnsInfo );
  190. }
  191. //
  192. // Now, create the trusted domain objects
  193. //
  194. if ( NT_SUCCESS( Status ) ) {
  195. DSROLEP_CURRENT_OP1( DSROLEEVT_CREATE_PARENT_TRUST,
  196. ParentDnsDomainInfo->DnsDomainName.Buffer );
  197. if ( !FLAG_ON( Options, DSROLE_DC_PARENT_TRUST_EXISTS ) ||
  198. FLAG_ON( Options, DSROLE_DC_CREATE_TRUST_AS_REQUIRED ) ) {
  199. DsRoleDebugOut(( DEB_TRACE_DS, "Creating trust object ( %lu ) on %ws\n",
  200. Options,
  201. ParentDc ));
  202. Status = DsRolepCreateParentTrustObject( CallerToken,
  203. ParentPolicy,
  204. LocalDnsInfo,
  205. Options,
  206. &AuthInfoEx,
  207. &ParentTrustedDomain );
  208. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  209. DSROLEP_FAIL2( RtlNtStatusToDosError( Status ),
  210. DSROLERES_PARENT_TRUST_EXISTS, ParentDc, DnsDomainName );
  211. } else {
  212. DSROLEP_FAIL2( RtlNtStatusToDosError( Status ),
  213. DSROLERES_PARENT_TRUST_FAIL, DnsDomainName, ParentDc );
  214. }
  215. }
  216. //
  217. // Now the child
  218. //
  219. if ( NT_SUCCESS( Status ) ) {
  220. DSROLEP_CURRENT_OP1( DSROLEEVT_CREATE_TRUST,
  221. LocalDnsInfo->DnsDomainName.Buffer );
  222. Status = DsRolepCreateChildTrustObject( CallerToken,
  223. ParentPolicy,
  224. LocalPolicy,
  225. ParentDnsDomainInfo,
  226. LocalDnsInfo,
  227. &AuthInfoEx,
  228. Options );
  229. if ( !NT_SUCCESS( Status ) ) {
  230. DsRolepLogPrint(( DEB_TRACE,
  231. "DsRolepCreateChildTrustObject failed: 0x%lx\n",
  232. Status ));
  233. }
  234. //
  235. // If we created the parent object, we had better try and delete it now. Note that
  236. // it isn't fatal if we can't
  237. //
  238. if ( !NT_SUCCESS( Status ) && !FLAG_ON( Options, DSROLE_DC_PARENT_TRUST_EXISTS ) ) {
  239. NTSTATUS Status2;
  240. Status2 = ImpLsaDelete( CallerToken, ParentTrustedDomain );
  241. if ( !NT_SUCCESS( Status2 ) ) {
  242. DsRolepLogPrint(( DEB_TRACE,
  243. "LsaDelete of ParentTrustedDomain failed: 0x%lx\n",
  244. Status2 ));
  245. }
  246. } else {
  247. if ( ParentTrustedDomain ) {
  248. ImpLsaClose( CallerToken, ParentTrustedDomain );
  249. }
  250. }
  251. }
  252. }
  253. LsaFreeMemory( LocalDnsInfo );
  254. if ( LocalPolicy ) {
  255. LsaClose( LocalPolicy );
  256. }
  257. if ( ParentPolicy ) {
  258. ImpLsaClose( CallerToken, ParentPolicy );
  259. }
  260. // Don't leave the information in the pagefile
  261. RtlZeroMemory( &AuthInfoEx, sizeof(AuthInfoEx) );
  262. RtlZeroMemory( &AuthData, sizeof(AuthData) );
  263. RtlZeroMemory( &GeneratedPassword, sizeof(GeneratedPassword) );
  264. //
  265. // We won't bother cleaning up any of the DnsTreeInformation we set on the local machine in
  266. // the failure case, since it won't hurt anything to have it here.
  267. //
  268. return( RtlNtStatusToDosError( Status ) );
  269. }
  270. NTSTATUS
  271. DsRolepHandlePreExistingTrustObject(
  272. IN HANDLE Token, OPTIONAL
  273. IN LSA_HANDLE Lsa,
  274. TRUSTED_DOMAIN_INFORMATION_EX *pTDIEx,
  275. TRUSTED_DOMAIN_AUTH_INFORMATION * pAuthInfoEx,
  276. OUT PLSA_HANDLE TrustedDomainHandle
  277. )
  278. /*++
  279. This routine does the appropriate handling for the case of the pre existing
  280. trust object ( ie opening the object, checking if it were the right one
  281. and then deleting it if required
  282. Paramters
  283. Token -- token to impersonate if necessary (used when talking to remote
  284. server)
  285. Lsa Handle to the LSA
  286. pTDIEx the TDO that is being created that recieved the object name collision error
  287. Return Values
  288. STATUS_SUCCESS
  289. Other Error Codes
  290. --*/
  291. {
  292. NTSTATUS Status = STATUS_SUCCESS;
  293. LSA_HANDLE TrustedDomain = 0;
  294. *TrustedDomainHandle = 0;
  295. // We should have something to go on
  296. ASSERT( pTDIEx->Sid
  297. || (pTDIEx->FlatName.Length > 0)
  298. || (pTDIEx->Name.Length > 0) );
  299. //
  300. // We have a conflict, either by name or by sid.
  301. // Try to open by sid, dns domain name, and then flat domain name
  302. //
  303. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  304. if ( (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  305. && pTDIEx->Sid ) {
  306. if ( ARGUMENT_PRESENT(Token) ) {
  307. Status = ImpLsaOpenTrustedDomain( Token,
  308. Lsa,
  309. pTDIEx->Sid,
  310. DELETE,
  311. ( PVOID * )&TrustedDomain);
  312. } else {
  313. Status = LsaOpenTrustedDomain( Lsa,
  314. pTDIEx->Sid,
  315. DELETE,
  316. ( PVOID * )&TrustedDomain);
  317. }
  318. if ( !NT_SUCCESS( Status ) ) {
  319. DsRolepLogPrint(( DEB_WARN,
  320. "Failed to find trust object by sid: 0x%lx\n",
  321. Status ));
  322. if ( STATUS_NO_SUCH_DOMAIN == Status ) {
  323. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  324. }
  325. }
  326. }
  327. if ( (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  328. && pTDIEx->Name.Length > 0 ) {
  329. //
  330. // Couldn't find by sid -- try dns name
  331. //
  332. if ( ARGUMENT_PRESENT(Token) ) {
  333. Status = ImpLsaOpenTrustedDomainByName( Token,
  334. Lsa,
  335. &pTDIEx->Name,
  336. DELETE,
  337. ( PVOID * ) &TrustedDomain );
  338. } else {
  339. Status = LsaOpenTrustedDomainByName( Lsa,
  340. &pTDIEx->Name,
  341. DELETE,
  342. ( PVOID * ) &TrustedDomain );
  343. }
  344. if ( !NT_SUCCESS( Status ) ) {
  345. WCHAR *BufpTDIEx = NULL;
  346. DsRolepUnicodestringtowstr( BufpTDIEx, pTDIEx->Name )
  347. if (BufpTDIEx) {
  348. DsRolepLogPrint(( DEB_WARN,
  349. "Failed to find trust object for %ws: 0x%lx\n",
  350. BufpTDIEx,
  351. Status ));
  352. free(BufpTDIEx);
  353. }
  354. }
  355. }
  356. if ( (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  357. && pTDIEx->FlatName.Length > 0 ) {
  358. //
  359. // Couldn't find by dns name -- try flat name
  360. //
  361. if ( ARGUMENT_PRESENT(Token) ) {
  362. Status = ImpLsaOpenTrustedDomainByName( Token,
  363. Lsa,
  364. &pTDIEx->FlatName,
  365. DELETE,
  366. ( PVOID * )&TrustedDomain );
  367. } else {
  368. Status = LsaOpenTrustedDomainByName( Lsa,
  369. &pTDIEx->FlatName,
  370. DELETE,
  371. ( PVOID * )&TrustedDomain );
  372. }
  373. if ( !NT_SUCCESS( Status ) ) {
  374. WCHAR *BufpTDIEx = NULL;
  375. DsRolepUnicodestringtowstr( BufpTDIEx, pTDIEx->FlatName )
  376. if (BufpTDIEx) {
  377. DsRolepLogPrint(( DEB_WARN,
  378. "Failed to find trust object for %ws: 0x%lx\n",
  379. BufpTDIEx,
  380. Status ));
  381. free(BufpTDIEx);
  382. }
  383. }
  384. }
  385. if ( NT_SUCCESS( Status ) ) {
  386. //
  387. // We found it
  388. //
  389. ASSERT( 0 != TrustedDomain );
  390. if ( ARGUMENT_PRESENT(Token) ) {
  391. Status = ImpLsaDelete( Token, TrustedDomain );
  392. } else {
  393. Status = LsaDelete( TrustedDomain );
  394. }
  395. if ( NT_SUCCESS( Status ) ) {
  396. //
  397. // Raise an event that we had deleted an existing trust object
  398. //
  399. SpmpReportEvent( TRUE,
  400. EVENTLOG_WARNING_TYPE,
  401. DSROLERES_INCOMPATIBLE_TRUST,
  402. 0,
  403. sizeof( ULONG ),
  404. &Status,
  405. 1,
  406. pTDIEx->Name.Buffer );
  407. DSROLEP_SET_NON_FATAL_ERROR( 0 );
  408. } else {
  409. DsRolepLogPrint(( DEB_WARN,
  410. "Failed to delete trust object: 0x%lx\n",
  411. Status ));
  412. }
  413. } else {
  414. DsRolepLogPrint(( DEB_WARN,
  415. "Couldn't find existing trust object: 0x%lx\n",
  416. Status ));
  417. }
  418. //
  419. // At this point, we tried our best to remove the offending object
  420. // Retry the create
  421. //
  422. Status = STATUS_SUCCESS;
  423. DsRolepLogPrint(( DEB_TRACE, "Attempting to recreate trust object\n" ));
  424. //
  425. // Now, let us go ahead and recreate the trust object on the
  426. // parent
  427. //
  428. if ( ARGUMENT_PRESENT(Token) ) {
  429. Status = ImpLsaCreateTrustedDomainEx( Token,
  430. Lsa,
  431. pTDIEx,
  432. pAuthInfoEx,
  433. DELETE, // the only thing we do with
  434. // this handle is delete on
  435. // failure
  436. &TrustedDomain );
  437. } else {
  438. Status = LsaCreateTrustedDomainEx( Lsa,
  439. pTDIEx,
  440. pAuthInfoEx,
  441. DELETE, // the only thing we do with
  442. // this handle is delete on
  443. // failure
  444. &TrustedDomain );
  445. }
  446. if ( !NT_SUCCESS( Status ) ) {
  447. //
  448. // We want to capture and examine these cases
  449. //
  450. WCHAR *BufpTDIEx = NULL;
  451. ASSERT( NT_SUCCESS( Status ) );
  452. DsRolepUnicodestringtowstr( BufpTDIEx, pTDIEx->Name )
  453. if (BufpTDIEx) {
  454. DsRolepLogPrint(( DEB_TRACE,
  455. "Second Trust creation"
  456. "with %ws failed with 0x%lx\n",
  457. BufpTDIEx,
  458. Status ));
  459. free(BufpTDIEx);
  460. }
  461. }
  462. if (NT_SUCCESS(Status))
  463. {
  464. *TrustedDomainHandle = TrustedDomain;
  465. }
  466. else
  467. {
  468. ASSERT(!TrustedDomain);
  469. }
  470. return (Status);
  471. }
  472. NTSTATUS
  473. DsRolepCreateParentTrustObject(
  474. IN HANDLE CallerToken,
  475. IN LSA_HANDLE ParentLsa,
  476. IN PPOLICY_DNS_DOMAIN_INFO ChildDnsInfo,
  477. IN ULONG Options,
  478. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx,
  479. OUT PLSA_HANDLE TrustedDomainHandle
  480. )
  481. /*++
  482. Routine Description:
  483. Creates the trusted domain object on the parent domain. If the object does not exist,
  484. it will create the object and initialize it with a random password
  485. Arguments:
  486. CallerToken - token to impersonate when talking to remote server
  487. ParentLsa - Handle to the Lsa on the parent Dc
  488. ChildDnsInfo - POLICY_DNS_DOMAIN_INFORMAITON from ourself
  489. Options - Options that dictate what steps are taken
  490. TrustedDomainHandle - Where the trusted domain handle is returned
  491. Returns:
  492. ERROR_SUCCESS - Success
  493. ERROR_INVALID_PARAMETER - A bad results pointer was given
  494. --*/
  495. {
  496. NTSTATUS Status = STATUS_SUCCESS;
  497. WCHAR GeneratedPassword[ PWLEN + 1 ];
  498. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  499. LSA_AUTH_INFORMATION AuthData;
  500. PTRUSTED_DOMAIN_INFORMATION_EX TrustInfoEx = NULL;
  501. LSA_HANDLE TrustedDomain;
  502. LARGE_INTEGER Time;
  503. ULONG Seed, Length = PWLEN, i, Win32Err;
  504. PSID OpenSid = NULL;
  505. BOOLEAN DeleteExistingTrust = FALSE;
  506. RtlCopyMemory( &TDIEx.Name, &ChildDnsInfo->DnsDomainName,
  507. sizeof( UNICODE_STRING ) );
  508. RtlCopyMemory( &TDIEx.FlatName, &ChildDnsInfo->Name,
  509. sizeof( UNICODE_STRING ) );
  510. TDIEx.Sid = ChildDnsInfo->Sid;
  511. if ( TDIEx.Name.Length &&
  512. TDIEx.Name.Buffer[ ( TDIEx.Name.Length - 1 ) / sizeof(WCHAR)] == L'.' ) {
  513. TDIEx.Name.Buffer[ ( TDIEx.Name.Length - 1 ) / sizeof(WCHAR)] = UNICODE_NULL;
  514. TDIEx.Name.Length -= sizeof(WCHAR);
  515. }
  516. TDIEx.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  517. TDIEx.TrustType = TRUST_TYPE_UPLEVEL;
  518. TDIEx.TrustAttributes = 0;
  519. {
  520. WCHAR *BufpTDIEx = NULL;
  521. DsRolepLogPrint(( DEB_TRACE, "Creating trusted domain object on parent\n" ));
  522. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.Name );
  523. if (BufpTDIEx) {
  524. DsRolepLogPrint(( DEB_TRACE,
  525. "\tDnsDomain: %ws\n",
  526. BufpTDIEx,
  527. Status ));
  528. free(BufpTDIEx);
  529. }
  530. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.FlatName );
  531. if (BufpTDIEx) {
  532. DsRolepLogPrint(( DEB_TRACE,
  533. "\tFlat name: %ws\n",
  534. BufpTDIEx,
  535. Status ));
  536. free(BufpTDIEx);
  537. }
  538. DsRolepLogPrint(( DEB_TRACE, "\tDirection: %lu\n", TDIEx.TrustDirection ));
  539. DsRolepLogPrint(( DEB_TRACE, "\tType: %lu\n", TDIEx.TrustType ));
  540. DsRolepLogPrint(( DEB_TRACE, "\tAttributes: 0x%lx\n", TDIEx.TrustAttributes ));
  541. }
  542. Status = ImpLsaCreateTrustedDomainEx( CallerToken,
  543. ParentLsa,
  544. &TDIEx,
  545. AuthInfoEx,
  546. DELETE, // we may have to delete on
  547. // rollback
  548. &TrustedDomain );
  549. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  550. DsRolepLogPrint(( DEB_TRACE, "Parent trust object already exists on parent\n" ));
  551. Status = DsRolepHandlePreExistingTrustObject(
  552. CallerToken,
  553. ParentLsa,
  554. &TDIEx,
  555. AuthInfoEx,
  556. &TrustedDomain
  557. );
  558. } else if ( Status != STATUS_SUCCESS ) {
  559. WCHAR *BufpTDIEx = NULL;
  560. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.Name );
  561. if (BufpTDIEx) {
  562. DsRolepLogPrint(( DEB_TRACE,
  563. "Parent LsaCreateTrustedDomainEx on %ws failed with 0x%lx\n",
  564. BufpTDIEx,
  565. Status ));
  566. free(BufpTDIEx);
  567. }
  568. }
  569. if ( NT_SUCCESS( Status ) ) {
  570. *TrustedDomainHandle = TrustedDomain;
  571. }
  572. return( Status );
  573. }
  574. NTSTATUS
  575. DsRolepCreateChildTrustObject(
  576. IN HANDLE CallerToken,
  577. IN LSA_HANDLE ParentLsa,
  578. IN LSA_HANDLE ChildLsa,
  579. IN PPOLICY_DNS_DOMAIN_INFO ParentDnsInfo,
  580. IN PPOLICY_DNS_DOMAIN_INFO ChildDnsInfo,
  581. IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx,
  582. IN ULONG Options
  583. )
  584. /*++
  585. Routine Description:
  586. Creates the trusted domain object on the child domain. It does this by reading the
  587. auth info stored on the parent object, swapping its order, and writing it on the child
  588. object
  589. Arguments:
  590. ParentLsa - Handle to the Lsa on the parent Dc
  591. ChildLsa - Handle to our local Lsa
  592. ParentDnsInfo - POLICY_DNS_DOMAIN_INFORMATION from our parent Dc
  593. ChildDnsInfo - POLICY_DNS_DOMAIN_INFORMAITON from ourself
  594. Options - Options that dictate what steps are taken
  595. Returns:
  596. ERROR_SUCCESS - Success
  597. ERROR_INVALID_PARAMETER - A bad results pointer was given
  598. --*/
  599. {
  600. NTSTATUS Status = STATUS_SUCCESS, SecondaryStatus;
  601. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  602. PTRUSTED_DOMAIN_INFORMATION_EX ParentEx;
  603. PTRUSTED_DOMAIN_AUTH_INFORMATION ParentAuthData;
  604. LSA_HANDLE TrustedDomain;
  605. UNICODE_STRING ChildDnsName;
  606. //
  607. // Basically, we'll create a trusted domain object with no auth data, and then pull over the
  608. // auth data from our parent.
  609. //
  610. RtlCopyMemory( &TDIEx.Name, &ParentDnsInfo->DnsDomainName,
  611. sizeof( UNICODE_STRING ) );
  612. RtlCopyMemory( &TDIEx.FlatName, &ParentDnsInfo->Name,
  613. sizeof( UNICODE_STRING ) );
  614. TDIEx.Sid = ParentDnsInfo->Sid;
  615. TDIEx.TrustAttributes = 0;
  616. //
  617. // Note that if the parent object exists, we'll want to read it's properties, and
  618. // set our trust up accordingly
  619. //
  620. if ( FLAG_ON( Options, DSROLE_DC_PARENT_TRUST_EXISTS ) ) {
  621. Status = ImpLsaQueryTrustedDomainInfoByName( CallerToken,
  622. ParentLsa,
  623. &ChildDnsInfo->DnsDomainName,
  624. TrustedDomainInformationEx,
  625. ( PVOID * )&ParentEx );
  626. if ( !NT_SUCCESS( Status ) ) {
  627. WCHAR *BufDnsDomainName = NULL;
  628. DsRolepUnicodestringtowstr( BufDnsDomainName, ChildDnsInfo->DnsDomainName );
  629. if (BufDnsDomainName) {
  630. DsRolepLogPrint(( DEB_TRACE,
  631. "Failed to read trust info from parent for %ws: 0x%lx\n",
  632. BufDnsDomainName,
  633. Status ));
  634. free(BufDnsDomainName);
  635. }
  636. }
  637. if ( NT_SUCCESS( Status ) ) {
  638. //
  639. // Make sure that the trust on the parent object is correct
  640. //
  641. if ( ChildDnsInfo->Sid == NULL ||
  642. ParentEx->Sid == NULL ||
  643. !RtlEqualSid( ChildDnsInfo->Sid, ParentEx->Sid ) ||
  644. RtlEqualUnicodeString( &ChildDnsInfo->Name, &ParentEx->Name, TRUE ) ) {
  645. Status = STATUS_DOMAIN_TRUST_INCONSISTENT;
  646. }
  647. }
  648. if ( NT_SUCCESS( Status ) ) {
  649. TDIEx.TrustDirection = 0;
  650. TDIEx.TrustType = 0;
  651. if ( FLAG_ON( ParentEx->TrustDirection, TRUST_DIRECTION_INBOUND ) ) {
  652. TDIEx.TrustDirection |= TRUST_DIRECTION_OUTBOUND;
  653. }
  654. if ( FLAG_ON( ParentEx->TrustDirection, TRUST_DIRECTION_OUTBOUND ) ) {
  655. TDIEx.TrustDirection |= TRUST_DIRECTION_INBOUND;
  656. }
  657. TDIEx.TrustType = ParentEx->TrustType;
  658. LsaFreeMemory( ParentEx );
  659. }
  660. DSROLEP_FAIL1( RtlNtStatusToDosError( Status ),
  661. DSROLERES_NO_PARENT_TRUST, ParentDnsInfo->DnsDomainName.Buffer );
  662. } else {
  663. TDIEx.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  664. TDIEx.TrustType = TRUST_TYPE_UPLEVEL;
  665. RtlCopyMemory( &ChildDnsName, &ChildDnsInfo->DnsDomainName, sizeof( UNICODE_STRING ) );
  666. if ( ChildDnsName.Buffer[ (ChildDnsName.Length - 1) / sizeof(WCHAR)] == L'.' ) {
  667. ChildDnsName.Buffer[ (ChildDnsName.Length - 1) / sizeof(WCHAR)] = UNICODE_NULL;
  668. ChildDnsName.Length -= sizeof(WCHAR);
  669. }
  670. }
  671. if ( NT_SUCCESS( Status ) ) {
  672. {
  673. WCHAR *BufpTDIEx = NULL;
  674. DsRolepLogPrint(( DEB_TRACE, "Creating trusted domain object on child\n" ));
  675. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.Name );
  676. if (BufpTDIEx) {
  677. DsRolepLogPrint(( DEB_TRACE,
  678. "\tDnsDomain: %ws\n",
  679. BufpTDIEx,
  680. Status ));
  681. free(BufpTDIEx);
  682. }
  683. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.FlatName );
  684. if (BufpTDIEx) {
  685. DsRolepLogPrint(( DEB_TRACE,
  686. "\tFlat name: %ws\n",
  687. BufpTDIEx,
  688. Status ));
  689. free(BufpTDIEx);
  690. }
  691. DsRolepLogPrint(( DEB_TRACE, "\tDirection: %lu\n", TDIEx.TrustDirection ));
  692. DsRolepLogPrint(( DEB_TRACE, "\tType: %lu\n", TDIEx.TrustType ));
  693. DsRolepLogPrint(( DEB_TRACE, "\tAttributes: 0x%lx\n", TDIEx.TrustAttributes ));
  694. }
  695. Status = LsaCreateTrustedDomainEx( ChildLsa,
  696. &TDIEx,
  697. AuthInfoEx,
  698. 0, // no access necessary
  699. &TrustedDomain );
  700. }
  701. if (STATUS_OBJECT_NAME_COLLISION==Status)
  702. {
  703. //
  704. // The object might actually exist, in cases we are upgrading from NT4 etc
  705. //
  706. DsRolepLogPrint(( DEB_TRACE, "Child domain trust object already exists on child\n" ));
  707. Status = DsRolepHandlePreExistingTrustObject(
  708. NULL,
  709. ChildLsa,
  710. &TDIEx,
  711. AuthInfoEx,
  712. &TrustedDomain
  713. );
  714. }
  715. if ( !NT_SUCCESS( Status ) ) {
  716. WCHAR *BufpTDIEx = NULL;
  717. DsRolepUnicodestringtowstr( BufpTDIEx, TDIEx.Name );
  718. if (BufpTDIEx) {
  719. DsRolepLogPrint(( DEB_TRACE,
  720. "Child LsaCreateTrustedDomainEx on %ws failed with 0x%lx\n",
  721. BufpTDIEx,
  722. Status ));
  723. free(BufpTDIEx);
  724. }
  725. DSROLEP_FAIL1( RtlNtStatusToDosError( Status ),
  726. DSROLERES_NO_PARENT_TRUST, ParentDnsInfo->DnsDomainName.Buffer );
  727. } else {
  728. //
  729. // We should have a trusted domain object
  730. //
  731. ASSERT( 0 != TrustedDomain );
  732. if ( TrustedDomain ) {
  733. LsaClose( TrustedDomain );
  734. }
  735. }
  736. return( Status );
  737. }
  738. DWORD
  739. DsRolepRemoveTrustedDomainObjects(
  740. IN HANDLE CallerToken,
  741. IN LPWSTR ParentDc,
  742. IN PPOLICY_DNS_DOMAIN_INFO ParentDnsDomainInfo,
  743. IN ULONG Options
  744. )
  745. /*++
  746. Routine Description:
  747. This function will remove the trusted domain objects as a link is being torn down.
  748. It will determine who the trust is with, and remove the local trust to that object.
  749. Optionally, it will also remove the trust from the parent
  750. Arguments:
  751. ParentDc - Optional name of a Dc on our parent
  752. ParentDnsDomainInfo - DNS Domain information from the parent
  753. Options - Whether to remove the parents object or not
  754. Returns:
  755. ERROR_SUCCESS - Success
  756. ERROR_INVALID_PARAMETER - A bad option was provided
  757. --*/
  758. {
  759. NTSTATUS Status = STATUS_SUCCESS;
  760. UNICODE_STRING ParentServer;
  761. HANDLE LocalPolicy = NULL , ParentPolicy = NULL;
  762. HANDLE Trust;
  763. PPOLICY_DNS_DOMAIN_INFO LocalDnsInfo = NULL;
  764. OBJECT_ATTRIBUTES ObjectAttributes;
  765. DSROLEP_CURRENT_OP0( DSROLEEVT_DELETE_TRUST );
  766. //
  767. // If there is no parent Dc, there is no trust...
  768. //
  769. if ( ParentDc == NULL ) {
  770. return( ERROR_SUCCESS );
  771. }
  772. //
  773. // Open both lsas
  774. //
  775. RtlInitUnicodeString( &ParentServer, ParentDc );
  776. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  777. Status = ImpLsaOpenPolicy( CallerToken,
  778. &ParentServer,
  779. &ObjectAttributes,
  780. MAXIMUM_ALLOWED,
  781. &ParentPolicy );
  782. if ( NT_SUCCESS( Status ) ) {
  783. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  784. Status = LsaOpenPolicy( NULL,
  785. &ObjectAttributes,
  786. MAXIMUM_ALLOWED,
  787. &LocalPolicy );
  788. } else {
  789. DsRolepLogPrint(( DEB_TRACE,
  790. "OpenPolicy on %ws failed with 0x%lx\n",
  791. ParentDc,
  792. Status ));
  793. }
  794. //
  795. // Get the DnsTree information from the local machine
  796. //
  797. if ( NT_SUCCESS( Status ) ) {
  798. Status = LsaQueryInformationPolicy( LocalPolicy,
  799. PolicyDnsDomainInformation,
  800. &LocalDnsInfo );
  801. }
  802. //
  803. // Now, open the parent trusted domain object
  804. //
  805. if ( NT_SUCCESS( Status ) && FLAG_ON( Options, DSROLE_DC_DELETE_PARENT_TRUST ) ) {
  806. Status = ImpLsaOpenTrustedDomain( CallerToken,
  807. ParentPolicy,
  808. LocalDnsInfo->Sid,
  809. DELETE,
  810. &Trust );
  811. if ( NT_SUCCESS( Status ) ) {
  812. Status = ImpLsaDelete( CallerToken, Trust );
  813. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  814. Status = STATUS_SUCCESS;
  815. }
  816. }
  817. //
  818. // Now, the local one
  819. //
  820. if ( NT_SUCCESS( Status ) ) {
  821. Status = LsaOpenTrustedDomain( LocalPolicy,
  822. ParentDnsDomainInfo->Sid,
  823. DELETE,
  824. &Trust );
  825. if ( NT_SUCCESS( Status ) ) {
  826. Status = LsaDelete( Trust );
  827. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  828. Status = STATUS_SUCCESS;
  829. }
  830. }
  831. //
  832. // Cleanup
  833. //
  834. LsaFreeMemory( LocalDnsInfo );
  835. if ( LocalPolicy ) {
  836. LsaClose( LocalPolicy );
  837. }
  838. if ( ParentPolicy ) {
  839. ImpLsaClose( CallerToken, ParentPolicy );
  840. }
  841. return( RtlNtStatusToDosError( Status ) );
  842. }
  843. DWORD
  844. DsRolepDeleteParentTrustObject(
  845. IN HANDLE CallerToken,
  846. IN LPWSTR ParentDc,
  847. IN PPOLICY_DNS_DOMAIN_INFO ChildDomainInfo
  848. )
  849. /*++
  850. Routine Description:
  851. Deletes the trusted domain object on the parent domain.
  852. Arguments:
  853. ParentDc - Name of a Dc in the parent domain to connect to
  854. ChildDnsInfo - POLICY_DNS_DOMAIN_INFORMAITON from ourself
  855. Returns:
  856. ERROR_SUCCESS - Success
  857. ERROR_INVALID_PARAMETER - A bad results pointer was given
  858. --*/
  859. {
  860. NTSTATUS Status = STATUS_SUCCESS;
  861. UNICODE_STRING ParentServer;
  862. HANDLE ParentPolicy = NULL;
  863. OBJECT_ATTRIBUTES ObjectAttributes;
  864. LSA_HANDLE ParentTrustedDomain, TrustedDomain;
  865. RtlInitUnicodeString( &ParentServer, ParentDc );
  866. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  867. Status = ImpLsaOpenPolicy( CallerToken,
  868. &ParentServer,
  869. &ObjectAttributes,
  870. POLICY_TRUST_ADMIN|POLICY_VIEW_LOCAL_INFORMATION,
  871. &ParentPolicy );
  872. if ( NT_SUCCESS( Status ) ) {
  873. Status = ImpLsaOpenTrustedDomain( CallerToken,
  874. ParentPolicy,
  875. ChildDomainInfo->Sid,
  876. DELETE,
  877. &TrustedDomain );
  878. if ( NT_SUCCESS( Status ) ) {
  879. Status = ImpLsaDelete( CallerToken, TrustedDomain );
  880. if ( !NT_SUCCESS( Status ) ) {
  881. ImpLsaClose( CallerToken, TrustedDomain );
  882. }
  883. }
  884. ImpLsaClose( CallerToken, ParentPolicy );
  885. }
  886. return( RtlNtStatusToDosError( Status ) );
  887. }