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.

5654 lines
185 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1998 - 2001
  4. Module Name:
  5. trust.cxx
  6. Abstract:
  7. Handles the various functions for managing domain trust.
  8. --*/
  9. #include "pch.h"
  10. #pragma hdrstop
  11. #include <netdom.h>
  12. VOID
  13. NetDompFreeDomInfo(
  14. IN OUT PND5_TRUST_INFO TrustInfo
  15. )
  16. {
  17. if ( TrustInfo->Connected ) {
  18. LOG_VERBOSE(( MSG_VERBOSE_DELETE_SESSION, TrustInfo->Server ));
  19. NetpManageIPCConnect( TrustInfo->Server,
  20. NULL,
  21. NULL,
  22. NETSETUPP_DISCONNECT_IPC );
  23. }
  24. NetApiBufferFree( TrustInfo->Server );
  25. if (TrustInfo->BlobToFree)
  26. {
  27. LsaFreeMemory( TrustInfo->BlobToFree );
  28. }
  29. else
  30. {
  31. if (TrustInfo->DomainName && TrustInfo->DomainName->Buffer)
  32. {
  33. NetApiBufferFree(TrustInfo->DomainName->Buffer);
  34. NetApiBufferFree(TrustInfo->DomainName);
  35. }
  36. }
  37. if ( TrustInfo->LsaHandle ) {
  38. LsaClose( TrustInfo->LsaHandle );
  39. }
  40. if ( TrustInfo->TrustHandle ) {
  41. LsaClose( TrustInfo->TrustHandle );
  42. }
  43. }
  44. DWORD
  45. NetDompTrustGetDomInfo(
  46. IN PWSTR Domain,
  47. IN PWSTR DomainController OPTIONAL,
  48. IN PND5_AUTH_INFO AuthInfo,
  49. IN OUT PND5_TRUST_INFO TrustInfo,
  50. IN BOOL ManageTrust,
  51. IN BOOL fForce,
  52. IN BOOL fUseNullSession
  53. )
  54. /*++
  55. Routine Description:
  56. This function will connect to the domain controller for a given domain and determine the
  57. appropriate information required for managing trusts.
  58. Arguments:
  59. Domain - Domain to connect to
  60. DomainController - Optional name of a dc within the domain to connect to
  61. TrustInfo - Trusted domain info to accumulate
  62. ManageTrust - Determines how the Lsa is opened. Also if true, and DomainController is NULL,
  63. find a writable DC
  64. fForce - If true, set the name info even if the domain can't be contacted.
  65. Return Value:
  66. ERROR_SUCCESS - Success
  67. ERROR_INVALID_PARAMETER - No object name was supplied
  68. --*/
  69. {
  70. DWORD Win32Err = ERROR_SUCCESS;
  71. PDOMAIN_CONTROLLER_INFO DcInfo = NULL;
  72. PPOLICY_PRIMARY_DOMAIN_INFO PolicyPDI = NULL;
  73. PPOLICY_DNS_DOMAIN_INFO PolicyDDI = NULL;
  74. OBJECT_ATTRIBUTES OA;
  75. PWSTR pwzDomainName;
  76. UNICODE_STRING ServerU, DomainNameU;
  77. NTSTATUS Status;
  78. ULONG DsGetDcOptions = DS_DIRECTORY_SERVICE_PREFERRED, LsaOptions;
  79. HRESULT hr = NULL;
  80. if ( !DomainController ) {
  81. if ( ManageTrust ) {
  82. DsGetDcOptions |= DS_WRITABLE_REQUIRED;
  83. }
  84. if (TrustInfo->Flags & NETDOM_TRUST_PDC_REQUIRED)
  85. {
  86. DsGetDcOptions |= DS_PDC_REQUIRED;
  87. }
  88. Win32Err = DsGetDcName( NULL,
  89. Domain,
  90. NULL,
  91. NULL,
  92. DsGetDcOptions,
  93. &DcInfo );
  94. if ( Win32Err == ERROR_SUCCESS ) {
  95. DomainController = DcInfo->DomainControllerName;
  96. }
  97. }
  98. //
  99. // Save off the server name
  100. //
  101. if ( Win32Err == ERROR_SUCCESS )
  102. {
  103. size_t cchName = 0;
  104. hr = StringCchLengthW ( DomainController, MAXSTR, &cchName );
  105. if ( SUCCEEDED (hr) )
  106. {
  107. Win32Err = NetApiBufferAllocate( ( cchName + 1 ) * sizeof( WCHAR ), (PVOID*)&( TrustInfo->Server ) );
  108. }
  109. else
  110. {
  111. Win32Err = HRESULT_CODE ( hr );
  112. }
  113. if ( Win32Err == ERROR_SUCCESS )
  114. {
  115. wcsncpy( TrustInfo->Server, DomainController, cchName + 1 );
  116. }
  117. }
  118. //
  119. // Connect to the machine
  120. //
  121. if ( Win32Err == ERROR_SUCCESS ) {
  122. LOG_VERBOSE(( MSG_VERBOSE_ESTABLISH_SESSION, DomainController ));
  123. Win32Err = NetpManageIPCConnect( DomainController,
  124. (fUseNullSession) ? L"" : AuthInfo->User,
  125. (fUseNullSession) ? L"" : AuthInfo->Password,
  126. (fUseNullSession) ?
  127. NETSETUPP_NULL_SESSION_IPC : NETSETUPP_CONNECT_IPC);
  128. if ( Win32Err == ERROR_SUCCESS ) {
  129. TrustInfo->Connected = TRUE;
  130. }
  131. if (ERROR_SESSION_CREDENTIAL_CONFLICT == Win32Err)
  132. {
  133. if (fUseNullSession)
  134. {
  135. // Ignore conflict of creds.
  136. //
  137. Win32Err = ERROR_SUCCESS;
  138. }
  139. else
  140. {
  141. NetDompDisplayMessage(MSG_ALREADY_CONNECTED, DomainController);
  142. }
  143. }
  144. if (ERROR_LOGON_FAILURE == Win32Err)
  145. {
  146. NetApiBufferFree( DcInfo );
  147. return Win32Err;
  148. }
  149. }
  150. //
  151. // Get the domain information
  152. //
  153. if ( Win32Err == ERROR_SUCCESS ) {
  154. RtlInitUnicodeString( &ServerU, DomainController );
  155. InitializeObjectAttributes( &OA, NULL, 0, NULL, NULL );
  156. LOG_VERBOSE(( MSG_VERBOSE_GET_LSA ));
  157. LsaOptions = POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES;
  158. if ( ManageTrust ) {
  159. LsaOptions |= POLICY_CREATE_SECRET | POLICY_TRUST_ADMIN;
  160. }
  161. Status = LsaOpenPolicy( &ServerU,
  162. &OA,
  163. LsaOptions,
  164. &( TrustInfo->LsaHandle ) );
  165. if ( NT_SUCCESS( Status ) ) {
  166. Status = LsaQueryInformationPolicy( TrustInfo->LsaHandle,
  167. PolicyDnsDomainInformation,
  168. ( PVOID * )&PolicyDDI );
  169. if ( NT_SUCCESS( Status ) ) {
  170. TrustInfo->DomainName = &PolicyDDI->DnsDomainName;
  171. TrustInfo->FlatName = &PolicyDDI->Name;
  172. TrustInfo->ForestName = &PolicyDDI->DnsForestName;
  173. TrustInfo->Sid = PolicyDDI->Sid;
  174. TrustInfo->BlobToFree = ( PVOID )PolicyDDI;
  175. TrustInfo->Uplevel = TRUE;
  176. TrustInfo->fWasDownlevel = FALSE;
  177. } else if ( Status == RPC_NT_PROCNUM_OUT_OF_RANGE ) {
  178. Status = LsaQueryInformationPolicy( TrustInfo->LsaHandle,
  179. PolicyPrimaryDomainInformation,
  180. ( PVOID * )&PolicyPDI );
  181. if ( NT_SUCCESS( Status ) ) {
  182. TrustInfo->DomainName = &PolicyPDI->Name;
  183. TrustInfo->FlatName = &PolicyPDI->Name;
  184. TrustInfo->Sid = PolicyPDI->Sid;
  185. TrustInfo->BlobToFree = ( PVOID )PolicyPDI;
  186. TrustInfo->Uplevel = TrustInfo->fWasDownlevel = FALSE;
  187. }
  188. }
  189. }
  190. Win32Err = RtlNtStatusToDosError( Status );
  191. if ( Win32Err != ERROR_SUCCESS ) {
  192. LOG_VERBOSE(( MSG_VERBOSE_DELETE_SESSION, DomainController ));
  193. NetpManageIPCConnect( DomainController,
  194. NULL,
  195. NULL,
  196. NETSETUPP_DISCONNECT_IPC );
  197. TrustInfo->Connected = FALSE;
  198. }
  199. } else if (fForce) {
  200. LOG_VERBOSE(( MSG_VERBOSE_DOMAIN_NOT_FOUND, Domain ));
  201. TrustInfo->Flags = NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND;
  202. // Allocate space to save the user-entered domain name.
  203. size_t cchName = 0;
  204. hr = StringCchLengthW ( Domain, MAXSTR, &cchName );
  205. if ( SUCCEEDED (hr) )
  206. {
  207. Win32Err = NetApiBufferAllocate( (cchName + 1) * sizeof(WCHAR), (PVOID*)&pwzDomainName);
  208. }
  209. else
  210. {
  211. Win32Err = HRESULT_CODE ( hr );
  212. }
  213. if ( Win32Err == ERROR_SUCCESS ) {
  214. Win32Err = NetApiBufferAllocate(sizeof(UNICODE_STRING), (PVOID*)&TrustInfo->DomainName);
  215. if ( Win32Err == ERROR_SUCCESS ) {
  216. wcsncpy( pwzDomainName, Domain, cchName + 1 );
  217. RtlInitUnicodeString( TrustInfo->DomainName, pwzDomainName );
  218. TrustInfo->FlatName = TrustInfo->DomainName;
  219. }
  220. }
  221. }
  222. else
  223. {
  224. LOG_VERBOSE((MSG_DOMAIN_NOT_FOUND, Domain));
  225. }
  226. NetApiBufferFree( DcInfo );
  227. return( Win32Err );
  228. }
  229. DWORD
  230. NetDompTrustRemoveIncomingDownlevelObject(
  231. IN PND5_TRUST_INFO TrustingInfo,
  232. IN PND5_TRUST_INFO TrustedInfo
  233. )
  234. /*++
  235. Routine Description:
  236. This function removes the interdomain trust account object on
  237. the trusted domain.
  238. Arguments:
  239. TrustingInfo - Info on the trusting domain
  240. TrustedInfo - Info on the trusted domain
  241. Return Value:
  242. ERROR_INVALID_PARAMETER - No object name was supplied
  243. --*/
  244. {
  245. DWORD Win32Err = ERROR_SUCCESS;
  246. WCHAR AccountName[ UNLEN + 1 ];
  247. PWSTR FullServer = NULL;
  248. HRESULT hr = NULL;
  249. if ( TrustingInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  250. return( ERROR_INVALID_DOMAINNAME );
  251. }
  252. if ( TrustedInfo->Server && *( TrustedInfo->Server ) != L'\\' )
  253. {
  254. size_t cchName = 0;
  255. hr = StringCchLengthW ( TrustedInfo->Server, MAXSTR, &cchName );
  256. if ( SUCCEEDED ( hr ) )
  257. {
  258. Win32Err = NetApiBufferAllocate( ( cchName + 3 ) * sizeof( WCHAR ), ( PVOID * )&FullServer );
  259. }
  260. else
  261. {
  262. Win32Err = HRESULT_CODE (hr);
  263. }
  264. if ( Win32Err == ERROR_SUCCESS )
  265. {
  266. hr = StringCchPrintfW ( FullServer, cchName + 3, L"\\\\%ws", TrustedInfo->Server );
  267. if ( FAILED (hr) )
  268. {
  269. Win32Err = HRESULT_CODE (hr);
  270. }
  271. }
  272. }
  273. else
  274. {
  275. FullServer = TrustedInfo->Server;
  276. }
  277. //
  278. // Build the account name...
  279. //
  280. if ( Win32Err == ERROR_SUCCESS ) {
  281. hr = StringCchPrintfW ( AccountName,
  282. sizeof (AccountName) / sizeof (AccountName[0]),
  283. L"%ws$",
  284. (PWSTR) CSafeUnicodeString ( *(TrustingInfo->FlatName ) )
  285. );
  286. if ( SUCCEEDED ( hr ) )
  287. {
  288. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TACCT, AccountName ));
  289. Win32Err = NetUserDel( FullServer, AccountName );
  290. }
  291. else
  292. {
  293. Win32Err = HRESULT_CODE (hr);
  294. }
  295. }
  296. if ( FullServer != TrustedInfo->Server ) {
  297. NetApiBufferFree( FullServer );
  298. }
  299. return( Win32Err );
  300. }
  301. DWORD
  302. NetDompTrustRemoveOutgoingDownlevelObject(
  303. IN PND5_TRUST_INFO TrustingInfo,
  304. IN PND5_TRUST_INFO TrustedInfo
  305. )
  306. /*++
  307. Routine Description:
  308. This function deletes the trust object/secret on the trusting domain.
  309. Arguments:
  310. TrustingInfo - Info on the trusting domain
  311. TrustedInfo - Info on the trusted domain
  312. Return Value:
  313. ERROR_INVALID_PARAMETER - No object name was supplied
  314. --*/
  315. {
  316. DWORD Win32Err = ERROR_SUCCESS;
  317. WCHAR SecretName[ DNLEN + 4 ];
  318. LSA_HANDLE TrustedDomain, SecretHandle;
  319. NTSTATUS Status;
  320. UNICODE_STRING Secret;
  321. HRESULT hr;
  322. if ( TrustedInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  323. return( ERROR_INVALID_DOMAINNAME );
  324. }
  325. if ( !TrustedInfo->Sid ) {
  326. // Must be an orphaned trust, nothing we can do.
  327. return NO_ERROR;
  328. }
  329. //
  330. // Build the secret name
  331. //
  332. hr = StringCchPrintfW (
  333. SecretName,
  334. sizeof ( SecretName ) / sizeof ( SecretName[0] ),
  335. L"%ws$%ws",
  336. LSA_GLOBAL_SECRET_PREFIX,
  337. (PWSTR) CSafeUnicodeString ( *(TrustedInfo->FlatName))
  338. );
  339. if ( FAILED ( hr ) )
  340. return HRESULT_CODE ( hr );
  341. //
  342. // Ok, first, delete the trust object. It's ok if the trust object is deleted but the
  343. // secret is not
  344. //
  345. LOG_VERBOSE(( MSG_VERBOSE_OPEN_TRUST, (PWSTR) CSafeUnicodeString ( * (TrustedInfo->DomainName ) ) ) );
  346. Status = LsaOpenTrustedDomain( TrustingInfo->LsaHandle,
  347. TrustedInfo->Sid,
  348. DELETE,
  349. &TrustedDomain );
  350. if ( NT_SUCCESS( Status ) ) {
  351. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, (PWSTR) CSafeUnicodeString ( * (TrustedInfo->DomainName) ) ));
  352. Status = LsaDelete( TrustedDomain );
  353. if ( !NT_SUCCESS( Status ) ) {
  354. LsaClose( TrustedDomain );
  355. }
  356. }
  357. //
  358. // Now, the same with the secret
  359. //
  360. if ( NT_SUCCESS( Status ) ) {
  361. RtlInitUnicodeString( &Secret, SecretName );
  362. LOG_VERBOSE(( MSG_VERBOSE_OPEN_SECRET, (PWSTR) CSafeUnicodeString (Secret) ));
  363. Status = LsaOpenSecret( TrustingInfo->LsaHandle,
  364. &Secret,
  365. DELETE,
  366. &SecretHandle );
  367. if ( NT_SUCCESS( Status ) ) {
  368. LOG_VERBOSE(( MSG_VERBOSE_DELETE_SECRET, (PWSTR) CSafeUnicodeString (Secret)));
  369. Status = LsaDelete( SecretHandle );
  370. if ( !NT_SUCCESS( Status ) ) {
  371. LsaClose( SecretHandle );
  372. }
  373. }
  374. }
  375. Win32Err = RtlNtStatusToDosError( Status );
  376. return( Win32Err );
  377. }
  378. DWORD
  379. NetDompTrustSetPasswordSam(
  380. IN PWSTR Server,
  381. IN PWSTR AccountName,
  382. IN PWSTR Password
  383. )
  384. /*++
  385. Routine Description:
  386. This function will set the password on a SAM trust object
  387. Arguments:
  388. Server - Server that holds the account object
  389. AccountName - Name of the account
  390. Password - Password to set
  391. Return Value:
  392. ERROR_SUCCESS - The function succeeded
  393. --*/
  394. {
  395. DWORD Win32Err = ERROR_SUCCESS;
  396. USER_INFO_1 UI1, *ReadUI1 = NULL;
  397. PWSTR FullServer = NULL;
  398. HRESULT hr = NULL;
  399. size_t cchName = 0;
  400. if ( Server && *( Server ) != L'\\' ) {
  401. hr = StringCchLengthW ( Server, MAXSTR, &cchName );
  402. if ( SUCCEEDED (hr) )
  403. {
  404. Win32Err = NetApiBufferAllocate( ( cchName + 3 ) * sizeof( WCHAR ), ( PVOID * )&FullServer );
  405. }
  406. else
  407. {
  408. Win32Err = HRESULT_CODE (hr);
  409. }
  410. if ( Win32Err == ERROR_SUCCESS )
  411. {
  412. hr = StringCchPrintfW ( FullServer, cchName + 3, L"\\\\%ws", Server );
  413. if ( FAILED (hr) )
  414. {
  415. Win32Err = HRESULT_CODE ( hr );
  416. }
  417. }
  418. } else {
  419. FullServer = Server;
  420. }
  421. if ( Win32Err == ERROR_SUCCESS ) {
  422. Win32Err = NetUserGetInfo( FullServer,
  423. AccountName,
  424. 1,
  425. ( LPBYTE * )&ReadUI1 );
  426. if ( Win32Err == ERROR_SUCCESS ) {
  427. if ( !FLAG_ON( ReadUI1->usri1_flags, UF_INTERDOMAIN_TRUST_ACCOUNT ) ) {
  428. Win32Err = ERROR_SPECIAL_ACCOUNT;
  429. } else {
  430. ReadUI1->usri1_password = Password;
  431. ReadUI1->usri1_flags = UF_INTERDOMAIN_TRUST_ACCOUNT | UF_SCRIPT;
  432. Win32Err = NetUserSetInfo( FullServer,
  433. AccountName,
  434. 1,
  435. ( LPBYTE )ReadUI1,
  436. NULL );
  437. }
  438. NetApiBufferFree( ReadUI1 );
  439. }
  440. }
  441. if ( FullServer != Server ) {
  442. NetApiBufferFree( FullServer );
  443. }
  444. return( Win32Err );
  445. }
  446. DWORD
  447. NetDompTrustAddIncomingDownlevelObject(
  448. IN PND5_TRUST_INFO TrustingInfo,
  449. IN PND5_TRUST_INFO TrustedInfo,
  450. IN PWSTR TrustPassword,
  451. IN ULONG PasswordLength
  452. )
  453. /*++
  454. Routine Description:
  455. This function creates the interdomain trust account object on
  456. the trusted domain.
  457. Arguments:
  458. TrustingInfo - Info on the trusting domain
  459. TrustedInfo - Info on the trusted domain
  460. Return Value:
  461. ERROR_INVALID_PARAMETER - No object name was supplied
  462. --*/
  463. {
  464. DWORD Win32Err = ERROR_SUCCESS;
  465. WCHAR AccountName[ UNLEN + 1 ];
  466. USER_INFO_1 UI1;
  467. PWSTR FullServer = NULL;
  468. HRESULT hr = NULL;
  469. size_t cchName = 0;
  470. if ( TrustingInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  471. return( ERROR_INVALID_DOMAINNAME );
  472. }
  473. //
  474. // Build the account name...
  475. //
  476. hr = StringCchPrintfW (
  477. AccountName,
  478. sizeof ( AccountName ) / sizeof ( AccountName[0] ),
  479. L"%ws$",
  480. (PWSTR) CSafeUnicodeString ( *(TrustingInfo->FlatName) )
  481. );
  482. if ( FAILED ( hr ) )
  483. return HRESULT_CODE ( hr );
  484. LOG_VERBOSE(( MSG_VERBOSE_ADD_TACCT, AccountName ));
  485. UI1.usri1_name = AccountName;
  486. UI1.usri1_password = TrustPassword;
  487. UI1.usri1_password_age = 0;
  488. UI1.usri1_priv = USER_PRIV_USER;
  489. UI1.usri1_home_dir = NULL;
  490. UI1.usri1_comment = NULL;
  491. UI1.usri1_flags = UF_INTERDOMAIN_TRUST_ACCOUNT | UF_SCRIPT;
  492. UI1.usri1_script_path = NULL;
  493. if ( TrustedInfo->Server && *( TrustedInfo->Server ) != L'\\' ) {
  494. hr = StringCchLengthW ( TrustedInfo->Server, MAXSTR, &cchName );
  495. if ( SUCCEEDED ( hr ) )
  496. {
  497. Win32Err = NetApiBufferAllocate( ( cchName + 3 ) * sizeof( WCHAR ), ( PVOID * )&FullServer );
  498. }
  499. else
  500. Win32Err = HRESULT_CODE ( hr );
  501. if ( Win32Err == ERROR_SUCCESS ) {
  502. hr = StringCchPrintfW ( FullServer, cchName + 3, L"\\\\%ws", TrustedInfo->Server );
  503. if ( FAILED (hr) )
  504. Win32Err = HRESULT_CODE ( hr );
  505. }
  506. } else {
  507. FullServer = TrustedInfo->Server;
  508. }
  509. if ( Win32Err == ERROR_SUCCESS ) {
  510. Win32Err = NetUserAdd( FullServer,
  511. 1,
  512. ( LPBYTE )&UI1,
  513. NULL );
  514. if ( Win32Err == NERR_UserExists ) {
  515. Win32Err = NetDompTrustSetPasswordSam( FullServer,
  516. AccountName,
  517. TrustPassword );
  518. }
  519. }
  520. if ( FullServer != TrustedInfo->Server ) {
  521. NetApiBufferFree( FullServer );
  522. }
  523. return( Win32Err );
  524. }
  525. DWORD
  526. NetDompTrustAddOutgoingDownlevelObject(
  527. IN PND5_TRUST_INFO TrustingInfo,
  528. IN PND5_TRUST_INFO TrustedInfo,
  529. IN PWSTR TrustPassword,
  530. IN ULONG PasswordLength
  531. )
  532. /*++
  533. Routine Description:
  534. This function creates the trust secret on the trusting domain.
  535. Arguments:
  536. TrustingInfo - Info on the trusting domain
  537. TrustedInfo - Info on the trusted domain
  538. Return Value:
  539. ERROR_INVALID_PARAMETER - No object name was supplied
  540. --*/
  541. {
  542. DWORD Win32Err = ERROR_SUCCESS;
  543. WCHAR SecretName[ DNLEN + 4 ];
  544. LSA_HANDLE TrustedDomain = NULL, SecretHandle = NULL;
  545. NTSTATUS Status;
  546. UNICODE_STRING Secret, Password;
  547. BOOL DeleteSecret = FALSE;
  548. LSA_TRUST_INFORMATION TrustInfo;
  549. HRESULT hr = NULL;
  550. if ( TrustedInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  551. return( ERROR_INVALID_DOMAINNAME );
  552. }
  553. //
  554. // Build the secret name
  555. //
  556. hr = StringCchPrintfW (
  557. SecretName,
  558. sizeof ( SecretName ) / sizeof ( SecretName[0] ),
  559. L"%ws$%ws", LSA_GLOBAL_SECRET_PREFIX,
  560. (PWSTR) CSafeUnicodeString ( * (TrustedInfo->FlatName) )
  561. );
  562. if ( FAILED ( hr ) )
  563. return HRESULT_CODE ( hr );
  564. //
  565. // Ok, first, create the secret, It's ok if the secret is created but the
  566. // trust object is not
  567. //
  568. RtlInitUnicodeString( &Secret, SecretName );
  569. LOG_VERBOSE(( MSG_VERBOSE_CREATE_SECRET, (PWSTR) CSafeUnicodeString ( Secret )));
  570. Status = LsaCreateSecret( TrustingInfo->LsaHandle,
  571. &Secret,
  572. SECRET_SET_VALUE,
  573. &SecretHandle );
  574. if ( NT_SUCCESS( Status ) ) {
  575. DeleteSecret = TRUE;
  576. } else if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  577. LOG_VERBOSE(( MSG_VERBOSE_OPEN_SECRET, (PWSTR) CSafeUnicodeString ( Secret ) ));
  578. Status = LsaOpenSecret( TrustingInfo->LsaHandle,
  579. &Secret,
  580. SECRET_SET_VALUE,
  581. &SecretHandle );
  582. }
  583. if ( NT_SUCCESS( Status ) ) {
  584. RtlInitUnicodeString( &Password, TrustPassword );
  585. Status = LsaSetSecret( SecretHandle,
  586. &Password,
  587. NULL );
  588. }
  589. //
  590. // Ok, now create the trust object
  591. //
  592. if ( NT_SUCCESS( Status ) ) {
  593. TrustInfo.Sid = TrustedInfo->Sid;
  594. RtlCopyMemory( &TrustInfo.Name, TrustedInfo->FlatName, sizeof( UNICODE_STRING ) );
  595. LOG_VERBOSE(( MSG_VERBOSE_CREATE_TRUST, (PWSTR) CSafeUnicodeString ( TrustInfo.Name )));
  596. Status = LsaCreateTrustedDomain( TrustingInfo->LsaHandle,
  597. &TrustInfo,
  598. TRUSTED_QUERY_DOMAIN_NAME,
  599. &TrustedDomain );
  600. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  601. Status = STATUS_SUCCESS;
  602. }
  603. }
  604. if ( !NT_SUCCESS( Status ) && DeleteSecret ) {
  605. LsaDelete( SecretHandle );
  606. SecretHandle = NULL;
  607. }
  608. Win32Err = RtlNtStatusToDosError( Status );
  609. if ( SecretHandle ) {
  610. LsaClose( SecretHandle );
  611. }
  612. if ( TrustedDomain ) {
  613. LsaClose( TrustedDomain );
  614. }
  615. return( Win32Err );
  616. }
  617. BOOL g_fQuarantineSet = FALSE;
  618. DWORD
  619. NetDompAddOnTrustingSide(
  620. IN PND5_TRUST_INFO TrustedInfo,
  621. IN PND5_TRUST_INFO TrustingInfo,
  622. IN PWSTR TrustPassword,
  623. IN ULONG Direction,
  624. IN BOOL Mit
  625. )
  626. /*++
  627. Routine Description:
  628. This function creates the trust object on the trusting domain.
  629. Arguments:
  630. TrustedInfo - Info on the trusted domain
  631. TrustingInfo - Info on the trusting domain
  632. Direction - The direction of the trust
  633. Mit - If true, this is an MIT style trust
  634. Return Value:
  635. ERROR_INVALID_PARAMETER - No object name was supplied
  636. --*/
  637. {
  638. DWORD Win32Err = ERROR_SUCCESS;
  639. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  640. PTRUSTED_DOMAIN_FULL_INFORMATION pFullInfo;
  641. TRUSTED_DOMAIN_AUTH_INFORMATION TDAI;
  642. LSA_AUTH_INFORMATION AuthData;
  643. HRESULT hr = NULL;
  644. size_t PasswordLength = 0;
  645. NTSTATUS Status;
  646. BOOL fSidSet = FALSE;
  647. PLSA_UNICODE_STRING pName;
  648. BOOL fExternalTrust = FALSE;
  649. BOOL fQuarantineSet = FALSE;
  650. hr = StringCchLengthW ( TrustPassword, PWLEN, &PasswordLength );
  651. if ( FAILED ( hr ) )
  652. return HRESULT_CODE ( hr );
  653. if (TrustingInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  654. {
  655. if (Mit)
  656. {
  657. return ERROR_SUCCESS;
  658. }
  659. else
  660. {
  661. return ERROR_INVALID_PARAMETER;
  662. }
  663. }
  664. if ( TrustingInfo->Uplevel ) {
  665. RtlCopyMemory( &TDIEx.Name, TrustedInfo->DomainName, sizeof( UNICODE_STRING ) );
  666. TDIEx.Sid = TrustedInfo->Sid;
  667. TDIEx.TrustDirection = Direction;
  668. if ( Mit ) {
  669. TDIEx.TrustType = TRUST_TYPE_MIT;
  670. TDIEx.TrustAttributes = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  671. RtlCopyMemory( &TDIEx.FlatName, TrustedInfo->DomainName, sizeof( UNICODE_STRING ) );
  672. } else {
  673. TDIEx.TrustType = TrustedInfo->Uplevel ? TRUST_TYPE_UPLEVEL : TRUST_TYPE_DOWNLEVEL;
  674. if ( TDIEx.TrustType == TRUST_TYPE_DOWNLEVEL )
  675. {
  676. // Downlevel trusts are always external
  677. fExternalTrust = TRUE;
  678. }
  679. else
  680. {
  681. // Compare the forest names of the two domains
  682. // to determine if the trust is external or not
  683. fExternalTrust = _wcsicmp ( (PWSTR) CSafeUnicodeString ( * (TrustedInfo->ForestName) ),
  684. (PWSTR) CSafeUnicodeString ( * (TrustingInfo->ForestName) )
  685. ) != 0;
  686. }
  687. TDIEx.TrustAttributes = 0;
  688. RtlCopyMemory( &TDIEx.FlatName, TrustedInfo->FlatName, sizeof( UNICODE_STRING ) );
  689. }
  690. Status = NtQuerySystemTime( &AuthData.LastUpdateTime );
  691. if ( NT_SUCCESS( Status ) ) {
  692. AuthData.AuthType = TRUST_AUTH_TYPE_CLEAR;
  693. AuthData.AuthInfoLength = PasswordLength * sizeof( WCHAR );
  694. AuthData.AuthInfo = ( PUCHAR )TrustPassword;
  695. TDAI.OutgoingAuthInfos = 1;
  696. TDAI.OutgoingAuthenticationInformation = &AuthData;
  697. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  698. // All outgoing external trusts have SID Filtering enabled by default
  699. if ( fExternalTrust && FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) )
  700. {
  701. TDIEx.TrustAttributes |= TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  702. g_fQuarantineSet = TRUE;
  703. }
  704. if ( FLAG_ON( Direction, TRUST_DIRECTION_INBOUND ) ) {
  705. TDAI.IncomingAuthInfos = 1;
  706. TDAI.IncomingAuthenticationInformation = &AuthData;
  707. TDAI.IncomingPreviousAuthenticationInformation = NULL;
  708. } else {
  709. TDAI.IncomingAuthInfos = 0;
  710. TDAI.IncomingAuthenticationInformation = NULL;
  711. TDAI.IncomingPreviousAuthenticationInformation = NULL;
  712. }
  713. Status = LsaCreateTrustedDomainEx( TrustingInfo->LsaHandle,
  714. &TDIEx,
  715. &TDAI,
  716. TRUSTED_ALL_ACCESS,
  717. &( TrustingInfo->TrustHandle ) );
  718. //
  719. // If the object already exists, morph our info into it.
  720. //
  721. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  722. pName = &TDIEx.Name;
  723. Status = LsaQueryTrustedDomainInfoByName(TrustingInfo->LsaHandle,
  724. pName,
  725. TrustedDomainFullInformation,
  726. (PVOID*)&pFullInfo);
  727. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  728. {
  729. // Now try by flat name; can get here if a downlevel domain
  730. // is upgraded to NT5. The name used above was the DNS name
  731. // but the TDO would be named after the flat name.
  732. //
  733. pName = TrustingInfo->FlatName;
  734. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  735. pName,
  736. TrustedDomainFullInformation,
  737. (PVOID*)&pFullInfo);
  738. }
  739. if ( NT_SUCCESS( Status ) ) {
  740. if ( pFullInfo->Information.TrustDirection == Direction ) {
  741. Status = STATUS_OBJECT_NAME_COLLISION;
  742. } else {
  743. // All outgoing external trusts have SID Filtering enabled by default
  744. // add the flag only if the Outgoing side of the trust is being added
  745. if ( fExternalTrust &&
  746. FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) &&
  747. !FLAG_ON( pFullInfo->Information.TrustDirection, TRUST_DIRECTION_OUTBOUND )
  748. )
  749. {
  750. pFullInfo->Information.TrustAttributes |= TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  751. g_fQuarantineSet = TRUE;
  752. }
  753. pFullInfo->Information.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  754. pFullInfo->AuthInformation.OutgoingAuthInfos = 1;
  755. pFullInfo->AuthInformation.OutgoingAuthenticationInformation = &AuthData;
  756. pFullInfo->AuthInformation.OutgoingPreviousAuthenticationInformation = NULL;
  757. // Check for a NULL domain SID. The SID can be NULL if the
  758. // trust was created when the domain was still NT4.
  759. //
  760. if (!pFullInfo->Information.Sid)
  761. {
  762. pFullInfo->Information.Sid = TrustedInfo->Sid;
  763. fSidSet = TRUE;
  764. }
  765. Status = LsaSetTrustedDomainInfoByName(TrustingInfo->LsaHandle,
  766. pName,
  767. TrustedDomainFullInformation,
  768. pFullInfo);
  769. }
  770. }
  771. if (fSidSet)
  772. {
  773. // Sid memory is owned by the TrustingInfo struct, so don't free
  774. // it here.
  775. //
  776. pFullInfo->Information.Sid = NULL;
  777. }
  778. LsaFreeMemory( pFullInfo );
  779. }
  780. }
  781. Win32Err = RtlNtStatusToDosError( Status );
  782. } else {
  783. //
  784. // Doing downlevel
  785. //
  786. if ( Mit ) {
  787. Win32Err = ERROR_INVALID_PARAMETER;
  788. } else {
  789. Win32Err = NetDompTrustAddOutgoingDownlevelObject( TrustingInfo,
  790. TrustedInfo,
  791. TrustPassword,
  792. PasswordLength );
  793. if ( Win32Err == ERROR_SUCCESS &&
  794. Direction == TRUST_DIRECTION_BIDIRECTIONAL ) {
  795. Win32Err = NetDompTrustAddIncomingDownlevelObject( TrustedInfo,
  796. TrustingInfo,
  797. TrustPassword,
  798. PasswordLength );
  799. if ( Win32Err != ERROR_SUCCESS ) {
  800. Win32Err = NetDompTrustRemoveOutgoingDownlevelObject( TrustingInfo,
  801. TrustedInfo );
  802. }
  803. }
  804. }
  805. }
  806. if (ERROR_SUCCESS == Win32Err)
  807. {
  808. LOG_VERBOSE((MSG_VERBOSE_CREATED_TRUST, (PWSTR) CSafeUnicodeString ( *(TrustedInfo->DomainName) ),
  809. (PWSTR) CSafeUnicodeString ( * (TrustingInfo->DomainName ) ) ));
  810. }
  811. return( Win32Err );
  812. }
  813. DWORD
  814. NetDompAddOnTrustedSide(
  815. IN PND5_TRUST_INFO TrustedInfo,
  816. IN PND5_TRUST_INFO TrustingInfo,
  817. IN PWSTR TrustPassword,
  818. IN ULONG Direction,
  819. IN BOOL Mit
  820. )
  821. /*++
  822. Routine Description:
  823. This function creates the trust object on the trusted domain.
  824. Arguments:
  825. TrustedInfo - Info on the trusted domain
  826. TrustingInfo - Info on the trusting domain
  827. Direction - The direction of the trust
  828. Mit - If true, this is an MIT style trust
  829. Return Value:
  830. ERROR_INVALID_PARAMETER - No object name was supplied
  831. --*/
  832. {
  833. DWORD Win32Err = ERROR_SUCCESS;
  834. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  835. PTRUSTED_DOMAIN_FULL_INFORMATION pFullInfo;
  836. LSA_AUTH_INFORMATION AuthData;
  837. TRUSTED_DOMAIN_AUTH_INFORMATION TDAI;
  838. size_t PasswordLength = 0;
  839. NTSTATUS Status;
  840. BOOL fSidSet = FALSE;
  841. PLSA_UNICODE_STRING pName;
  842. HRESULT hr = NULL;
  843. BOOL fExternalTrust = FALSE;
  844. BOOL fQuarantineSet = FALSE;
  845. hr = StringCchLengthW ( TrustPassword, PWLEN, &PasswordLength );
  846. if ( FAILED ( hr ) )
  847. return HRESULT_CODE (hr);
  848. if (TrustedInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  849. {
  850. if (Mit)
  851. {
  852. return ERROR_SUCCESS;
  853. }
  854. else
  855. {
  856. return ERROR_INVALID_PARAMETER;
  857. }
  858. }
  859. if ( TrustedInfo->Uplevel) {
  860. RtlCopyMemory( &TDIEx.Name, TrustingInfo->DomainName, sizeof( UNICODE_STRING ) );
  861. TDIEx.Sid = TrustingInfo->Sid;
  862. TDIEx.TrustDirection = Direction;
  863. if ( Mit ) {
  864. TDIEx.TrustType = TRUST_TYPE_MIT;
  865. TDIEx.TrustAttributes = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  866. RtlCopyMemory( &TDIEx.FlatName, TrustingInfo->DomainName, sizeof( UNICODE_STRING ) );
  867. } else {
  868. TDIEx.TrustType = TrustingInfo->Uplevel ? TRUST_TYPE_UPLEVEL : TRUST_TYPE_DOWNLEVEL;
  869. if ( TDIEx.TrustType == TRUST_TYPE_DOWNLEVEL )
  870. {
  871. // Downlevel trusts are always external
  872. fExternalTrust = TRUE;
  873. }
  874. else
  875. {
  876. // Compare the forest names of the two domains
  877. // to determine if the trust is external or not
  878. fExternalTrust = _wcsicmp ( (PWSTR) CSafeUnicodeString ( * (TrustedInfo->ForestName) ),
  879. (PWSTR) CSafeUnicodeString ( * (TrustingInfo->ForestName) )
  880. ) != 0;
  881. }
  882. TDIEx.TrustAttributes = 0;
  883. RtlCopyMemory( &TDIEx.FlatName, TrustingInfo->FlatName, sizeof( UNICODE_STRING ) );
  884. }
  885. Status = NtQuerySystemTime( &AuthData.LastUpdateTime );
  886. if ( NT_SUCCESS( Status ) ) {
  887. AuthData.AuthType = TRUST_AUTH_TYPE_CLEAR;
  888. AuthData.AuthInfoLength = PasswordLength * sizeof( WCHAR );
  889. AuthData.AuthInfo = ( PUCHAR )TrustPassword;
  890. TDAI.IncomingAuthInfos = 1;
  891. TDAI.IncomingAuthenticationInformation = &AuthData;
  892. TDAI.IncomingPreviousAuthenticationInformation = &AuthData;
  893. if ( FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  894. TDAI.OutgoingAuthInfos = 1;
  895. TDAI.OutgoingAuthenticationInformation = &AuthData;
  896. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  897. // All outgoing external trusts have SID Filtering enabled by default
  898. if ( fExternalTrust )
  899. {
  900. TDIEx.TrustAttributes |= TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  901. g_fQuarantineSet = TRUE;
  902. }
  903. } else {
  904. TDAI.OutgoingAuthInfos = 0;
  905. TDAI.OutgoingAuthenticationInformation = NULL;
  906. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  907. }
  908. Status = LsaCreateTrustedDomainEx( TrustedInfo->LsaHandle,
  909. &TDIEx,
  910. &TDAI,
  911. TRUSTED_ALL_ACCESS,
  912. &( TrustedInfo->TrustHandle ) );
  913. //
  914. // If the object already exists, morph our info into it.
  915. //
  916. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  917. pName = &TDIEx.Name;
  918. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  919. pName,
  920. TrustedDomainFullInformation,
  921. (PVOID*)&pFullInfo);
  922. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  923. {
  924. // Now try by flat name; can get here if a downlevel domain
  925. // is upgraded to NT5. The name used above was the DNS name
  926. // but the TDO would be named after the flat name.
  927. //
  928. pName = TrustingInfo->FlatName;
  929. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  930. pName,
  931. TrustedDomainFullInformation,
  932. (PVOID*)&pFullInfo);
  933. }
  934. if ( NT_SUCCESS( Status ) ) {
  935. if ( pFullInfo->Information.TrustDirection == Direction ) {
  936. Status = STATUS_OBJECT_NAME_COLLISION;
  937. } else {
  938. // All outgoing external trusts have SID Filtering enabled by default
  939. // add the flag only if the Outgoing side of the trust is being added
  940. if ( fExternalTrust &&
  941. FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) &&
  942. !FLAG_ON( pFullInfo->Information.TrustDirection, TRUST_DIRECTION_OUTBOUND )
  943. )
  944. {
  945. pFullInfo->Information.TrustAttributes |= TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  946. g_fQuarantineSet = TRUE;
  947. }
  948. pFullInfo->Information.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  949. pFullInfo->AuthInformation.IncomingAuthInfos = 1;
  950. pFullInfo->AuthInformation.IncomingAuthenticationInformation = &AuthData;
  951. pFullInfo->AuthInformation.IncomingPreviousAuthenticationInformation = NULL;
  952. // Check for a NULL domain SID. The SID can be NULL if the
  953. // trust was created when the domain was still NT4.
  954. //
  955. if (!pFullInfo->Information.Sid)
  956. {
  957. pFullInfo->Information.Sid = TrustingInfo->Sid;
  958. fSidSet = TRUE;
  959. }
  960. Status = LsaSetTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  961. pName,
  962. TrustedDomainFullInformation,
  963. pFullInfo);
  964. }
  965. }
  966. if (fSidSet)
  967. {
  968. // Sid memory is owned by the TrustingInfo struct, so don't free
  969. // it here.
  970. //
  971. pFullInfo->Information.Sid = NULL;
  972. }
  973. LsaFreeMemory( pFullInfo );
  974. }
  975. }
  976. Win32Err = RtlNtStatusToDosError( Status );
  977. } else {
  978. //
  979. // Doing downlevel
  980. //
  981. if ( Mit ) {
  982. Win32Err = ERROR_INVALID_PARAMETER;
  983. } else {
  984. Win32Err = NetDompTrustAddIncomingDownlevelObject( TrustingInfo,
  985. TrustedInfo,
  986. TrustPassword,
  987. PasswordLength );
  988. if ( Win32Err == ERROR_SUCCESS &&
  989. FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  990. Win32Err = NetDompTrustAddOutgoingDownlevelObject( TrustedInfo,
  991. TrustingInfo,
  992. TrustPassword,
  993. PasswordLength );
  994. if ( Win32Err != ERROR_SUCCESS ) {
  995. Win32Err = NetDompTrustRemoveIncomingDownlevelObject( TrustingInfo,
  996. TrustedInfo );
  997. }
  998. }
  999. }
  1000. }
  1001. if (ERROR_SUCCESS == Win32Err)
  1002. {
  1003. LOG_VERBOSE((MSG_VERBOSE_CREATED_TRUST, (PWSTR) CSafeUnicodeString ( * (TrustingInfo->DomainName ) ),
  1004. (PWSTR) CSafeUnicodeString ( *(TrustedInfo->DomainName) ) ));
  1005. }
  1006. return( Win32Err );
  1007. }
  1008. DWORD
  1009. NetDompResetTrustSC(
  1010. IN PND5_TRUST_INFO TrustingInfo,
  1011. IN PND5_TRUST_INFO TrustedInfo
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. This function will reset the secure channel between two domains
  1016. Arguments:
  1017. TrustingInfo - Information on the trusting side of the domain
  1018. TrustedInfo - Information on the trusted side of the domain
  1019. Return Value:
  1020. ERROR_SUCCESS - The function succeeded
  1021. --*/
  1022. {
  1023. DWORD Win32Err = ERROR_SUCCESS;
  1024. PWSTR ScDomain = NULL;
  1025. PNETLOGON_INFO_2 NetlogonInfo2 = NULL;
  1026. PWSTR FullServer = NULL, pwzDomName = NULL;
  1027. HRESULT hr = NULL;
  1028. size_t cchName = 0;
  1029. size_t cchScDomain = 0;
  1030. if (!TrustingInfo->Server)
  1031. {
  1032. return ERROR_INVALID_PARAMETER;
  1033. }
  1034. hr = StringCchLengthW ( TrustedInfo->Server, MAXSTR, &cchName );
  1035. if ( SUCCEEDED (hr) )
  1036. {
  1037. Win32Err = NetApiBufferAllocate( TrustedInfo->DomainName->Length + sizeof( WCHAR ) +
  1038. ( cchName * sizeof( WCHAR ) ) +
  1039. sizeof( WCHAR ),
  1040. (PVOID*)&ScDomain );
  1041. cchScDomain = ( TrustedInfo->DomainName->Length + sizeof( WCHAR ) +
  1042. ( cchName * sizeof( WCHAR ) ) +
  1043. sizeof( WCHAR )
  1044. ) / sizeof ( WCHAR );
  1045. }
  1046. else
  1047. Win32Err = HRESULT_CODE (hr);
  1048. if (ERROR_SUCCESS != Win32Err)
  1049. {
  1050. return Win32Err;
  1051. }
  1052. if (*(TrustingInfo->Server) == L'\\')
  1053. {
  1054. FullServer = TrustingInfo->Server;
  1055. }
  1056. else
  1057. {
  1058. hr = StringCchLengthW ( TrustingInfo->Server, MAXSTR, &cchName );
  1059. if ( SUCCEEDED (hr) )
  1060. {
  1061. Win32Err = NetApiBufferAllocate( ( cchName + 3) * sizeof(WCHAR),
  1062. (PVOID *)&FullServer);
  1063. }
  1064. else
  1065. Win32Err = HRESULT_CODE ( hr );
  1066. if (ERROR_SUCCESS != Win32Err)
  1067. {
  1068. return Win32Err;
  1069. }
  1070. hr = StringCchPrintfW ( FullServer, cchName + 3, L"\\\\%ws", TrustingInfo->Server);
  1071. if ( FAILED (hr) )
  1072. return HRESULT_CODE (hr);
  1073. }
  1074. CSafeUnicodeString *psustrDomName = NULL;
  1075. if (TrustedInfo->fWasDownlevel)
  1076. {
  1077. psustrDomName = new CSafeUnicodeString ( *(TrustedInfo->FlatName) );
  1078. if ( !psustrDomName )
  1079. return ERROR_NOT_ENOUGH_MEMORY;
  1080. pwzDomName = (PWSTR) (*psustrDomName);
  1081. }
  1082. else
  1083. {
  1084. psustrDomName = new CSafeUnicodeString ( *(TrustedInfo->DomainName) );
  1085. if ( !psustrDomName )
  1086. return ERROR_NOT_ENOUGH_MEMORY;
  1087. pwzDomName = (PWSTR) (*psustrDomName);
  1088. }
  1089. if (*(TrustedInfo->Server) == L'\\')
  1090. {
  1091. hr = StringCchPrintfW ( ScDomain, cchScDomain, L"%ws%ws", pwzDomName, TrustedInfo->Server + 1);
  1092. }
  1093. else
  1094. {
  1095. hr = StringCchPrintfW ( ScDomain, cchScDomain, L"%ws\\%ws", pwzDomName, TrustedInfo->Server);
  1096. }
  1097. delete psustrDomName;
  1098. if ( FAILED (hr) )
  1099. Win32Err = HRESULT_CODE ( hr );
  1100. if ( Win32Err == ERROR_SUCCESS ) {
  1101. LOG_VERBOSE(( MSG_VERBOSE_RESET_SC, ScDomain ));
  1102. Win32Err = I_NetLogonControl2( FullServer,
  1103. NETLOGON_CONTROL_REDISCOVER,
  1104. 2,
  1105. ( LPBYTE )&ScDomain,
  1106. ( LPBYTE *)&NetlogonInfo2 );
  1107. if ( Win32Err == ERROR_NO_SUCH_DOMAIN || Win32Err == ERROR_INVALID_PARAMETER ) {
  1108. LOG_VERBOSE(( MSG_VERBOSE_RETRY_RESET_SC, ScDomain, (PWSTR) CSafeUnicodeString ( *(TrustedInfo->DomainName))));
  1109. //
  1110. // Must be using an downlevel domain, so try it again with out the server
  1111. //
  1112. CSafeUnicodeString st( *(TrustedInfo->DomainName) );
  1113. PWSTR pwszSt = (PWSTR) st;
  1114. Win32Err = I_NetLogonControl2( FullServer,
  1115. NETLOGON_CONTROL_REDISCOVER,
  1116. 2,
  1117. ( LPBYTE )&st,
  1118. ( LPBYTE *)&NetlogonInfo2 );
  1119. if ( Win32Err == ERROR_SUCCESS ) {
  1120. LOG_VERBOSE(( MSG_VERBOSE_RESET_NOT_NAMED, TrustedInfo->Server ));
  1121. }
  1122. }
  1123. }
  1124. NetApiBufferFree( ScDomain );
  1125. if (FullServer != TrustingInfo->Server)
  1126. {
  1127. NetApiBufferFree(FullServer);
  1128. }
  1129. return( Win32Err );
  1130. }
  1131. DWORD
  1132. NetDompTrustRemoveObject(
  1133. IN PND5_TRUST_INFO LocalDomainInfo,
  1134. IN PND5_TRUST_INFO TrustDomainInfo,
  1135. IN ULONG Direction,
  1136. IN BOOL fForce,
  1137. IN PND5_AUTH_INFO pAuthInfo
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This function removes the specified trust
  1142. Arguments:
  1143. LocalDomainInfo - Info on the domain where the operation is being performed
  1144. TrustDomainInfo - Info on the trusted/trusting domain
  1145. Direction - The direction of the trust
  1146. fForce - If true, remove even if a child.
  1147. Return Value:
  1148. ERROR_INVALID_PARAMETER - No object name was supplied
  1149. --*/
  1150. {
  1151. DWORD Win32Err = ERROR_SUCCESS;
  1152. NTSTATUS Status = STATUS_SUCCESS;
  1153. PTRUSTED_DOMAIN_INFORMATION_EX ReadTDIEx = NULL;
  1154. BOOL fChild = (TrustDomainInfo->Flags & NETDOM_TRUST_FLAG_CHILD);
  1155. PLDAP pLdap;
  1156. HANDLE hDS;
  1157. PWSTR pwzConfigPath, pwzPartitionsPath, pwzFSMORoleOwner, pwzServerPath,
  1158. pwzServerDNSname, pwzDomainName, pwzNcName, pwzServerObjDN, pwzSettingsDN,
  1159. pwzFilter;
  1160. WCHAR wzPartition[] = L"CN=Partitions,";
  1161. WCHAR wzFilterFormat[] = L"(&(objectClass=nTDSDSA)(hasMasterNCs=%s))";
  1162. RPC_AUTH_IDENTITY_HANDLE AuthHandle;
  1163. PDS_NAME_RESULT pNameResult;
  1164. LDAPMessage *Message = NULL, *Entry;
  1165. PWSTR Attrib[2] = {
  1166. L"foo",
  1167. NULL
  1168. };
  1169. ASSERT(!(fChild && !fForce));
  1170. ASSERT(!(TrustDomainInfo->Flags & NETDOM_TRUST_FLAG_PARENT));
  1171. if ( LocalDomainInfo->Uplevel )
  1172. {
  1173. LOG_VERBOSE(( MSG_VERBOSE_OPEN_TRUST, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName)) ));
  1174. if ( !LocalDomainInfo->TrustHandle ) {
  1175. Status = LsaOpenTrustedDomainByName( LocalDomainInfo->LsaHandle,
  1176. TrustDomainInfo->DomainName,
  1177. TRUSTED_ALL_ACCESS, // DELETE | TRUSTED_QUERY_DOMAIN_NAME,
  1178. &( LocalDomainInfo->TrustHandle ) );
  1179. }
  1180. if (STATUS_OBJECT_NAME_NOT_FOUND == Status && TrustDomainInfo->Uplevel) {
  1181. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  1182. // have a flat name.
  1183. //
  1184. TrustDomainInfo->fWasDownlevel = TRUE;
  1185. Status = LsaOpenTrustedDomainByName( LocalDomainInfo->LsaHandle,
  1186. TrustDomainInfo->FlatName,
  1187. TRUSTED_ALL_ACCESS, // DELETE | TRUSTED_QUERY_DOMAIN_NAME,
  1188. &( LocalDomainInfo->TrustHandle ) );
  1189. }
  1190. if ( STATUS_OBJECT_NAME_NOT_FOUND == Status && TrustDomainInfo->Sid )
  1191. {
  1192. Status = LsaOpenTrustedDomain ( LocalDomainInfo->LsaHandle,
  1193. TrustDomainInfo->Sid,
  1194. TRUSTED_ALL_ACCESS, // DELETE | TRUSTED_QUERY_DOMAIN_NAME,
  1195. &( LocalDomainInfo->TrustHandle ) );
  1196. }
  1197. if ( NT_SUCCESS( Status ) ) {
  1198. if ( Direction == TRUST_DIRECTION_BIDIRECTIONAL ) {
  1199. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName)) ));
  1200. Status = LsaDelete( LocalDomainInfo->TrustHandle );
  1201. if ( NT_SUCCESS( Status ) ) {
  1202. LocalDomainInfo->TrustHandle = NULL;
  1203. }
  1204. } else {
  1205. LOG_VERBOSE(( MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName) ) ));
  1206. Status = LsaQueryInfoTrustedDomain( LocalDomainInfo->TrustHandle,
  1207. TrustedDomainInformationEx,
  1208. (PVOID*)&ReadTDIEx );
  1209. if ( NT_SUCCESS( Status ) ) {
  1210. // If the outgoing side of the trust is being removed, clear the
  1211. // SID filtering bit
  1212. ReadTDIEx->TrustDirection &= ~Direction;
  1213. if ( ! ( ReadTDIEx->TrustDirection & TRUST_DIRECTION_OUTBOUND ) )
  1214. {
  1215. ReadTDIEx->TrustAttributes &= ~TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  1216. }
  1217. if ( 0 == ReadTDIEx->TrustDirection ) {
  1218. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName)) ));
  1219. Status = LsaDelete( LocalDomainInfo->TrustHandle );
  1220. if ( NT_SUCCESS( Status ) ) {
  1221. LocalDomainInfo->TrustHandle = NULL;
  1222. }
  1223. }
  1224. else {
  1225. LOG_VERBOSE(( MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( * (TrustDomainInfo->DomainName)) ));
  1226. Status = LsaSetInformationTrustedDomain( LocalDomainInfo->TrustHandle,
  1227. TrustedDomainInformationEx,
  1228. ReadTDIEx );
  1229. }
  1230. LsaFreeMemory( ReadTDIEx );
  1231. }
  1232. }
  1233. }
  1234. else {
  1235. if (STATUS_OBJECT_NAME_NOT_FOUND == Status) {
  1236. LOG_VERBOSE(( MSG_VERBOSE_TDO_NOT_FOUND, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName)) ));
  1237. }
  1238. }
  1239. Win32Err = LsaNtStatusToWinError(Status);
  1240. DBG_VERBOSE(("Return code from LsaOpen: %d (LSA: %x)\n", Win32Err, Status));
  1241. if (fChild) {
  1242. // Remove the cross ref object. To do that, locate and bind to the naming
  1243. // FSMO DC.
  1244. //
  1245. LOG_VERBOSE((MSG_VERBOSE_DELETE_CROSS_REF, (PWSTR) CSafeUnicodeString ( *(TrustDomainInfo->DomainName)) ));
  1246. Win32Err = NetDompLdapBind(LocalDomainInfo->Server + 2, // skip the backslashes
  1247. (pAuthInfo->pwzUsersDomain) ?
  1248. pAuthInfo->pwzUsersDomain : NULL,
  1249. (pAuthInfo->pwzUserWoDomain) ?
  1250. pAuthInfo->pwzUserWoDomain : pAuthInfo->User,
  1251. pAuthInfo->Password,
  1252. LDAP_AUTH_SSPI,
  1253. &pLdap);
  1254. if (Win32Err != ERROR_SUCCESS)
  1255. {
  1256. return Win32Err;
  1257. }
  1258. DBG_VERBOSE(("bind succeeded\n"));
  1259. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1260. NULL, //L"RootDSE",
  1261. L"configurationNamingContext",
  1262. &pwzConfigPath);
  1263. if (Win32Err != ERROR_SUCCESS)
  1264. {
  1265. NetDompLdapUnbind(pLdap);
  1266. return Win32Err;
  1267. }
  1268. Win32Err = NetApiBufferAllocate((wcslen(pwzConfigPath) + wcslen(wzPartition) + 1) * sizeof(WCHAR),
  1269. (PVOID*)&pwzPartitionsPath);
  1270. if (Win32Err != ERROR_SUCCESS)
  1271. {
  1272. NetApiBufferFree(pwzConfigPath);
  1273. NetDompLdapUnbind(pLdap);
  1274. return Win32Err;
  1275. }
  1276. wsprintf(pwzPartitionsPath, L"%s%s", wzPartition, pwzConfigPath);
  1277. DBG_VERBOSE(("path: %ws\n", pwzPartitionsPath));
  1278. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1279. pwzPartitionsPath,
  1280. L"fSMORoleOwner",
  1281. &pwzFSMORoleOwner);
  1282. NetApiBufferFree(pwzPartitionsPath);
  1283. if (Win32Err != ERROR_SUCCESS)
  1284. {
  1285. NetApiBufferFree(pwzConfigPath);
  1286. NetDompLdapUnbind(pLdap);
  1287. return Win32Err;
  1288. }
  1289. DBG_VERBOSE(("fSMORoleOwner: %ws\n", pwzFSMORoleOwner));
  1290. pwzServerPath = wcschr(pwzFSMORoleOwner, L',');
  1291. if (!pwzServerPath)
  1292. {
  1293. NetApiBufferFree(pwzConfigPath);
  1294. NetApiBufferFree(pwzFSMORoleOwner);
  1295. NetDompLdapUnbind(pLdap);
  1296. return ERROR_INVALID_DATA;
  1297. }
  1298. pwzServerPath++;
  1299. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1300. pwzServerPath,
  1301. L"dNSHostName",
  1302. &pwzServerDNSname);
  1303. NetApiBufferFree(pwzFSMORoleOwner);
  1304. if (Win32Err != ERROR_SUCCESS)
  1305. {
  1306. NetApiBufferFree(pwzConfigPath);
  1307. NetDompLdapUnbind(pLdap);
  1308. return Win32Err;
  1309. }
  1310. DBG_VERBOSE(("Role owner server DNS name: %ws\n", pwzServerDNSname));
  1311. Win32Err = DsMakePasswordCredentials((pAuthInfo->pwzUserWoDomain) ?
  1312. pAuthInfo->pwzUserWoDomain : pAuthInfo->User,
  1313. (pAuthInfo->pwzUsersDomain) ?
  1314. pAuthInfo->pwzUsersDomain : NULL,
  1315. pAuthInfo->Password,
  1316. &AuthHandle);
  1317. if (Win32Err != ERROR_SUCCESS)
  1318. {
  1319. NetApiBufferFree(pwzConfigPath);
  1320. NetApiBufferFree(pwzServerDNSname);
  1321. return Win32Err;
  1322. }
  1323. Win32Err = DsBindWithCred(pwzServerDNSname, NULL, AuthHandle, &hDS);
  1324. NetApiBufferFree(pwzServerDNSname);
  1325. DsFreePasswordCredentials(AuthHandle);
  1326. if (Win32Err != ERROR_SUCCESS)
  1327. {
  1328. NetApiBufferFree(pwzConfigPath);
  1329. return Win32Err;
  1330. }
  1331. DBG_VERBOSE(("DsBind Succeeded, getting domain NC name.\n"));
  1332. CSafeUnicodeString susDomName ( * (TrustDomainInfo->DomainName) );
  1333. Win32Err = NetApiBufferAllocate( ( susDomName.Length () + 2) * sizeof(WCHAR),
  1334. (PVOID*)&pwzDomainName);
  1335. if (Win32Err != ERROR_SUCCESS)
  1336. {
  1337. NetApiBufferFree(pwzConfigPath);
  1338. NetDompLdapUnbind(pLdap);
  1339. DsUnBind(&hDS);
  1340. return Win32Err;
  1341. }
  1342. //
  1343. // Get the domain Naming Context DN to use for the removal of the cross-ref.
  1344. // On the first try to get the domain NC DN, assume that the domain name is
  1345. // an NT4 flat name. A backslash must be appended.
  1346. //
  1347. wcscpy(pwzDomainName, (PWSTR) susDomName);
  1348. wcscat(pwzDomainName, L"\\");
  1349. DBG_VERBOSE(("Name passed to DsCrackNames is %ws.\n", pwzDomainName));
  1350. Win32Err = DsCrackNames(hDS,
  1351. DS_NAME_NO_FLAGS,
  1352. DS_NT4_ACCOUNT_NAME,
  1353. DS_FQDN_1779_NAME,
  1354. 1,
  1355. &pwzDomainName,
  1356. &pNameResult);
  1357. if (Win32Err != ERROR_SUCCESS)
  1358. {
  1359. NetApiBufferFree(pwzConfigPath);
  1360. NetApiBufferFree(pwzDomainName);
  1361. NetDompLdapUnbind(pLdap);
  1362. DsUnBind(&hDS);
  1363. return Win32Err;
  1364. }
  1365. ASSERT(pNameResult);
  1366. ASSERT(pNameResult->cItems == 1);
  1367. if (DS_NAME_NO_ERROR != pNameResult->rItems->status)
  1368. {
  1369. // Try again, this time assume that it might be a DNS name. Replace
  1370. // the back slash with a forward slash.
  1371. //
  1372. pwzDomainName[wcslen(pwzDomainName) -1] = L'/';
  1373. DsFreeNameResultW(pNameResult);
  1374. DBG_VERBOSE(("Try again, name passed to DsCrackNames is %ws.\n", pwzDomainName));
  1375. Win32Err = DsCrackNames(hDS,
  1376. DS_NAME_NO_FLAGS,
  1377. DS_CANONICAL_NAME,
  1378. DS_FQDN_1779_NAME,
  1379. 1,
  1380. &pwzDomainName,
  1381. &pNameResult);
  1382. if (Win32Err != ERROR_SUCCESS)
  1383. {
  1384. NetApiBufferFree(pwzConfigPath);
  1385. NetApiBufferFree(pwzDomainName);
  1386. NetDompLdapUnbind(pLdap);
  1387. DsUnBind(&hDS);
  1388. return Win32Err;
  1389. }
  1390. ASSERT(pNameResult);
  1391. ASSERT(pNameResult->cItems == 1);
  1392. }
  1393. NetApiBufferFree(pwzDomainName);
  1394. if (DS_NAME_NO_ERROR != pNameResult->rItems->status)
  1395. {
  1396. NetApiBufferFree(pwzConfigPath);
  1397. DsFreeNameResultW(pNameResult);
  1398. NetDompLdapUnbind(pLdap);
  1399. DsUnBind(&hDS);
  1400. return ERROR_NO_SUCH_DOMAIN;
  1401. }
  1402. //
  1403. // Delete the Server object for the domain. Get the name of the server
  1404. // object by searching for the NTDS-Settings object that references the
  1405. // domain NC.
  1406. //
  1407. Win32Err = NetApiBufferAllocate((wcslen(wzFilterFormat) + wcslen(pNameResult->rItems->pName) + 1) * sizeof(WCHAR),
  1408. (PVOID*)&pwzFilter);
  1409. if (Win32Err != ERROR_SUCCESS)
  1410. {
  1411. DsFreeNameResultW(pNameResult);
  1412. NetApiBufferFree(pwzConfigPath);
  1413. NetDompLdapUnbind(pLdap);
  1414. DsUnBind(&hDS);
  1415. return Win32Err;
  1416. }
  1417. swprintf(pwzFilter, wzFilterFormat, pNameResult->rItems->pName);
  1418. DBG_VERBOSE(("search filter: %ws\n", pwzFilter));
  1419. Win32Err = LdapMapErrorToWin32(ldap_search_s(pLdap,
  1420. pwzConfigPath,
  1421. LDAP_SCOPE_SUBTREE,
  1422. pwzFilter,
  1423. Attrib,
  1424. 0,
  1425. &Message));
  1426. if (Win32Err != ERROR_SUCCESS)
  1427. {
  1428. if (Message) ldap_msgfree(Message);
  1429. DBG_VERBOSE(("search for Settings object failed with error %d\n", Win32Err));
  1430. NetApiBufferFree(pwzConfigPath);
  1431. DsFreeNameResultW(pNameResult);
  1432. NetDompLdapUnbind(pLdap);
  1433. DsUnBind(&hDS);
  1434. return Win32Err;
  1435. }
  1436. Entry = ldap_first_entry(pLdap, Message);
  1437. if (Entry) {
  1438. pwzSettingsDN = ldap_get_dnW(pLdap, Entry);
  1439. DBG_VERBOSE(("NTDS Settings object DN: %ws\n", pwzSettingsDN));
  1440. if (pwzSettingsDN) {
  1441. pwzServerObjDN = wcschr(pwzSettingsDN, L',');
  1442. if (pwzServerObjDN) {
  1443. pwzServerObjDN++;
  1444. Win32Err = DsRemoveDsServerW(hDS,
  1445. pwzServerObjDN,
  1446. NULL,
  1447. NULL,
  1448. TRUE);
  1449. if (Win32Err == ERROR_SUCCESS)
  1450. {
  1451. LOG_VERBOSE((MSG_VERBOSE_NTDSDSA_DELETED, pwzServerObjDN));
  1452. }
  1453. else
  1454. {
  1455. DBG_VERBOSE(("DsRemoveDsServer failed with error %d\n", Win32Err));
  1456. LOG_VERBOSE((MSG_VERBOSE_NTDSDSA_NOT_REMOVED, pwzServerObjDN));
  1457. }
  1458. }
  1459. }
  1460. ldap_memfree(pwzSettingsDN);
  1461. } else {
  1462. Win32Err = LdapMapErrorToWin32(pLdap->ld_errno);
  1463. DBG_VERBOSE(("search results for Settings object failed with error %d\n", Win32Err));
  1464. }
  1465. ldap_msgfree(Message);
  1466. NetDompLdapUnbind(pLdap); // add to error returns above.
  1467. NetApiBufferFree(pwzConfigPath);
  1468. //
  1469. // Now remove the cross-ref object.
  1470. //
  1471. DBG_VERBOSE(("About to remove the cross-ref for NC %ws.\n", pNameResult->rItems->pName));
  1472. Win32Err = DsRemoveDsDomainW(hDS, pNameResult->rItems->pName);
  1473. if (Win32Err == ERROR_SUCCESS)
  1474. {
  1475. LOG_VERBOSE((MSG_VERBOSE_CROSS_REF_DELETED, pNameResult->rItems->pName));
  1476. }
  1477. else
  1478. {
  1479. DBG_VERBOSE(("DsRemoveDsDomain returned %d.\n", Win32Err));
  1480. if (ERROR_DS_NO_CROSSREF_FOR_NC == Win32Err)
  1481. {
  1482. LOG_VERBOSE((MSG_VERBOSE_CROSS_REF_NOT_FOUND, pNameResult->rItems->pName));
  1483. }
  1484. }
  1485. DsFreeNameResultW(pNameResult);
  1486. DsUnBind(&hDS);
  1487. }
  1488. } else {
  1489. if ( FLAG_ON( Direction, TRUST_DIRECTION_INBOUND ) ) {
  1490. Win32Err = NetDompTrustRemoveIncomingDownlevelObject( TrustDomainInfo,
  1491. LocalDomainInfo );
  1492. if ( Win32Err == NERR_UserNotFound ) {
  1493. Win32Err = ERROR_SUCCESS;
  1494. }
  1495. }
  1496. if ( Win32Err == ERROR_SUCCESS && FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  1497. Win32Err = NetDompTrustRemoveOutgoingDownlevelObject( LocalDomainInfo,
  1498. TrustDomainInfo );
  1499. }
  1500. }
  1501. return( Win32Err );
  1502. }
  1503. DWORD
  1504. NetDompCreateTrustObject(
  1505. IN ARG_RECORD * rgNetDomArgs,
  1506. IN PWSTR TrustingDomain,
  1507. IN PWSTR TrustedDomain,
  1508. IN PND5_AUTH_INFO pTrustingCreds,
  1509. IN PND5_AUTH_INFO pTrustedCreds,
  1510. IN PWSTR pwzTrustPW,
  1511. IN PWSTR pwzWhichSide
  1512. )
  1513. /*++
  1514. Routine Description:
  1515. This function will handle the adding of a trusted domain object
  1516. Arguments:
  1517. rgNetDomArgs - List of arguments present in the Args list
  1518. TrustingDomain - Trusting side of the trust
  1519. TrustedDomain - Trusted side of the trust
  1520. pTrustingCreds - Credentials to use when connecting to a domain controller in the
  1521. trusting domain
  1522. pTrustedCreds - Credentials to use when connecting to a domain controller in the
  1523. trusted domain
  1524. pwzTrustPW - Required for creating MIT trust.
  1525. pwzWhichSide - Required for creating one-side-only, names the side.
  1526. Return Value:
  1527. ERROR_INVALID_PARAMETER - No object name was supplied
  1528. --*/
  1529. {
  1530. DWORD Win32Err = ERROR_SUCCESS;
  1531. ND5_TRUST_INFO TrustingInfo, TrustedInfo;
  1532. WCHAR TrustPassword[ LM20_PWLEN + 1 ];
  1533. PWSTR pwzPW = NULL;
  1534. WCHAR wzTrusted[NETDOM_STR_LEN], wzTrusting[NETDOM_STR_LEN];
  1535. BOOL fCreateOnTrusted = FALSE, fCreateOnTrusting = FALSE;
  1536. g_fQuarantineSet = FALSE;
  1537. RtlZeroMemory( &TrustingInfo, sizeof( TrustingInfo ) );
  1538. RtlZeroMemory( &TrustedInfo, sizeof( TrustedInfo ) );
  1539. if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  1540. {
  1541. if (!LoadString(g_hInstance, IDS_ONESIDE_TRUSTED, wzTrusted, NETDOM_STR_LEN) ||
  1542. !LoadString(g_hInstance, IDS_ONESIDE_TRUSTING, wzTrusting, NETDOM_STR_LEN))
  1543. {
  1544. printf("LoadString FAILED!\n");
  1545. return ERROR_RESOURCE_NAME_NOT_FOUND;
  1546. }
  1547. // Determine on which domain the trust should be created.
  1548. //
  1549. if (_wcsicmp(pwzWhichSide, wzTrusted) == 0)
  1550. {
  1551. fCreateOnTrusted = TRUE;
  1552. }
  1553. else if (_wcsicmp(pwzWhichSide, wzTrusting) == 0)
  1554. {
  1555. fCreateOnTrusting = TRUE;
  1556. }
  1557. else
  1558. {
  1559. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  1560. return ERROR_INVALID_PARAMETER;
  1561. }
  1562. }
  1563. Win32Err = NetDompTrustGetDomInfo( TrustingDomain,
  1564. NULL,
  1565. pTrustingCreds,
  1566. &TrustingInfo,
  1567. !fCreateOnTrusted,
  1568. CmdFlagOn(rgNetDomArgs, eTrustRealm),
  1569. fCreateOnTrusted);
  1570. if ( Win32Err == ERROR_SUCCESS ) {
  1571. Win32Err = NetDompTrustGetDomInfo( TrustedDomain,
  1572. NULL,
  1573. pTrustedCreds,
  1574. &TrustedInfo,
  1575. !fCreateOnTrusting,
  1576. CmdFlagOn(rgNetDomArgs, eTrustRealm),
  1577. fCreateOnTrusting);
  1578. }
  1579. if ( Win32Err != ERROR_SUCCESS ) {
  1580. goto TrustAddExit;
  1581. }
  1582. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  1583. {
  1584. if (!(TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  1585. !(TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  1586. {
  1587. // Both domains found (both are Windows domains), can't establish an MIT trust.
  1588. //
  1589. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  1590. Win32Err = ERROR_INVALID_PARAMETER;
  1591. goto TrustAddExit;
  1592. }
  1593. pwzPW = pwzTrustPW;
  1594. }
  1595. else if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  1596. {
  1597. // Create the trust on only one of the two domains.
  1598. //
  1599. if (fCreateOnTrusted)
  1600. {
  1601. Win32Err = NetDompAddOnTrustedSide(&TrustedInfo,
  1602. &TrustingInfo,
  1603. pwzTrustPW,
  1604. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1605. TRUST_DIRECTION_BIDIRECTIONAL :
  1606. TRUST_DIRECTION_INBOUND,
  1607. FALSE);
  1608. }
  1609. else
  1610. {
  1611. Win32Err = NetDompAddOnTrustingSide(&TrustedInfo,
  1612. &TrustingInfo,
  1613. pwzTrustPW,
  1614. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1615. TRUST_DIRECTION_BIDIRECTIONAL :
  1616. TRUST_DIRECTION_OUTBOUND,
  1617. FALSE);
  1618. }
  1619. goto TrustAddExit;
  1620. }
  1621. else
  1622. {
  1623. Win32Err = NetDompGenerateRandomPassword( TrustPassword,
  1624. LM20_PWLEN );
  1625. if ( Win32Err != ERROR_SUCCESS ) {
  1626. goto TrustAddExit;
  1627. }
  1628. pwzPW = TrustPassword;
  1629. }
  1630. //
  1631. // Ok, now that we have the password, let's create the trust
  1632. //
  1633. Win32Err = NetDompAddOnTrustedSide( &TrustedInfo,
  1634. &TrustingInfo,
  1635. pwzPW,
  1636. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1637. TRUST_DIRECTION_BIDIRECTIONAL :
  1638. TRUST_DIRECTION_INBOUND,
  1639. CmdFlagOn(rgNetDomArgs, eTrustRealm));
  1640. if ( Win32Err == ERROR_SUCCESS ) {
  1641. Win32Err = NetDompAddOnTrustingSide( &TrustedInfo,
  1642. &TrustingInfo,
  1643. pwzPW,
  1644. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1645. TRUST_DIRECTION_BIDIRECTIONAL :
  1646. TRUST_DIRECTION_OUTBOUND,
  1647. CmdFlagOn(rgNetDomArgs, eTrustRealm));
  1648. }
  1649. TrustAddExit:
  1650. if ( g_fQuarantineSet )
  1651. {
  1652. NetDompDisplayMessage ( MSG_QUARANTINE_SET_TRUST_CREATION );
  1653. }
  1654. NetDompFreeDomInfo( &TrustedInfo );
  1655. NetDompFreeDomInfo( &TrustingInfo );
  1656. return( Win32Err );
  1657. }
  1658. DWORD
  1659. NetDompRemoveTrustObject(
  1660. IN ARG_RECORD * rgNetDomArgs,
  1661. IN PWSTR TrustingDomain,
  1662. IN PWSTR TrustedDomain,
  1663. IN PND5_AUTH_INFO pTrustingCreds,
  1664. IN PND5_AUTH_INFO pTrustedCreds,
  1665. IN PWSTR pwzWhichSide
  1666. )
  1667. /*++
  1668. Routine Description:
  1669. This function will handle the removal of a trusted domain object
  1670. Arguments:
  1671. rgNetDomArgs - List of arguments present in the Args list
  1672. TrustingDomain - Trusting side of the trust
  1673. TrustedDomain - Trusted side of the trust
  1674. pTrustingCreds - Credentials to use when connecting to a domain controller in the
  1675. trusting domain
  1676. pTrustedCreds - Credentials to use when connecting to a domain controller in the
  1677. trusted domain
  1678. pwzWhichSide - Domain from which trust is to be removed. If /OneSide is specified
  1679. then must be trusting or trusted. Otherwise should be NULL
  1680. Return Value:
  1681. ERROR_INVALID_PARAMETER - No object name was supplied
  1682. --*/
  1683. {
  1684. DWORD Win32Err = ERROR_SUCCESS;
  1685. ND5_TRUST_INFO TrustingInfo, TrustedInfo;
  1686. BOOL fForce = CmdFlagOn(rgNetDomArgs, eCommForce);
  1687. BOOL TwoWay = CmdFlagOn(rgNetDomArgs, eTrustTwoWay);
  1688. BOOL fParentChild = FALSE, fVerifyChildDelete = FALSE;
  1689. RtlZeroMemory( &TrustingInfo, sizeof( TrustingInfo ) );
  1690. RtlZeroMemory( &TrustedInfo, sizeof( TrustedInfo ) );
  1691. WCHAR wzTrusted[NETDOM_STR_LEN], wzTrusting[NETDOM_STR_LEN];
  1692. BOOL fDeleteOnTrusted = TRUE, fDeleteOnTrusting = TRUE;
  1693. if (CmdFlagOn(rgNetDomArgs, eTrustOneSide) )
  1694. {
  1695. ASSERT ( pwzWhichSide );
  1696. if ( !pwzWhichSide )
  1697. {
  1698. return ERROR_INVALID_PARAMETER;
  1699. }
  1700. if (!LoadString(g_hInstance, IDS_ONESIDE_TRUSTED, wzTrusted, NETDOM_STR_LEN) ||
  1701. !LoadString(g_hInstance, IDS_ONESIDE_TRUSTING, wzTrusting, NETDOM_STR_LEN))
  1702. {
  1703. printf("LoadString FAILED!\n");
  1704. return ERROR_RESOURCE_NAME_NOT_FOUND;
  1705. }
  1706. // Determine on which domain the trust should be deleted.
  1707. //
  1708. if (_wcsicmp(pwzWhichSide, wzTrusted) == 0)
  1709. {
  1710. fDeleteOnTrusting = FALSE;
  1711. }
  1712. else if (_wcsicmp(pwzWhichSide, wzTrusting) == 0)
  1713. {
  1714. fDeleteOnTrusted = FALSE;
  1715. }
  1716. else
  1717. {
  1718. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  1719. return ERROR_INVALID_PARAMETER;
  1720. }
  1721. }
  1722. Win32Err = NetDompTrustGetDomInfo( TrustingDomain,
  1723. NULL,
  1724. pTrustingCreds,
  1725. &TrustingInfo,
  1726. fDeleteOnTrusting,
  1727. fForce || !fDeleteOnTrusting,
  1728. !fDeleteOnTrusting );
  1729. if ( Win32Err == ERROR_SUCCESS ) {
  1730. Win32Err = NetDompTrustGetDomInfo( TrustedDomain,
  1731. NULL,
  1732. pTrustedCreds,
  1733. &TrustedInfo,
  1734. fDeleteOnTrusted,
  1735. fForce || !fDeleteOnTrusted,
  1736. !fDeleteOnTrusted );
  1737. }
  1738. if ( Win32Err != ERROR_SUCCESS ) {
  1739. if (ERROR_NO_SUCH_DOMAIN == Win32Err) {
  1740. NetDompDisplayMessage(MSG_TRUST_DOMAIN_NOT_FOUND);
  1741. }
  1742. goto TrustRemoveExit;
  1743. }
  1744. Win32Err = NetDompIsParentChild(&TrustingInfo,
  1745. &TrustedInfo,
  1746. &fParentChild);
  1747. if ( Win32Err != ERROR_SUCCESS )
  1748. {
  1749. goto TrustRemoveExit;
  1750. }
  1751. if (fParentChild)
  1752. {
  1753. // Enforce rules for parent-child trust.
  1754. //
  1755. if (TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1756. {
  1757. if (TrustingInfo.Flags & NETDOM_TRUST_FLAG_PARENT)
  1758. {
  1759. // The domain that wasn't found was the parent, deletion not allowed.
  1760. //
  1761. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT);
  1762. printf("\n");
  1763. Win32Err = ERROR_NOT_SUPPORTED;
  1764. goto TrustRemoveExit;
  1765. }
  1766. else
  1767. {
  1768. if (!fForce)
  1769. {
  1770. // Force flag required to delete non-existant child.
  1771. //
  1772. NetDompDisplayMessage(MSG_DELETE_CHILD_FORCE_REQ);
  1773. printf("\n");
  1774. Win32Err = ERROR_NOT_SUPPORTED;
  1775. goto TrustRemoveExit;
  1776. }
  1777. else
  1778. {
  1779. fVerifyChildDelete = TRUE;
  1780. }
  1781. }
  1782. }
  1783. else {
  1784. if (TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1785. {
  1786. if (TrustedInfo.Flags & NETDOM_TRUST_FLAG_PARENT)
  1787. {
  1788. // The domain that wasn't found was the parent, deletion not allowed.
  1789. //
  1790. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT);
  1791. printf("\n");
  1792. Win32Err = ERROR_NOT_SUPPORTED;
  1793. goto TrustRemoveExit;
  1794. }
  1795. else
  1796. {
  1797. if (!fForce)
  1798. {
  1799. // Force flag required to delete non-existant child.
  1800. //
  1801. NetDompDisplayMessage(MSG_DELETE_CHILD_FORCE_REQ);
  1802. printf("\n");
  1803. Win32Err = ERROR_NOT_SUPPORTED;
  1804. goto TrustRemoveExit;
  1805. }
  1806. else
  1807. {
  1808. fVerifyChildDelete = TRUE;
  1809. }
  1810. }
  1811. }
  1812. else
  1813. {
  1814. // Both domains were found, don't allow deletion.
  1815. //
  1816. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT_CHILD);
  1817. printf("\n");
  1818. Win32Err = ERROR_NOT_SUPPORTED;
  1819. goto TrustRemoveExit;
  1820. }
  1821. }
  1822. }
  1823. if (fVerifyChildDelete)
  1824. {
  1825. // Put up a message box asking for confirmation of the deletion.
  1826. //
  1827. CSafeUnicodeString sustrDomain = CSafeUnicodeString ( (TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) ?
  1828. *( TrustingInfo.DomainName ) : *( TrustedInfo.DomainName ) );
  1829. PWSTR pwzDomain = (PWSTR) sustrDomain ;
  1830. if (!NetDompGetUserConfirmation(IDS_PROMPT_DEL_TRUST, pwzDomain))
  1831. {
  1832. goto TrustRemoveExit;
  1833. }
  1834. }
  1835. if (!(TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  1836. fDeleteOnTrusting
  1837. )
  1838. {
  1839. Win32Err = NetDompTrustRemoveObject( &TrustingInfo,
  1840. &TrustedInfo,
  1841. (TwoWay || fForce) ?
  1842. TRUST_DIRECTION_BIDIRECTIONAL :
  1843. TRUST_DIRECTION_OUTBOUND,
  1844. fForce,
  1845. pTrustingCreds );
  1846. }
  1847. if (
  1848. Win32Err == ERROR_SUCCESS &&
  1849. fDeleteOnTrusted &&
  1850. !CmdFlagOn(rgNetDomArgs, eTrustRealm) &&
  1851. !(TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1852. )
  1853. {
  1854. Win32Err = NetDompTrustRemoveObject( &TrustedInfo,
  1855. &TrustingInfo,
  1856. (TwoWay || fForce) ?
  1857. TRUST_DIRECTION_BIDIRECTIONAL :
  1858. TRUST_DIRECTION_INBOUND,
  1859. fForce,
  1860. pTrustedCreds );
  1861. }
  1862. TrustRemoveExit:
  1863. NetDompFreeDomInfo( &TrustedInfo );
  1864. NetDompFreeDomInfo( &TrustingInfo );
  1865. return( Win32Err );
  1866. }
  1867. DWORD
  1868. NetDompSetTrustPW(
  1869. IN PND5_TRUST_INFO pDomain1Info,
  1870. IN PND5_TRUST_INFO pDomain2Info,
  1871. IN PWSTR pwzNewTrustPW,
  1872. OUT PDWORD pDirection,
  1873. IN BOOL bErasePWHistory = FALSE OPTIONAL
  1874. )
  1875. /*++
  1876. Routine Description:
  1877. This function will set the trust password on Domain1.
  1878. Arguments:
  1879. pDomain1Info - Domain on which to set the trust passwords
  1880. pDomain2Info - Domain whose TDO should be set.
  1881. pwzNewTrustPW - new trust password to use.
  1882. Return Value:
  1883. ERROR_INVALID_PARAMETER - No object name was supplied
  1884. --*/
  1885. {
  1886. DWORD Win32Err = ERROR_SUCCESS;
  1887. PTRUSTED_DOMAIN_FULL_INFORMATION pOldDomain1TDFInfo = NULL;
  1888. TRUSTED_DOMAIN_FULL_INFORMATION NewDomain1TDFInfo;
  1889. LSA_AUTH_INFORMATION NewAuthInfo;
  1890. LARGE_INTEGER ft;
  1891. NTSTATUS Status = STATUS_SUCCESS;
  1892. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomain1Info->DomainName )) ));
  1893. if (pDomain2Info->Sid)
  1894. {
  1895. Status = LsaQueryTrustedDomainInfo(pDomain1Info->LsaHandle,
  1896. pDomain2Info->Sid,
  1897. TrustedDomainFullInformation,
  1898. (PVOID *)&pOldDomain1TDFInfo);
  1899. }
  1900. else
  1901. {
  1902. Status = LsaQueryTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1903. pDomain2Info->DomainName,
  1904. TrustedDomainFullInformation,
  1905. (PVOID *)&pOldDomain1TDFInfo);
  1906. }
  1907. Win32Err = LsaNtStatusToWinError(Status);
  1908. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  1909. if (pDirection)
  1910. {
  1911. *pDirection = pOldDomain1TDFInfo->Information.TrustDirection;
  1912. }
  1913. GetSystemTimeAsFileTime((PFILETIME)&ft);
  1914. //
  1915. // Set the current password data.
  1916. //
  1917. NewAuthInfo.LastUpdateTime = ft;
  1918. NewAuthInfo.AuthType = TRUST_AUTH_TYPE_CLEAR;
  1919. NewAuthInfo.AuthInfoLength = wcslen(pwzNewTrustPW) * sizeof(WCHAR);
  1920. NewAuthInfo.AuthInfo = (PUCHAR)pwzNewTrustPW;
  1921. ZeroMemory(&NewDomain1TDFInfo, sizeof(TRUSTED_DOMAIN_FULL_INFORMATION));
  1922. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_INBOUND)
  1923. {
  1924. NewDomain1TDFInfo.AuthInformation.IncomingAuthInfos = 1;
  1925. NewDomain1TDFInfo.AuthInformation.IncomingAuthenticationInformation = &NewAuthInfo;
  1926. NewDomain1TDFInfo.AuthInformation.IncomingPreviousAuthenticationInformation = bErasePWHistory ? &NewAuthInfo : NULL;
  1927. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  1928. }
  1929. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_OUTBOUND)
  1930. {
  1931. NewDomain1TDFInfo.AuthInformation.OutgoingAuthInfos = 1;
  1932. NewDomain1TDFInfo.AuthInformation.OutgoingAuthenticationInformation = &NewAuthInfo;
  1933. NewDomain1TDFInfo.AuthInformation.OutgoingPreviousAuthenticationInformation = bErasePWHistory ? &NewAuthInfo : NULL;
  1934. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  1935. }
  1936. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomain1Info->DomainName )) ));
  1937. // Save changes.
  1938. //
  1939. Status = LsaSetTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1940. pDomain2Info->DomainName,
  1941. TrustedDomainFullInformation,
  1942. &NewDomain1TDFInfo);
  1943. if (STATUS_OBJECT_NAME_NOT_FOUND == Status && pDomain2Info->Uplevel)
  1944. {
  1945. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  1946. // have a flat name.
  1947. //
  1948. pDomain2Info->fWasDownlevel = TRUE;
  1949. Status = LsaSetTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1950. pDomain2Info->FlatName,
  1951. TrustedDomainFullInformation,
  1952. &NewDomain1TDFInfo);
  1953. }
  1954. Win32Err = LsaNtStatusToWinError(Status);
  1955. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  1956. TrustPwSetExit:
  1957. if (pOldDomain1TDFInfo)
  1958. LsaFreeMemory(pOldDomain1TDFInfo);
  1959. return Win32Err;
  1960. }
  1961. DWORD
  1962. NetDompSetTrustPW(
  1963. IN PND5_TRUST_INFO pDomain1Info,
  1964. IN PWSTR pwzDomain2Name,
  1965. IN PWSTR pwzNewTrustPW,
  1966. OUT PDWORD pDirection,
  1967. IN BOOL bErasePWHistory = FALSE OPTIONAL
  1968. )
  1969. /*++
  1970. Routine Description:
  1971. This function will set the trust password on Domain1. In this version
  1972. of the function only the dns ( or flat name for the case of trusts upgraded
  1973. from NT4) of the trusted domain is provided. This version can be called even
  1974. if the DC of Domain2 cannot be contacted.
  1975. Arguments:
  1976. pDomain1Info - Domain on which to set the trust passwords
  1977. pDomain2Name - Domain whose TDO should be set.
  1978. pwzNewTrustPW - new trust password to use.
  1979. pDirection
  1980. bErasePWHistory - Set the password in such a way that the password history
  1981. is cleared.
  1982. Return Value:
  1983. ERROR_INVALID_PARAMETER - No object name was supplied
  1984. --*/
  1985. {
  1986. DWORD Win32Err = ERROR_SUCCESS;
  1987. PTRUSTED_DOMAIN_FULL_INFORMATION pOldDomain1TDFInfo = NULL;
  1988. TRUSTED_DOMAIN_FULL_INFORMATION NewDomain1TDFInfo;
  1989. LSA_AUTH_INFORMATION NewAuthInfo;
  1990. LARGE_INTEGER ft;
  1991. NTSTATUS Status = STATUS_SUCCESS;
  1992. LSA_UNICODE_STRING Domain2Name;
  1993. RtlInitUnicodeString ( &Domain2Name, pwzDomain2Name);
  1994. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomain1Info->DomainName )) ));
  1995. Status = LsaQueryTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1996. &Domain2Name,
  1997. TrustedDomainFullInformation,
  1998. (PVOID *)&pOldDomain1TDFInfo);
  1999. Win32Err = LsaNtStatusToWinError(Status);
  2000. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  2001. if (pDirection)
  2002. {
  2003. *pDirection = pOldDomain1TDFInfo->Information.TrustDirection;
  2004. }
  2005. GetSystemTimeAsFileTime((PFILETIME)&ft);
  2006. //
  2007. // Set the current password data.
  2008. //
  2009. NewAuthInfo.LastUpdateTime = ft;
  2010. NewAuthInfo.AuthType = TRUST_AUTH_TYPE_CLEAR;
  2011. NewAuthInfo.AuthInfoLength = wcslen(pwzNewTrustPW) * sizeof(WCHAR);
  2012. NewAuthInfo.AuthInfo = (PUCHAR)pwzNewTrustPW;
  2013. ZeroMemory(&NewDomain1TDFInfo, sizeof(TRUSTED_DOMAIN_FULL_INFORMATION));
  2014. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_INBOUND)
  2015. {
  2016. NewDomain1TDFInfo.AuthInformation.IncomingAuthInfos = 1;
  2017. NewDomain1TDFInfo.AuthInformation.IncomingAuthenticationInformation = &NewAuthInfo;
  2018. NewDomain1TDFInfo.AuthInformation.IncomingPreviousAuthenticationInformation = bErasePWHistory ? &NewAuthInfo : NULL;
  2019. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  2020. }
  2021. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_OUTBOUND)
  2022. {
  2023. NewDomain1TDFInfo.AuthInformation.OutgoingAuthInfos = 1;
  2024. NewDomain1TDFInfo.AuthInformation.OutgoingAuthenticationInformation = &NewAuthInfo;
  2025. NewDomain1TDFInfo.AuthInformation.OutgoingPreviousAuthenticationInformation = bErasePWHistory ? &NewAuthInfo : NULL;
  2026. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  2027. }
  2028. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomain1Info->DomainName )) ));
  2029. // Save changes.
  2030. //
  2031. Status = LsaSetTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  2032. &Domain2Name,
  2033. TrustedDomainFullInformation,
  2034. &NewDomain1TDFInfo);
  2035. Win32Err = LsaNtStatusToWinError(Status);
  2036. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  2037. TrustPwSetExit:
  2038. if (pOldDomain1TDFInfo)
  2039. LsaFreeMemory(pOldDomain1TDFInfo);
  2040. return Win32Err;
  2041. }
  2042. DWORD
  2043. NetDompResetTrustPasswords(
  2044. IN PWSTR pwzDomain1,
  2045. IN PWSTR pwzDomain2,
  2046. IN PND5_AUTH_INFO pDomain1Creds,
  2047. IN PND5_AUTH_INFO pDomain2Creds
  2048. )
  2049. /*++
  2050. Routine Description:
  2051. This function will handle the password reset of the trusted domain objects
  2052. Arguments:
  2053. pwzDomain1, pwzDomain2 - Names of domains with trust.
  2054. pDomain1Creds, pDomain2Creds - Credentials to use when connecting to a domain controller
  2055. in the domain
  2056. --*/
  2057. {
  2058. DWORD Win32Err = ERROR_SUCCESS;
  2059. NTSTATUS Status = STATUS_SUCCESS;
  2060. ND5_TRUST_INFO Domain1Info, Domain2Info;
  2061. WCHAR wzNewPw[MAX_COMPUTERNAME_LENGTH];
  2062. ULONG Length, i;
  2063. LARGE_INTEGER ft;
  2064. DWORD Direction;
  2065. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  2066. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  2067. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  2068. NULL,
  2069. pDomain1Creds,
  2070. &Domain1Info,
  2071. TRUE,
  2072. FALSE, FALSE );
  2073. if (Win32Err == ERROR_SUCCESS)
  2074. {
  2075. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2076. NULL,
  2077. pDomain2Creds,
  2078. &Domain2Info,
  2079. TRUE,
  2080. FALSE, FALSE );
  2081. }
  2082. CHECK_WIN32(Win32Err, goto TrustResetExit);
  2083. if (Domain1Info.Uplevel && Domain2Info.Uplevel)
  2084. {
  2085. NetDompDisplayMessage(MSG_RESET_TRUST_STARTING, pwzDomain1, pwzDomain2);
  2086. }
  2087. else
  2088. {
  2089. NetDompDisplayMessage(MSG_RESET_TRUST_NOT_UPLEVEL);
  2090. goto TrustResetExit;
  2091. }
  2092. //
  2093. // Build a random password
  2094. //
  2095. CDGenerateRandomBits((PUCHAR)wzNewPw, sizeof(wzNewPw));
  2096. // Terminate the password
  2097. Length = MAX_COMPUTERNAME_LENGTH;
  2098. Length--;
  2099. wzNewPw[Length] = L'\0';
  2100. // Make sure there aren't any NULL's in the password
  2101. for (i = 0; i < Length; i++)
  2102. {
  2103. if (wzNewPw[i] == L'\0')
  2104. {
  2105. // arbitrary letter
  2106. wzNewPw[i] = L'c';
  2107. }
  2108. }
  2109. Win32Err = NetDompSetTrustPW(&Domain1Info,
  2110. &Domain2Info,
  2111. wzNewPw,
  2112. &Direction);
  2113. CHECK_WIN32(Win32Err, goto TrustResetExit);
  2114. Win32Err = NetDompSetTrustPW(&Domain2Info,
  2115. &Domain1Info,
  2116. wzNewPw,
  2117. NULL);
  2118. CHECK_WIN32(Win32Err, goto TrustResetExit);
  2119. //
  2120. // Verify the repaired trust.
  2121. //
  2122. if (Direction & TRUST_DIRECTION_OUTBOUND)
  2123. {
  2124. Win32Err = NetDompResetTrustSC( &Domain1Info, &Domain2Info );
  2125. CHECK_WIN32(Win32Err, goto TrustResetExit);
  2126. }
  2127. if (Direction & TRUST_DIRECTION_INBOUND)
  2128. {
  2129. Win32Err = NetDompResetTrustSC( &Domain2Info, &Domain1Info );
  2130. CHECK_WIN32(Win32Err, goto TrustResetExit);
  2131. }
  2132. NetDompDisplayMessage(MSG_RESET_TRUST_OK, pwzDomain1, pwzDomain2);
  2133. TrustResetExit:
  2134. NetDompFreeDomInfo( &Domain2Info );
  2135. NetDompFreeDomInfo( &Domain1Info );
  2136. return( Win32Err );
  2137. }
  2138. DWORD
  2139. NetDompResetTrustPWOneSide(
  2140. IN PWSTR pwzDomain1,
  2141. IN PWSTR pwzDomain2,
  2142. IN PND5_AUTH_INFO pDomain1Creds,
  2143. IN PND5_AUTH_INFO pDomain2Creds,
  2144. IN PWSTR pwzNewTrustPW
  2145. )
  2146. {
  2147. DWORD Win32Err = ERROR_SUCCESS;
  2148. NTSTATUS Status = STATUS_SUCCESS;
  2149. ND5_TRUST_INFO Domain1Info, Domain2Info;
  2150. WCHAR wzNewPw[MAX_COMPUTERNAME_LENGTH];
  2151. ULONG Length, i;
  2152. LARGE_INTEGER ft;
  2153. DWORD Direction;
  2154. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  2155. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  2156. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  2157. NULL,
  2158. pDomain1Creds,
  2159. &Domain1Info,
  2160. TRUE,
  2161. FALSE, FALSE );
  2162. CHECK_WIN32(Win32Err, goto TrustResetOneSideExit);
  2163. // Try to contact the trust partners's DC
  2164. if (Win32Err == ERROR_SUCCESS)
  2165. {
  2166. // If user has provided credentials for trusted domain
  2167. // then use them, else use null credentials
  2168. if ( pDomain2Creds && pDomain2Creds->User )
  2169. {
  2170. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2171. NULL,
  2172. pDomain2Creds,
  2173. &Domain2Info,
  2174. FALSE, //Need only readOnly rights on trusted domain
  2175. FALSE, FALSE );
  2176. }
  2177. else
  2178. {
  2179. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2180. NULL,
  2181. NULL,
  2182. &Domain2Info,
  2183. FALSE, //Need only readOnly rights on trusted domain
  2184. FALSE, TRUE );
  2185. }
  2186. }
  2187. // If the trust partner's DC cannot be contacted, this is not an Error,
  2188. // but we will have to assume it's specifed domain name (pwzDomain2) is the CN for the TDO
  2189. if ( Win32Err != ERROR_SUCCESS )
  2190. {
  2191. Win32Err = ERROR_SUCCESS;
  2192. // Other domains DC could not be contacted
  2193. if (Domain1Info.Uplevel)
  2194. {
  2195. NetDompDisplayMessage( MSG_RESET_ONE_SIDE_TRUST_STARTING, pwzDomain1, pwzDomain2);
  2196. }
  2197. else
  2198. {
  2199. NetDompDisplayMessage(MSG_RESET_TRUST_NOT_UPLEVEL);
  2200. goto TrustResetOneSideExit;
  2201. }
  2202. // Use the version of the NetDompSetTrustPW that takes the CN of the second domain
  2203. Win32Err = NetDompSetTrustPW(&Domain1Info,
  2204. pwzDomain2, // The CN of the second domain
  2205. pwzNewTrustPW,
  2206. &Direction,
  2207. TRUE //Erase Password History
  2208. );
  2209. }
  2210. else
  2211. {
  2212. if (Domain1Info.Uplevel && Domain2Info.Uplevel )
  2213. {
  2214. NetDompDisplayMessage( MSG_RESET_ONE_SIDE_TRUST_STARTING, pwzDomain1, pwzDomain2);
  2215. }
  2216. else
  2217. {
  2218. NetDompDisplayMessage(MSG_RESET_TRUST_NOT_UPLEVEL);
  2219. goto TrustResetOneSideExit;
  2220. }
  2221. Win32Err = NetDompSetTrustPW( &Domain1Info,
  2222. &Domain2Info,
  2223. pwzNewTrustPW,
  2224. &Direction,
  2225. TRUE //Erase Password History
  2226. );
  2227. }
  2228. CHECK_WIN32(Win32Err, goto TrustResetOneSideExit);
  2229. TrustResetOneSideExit:
  2230. NetDompFreeDomInfo( &Domain2Info );
  2231. NetDompFreeDomInfo( &Domain1Info );
  2232. return Win32Err;
  2233. }
  2234. DWORD
  2235. NetDompSetMitTrustPW (
  2236. IN PWSTR pwzDomain1,
  2237. IN PWSTR pwzDomain2,
  2238. IN PND5_AUTH_INFO pDomain1Creds,
  2239. IN PND5_AUTH_INFO pDomain2Creds,
  2240. IN PWSTR pwzNewTrustPW
  2241. )
  2242. /*++
  2243. Routine Description:
  2244. This function will handle the password reset of an MIT trusted domain object
  2245. Arguments:
  2246. pwzDomain1, pwzDomain2 - Trusted domains
  2247. pDomain1Creds - Credentials to use when connecting to a domain controller in
  2248. domain21
  2249. pDomain2Creds - Credentials to use when connecting to a domain controller in
  2250. domain 2
  2251. pwzNewTrustPW - new trust password to use.
  2252. Return Value:
  2253. ERROR_INVALID_PARAMETER - No object name was supplied
  2254. --*/
  2255. {
  2256. DWORD Win32Err = ERROR_SUCCESS;
  2257. ND5_TRUST_INFO Domain1Info, Domain2Info;
  2258. PND5_TRUST_INFO pDomFoundInfo, pMitDomInfo;
  2259. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  2260. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  2261. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  2262. NULL,
  2263. pDomain1Creds,
  2264. &Domain1Info,
  2265. TRUE,
  2266. TRUE, FALSE );
  2267. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  2268. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2269. NULL,
  2270. pDomain2Creds,
  2271. &Domain2Info,
  2272. TRUE,
  2273. TRUE, FALSE );
  2274. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  2275. if ((Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  2276. (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  2277. {
  2278. // at least one must be found.
  2279. //
  2280. Win32Err = ERROR_NO_SUCH_DOMAIN;
  2281. goto MitTrustPwSetExit;
  2282. }
  2283. if (Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2284. {
  2285. pMitDomInfo = &Domain1Info;
  2286. pDomFoundInfo = &Domain2Info;
  2287. }
  2288. else
  2289. {
  2290. if (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2291. {
  2292. pMitDomInfo = &Domain2Info;
  2293. pDomFoundInfo = &Domain1Info;
  2294. }
  2295. else
  2296. {
  2297. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  2298. Win32Err = ERROR_INVALID_PARAMETER;
  2299. goto MitTrustPwSetExit;
  2300. }
  2301. }
  2302. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_STARTING, (PWSTR) CSafeUnicodeString ( *( pDomFoundInfo->DomainName)),
  2303. (PWSTR) CSafeUnicodeString ( *( pMitDomInfo->DomainName)) );
  2304. Win32Err = NetDompSetTrustPW(pDomFoundInfo,
  2305. pMitDomInfo,
  2306. pwzNewTrustPW,
  2307. NULL);
  2308. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  2309. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_OK, (PWSTR) CSafeUnicodeString ( *( pMitDomInfo->DomainName) ) );
  2310. MitTrustPwSetExit:
  2311. NetDompFreeDomInfo( &Domain2Info );
  2312. NetDompFreeDomInfo( &Domain1Info );
  2313. return( Win32Err );
  2314. }
  2315. DWORD
  2316. NetDomTransitivity(PWSTR pwzTransArg,
  2317. PWSTR pwzDomain1,
  2318. PWSTR pwzDomain2,
  2319. PND5_AUTH_INFO pDomain1Creds,
  2320. PND5_AUTH_INFO pDomain2Creds)
  2321. /*++
  2322. Routine Description:
  2323. This routine will display or change the transitivity of a trust.
  2324. Arguments:
  2325. pwzTransArg -- Either blank (display the transitivity) or one of
  2326. yes or no (change the transitivity).
  2327. pwzDomain1 -- Name of one domain
  2328. pwzDomain2 -- Name of the other domain
  2329. pDomain1Creds -- Credentials of the user of domain1
  2330. pDomain2Creds -- Credentials of the user of domain2
  2331. Return Value:
  2332. STATUS_SUCCESS -- Success
  2333. --*/
  2334. {
  2335. DWORD Win32Err = ERROR_SUCCESS;
  2336. NTSTATUS Status = STATUS_SUCCESS;
  2337. BOOL fDisplayOnly = FALSE;
  2338. BOOL fTransOn = FALSE;
  2339. ND5_TRUST_INFO Domain1Info, Domain2Info;
  2340. PND5_TRUST_INFO pDomFoundInfo, pMitDomInfo;
  2341. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  2342. WCHAR wzYes[NETDOM_STR_LEN], wzNo[NETDOM_STR_LEN];
  2343. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  2344. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  2345. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  2346. NULL,
  2347. pDomain1Creds,
  2348. &Domain1Info,
  2349. TRUE,
  2350. TRUE, FALSE );
  2351. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  2352. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2353. NULL,
  2354. pDomain2Creds,
  2355. &Domain2Info,
  2356. TRUE,
  2357. TRUE, FALSE );
  2358. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  2359. if ((Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  2360. (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  2361. {
  2362. // at least one must be found.
  2363. //
  2364. Win32Err = ERROR_NO_SUCH_DOMAIN;
  2365. goto TrustSetTransExit;
  2366. }
  2367. if (Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2368. {
  2369. pMitDomInfo = &Domain1Info;
  2370. pDomFoundInfo = &Domain2Info;
  2371. }
  2372. else
  2373. {
  2374. if (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2375. {
  2376. pMitDomInfo = &Domain2Info;
  2377. pDomFoundInfo = &Domain1Info;
  2378. }
  2379. else
  2380. {
  2381. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  2382. Win32Err = ERROR_INVALID_PARAMETER;
  2383. goto TrustSetTransExit;
  2384. }
  2385. }
  2386. if (NULL == pwzTransArg)
  2387. {
  2388. fDisplayOnly = TRUE;
  2389. }
  2390. else
  2391. {
  2392. if (!LoadString(g_hInstance, IDS_YES, wzYes, NETDOM_STR_LEN) ||
  2393. !LoadString(g_hInstance, IDS_NO, wzNo, NETDOM_STR_LEN))
  2394. {
  2395. printf("LoadString FAILED!\n");
  2396. Win32Err = ERROR_RESOURCE_NAME_NOT_FOUND;
  2397. goto TrustSetTransExit;
  2398. }
  2399. if (_wcsicmp(wzYes, pwzTransArg) == 0)
  2400. {
  2401. fTransOn = TRUE;
  2402. }
  2403. else
  2404. {
  2405. if (_wcsicmp(wzNo, pwzTransArg) != 0)
  2406. {
  2407. fDisplayOnly = TRUE;
  2408. }
  2409. }
  2410. }
  2411. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomFoundInfo->DomainName)) ));
  2412. if (pMitDomInfo->Sid)
  2413. {
  2414. Status = LsaQueryTrustedDomainInfo(pDomFoundInfo->LsaHandle,
  2415. pMitDomInfo->Sid,
  2416. TrustedDomainInformationEx,
  2417. (PVOID *)&pTDIx);
  2418. }
  2419. else
  2420. {
  2421. Status = LsaQueryTrustedDomainInfoByName(pDomFoundInfo->LsaHandle,
  2422. pMitDomInfo->DomainName,
  2423. TrustedDomainInformationEx,
  2424. (PVOID *)&pTDIx);
  2425. }
  2426. Win32Err = LsaNtStatusToWinError(Status);
  2427. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  2428. if (TRUST_TYPE_MIT != pTDIx->TrustType)
  2429. {
  2430. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  2431. Win32Err = ERROR_INVALID_PARAMETER;
  2432. goto TrustSetTransExit;
  2433. }
  2434. if (fDisplayOnly)
  2435. {
  2436. NetDompDisplayMessage((pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE) ?
  2437. MSG_TRUST_NON_TRANSITIVE : MSG_TRUST_TRANSITIVE);
  2438. goto TrustSetTransExit;
  2439. }
  2440. if (fTransOn)
  2441. {
  2442. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE)
  2443. {
  2444. NetDompDisplayMessage(MSG_TRUST_SET_TRANSITIVE);
  2445. pTDIx->TrustAttributes &= ~(TRUST_ATTRIBUTE_NON_TRANSITIVE);
  2446. }
  2447. else
  2448. {
  2449. NetDompDisplayMessage(MSG_TRUST_ALREADY_TRANSITIVE);
  2450. goto TrustSetTransExit;
  2451. }
  2452. }
  2453. else
  2454. {
  2455. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE)
  2456. {
  2457. NetDompDisplayMessage(MSG_TRUST_ALREADY_NON_TRANSITIVE);
  2458. goto TrustSetTransExit;
  2459. }
  2460. else
  2461. {
  2462. NetDompDisplayMessage(MSG_TRUST_SET_NON_TRANSITIVE);
  2463. pTDIx->TrustAttributes |= TRUST_ATTRIBUTE_NON_TRANSITIVE;
  2464. }
  2465. }
  2466. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( *( pDomFoundInfo->DomainName )) ));
  2467. Status = LsaSetTrustedDomainInfoByName(pDomFoundInfo->LsaHandle,
  2468. pMitDomInfo->DomainName,
  2469. TrustedDomainInformationEx,
  2470. pTDIx);
  2471. Win32Err = LsaNtStatusToWinError(Status);
  2472. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  2473. TrustSetTransExit:
  2474. NetDompFreeDomInfo( &Domain2Info );
  2475. NetDompFreeDomInfo( &Domain1Info );
  2476. if (pTDIx)
  2477. LsaFreeMemory(pTDIx);
  2478. return Win32Err;
  2479. }
  2480. DWORD
  2481. NetDomToggleTrustAttribute ( PWSTR pwzAttributeArg,
  2482. PWSTR pwzTrustingDomain,
  2483. PWSTR pwzTrustedDomain,
  2484. PND5_AUTH_INFO pTrustingDomainCreds,
  2485. ULONG TrustAttribute)
  2486. /*++
  2487. Routine Description:
  2488. This routine will display or change the specified TrustAttribute
  2489. of a trust. This is currently limited to Attributes:
  2490. TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
  2491. TRUST_ATTRIBUTE_FOREST_TRANSITIVE
  2492. TRUST_ATTRIBUTE_CROSS_ORGANIZATION
  2493. Arguments:
  2494. pwzAttributeArg -- Either blank (display the state) or one of
  2495. yes or no (change the state).
  2496. pwzTrustingDomain -- Name of the trusting domain domain
  2497. pwzTrustedDomain -- Name of the trusted domain
  2498. pTrustingDomainCreds -- Credentials of the user of the trusting domain
  2499. TrustAttribute -- the attribute to toggle, can be one of:
  2500. TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
  2501. TRUST_ATTRIBUTE_FOREST_TRANSITIVE
  2502. TRUST_ATTRIBUTE_CROSS_ORGANIZATION
  2503. Return Value:
  2504. STATUS_SUCCESS -- Success
  2505. --*/
  2506. {
  2507. DWORD Win32Err = ERROR_SUCCESS;
  2508. NTSTATUS Status = STATUS_SUCCESS;
  2509. BOOL fDisplayOnly = FALSE;
  2510. BOOL fAttributeOn = FALSE;
  2511. ND5_TRUST_INFO TrustingDomainInfo;
  2512. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  2513. WCHAR wzYes[NETDOM_STR_LEN], wzNo[NETDOM_STR_LEN];
  2514. LSA_UNICODE_STRING TrustedDomainName;
  2515. // Ensure that TrustAttribute is only of the allowed attributes
  2516. if ( ! (
  2517. (TrustAttribute == TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL) ||
  2518. (TrustAttribute == TRUST_ATTRIBUTE_FOREST_TRANSITIVE) ||
  2519. (TrustAttribute == TRUST_ATTRIBUTE_CROSS_ORGANIZATION)
  2520. )
  2521. )
  2522. {
  2523. return ERROR_INVALID_PARAMETER;
  2524. }
  2525. RtlZeroMemory(&TrustingDomainInfo, sizeof(TrustingDomainInfo));
  2526. Win32Err = NetDompTrustGetDomInfo( pwzTrustingDomain,
  2527. NULL,
  2528. pTrustingDomainCreds,
  2529. &TrustingDomainInfo,
  2530. TRUE,
  2531. FALSE,
  2532. FALSE );
  2533. CHECK_WIN32(Win32Err, goto ToggleTrustAttributeExit);
  2534. RtlInitUnicodeString ( &TrustedDomainName, pwzTrustedDomain );
  2535. if (TrustingDomainInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2536. {
  2537. Win32Err = ERROR_NO_SUCH_DOMAIN;
  2538. goto ToggleTrustAttributeExit;
  2539. }
  2540. if (NULL == pwzAttributeArg)
  2541. {
  2542. fDisplayOnly = TRUE;
  2543. }
  2544. else
  2545. {
  2546. if (!LoadString(g_hInstance, IDS_YES, wzYes, NETDOM_STR_LEN) ||
  2547. !LoadString(g_hInstance, IDS_NO, wzNo, NETDOM_STR_LEN))
  2548. {
  2549. printf("LoadString FAILED!\n");
  2550. Win32Err = ERROR_RESOURCE_NAME_NOT_FOUND;
  2551. goto ToggleTrustAttributeExit;
  2552. }
  2553. if (_wcsicmp(wzYes, pwzAttributeArg) == 0)
  2554. {
  2555. fAttributeOn = TRUE;
  2556. }
  2557. else
  2558. {
  2559. if (_wcsicmp(wzNo, pwzAttributeArg) != 0)
  2560. {
  2561. fDisplayOnly = TRUE;
  2562. }
  2563. }
  2564. }
  2565. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *( TrustingDomainInfo.DomainName )) ));
  2566. Status = LsaQueryTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2567. &TrustedDomainName,
  2568. TrustedDomainInformationEx,
  2569. (PVOID *)&pTDIx);
  2570. Win32Err = LsaNtStatusToWinError(Status);
  2571. CHECK_WIN32(Win32Err, goto ToggleTrustAttributeExit);
  2572. // Special check for the case of TRUST_ATTRIBUTE_FOREST_TRANSITIVE
  2573. // we only manipulating this bit for Realm trusts
  2574. if ( (TrustAttribute == TRUST_ATTRIBUTE_FOREST_TRANSITIVE) && (pTDIx->TrustType != TRUST_TYPE_MIT) )
  2575. {
  2576. NetDompDisplayMessage ( MSG_TRUST_CANNOT_SET_THIS_BIT_ON_NON_REALM_TRUST );
  2577. Win32Err = ERROR_INVALID_PARAMETER;
  2578. goto ToggleTrustAttributeExit;
  2579. }
  2580. if (fDisplayOnly)
  2581. {
  2582. switch ( TrustAttribute )
  2583. {
  2584. case TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL:
  2585. NetDompDisplayMessage((pTDIx->TrustAttributes & TrustAttribute ) ?
  2586. MSG_TRUST_TREAT_AS_EXTERNAL : MSG_TRUST_DONT_TREAT_AS_EXTERNAL );
  2587. break;
  2588. case TRUST_ATTRIBUTE_FOREST_TRANSITIVE:
  2589. NetDompDisplayMessage((pTDIx->TrustAttributes & TrustAttribute ) ?
  2590. MSG_TRUST_FOREST_TRANSITIVE : MSG_TRUST_NOT_FOREST_TRANSITIVE );
  2591. break;
  2592. case TRUST_ATTRIBUTE_CROSS_ORGANIZATION:
  2593. NetDompDisplayMessage((pTDIx->TrustAttributes & TrustAttribute ) ?
  2594. MSG_TRUST_CROSS_ORGANIZATION : MSG_TRUST_NOT_CROSS_ORGANIZATION );
  2595. break;
  2596. }
  2597. goto ToggleTrustAttributeExit;
  2598. }
  2599. if (fAttributeOn)
  2600. {
  2601. if (pTDIx->TrustAttributes & TrustAttribute)
  2602. {
  2603. switch ( TrustAttribute )
  2604. {
  2605. case TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL:
  2606. NetDompDisplayMessage(MSG_TRUST_ALREADY_TREAT_AS_EXTERNAL );
  2607. break;
  2608. case TRUST_ATTRIBUTE_FOREST_TRANSITIVE:
  2609. NetDompDisplayMessage(MSG_TRUST_ALREADY_FOREST_TRANSITIVE );
  2610. break;
  2611. case TRUST_ATTRIBUTE_CROSS_ORGANIZATION:
  2612. NetDompDisplayMessage(MSG_TRUST_ALREADY_CROSS_ORGANIZATION );
  2613. break;
  2614. }
  2615. goto ToggleTrustAttributeExit;
  2616. }
  2617. else
  2618. {
  2619. switch ( TrustAttribute )
  2620. {
  2621. case TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL:
  2622. NetDompDisplayMessage(MSG_TRUST_SET_TREAT_AS_EXTERNAL );
  2623. break;
  2624. case TRUST_ATTRIBUTE_FOREST_TRANSITIVE:
  2625. //TODO: Check if both are Forest Roots
  2626. NetDompDisplayMessage(MSG_TRUST_SET_FOREST_TRANSITIVE );
  2627. break;
  2628. case TRUST_ATTRIBUTE_CROSS_ORGANIZATION:
  2629. NetDompDisplayMessage(MSG_TRUST_SET_CROSS_ORGANIZATION );
  2630. break;
  2631. }
  2632. pTDIx->TrustAttributes |= TrustAttribute;
  2633. }
  2634. }
  2635. else
  2636. {
  2637. if (pTDIx->TrustAttributes & TrustAttribute)
  2638. {
  2639. switch ( TrustAttribute )
  2640. {
  2641. case TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL:
  2642. NetDompDisplayMessage(MSG_TRUST_SET_DONT_TREAT_AS_EXTERNAL);
  2643. break;
  2644. case TRUST_ATTRIBUTE_FOREST_TRANSITIVE:
  2645. NetDompDisplayMessage(MSG_TRUST_SET_NOT_FOREST_TRANSITIVE);
  2646. break;
  2647. case TRUST_ATTRIBUTE_CROSS_ORGANIZATION:
  2648. NetDompDisplayMessage(MSG_TRUST_SET_NOT_CROSS_ORGANIZATION);
  2649. break;
  2650. }
  2651. pTDIx->TrustAttributes &= ~(TrustAttribute);
  2652. }
  2653. else
  2654. {
  2655. switch ( TrustAttribute )
  2656. {
  2657. case TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL:
  2658. NetDompDisplayMessage(MSG_TRUST_ALREADY_DONT_TREAT_AS_EXTERNAL);
  2659. break;
  2660. case TRUST_ATTRIBUTE_FOREST_TRANSITIVE:
  2661. NetDompDisplayMessage(MSG_TRUST_ALREADY_NOT_FOREST_TRANSITIVE);
  2662. break;
  2663. case TRUST_ATTRIBUTE_CROSS_ORGANIZATION:
  2664. NetDompDisplayMessage(MSG_TRUST_ALREADY_NOT_CROSS_ORGANIZATION);
  2665. break;
  2666. }
  2667. goto ToggleTrustAttributeExit;
  2668. }
  2669. }
  2670. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( *( TrustingDomainInfo.DomainName )) ));
  2671. Status = LsaSetTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2672. &TrustedDomainName,
  2673. TrustedDomainInformationEx,
  2674. pTDIx);
  2675. Win32Err = LsaNtStatusToWinError(Status);
  2676. CHECK_WIN32(Win32Err, goto ToggleTrustAttributeExit);
  2677. ToggleTrustAttributeExit:
  2678. NetDompFreeDomInfo( &TrustingDomainInfo );
  2679. if (pTDIx)
  2680. LsaFreeMemory(pTDIx);
  2681. return Win32Err;
  2682. }
  2683. DWORD
  2684. NetDomFilterSID(PWSTR pwzFilterArg,
  2685. PWSTR pwzTrustingDomain,
  2686. PWSTR pwzTrustedDomain,
  2687. PND5_AUTH_INFO pTrustingDomainCreds,
  2688. PND5_AUTH_INFO pDomain2Creds)
  2689. /*++
  2690. Routine Description:
  2691. This routine will display or change the SID filtering state of a trust.
  2692. Arguments:
  2693. pwzFilterArg -- Either blank (display the filtering state) or one of
  2694. yes or no (change the filtering state).
  2695. pwzTrustingDomain -- Name of the trusting domain domain
  2696. pwzTrustedDomain -- Name of the trusted domain
  2697. pTrustingDomainCreds -- Credentials of the user of the trusting domain
  2698. pDomain2Creds -- Credentials of the user of domain2 BUGBUG not needed?
  2699. Return Value:
  2700. STATUS_SUCCESS -- Success
  2701. --*/
  2702. {
  2703. DWORD Win32Err = ERROR_SUCCESS;
  2704. NTSTATUS Status = STATUS_SUCCESS;
  2705. BOOL fDisplayOnly = FALSE;
  2706. BOOL fFilterOn = FALSE;
  2707. ND5_TRUST_INFO TrustingDomainInfo, TrustedDomainInfo;
  2708. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  2709. WCHAR wzYes[NETDOM_STR_LEN], wzNo[NETDOM_STR_LEN];
  2710. RtlZeroMemory(&TrustingDomainInfo, sizeof(TrustingDomainInfo));
  2711. RtlZeroMemory(&TrustedDomainInfo, sizeof(TrustedDomainInfo));
  2712. Win32Err = NetDompTrustGetDomInfo(pwzTrustingDomain,
  2713. NULL,
  2714. pTrustingDomainCreds,
  2715. &TrustingDomainInfo,
  2716. TRUE,
  2717. FALSE, FALSE);
  2718. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2719. Win32Err = NetDompTrustGetDomInfo(pwzTrustedDomain,
  2720. NULL,
  2721. NULL,
  2722. &TrustedDomainInfo,
  2723. FALSE,
  2724. TRUE, TRUE);
  2725. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2726. if (TrustingDomainInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2727. {
  2728. Win32Err = ERROR_NO_SUCH_DOMAIN;
  2729. goto TrustSetFilterExit;
  2730. }
  2731. if (NULL == pwzFilterArg)
  2732. {
  2733. fDisplayOnly = TRUE;
  2734. }
  2735. else
  2736. {
  2737. if (!LoadString(g_hInstance, IDS_YES, wzYes, NETDOM_STR_LEN) ||
  2738. !LoadString(g_hInstance, IDS_NO, wzNo, NETDOM_STR_LEN))
  2739. {
  2740. printf("LoadString FAILED!\n");
  2741. Win32Err = ERROR_RESOURCE_NAME_NOT_FOUND;
  2742. goto TrustSetFilterExit;
  2743. }
  2744. if (_wcsicmp(wzYes, pwzFilterArg) == 0)
  2745. {
  2746. fFilterOn = TRUE;
  2747. }
  2748. else
  2749. {
  2750. if (_wcsicmp(wzNo, pwzFilterArg) != 0)
  2751. {
  2752. fDisplayOnly = TRUE;
  2753. }
  2754. }
  2755. }
  2756. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, (PWSTR) CSafeUnicodeString ( *( TrustingDomainInfo.DomainName )) ));
  2757. if (TrustedDomainInfo.Sid)
  2758. {
  2759. Status = LsaQueryTrustedDomainInfo(TrustingDomainInfo.LsaHandle,
  2760. TrustedDomainInfo.Sid,
  2761. TrustedDomainInformationEx,
  2762. (PVOID *)&pTDIx);
  2763. }
  2764. else
  2765. {
  2766. Status = LsaQueryTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2767. TrustedDomainInfo.DomainName,
  2768. TrustedDomainInformationEx,
  2769. (PVOID *)&pTDIx);
  2770. }
  2771. Win32Err = LsaNtStatusToWinError(Status);
  2772. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2773. if (!(pTDIx->TrustDirection & TRUST_DIRECTION_OUTBOUND))
  2774. {
  2775. NetDompDisplayMessage(MSG_TRUST_FILTER_SIDS_WRONG_DIR, pwzTrustedDomain);
  2776. goto TrustSetFilterExit;
  2777. }
  2778. if (fDisplayOnly)
  2779. {
  2780. NetDompDisplayMessage((pTDIx->TrustAttributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ?
  2781. MSG_TRUST_FILTER_SIDS : MSG_TRUST_DONT_FILTER_SIDS);
  2782. goto TrustSetFilterExit;
  2783. }
  2784. if (fFilterOn)
  2785. {
  2786. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)
  2787. {
  2788. NetDompDisplayMessage(MSG_TRUST_ALREADY_FILTER_SIDS);
  2789. goto TrustSetFilterExit;
  2790. }
  2791. else
  2792. {
  2793. NetDompDisplayMessage(MSG_TRUST_SET_FILTER_SIDS);
  2794. pTDIx->TrustAttributes |= TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
  2795. }
  2796. }
  2797. else
  2798. {
  2799. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)
  2800. {
  2801. NetDompDisplayMessage(MSG_TRUST_SET_DONT_FILTER_SIDS);
  2802. pTDIx->TrustAttributes &= ~(TRUST_ATTRIBUTE_QUARANTINED_DOMAIN);
  2803. }
  2804. else
  2805. {
  2806. NetDompDisplayMessage(MSG_TRUST_ALREADY_DONT_FILTER_SIDS);
  2807. goto TrustSetFilterExit;
  2808. }
  2809. }
  2810. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, (PWSTR) CSafeUnicodeString ( *( TrustingDomainInfo.DomainName )) ));
  2811. Status = LsaSetTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2812. TrustedDomainInfo.DomainName,
  2813. TrustedDomainInformationEx,
  2814. pTDIx);
  2815. Win32Err = LsaNtStatusToWinError(Status);
  2816. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2817. TrustSetFilterExit:
  2818. NetDompFreeDomInfo( &TrustedDomainInfo );
  2819. NetDompFreeDomInfo( &TrustingDomainInfo );
  2820. if (pTDIx)
  2821. LsaFreeMemory(pTDIx);
  2822. return Win32Err;
  2823. }
  2824. typedef INT_PTR (*DSPROP_AddRemoveTLName)( PCWSTR pwzLocalDc,
  2825. PWSTR pwzTrust,
  2826. PCWSTR pwzTLN,
  2827. bool fExclusion,
  2828. PCWSTR pwzUser,
  2829. PCWSTR pwzPw);
  2830. DWORD
  2831. NetDomAddRemoveTLN ( PWSTR pwzLocalDomain,
  2832. PWSTR pwzRemoteDomain,
  2833. PWSTR pwzTLN,
  2834. bool fAdd,
  2835. bool fExclusion,
  2836. PND5_AUTH_INFO pLocalDomainCreds)
  2837. /*++
  2838. Routine Description:
  2839. This routine will add/remove the specified TLN/TLN Exclusion record to the TDO for
  2840. trust between the specified Domains. This operation is only allowed for Forest
  2841. Transitive Realm Trusts.
  2842. Arguments:
  2843. pwzLocalDomain Name of the local domain (Forest root)
  2844. pwzRemoteDomain Name of the remote domain ( MIT realm )
  2845. pwzTLN TLN or Exclusion to be added/removed
  2846. fAdd Specified if this as an add or remove operation
  2847. fExclusion Specifies if this a TLN or an exclusion
  2848. pLocalDomainCreds Credentials for the local domain.
  2849. Return Value:
  2850. STATUS_SUCCESS -- Success
  2851. --*/
  2852. {
  2853. DWORD Win32Err = ERROR_SUCCESS;
  2854. PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
  2855. ND5_TRUST_INFO LocalDomainInfo;
  2856. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  2857. PWSTR pwzDcName = NULL;
  2858. LSA_UNICODE_STRING TrustedDomainName;
  2859. NTSTATUS Status = STATUS_SUCCESS;
  2860. HMODULE hm = NULL;
  2861. DSPROP_AddRemoveTLName pAddRemoveTLName = NULL;
  2862. ASSERT( pwzTLN && pwzLocalDomain && pwzRemoteDomain && pLocalDomainCreds);
  2863. if ( !pwzTLN || !pwzLocalDomain || !pwzRemoteDomain || !pLocalDomainCreds )
  2864. {
  2865. return ERROR_INVALID_PARAMETER;
  2866. }
  2867. // Get Domain info about the Local Domain, this will give us its LsaHandle
  2868. Win32Err = NetDompTrustGetDomInfo( pwzLocalDomain,
  2869. NULL,
  2870. pLocalDomainCreds,
  2871. &LocalDomainInfo,
  2872. FALSE,
  2873. FALSE, FALSE);
  2874. CHECK_WIN32(Win32Err, return Win32Err);
  2875. RtlInitUnicodeString ( &TrustedDomainName, pwzRemoteDomain );
  2876. // Get the TDO info for the RemoteDomain.
  2877. Status = LsaQueryTrustedDomainInfoByName( LocalDomainInfo.LsaHandle,
  2878. &TrustedDomainName,
  2879. TrustedDomainInformationEx,
  2880. (PVOID *)&pTDIx);
  2881. Win32Err = LsaNtStatusToWinError(Status);
  2882. CHECK_WIN32(Win32Err, return Win32Err);
  2883. // All this to ensure that this is a Realm Trust. We allow adding removing TLN
  2884. // manually through Netdom only for Realm trusts.
  2885. if ( !( pTDIx->TrustType & TRUST_TYPE_MIT) )
  2886. {
  2887. NetDompDisplayMessage ( MSG_CANNOT_ADDREMOVE_TLN_NON_REALM );
  2888. NetDompFreeDomInfo ( &LocalDomainInfo );
  2889. LsaFreeMemory(pTDIx);
  2890. return ERROR_INVALID_PARAMETER;
  2891. }
  2892. NetDompFreeDomInfo ( &LocalDomainInfo );
  2893. LsaFreeMemory(pTDIx);
  2894. Win32Err = DsGetDcName( NULL,
  2895. pwzLocalDomain,
  2896. NULL,
  2897. NULL,
  2898. DS_PDC_REQUIRED,
  2899. &pDcInfo );
  2900. CHECK_WIN32(Win32Err, return Win32Err);
  2901. ASSERT(pDcInfo);
  2902. pwzDcName = pDcInfo->DomainControllerName;
  2903. hm = LoadLibrary(L"adprop.dll");
  2904. if (!hm)
  2905. {
  2906. Win32Err = GetLastError();
  2907. NetApiBufferFree(pDcInfo);
  2908. return Win32Err;
  2909. }
  2910. if ( fAdd )
  2911. {
  2912. pAddRemoveTLName = (DSPROP_AddRemoveTLName)GetProcAddress(hm, "DSPROP_AddTLName");
  2913. }
  2914. else
  2915. {
  2916. pAddRemoveTLName = (DSPROP_AddRemoveTLName)GetProcAddress(hm, "DSPROP_RemoveTLName");
  2917. }
  2918. if ( !pAddRemoveTLName )
  2919. {
  2920. Win32Err = GetLastError();
  2921. NetApiBufferFree(pDcInfo);
  2922. NetDompDisplayMessage(MSG_WRONG_DSPROP_DLL);
  2923. return Win32Err;
  2924. }
  2925. Win32Err = (DWORD)(*pAddRemoveTLName)( pwzDcName,
  2926. pwzRemoteDomain,
  2927. pwzTLN,
  2928. fExclusion,
  2929. pLocalDomainCreds->User,
  2930. pLocalDomainCreds->Password);
  2931. NetApiBufferFree(pDcInfo);
  2932. return Win32Err;
  2933. }
  2934. typedef INT_PTR (*DSPROP_DumpFTInfos)(PCWSTR pwzDcName, PCWSTR pwzTrust,
  2935. PCWSTR pwzUser, PCWSTR pwzPw);
  2936. typedef INT_PTR (*DSPROP_ToggleFTName)(PCWSTR pwzLocalDc, PWSTR pwzTrust, ULONG iSel,
  2937. PCWSTR pwzUser, PCWSTR pwzPW);
  2938. DWORD
  2939. NetDomForestSuffix(PWSTR pwzTrustPartnerArg,
  2940. ULONG iSel,
  2941. PWSTR pwzLocalDomain,
  2942. PND5_AUTH_INFO pLocalDomainCreds)
  2943. /*++
  2944. Routine Description:
  2945. This routine will toggle the status of a name suffix claimed by a forest trust domain
  2946. or if iSel is zero will display the name suffixes claimed by a forest trust domain.
  2947. Arguments:
  2948. pwzTrustPartnerArg -- the domain whose TDO will be read for the name suffixes
  2949. attribute (ms-DS-Trust-Forest-Trust-Info).
  2950. iSel -- the one-based index of the name to toggle (if zero, display the names).
  2951. pwzLocalDomain -- Name of the domain on which the TDO resides.
  2952. pLocalDomainCreds -- Credentials of the user of the local domain
  2953. Return Value:
  2954. STATUS_SUCCESS -- Success
  2955. --*/
  2956. {
  2957. DWORD Win32Err = ERROR_SUCCESS;
  2958. PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
  2959. PWSTR pwzDcName = NULL;
  2960. NTSTATUS Status = STATUS_SUCCESS;
  2961. HMODULE hm = NULL;
  2962. DSPROP_DumpFTInfos pDumpFTInfos = NULL;
  2963. DSPROP_ToggleFTName pToggleFTName = NULL;
  2964. ASSERT(pwzTrustPartnerArg && pwzLocalDomain && pLocalDomainCreds);
  2965. Win32Err = DsGetDcName(NULL,
  2966. pwzLocalDomain,
  2967. NULL,
  2968. NULL,
  2969. DS_PDC_REQUIRED,
  2970. &pDcInfo );
  2971. CHECK_WIN32(Win32Err, return Win32Err);
  2972. ASSERT(pDcInfo);
  2973. pwzDcName = pDcInfo->DomainControllerName;
  2974. hm = LoadLibrary(L"adprop.dll");
  2975. if (!hm)
  2976. {
  2977. Win32Err = GetLastError();
  2978. NetApiBufferFree(pDcInfo);
  2979. return Win32Err;
  2980. }
  2981. if (0 == iSel)
  2982. {
  2983. pDumpFTInfos = (DSPROP_DumpFTInfos)GetProcAddress(hm, "DSPROP_DumpFTInfos");
  2984. }
  2985. else
  2986. {
  2987. pToggleFTName = (DSPROP_ToggleFTName)GetProcAddress(hm, "DSPROP_ToggleFTName");
  2988. }
  2989. if (!pDumpFTInfos && !pToggleFTName)
  2990. {
  2991. Win32Err = GetLastError();
  2992. NetApiBufferFree(pDcInfo);
  2993. NetDompDisplayMessage(MSG_WRONG_DSPROP_DLL);
  2994. return Win32Err;
  2995. }
  2996. if (0 == iSel)
  2997. {
  2998. Win32Err = (DWORD)(*pDumpFTInfos)(pwzDcName, pwzTrustPartnerArg,
  2999. pLocalDomainCreds->User, pLocalDomainCreds->Password);
  3000. }
  3001. else
  3002. {
  3003. Win32Err = (DWORD)(*pToggleFTName)(pwzDcName, pwzTrustPartnerArg, iSel,
  3004. pLocalDomainCreds->User, pLocalDomainCreds->Password);
  3005. }
  3006. NetApiBufferFree(pDcInfo);
  3007. return Win32Err;
  3008. }
  3009. DWORD
  3010. NetDompVerifyIndividualTrustKerberos(
  3011. IN PWSTR TrustingDomain,
  3012. IN PWSTR TrustedDomain,
  3013. IN PND5_AUTH_INFO pTrustingCreds,
  3014. IN PND5_AUTH_INFO pTrustedCreds
  3015. )
  3016. /*++
  3017. Routine Description:
  3018. This routine will verify a single trust in the one direction only.
  3019. Arguments:
  3020. TrustingDomain -- Name of the domain on the outbound side
  3021. TrustedDomain -- Name of the domain on the inbound side
  3022. pTrustingCreds -- Credentials of the user on the outbound side
  3023. pTrustedCreds -- Credentials of the user on the inbound side
  3024. Return Value:
  3025. STATUS_SUCCESS -- Success
  3026. --*/
  3027. {
  3028. //
  3029. // Copy the relevant info into local pointers so that I don't have
  3030. // to rewrite the rest of the function.
  3031. //
  3032. PWSTR PackageName = NULL;
  3033. PWSTR UserNameU = pTrustedCreds->pwzUserWoDomain;
  3034. PWSTR DomainNameU = pTrustedCreds->pwzUsersDomain;
  3035. PWSTR PasswordU = pTrustedCreds->Password;
  3036. PWSTR ServerUserNameU = pTrustingCreds->pwzUserWoDomain;
  3037. PWSTR ServerDomainNameU = pTrustingCreds->pwzUsersDomain;
  3038. PWSTR ServerPasswordU = pTrustingCreds->Password;
  3039. ULONG ContextReq = 0;
  3040. ULONG CredFlags = 0;
  3041. SECURITY_STATUS SecStatus;
  3042. SECURITY_STATUS AcceptStatus;
  3043. SECURITY_STATUS InitStatus;
  3044. CredHandle CredentialHandle2;
  3045. CtxtHandle ClientContextHandle;
  3046. CtxtHandle ServerContextHandle;
  3047. TimeStamp Lifetime;
  3048. ULONG ContextAttributes;
  3049. ULONG PackageCount;
  3050. PSecPkgInfo PackageInfo = NULL;
  3051. ULONG ClientFlags;
  3052. ULONG ServerFlags;
  3053. BOOLEAN AcquiredServerCred = FALSE;
  3054. LPWSTR DomainName = NULL;
  3055. LPWSTR UserName = NULL;
  3056. TCHAR TargetName[256];
  3057. PSEC_WINNT_AUTH_IDENTITY_EXW AuthIdentity = NULL;
  3058. PSEC_WINNT_AUTH_IDENTITY_W ServerAuthIdentity = NULL;
  3059. PUCHAR Where;
  3060. ULONG CredSize;
  3061. SecBufferDesc NegotiateDesc;
  3062. SecBuffer NegotiateBuffer;
  3063. SecBufferDesc ChallengeDesc;
  3064. SecBuffer ChallengeBuffer;
  3065. SecBufferDesc AuthenticateDesc;
  3066. SecBuffer AuthenticateBuffer;
  3067. SecPkgCredentials_Names CredNames;
  3068. CredHandle ServerCredHandleStorage;
  3069. PCredHandle ServerCredHandle = NULL;
  3070. //
  3071. // Set the package to wide-char
  3072. //
  3073. if (PackageName == NULL)
  3074. {
  3075. PackageName = MICROSOFT_KERBEROS_NAME_W;
  3076. }
  3077. //
  3078. // Allocate the Authentication Identity for the outbound trust
  3079. //
  3080. if ((UserNameU != NULL) || (DomainNameU != NULL) || (PasswordU != NULL) || (CredFlags != 0))
  3081. {
  3082. CredSize = (((UserNameU != NULL) ? wcslen(UserNameU) + 1 : 0) +
  3083. ((DomainNameU != NULL) ? wcslen(DomainNameU) + 1 : 0 ) +
  3084. ((PasswordU != NULL) ? wcslen(PasswordU) + 1 : 0) ) * sizeof(WCHAR) +
  3085. sizeof(SEC_WINNT_AUTH_IDENTITY_EXW);
  3086. AuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_EXW) LocalAlloc(LMEM_ZEROINIT,CredSize);
  3087. if (!AuthIdentity)
  3088. {
  3089. return ERROR_NOT_ENOUGH_MEMORY;
  3090. }
  3091. AuthIdentity->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
  3092. Where = (PUCHAR) (AuthIdentity + 1);
  3093. if (UserNameU != NULL)
  3094. {
  3095. AuthIdentity->UserLength = wcslen(UserNameU);
  3096. AuthIdentity->User = (LPWSTR) Where;
  3097. wcscpy(
  3098. (LPWSTR) Where,
  3099. UserNameU
  3100. );
  3101. Where += (wcslen(UserNameU) + 1) * sizeof(WCHAR);
  3102. }
  3103. if (DomainNameU != NULL)
  3104. {
  3105. AuthIdentity->DomainLength = wcslen(DomainNameU);
  3106. AuthIdentity->Domain = (LPWSTR) Where;
  3107. wcscpy(
  3108. (LPWSTR) Where,
  3109. DomainNameU
  3110. );
  3111. Where += (wcslen(DomainNameU) + 1) * sizeof(WCHAR);
  3112. }
  3113. if (PasswordU != NULL)
  3114. {
  3115. AuthIdentity->PasswordLength = wcslen(PasswordU);
  3116. AuthIdentity->Password = (LPWSTR) Where;
  3117. wcscpy(
  3118. (LPWSTR) Where,
  3119. PasswordU
  3120. );
  3121. Where += (wcslen(PasswordU) + 1) * sizeof(WCHAR);
  3122. }
  3123. AuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | CredFlags;
  3124. }
  3125. //
  3126. // Allocate the Authentication Identity for the outbound trust
  3127. //
  3128. if ((ServerUserNameU != NULL) || (ServerDomainNameU != NULL) || (ServerPasswordU != NULL))
  3129. {
  3130. CredSize = (((ServerUserNameU != NULL) ? wcslen(ServerUserNameU) + 1 : 0) +
  3131. ((ServerDomainNameU != NULL) ? wcslen(ServerDomainNameU) + 1 : 0 ) +
  3132. ((ServerPasswordU != NULL) ? wcslen(ServerPasswordU) + 1 : 0) ) * sizeof(WCHAR) +
  3133. sizeof(SEC_WINNT_AUTH_IDENTITY);
  3134. ServerAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_W) LocalAlloc(LMEM_ZEROINIT,CredSize);
  3135. if (!ServerAuthIdentity)
  3136. {
  3137. return ERROR_NOT_ENOUGH_MEMORY;
  3138. }
  3139. Where = (PUCHAR) (ServerAuthIdentity + 1);
  3140. if (ServerUserNameU != NULL)
  3141. {
  3142. ServerAuthIdentity->UserLength = wcslen(ServerUserNameU);
  3143. ServerAuthIdentity->User = (LPWSTR) Where;
  3144. wcscpy(
  3145. (LPWSTR) Where,
  3146. ServerUserNameU
  3147. );
  3148. Where += (wcslen(ServerUserNameU) + 1) * sizeof(WCHAR);
  3149. }
  3150. if (ServerDomainNameU != NULL)
  3151. {
  3152. ServerAuthIdentity->DomainLength = wcslen(ServerDomainNameU);
  3153. ServerAuthIdentity->Domain = (LPWSTR) Where;
  3154. wcscpy(
  3155. (LPWSTR) Where,
  3156. ServerDomainNameU
  3157. );
  3158. Where += (wcslen(ServerDomainNameU) + 1) * sizeof(WCHAR);
  3159. }
  3160. if (ServerPasswordU != NULL)
  3161. {
  3162. ServerAuthIdentity->PasswordLength = wcslen(ServerPasswordU);
  3163. ServerAuthIdentity->Password = (LPWSTR) Where;
  3164. wcscpy(
  3165. (LPWSTR) Where,
  3166. ServerPasswordU
  3167. );
  3168. Where += (wcslen(ServerPasswordU) + 1) * sizeof(WCHAR);
  3169. }
  3170. ServerAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | SEC_WINNT_AUTH_IDENTITY_MARSHALLED;
  3171. }
  3172. CredNames.sUserName = NULL;
  3173. NegotiateBuffer.pvBuffer = NULL;
  3174. ChallengeBuffer.pvBuffer = NULL;
  3175. AuthenticateBuffer.pvBuffer = NULL;
  3176. DomainName = _wgetenv(L"USERDOMAIN");
  3177. UserName = _wgetenv(L"USERNAME");
  3178. //
  3179. // Get info about the security packages.
  3180. //
  3181. SecStatus = EnumerateSecurityPackages( &PackageCount, &PackageInfo );
  3182. if ( SecStatus != STATUS_SUCCESS )
  3183. {
  3184. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3185. TrustingDomain,
  3186. TrustedDomain );
  3187. return SecStatus;
  3188. }
  3189. //
  3190. // Get info about the security packages.
  3191. //
  3192. SecStatus = QuerySecurityPackageInfo( PackageName, &PackageInfo );
  3193. if ( SecStatus != STATUS_SUCCESS )
  3194. {
  3195. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3196. TrustingDomain,
  3197. TrustedDomain );
  3198. return SecStatus;
  3199. }
  3200. //
  3201. // Acquire a credential handle for the server side
  3202. //
  3203. if (ServerCredHandle == NULL)
  3204. {
  3205. ServerCredHandle = &ServerCredHandleStorage;
  3206. AcquiredServerCred = TRUE;
  3207. SecStatus = AcquireCredentialsHandle(
  3208. NULL,
  3209. PackageName,
  3210. SECPKG_CRED_INBOUND,
  3211. NULL,
  3212. ServerAuthIdentity,
  3213. NULL,
  3214. NULL,
  3215. ServerCredHandle,
  3216. &Lifetime );
  3217. if ( SecStatus != STATUS_SUCCESS )
  3218. {
  3219. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3220. TrustingDomain,
  3221. TrustedDomain );
  3222. return SecStatus;
  3223. }
  3224. }
  3225. //
  3226. // Acquire a credential handle for the client side
  3227. //
  3228. SecStatus = AcquireCredentialsHandle(
  3229. NULL, // New principal
  3230. PackageName,
  3231. SECPKG_CRED_OUTBOUND,
  3232. NULL,
  3233. AuthIdentity,
  3234. NULL,
  3235. NULL,
  3236. &CredentialHandle2,
  3237. &Lifetime );
  3238. if ( SecStatus != STATUS_SUCCESS )
  3239. {
  3240. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3241. TrustingDomain,
  3242. TrustedDomain );
  3243. return SecStatus;
  3244. }
  3245. //
  3246. // Query some cred attributes
  3247. //
  3248. SecStatus = QueryCredentialsAttributes(
  3249. &CredentialHandle2,
  3250. SECPKG_CRED_ATTR_NAMES,
  3251. &CredNames );
  3252. if ( SecStatus != STATUS_SUCCESS )
  3253. {
  3254. if ( !NT_SUCCESS(SecStatus) )
  3255. {
  3256. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3257. TrustingDomain,
  3258. TrustedDomain );
  3259. return SecStatus;
  3260. }
  3261. }
  3262. else
  3263. {
  3264. FreeContextBuffer(CredNames.sUserName);
  3265. }
  3266. //
  3267. // Do the same for the client
  3268. //
  3269. SecStatus = QueryCredentialsAttributes(
  3270. ServerCredHandle,
  3271. SECPKG_CRED_ATTR_NAMES,
  3272. &CredNames );
  3273. if ( SecStatus != STATUS_SUCCESS )
  3274. {
  3275. if ( !NT_SUCCESS(SecStatus) )
  3276. {
  3277. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3278. TrustingDomain,
  3279. TrustedDomain );
  3280. return SecStatus;
  3281. }
  3282. }
  3283. else
  3284. {
  3285. FreeContextBuffer(CredNames.sUserName);
  3286. }
  3287. //
  3288. // Get the NegotiateMessage (ClientSide)
  3289. //
  3290. NegotiateDesc.ulVersion = 0;
  3291. NegotiateDesc.cBuffers = 1;
  3292. NegotiateDesc.pBuffers = &NegotiateBuffer;
  3293. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  3294. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  3295. NegotiateBuffer.pvBuffer = LocalAlloc( 0, NegotiateBuffer.cbBuffer );
  3296. if ( NegotiateBuffer.pvBuffer == NULL )
  3297. {
  3298. DWORD dwError = GetLastError();
  3299. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3300. TrustingDomain,
  3301. TrustedDomain );
  3302. return dwError;
  3303. }
  3304. if (ContextReq == 0)
  3305. {
  3306. ClientFlags = ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY; // USE_DCE_STYLE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_USE_SESSION_KEY; // | ISC_REQ_DATAGRAM;
  3307. }
  3308. else
  3309. {
  3310. ClientFlags = ContextReq;
  3311. }
  3312. if (ServerUserNameU != NULL && ServerDomainNameU != NULL)
  3313. {
  3314. wcscpy(
  3315. TargetName,
  3316. ServerUserNameU
  3317. );
  3318. wcscat(
  3319. TargetName,
  3320. L"@"
  3321. );
  3322. wcscat(
  3323. TargetName,
  3324. ServerDomainNameU
  3325. );
  3326. }
  3327. InitStatus = InitializeSecurityContext(
  3328. &CredentialHandle2,
  3329. NULL, // No Client context yet
  3330. TargetName, // Faked target name
  3331. ClientFlags,
  3332. 0, // Reserved 1
  3333. SECURITY_NATIVE_DREP,
  3334. NULL, // No initial input token
  3335. 0, // Reserved 2
  3336. &ClientContextHandle,
  3337. &NegotiateDesc,
  3338. &ContextAttributes,
  3339. &Lifetime );
  3340. if ( InitStatus != STATUS_SUCCESS )
  3341. {
  3342. if ( !NT_SUCCESS(InitStatus) )
  3343. {
  3344. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3345. TrustingDomain,
  3346. TrustedDomain );
  3347. return InitStatus;
  3348. }
  3349. }
  3350. //
  3351. // Get the ChallengeMessage (ServerSide)
  3352. //
  3353. NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
  3354. ChallengeDesc.ulVersion = 0;
  3355. ChallengeDesc.cBuffers = 1;
  3356. ChallengeDesc.pBuffers = &ChallengeBuffer;
  3357. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  3358. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  3359. ChallengeBuffer.pvBuffer = LocalAlloc( 0, ChallengeBuffer.cbBuffer );
  3360. if ( ChallengeBuffer.pvBuffer == NULL )
  3361. {
  3362. DWORD dwError = GetLastError();
  3363. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3364. TrustingDomain,
  3365. TrustedDomain );
  3366. return dwError;
  3367. }
  3368. ServerFlags = ASC_REQ_EXTENDED_ERROR;
  3369. AcceptStatus = AcceptSecurityContext(
  3370. ServerCredHandle,
  3371. NULL, // No Server context yet
  3372. &NegotiateDesc,
  3373. ServerFlags,
  3374. SECURITY_NATIVE_DREP,
  3375. &ServerContextHandle,
  3376. &ChallengeDesc,
  3377. &ContextAttributes,
  3378. &Lifetime );
  3379. if ( AcceptStatus != STATUS_SUCCESS )
  3380. {
  3381. if ( !NT_SUCCESS(AcceptStatus) )
  3382. {
  3383. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3384. TrustingDomain,
  3385. TrustedDomain );
  3386. return AcceptStatus;
  3387. }
  3388. }
  3389. while (InitStatus != STATUS_SUCCESS)
  3390. {
  3391. //
  3392. // Get the AuthenticateMessage (ClientSide)
  3393. //
  3394. ChallengeBuffer.BufferType |= SECBUFFER_READONLY;
  3395. AuthenticateDesc.ulVersion = 0;
  3396. AuthenticateDesc.cBuffers = 1;
  3397. AuthenticateDesc.pBuffers = &AuthenticateBuffer;
  3398. AuthenticateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  3399. AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
  3400. if (AuthenticateBuffer.pvBuffer == NULL)
  3401. {
  3402. AuthenticateBuffer.pvBuffer = LocalAlloc( 0, AuthenticateBuffer.cbBuffer );
  3403. if ( AuthenticateBuffer.pvBuffer == NULL )
  3404. {
  3405. DWORD dwError = GetLastError();
  3406. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3407. TrustingDomain,
  3408. TrustedDomain );
  3409. return dwError;
  3410. }
  3411. }
  3412. InitStatus = InitializeSecurityContext(
  3413. NULL,
  3414. &ClientContextHandle,
  3415. TargetName,
  3416. ClientFlags,
  3417. 0, // Reserved 1
  3418. SECURITY_NATIVE_DREP,
  3419. &ChallengeDesc,
  3420. 0, // Reserved 2
  3421. &ClientContextHandle,
  3422. &AuthenticateDesc,
  3423. &ContextAttributes,
  3424. &Lifetime );
  3425. if ( InitStatus != STATUS_SUCCESS )
  3426. {
  3427. if ( !NT_SUCCESS(InitStatus) )
  3428. {
  3429. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3430. TrustingDomain,
  3431. TrustedDomain );
  3432. return InitStatus;
  3433. }
  3434. }
  3435. if (AcceptStatus != STATUS_SUCCESS)
  3436. {
  3437. //
  3438. // Finally authenticate the user (ServerSide)
  3439. //
  3440. AuthenticateBuffer.BufferType |= SECBUFFER_READONLY;
  3441. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  3442. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  3443. AcceptStatus = AcceptSecurityContext(
  3444. NULL,
  3445. &ServerContextHandle,
  3446. &AuthenticateDesc,
  3447. ServerFlags,
  3448. SECURITY_NATIVE_DREP,
  3449. &ServerContextHandle,
  3450. &ChallengeDesc,
  3451. &ContextAttributes,
  3452. &Lifetime );
  3453. if ( AcceptStatus != STATUS_SUCCESS )
  3454. {
  3455. if ( !NT_SUCCESS(AcceptStatus) )
  3456. {
  3457. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  3458. TrustingDomain,
  3459. TrustedDomain );
  3460. return AcceptStatus;
  3461. }
  3462. }
  3463. }
  3464. }
  3465. NetDompDisplayMessage( MSG_KERBEROS_TRUST_SUCCEEDED, TrustedDomain, TrustingDomain );
  3466. return AcceptStatus;
  3467. }
  3468. DWORD
  3469. NetDompVerifyTrust(
  3470. IN PND5_TRUST_INFO pTrustingInfo, // outbound
  3471. IN PND5_TRUST_INFO pTrustedInfo, // inbound
  3472. BOOL fShowResults
  3473. )
  3474. /*++
  3475. Routine Description:
  3476. This function will verify a trust connection
  3477. Arguments:
  3478. TrustingInfo - Information on the trusting (outbound) side of the domain
  3479. TrustedInfo - Information on the trusted (inbound) side of the domain
  3480. Return Value:
  3481. ERROR_SUCCESS - The function succeeded
  3482. --*/
  3483. {
  3484. NTSTATUS Status = STATUS_SUCCESS;
  3485. DWORD SidBuff[ sizeof( SID ) / sizeof( DWORD ) + 5 ];
  3486. PSID DomAdminSid = ( PSID )SidBuff;
  3487. PLSA_REFERENCED_DOMAIN_LIST Domains = NULL;
  3488. PLSA_TRANSLATED_NAME Names = NULL;
  3489. NET_API_STATUS NetStatus;
  3490. PNETLOGON_INFO_2 NetlogonInfo2 = NULL;
  3491. CSafeUnicodeString *psustrDomSvr = new CSafeUnicodeString ( *( pTrustedInfo->DomainName ) );
  3492. if ( !psustrDomSvr )
  3493. return ERROR_NOT_ENOUGH_MEMORY;
  3494. PWSTR pwzDomSvr = (PWSTR) *psustrDomSvr;
  3495. CSafeUnicodeString *psustrTrustedDomain = new CSafeUnicodeString ( *( pTrustedInfo->DomainName ) );
  3496. if ( !psustrTrustedDomain )
  3497. {
  3498. delete psustrDomSvr;
  3499. return ERROR_NOT_ENOUGH_MEMORY;
  3500. }
  3501. PWSTR pwzTrustedDomain = (PWSTR) *psustrTrustedDomain;
  3502. BOOL fBufferAlloced = FALSE;
  3503. ASSERT( RtlValidSid( pTrustedInfo->Sid ) );
  3504. if ( !RtlValidSid( pTrustedInfo->Sid ) ) {
  3505. // Dealloc old CSafeUnicodeString, dont need to check for value
  3506. // as its safe to delete null pointer
  3507. delete ( psustrDomSvr );
  3508. delete ( psustrTrustedDomain );
  3509. return( ERROR_INVALID_SID );
  3510. }
  3511. if (!pTrustingInfo->Uplevel)
  3512. {
  3513. // Dealloc old CSafeUnicodeString, dont need to check for value
  3514. // as its safe to delete null pointer
  3515. delete ( psustrDomSvr );
  3516. delete ( psustrTrustedDomain );
  3517. psustrDomSvr = new CSafeUnicodeString ( *( pTrustedInfo->FlatName ) );
  3518. if ( !psustrDomSvr )
  3519. return ERROR_NOT_ENOUGH_MEMORY;
  3520. psustrTrustedDomain = new CSafeUnicodeString ( *( pTrustedInfo->FlatName ) );
  3521. if ( !psustrTrustedDomain )
  3522. {
  3523. delete psustrDomSvr;
  3524. return ERROR_NOT_ENOUGH_MEMORY;
  3525. }
  3526. pwzTrustedDomain = (PWSTR) psustrTrustedDomain;
  3527. pwzDomSvr = (PWSTR) psustrDomSvr;
  3528. }
  3529. //
  3530. // Check netlogon's secure channel
  3531. //
  3532. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  3533. NETLOGON_CONTROL_TC_VERIFY,
  3534. 2,
  3535. (LPBYTE)&pwzTrustedDomain,
  3536. (LPBYTE *)&NetlogonInfo2);
  3537. if (ERROR_NO_SUCH_DOMAIN == NetStatus && pTrustingInfo->Uplevel)
  3538. {
  3539. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  3540. // have a flat name.
  3541. //
  3542. // Dealloc old CSafeUnicodeString, dont need to check for value
  3543. // as its safe to delete null pointer
  3544. delete ( psustrDomSvr );
  3545. delete ( psustrTrustedDomain );
  3546. psustrDomSvr = new CSafeUnicodeString ( *( pTrustedInfo->FlatName ) );
  3547. if ( !psustrDomSvr )
  3548. return ERROR_NOT_ENOUGH_MEMORY;
  3549. psustrTrustedDomain = new CSafeUnicodeString ( *( pTrustedInfo->FlatName ) );
  3550. if ( !psustrTrustedDomain )
  3551. {
  3552. delete ( psustrDomSvr );
  3553. return ERROR_NOT_ENOUGH_MEMORY;
  3554. }
  3555. pwzTrustedDomain = (PWSTR) psustrTrustedDomain;
  3556. pwzDomSvr = (PWSTR) psustrDomSvr;
  3557. pTrustedInfo->fWasDownlevel = TRUE;
  3558. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  3559. NETLOGON_CONTROL_TC_VERIFY,
  3560. 2,
  3561. (LPBYTE)&pwzTrustedDomain,
  3562. (LPBYTE *)&NetlogonInfo2);
  3563. }
  3564. bool fVerifyDone = true;
  3565. if (ERROR_NOT_SUPPORTED == NetStatus)
  3566. {
  3567. // Must be remoted to a Win2k/NT4 DC that doesn't support SC verify.
  3568. //
  3569. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  3570. NETLOGON_CONTROL_TC_QUERY,
  3571. 2,
  3572. (LPBYTE)&pwzTrustedDomain,
  3573. (LPBYTE *)&NetlogonInfo2);
  3574. fVerifyDone = false;
  3575. }
  3576. if (NERR_Success == NetStatus)
  3577. {
  3578. if (fVerifyDone &&
  3579. NETLOGON_VERIFY_STATUS_RETURNED & NetlogonInfo2->netlog2_flags)
  3580. {
  3581. // The status of the verification is in the
  3582. // netlog2_pdc_connection_status field.
  3583. //
  3584. NetStatus = NetlogonInfo2->netlog2_pdc_connection_status;
  3585. }
  3586. else
  3587. {
  3588. NetStatus = NetlogonInfo2->netlog2_tc_connection_status;
  3589. }
  3590. if (NERR_Success == NetStatus)
  3591. {
  3592. if (pTrustingInfo->Uplevel)
  3593. {
  3594. // Form the name domain\DC so a reset can done against the same
  3595. // DC that is currently being used for the secure channel.
  3596. //
  3597. NetStatus = NetApiBufferAllocate((wcslen(NetlogonInfo2->netlog2_trusted_dc_name) +
  3598. wcslen(pwzTrustedDomain) + 1) * sizeof(WCHAR),
  3599. (PVOID*)&pwzDomSvr);
  3600. if (NERR_Success != NetStatus)
  3601. {
  3602. // Dealloc old CSafeUnicodeString, dont need to check for value
  3603. // as its safe to delete null pointer
  3604. delete ( psustrDomSvr );
  3605. delete ( psustrTrustedDomain );
  3606. NetApiBufferFree( NetlogonInfo2 );
  3607. return ERROR_NOT_ENOUGH_MEMORY;
  3608. }
  3609. fBufferAlloced = TRUE;
  3610. wsprintf(pwzDomSvr, L"%s\\%s", pwzTrustedDomain,
  3611. (L'\\' == *NetlogonInfo2->netlog2_trusted_dc_name) ?
  3612. NetlogonInfo2->netlog2_trusted_dc_name + 2 :
  3613. NetlogonInfo2->netlog2_trusted_dc_name);
  3614. }
  3615. }
  3616. else
  3617. {
  3618. if (fShowResults)
  3619. {
  3620. // Report Query/Verify failure.
  3621. //
  3622. NetDompDisplayMessage(MSG_VERIFY_TRUST_QUERY_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  3623. NetDompDisplayErrorMessage(NetStatus);
  3624. if (ERROR_DOMAIN_TRUST_INCONSISTENT == NetStatus)
  3625. {
  3626. NetDompDisplayMessage(MSG_VERIFY_TRUST_INCONSISTENT);
  3627. printf("\n");
  3628. }
  3629. }
  3630. }
  3631. NetApiBufferFree( NetlogonInfo2 );
  3632. if (fVerifyDone && NERR_Success != NetStatus)
  3633. {
  3634. // If verify was done and failed, no need to do a reset.
  3635. //
  3636. // Dealloc old CSafeUnicodeString, dont need to check for value
  3637. // as its safe to delete null pointer
  3638. delete ( psustrDomSvr );
  3639. delete ( psustrTrustedDomain );
  3640. return NetStatus;
  3641. }
  3642. }
  3643. else
  3644. {
  3645. if (fShowResults)
  3646. {
  3647. // Report I_NetLogonControl2 error.
  3648. //
  3649. // Dealloc old CSafeUnicodeString, dont need to check for value
  3650. // as its safe to delete null pointer
  3651. delete ( psustrDomSvr );
  3652. delete ( psustrTrustedDomain );
  3653. NetDompDisplayMessage(MSG_VERIFY_TRUST_NLQUERY_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  3654. NetDompDisplayErrorMessage(NetStatus);
  3655. return NetStatus;
  3656. }
  3657. }
  3658. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  3659. NETLOGON_CONTROL_REDISCOVER,
  3660. 2,
  3661. (LPBYTE)&pwzDomSvr,
  3662. (LPBYTE *)&NetlogonInfo2 );
  3663. if (fBufferAlloced)
  3664. {
  3665. NetApiBufferFree(pwzDomSvr);
  3666. }
  3667. if (NERR_Success == NetStatus)
  3668. {
  3669. NetStatus = NetlogonInfo2->netlog2_tc_connection_status;
  3670. if (NERR_Success != NetStatus)
  3671. {
  3672. if (fShowResults)
  3673. {
  3674. // Report Reset failure.
  3675. //
  3676. NetDompDisplayMessage(MSG_VERIFY_TRUST_RESET_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  3677. NetDompDisplayErrorMessage(NetStatus);
  3678. }
  3679. // Dealloc old CSafeUnicodeString, dont need to check for value
  3680. // as its safe to delete null pointer
  3681. delete ( psustrDomSvr );
  3682. delete ( psustrTrustedDomain );
  3683. NetApiBufferFree( NetlogonInfo2 );
  3684. return NetStatus;
  3685. }
  3686. NetApiBufferFree( NetlogonInfo2 );
  3687. }
  3688. else
  3689. {
  3690. if (fShowResults)
  3691. {
  3692. // Report failure
  3693. //
  3694. NetDompDisplayMessage(MSG_VERIFY_TRUST_NLRESET_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  3695. NetDompDisplayErrorMessage(NetStatus);
  3696. }
  3697. // Dealloc old CSafeUnicodeString, dont need to check for value
  3698. // as its safe to delete null pointer
  3699. delete ( psustrDomSvr );
  3700. delete ( psustrTrustedDomain );
  3701. return NetStatus;
  3702. }
  3703. //
  3704. // Now, try a lookup
  3705. //
  3706. if (ERROR_SUCCESS == NetStatus)
  3707. {
  3708. //
  3709. // Build the domain admins sid for the inbound side of the trust
  3710. //
  3711. RtlCopyMemory( DomAdminSid,
  3712. pTrustedInfo->Sid,
  3713. RtlLengthSid( pTrustedInfo->Sid ) );
  3714. ( ( PISID )( DomAdminSid ) )->SubAuthorityCount++;
  3715. *( RtlSubAuthoritySid( DomAdminSid,
  3716. *( RtlSubAuthorityCountSid( pTrustedInfo->Sid ) ) ) ) =
  3717. DOMAIN_GROUP_RID_ADMINS;
  3718. //
  3719. // Now, we'll simply do a remote lookup, and ensure that we get back success
  3720. //
  3721. Status = LsaLookupSids( pTrustingInfo->LsaHandle,
  3722. 1,
  3723. &DomAdminSid,
  3724. &Domains,
  3725. &Names );
  3726. if ( NT_SUCCESS( Status ) )
  3727. {
  3728. LsaFreeMemory( Domains );
  3729. LsaFreeMemory( Names );
  3730. NetStatus = ERROR_SUCCESS;
  3731. }
  3732. else
  3733. {
  3734. if ( Status == STATUS_NONE_MAPPED )
  3735. {
  3736. NetStatus = ERROR_TRUSTED_DOMAIN_FAILURE;
  3737. }
  3738. else
  3739. {
  3740. NetStatus = RtlNtStatusToDosError( Status );
  3741. }
  3742. if (fShowResults)
  3743. {
  3744. // Report failure
  3745. //
  3746. NetDompDisplayMessage(MSG_VERIFY_TRUST_LOOKUP_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  3747. NetDompDisplayErrorMessage(NetStatus);
  3748. }
  3749. }
  3750. }
  3751. // Dealloc old CSafeUnicodeString, dont need to check for value
  3752. // as its safe to delete null pointer
  3753. delete ( psustrDomSvr );
  3754. delete ( psustrTrustedDomain );
  3755. return NetStatus;
  3756. }
  3757. DWORD
  3758. NetDompVerifyTrustObject(
  3759. IN ARG_RECORD * rgNetDomArgs,
  3760. IN PWSTR pwzDomain1,
  3761. IN PWSTR pwzDomain2,
  3762. IN PND5_AUTH_INFO pDomain1Creds,
  3763. IN PND5_AUTH_INFO pDomain2Creds
  3764. )
  3765. /*++
  3766. Routine Description:
  3767. This function will handle the verifying of a trust
  3768. Arguments:
  3769. rgNetDomArgs - List of arguments present in the Args list
  3770. pwzDomain1, pwzDomain2 - domains with trust
  3771. pDomain1Creds, pDomain2Creds - Credentials to use when connecting to
  3772. the domain controllers
  3773. Return Value:
  3774. ERROR_INVALID_PARAMETER - No object name was supplied
  3775. --*/
  3776. {
  3777. DWORD Win32Err, Win32Err1;
  3778. ND5_TRUST_INFO TrustInfo1, TrustInfo2;
  3779. PND5_TRUST_INFO pTrustInfoUplevel, pTrustInfoOther;
  3780. DWORD Direction;
  3781. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  3782. {
  3783. return ERROR_INVALID_PARAMETER;
  3784. }
  3785. RtlZeroMemory( &TrustInfo1, sizeof( TrustInfo1 ) );
  3786. RtlZeroMemory( &TrustInfo2, sizeof( TrustInfo2 ) );
  3787. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  3788. NULL,
  3789. pDomain1Creds,
  3790. &TrustInfo1,
  3791. TRUE,
  3792. FALSE, FALSE );
  3793. if (ERROR_SUCCESS == Win32Err) {
  3794. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  3795. NULL,
  3796. pDomain2Creds,
  3797. &TrustInfo2,
  3798. TRUE,
  3799. FALSE, FALSE );
  3800. }
  3801. if (ERROR_SUCCESS != Win32Err)
  3802. {
  3803. goto TrustVerifyExit;
  3804. }
  3805. Win32Err = NetDompGetTrustDirection(&TrustInfo1,
  3806. &TrustInfo2,
  3807. &Direction);
  3808. if (ERROR_SUCCESS != Win32Err)
  3809. {
  3810. goto TrustVerifyExit;
  3811. }
  3812. if (TRUST_DIRECTION_DISABLED == Direction)
  3813. {
  3814. NetDompDisplayMessage(MSG_VERIFY_TRUST_DISABLED);
  3815. goto TrustVerifyExit;
  3816. }
  3817. if (Direction & TRUST_DIRECTION_OUTBOUND)
  3818. {
  3819. LOG_VERBOSE((MSG_VERBOSE_VERIFY_TRUST, pwzDomain1, pwzDomain2));
  3820. Win32Err = NetDompVerifyTrust(&TrustInfo1,
  3821. &TrustInfo2,
  3822. TRUE);
  3823. }
  3824. if (Direction & TRUST_DIRECTION_INBOUND)
  3825. {
  3826. LOG_VERBOSE((MSG_VERBOSE_VERIFY_TRUST, pwzDomain2, pwzDomain1));
  3827. Win32Err1 = NetDompVerifyTrust(&TrustInfo2,
  3828. &TrustInfo1,
  3829. TRUE);
  3830. }
  3831. if (ERROR_SUCCESS == Win32Err && ERROR_SUCCESS == Win32Err1)
  3832. {
  3833. NetDompDisplayMessage(MSG_VERIFY_TRUST_OK, pwzDomain1, pwzDomain2);
  3834. }
  3835. TrustVerifyExit:
  3836. NetDompFreeDomInfo( &TrustInfo2 );
  3837. NetDompFreeDomInfo( &TrustInfo1 );
  3838. return( Win32Err );
  3839. }
  3840. DWORD
  3841. NetDompHandleTrust(ARG_RECORD * rgNetDomArgs)
  3842. /*++
  3843. Routine Description:
  3844. This function manages inter-domain trust
  3845. Arguments:
  3846. Args - List of command line arguments
  3847. Return Value:
  3848. ERROR_INVALID_PARAMETER - No object name was supplied
  3849. --*/
  3850. {
  3851. DWORD Win32Err = ERROR_SUCCESS;
  3852. ULONG Ops = 0, i;
  3853. NETDOM_ARG_ENUM BadOp = eArgBegin;
  3854. PWSTR TrustedDomain = NULL, pwzArgValue = NULL, pwzArgValue2 = NULL;
  3855. ND5_AUTH_INFO TrustedDomainUser, TrustingDomainUser;
  3856. RtlZeroMemory( &TrustedDomainUser, sizeof( ND5_AUTH_INFO ) );
  3857. RtlZeroMemory( &TrustingDomainUser, sizeof( ND5_AUTH_INFO ) );
  3858. PWSTR TrustingDomain = rgNetDomArgs[eObject].strValue;
  3859. if ( !TrustingDomain ) {
  3860. DisplayHelp(ePriTrust);
  3861. return( ERROR_INVALID_PARAMETER );
  3862. }
  3863. Win32Err = NetDompValidateSecondaryArguments(rgNetDomArgs,
  3864. eObject,
  3865. eCommDomain,
  3866. eCommUserNameO,
  3867. eCommPasswordO,
  3868. eCommUserNameD,
  3869. eCommPasswordD,
  3870. eTrustRealm,
  3871. eTrustPasswordT,
  3872. eCommAdd,
  3873. eCommRemove,
  3874. eTrustTwoWay,
  3875. eTrustKerberos,
  3876. eTrustTransitive,
  3877. eTrustOneSide,
  3878. eTrustNameSuffixes,
  3879. eTrustToggleSuffixes,
  3880. eTrustFilterSIDs,
  3881. eTrustResetOneSide,
  3882. eTrustTreatAsExternal,
  3883. eTrustForestTransitive,
  3884. eTrustCrossOrganization,
  3885. eTrustAddTLN,
  3886. eTrustAddTLNEX,
  3887. eTrustRemoveTLN,
  3888. eTrustRemoveTLNEX,
  3889. eCommVerify,
  3890. eCommReset,
  3891. eCommForce,
  3892. eCommVerbose,
  3893. eArgEnd);
  3894. if ( Win32Err != ERROR_SUCCESS ) {
  3895. DisplayHelp(ePriTrust);
  3896. return Win32Err;
  3897. }
  3898. //
  3899. // See if we are doing an add, remove, or verify
  3900. //
  3901. if ( CmdFlagOn(rgNetDomArgs, eCommAdd) ) {
  3902. Ops++;
  3903. if (CmdFlagOn(rgNetDomArgs, eTrustTransitive))
  3904. {
  3905. BadOp = eTrustTransitive;
  3906. }
  3907. }
  3908. if ( CmdFlagOn(rgNetDomArgs, eCommRemove) ) {
  3909. if ( Ops ) {
  3910. BadOp = eCommRemove;
  3911. } else {
  3912. Ops++;
  3913. }
  3914. if ( CmdFlagOn(rgNetDomArgs, eTrustRealm) ) {
  3915. BadOp = eTrustRealm;
  3916. }
  3917. }
  3918. if ( CmdFlagOn(rgNetDomArgs, eCommVerify) ) {
  3919. if ( Ops ) {
  3920. BadOp = eCommVerify;
  3921. } else {
  3922. Ops++;
  3923. }
  3924. }
  3925. if (BadOp != eArgBegin) {
  3926. Win32Err = ERROR_INVALID_PARAMETER;
  3927. NetDompDisplayUnexpectedParameter(rgNetDomArgs[BadOp].strArg1);
  3928. goto HandleTrustExit;
  3929. }
  3930. if (!CmdFlagOn(rgNetDomArgs, eTrustNameSuffixes)) {
  3931. //
  3932. // Make sure that we have a specified domain (if not listing claimed names).
  3933. //
  3934. Win32Err = NetDompGetDomainForOperation(rgNetDomArgs,
  3935. NULL, // no server specified
  3936. FALSE, // don't default to current domain.
  3937. &TrustedDomain);
  3938. if ( Win32Err != ERROR_SUCCESS ) {
  3939. goto HandleTrustExit;
  3940. }
  3941. }
  3942. //
  3943. // Get the password and user if it exists
  3944. //
  3945. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameD) ) {
  3946. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  3947. eCommUserNameD,
  3948. TrustedDomain,
  3949. &TrustedDomainUser );
  3950. if ( Win32Err != ERROR_SUCCESS ) {
  3951. goto HandleTrustExit;
  3952. }
  3953. }
  3954. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameO) ) {
  3955. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  3956. eCommUserNameO,
  3957. TrustingDomain,
  3958. &TrustingDomainUser );
  3959. if ( Win32Err != ERROR_SUCCESS ) {
  3960. goto HandleTrustExit;
  3961. }
  3962. }
  3963. bool fShowError = true;
  3964. if ( CmdFlagOn(rgNetDomArgs, eCommAdd) )
  3965. {
  3966. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  3967. {
  3968. // Get the trust PW.
  3969. //
  3970. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3971. eTrustPasswordT,
  3972. &pwzArgValue2);
  3973. if (ERROR_SUCCESS != Win32Err)
  3974. {
  3975. goto HandleTrustExit;
  3976. }
  3977. if (pwzArgValue2)
  3978. {
  3979. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  3980. TrustingDomain,
  3981. TrustedDomain,
  3982. &TrustingDomainUser,
  3983. &TrustedDomainUser,
  3984. pwzArgValue2,
  3985. NULL);
  3986. NetApiBufferFree(pwzArgValue2);
  3987. }
  3988. else
  3989. {
  3990. NetDompDisplayMessage(MSG_TRUST_PW_MISSING);
  3991. Win32Err = ERROR_INVALID_PARAMETER;
  3992. }
  3993. }
  3994. else if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  3995. {
  3996. // Get the trust PW.
  3997. //
  3998. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3999. eTrustPasswordT,
  4000. &pwzArgValue2);
  4001. if (ERROR_SUCCESS != Win32Err)
  4002. {
  4003. goto HandleTrustExit;
  4004. }
  4005. if (!pwzArgValue2)
  4006. {
  4007. NetDompDisplayMessage(MSG_TRUST_PW_MISSING);
  4008. Win32Err = ERROR_INVALID_PARAMETER;
  4009. goto HandleTrustExit;
  4010. }
  4011. // Get the side on which to create the trust.
  4012. //
  4013. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4014. eTrustOneSide,
  4015. &pwzArgValue);
  4016. if (ERROR_SUCCESS != Win32Err)
  4017. {
  4018. NetApiBufferFree(pwzArgValue2);
  4019. goto HandleTrustExit;
  4020. }
  4021. if (!pwzArgValue)
  4022. {
  4023. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  4024. Win32Err = ERROR_INVALID_PARAMETER;
  4025. NetApiBufferFree(pwzArgValue2);
  4026. goto HandleTrustExit;
  4027. }
  4028. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  4029. TrustingDomain,
  4030. TrustedDomain,
  4031. &TrustingDomainUser,
  4032. &TrustedDomainUser,
  4033. pwzArgValue2,
  4034. pwzArgValue);
  4035. NetApiBufferFree(pwzArgValue2);
  4036. }
  4037. else
  4038. {
  4039. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  4040. TrustingDomain,
  4041. TrustedDomain,
  4042. &TrustingDomainUser,
  4043. &TrustedDomainUser,
  4044. NULL, NULL);
  4045. }
  4046. }
  4047. else if ( CmdFlagOn(rgNetDomArgs, eCommRemove) )
  4048. {
  4049. if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  4050. {
  4051. // Get the side on which to delete the trust.
  4052. //
  4053. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4054. eTrustOneSide,
  4055. &pwzArgValue);
  4056. if (ERROR_SUCCESS != Win32Err)
  4057. {
  4058. goto HandleTrustExit;
  4059. }
  4060. if (!pwzArgValue)
  4061. {
  4062. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  4063. Win32Err = ERROR_INVALID_PARAMETER;
  4064. goto HandleTrustExit;
  4065. }
  4066. Win32Err = NetDompRemoveTrustObject( rgNetDomArgs,
  4067. TrustingDomain,
  4068. TrustedDomain,
  4069. &TrustingDomainUser,
  4070. &TrustedDomainUser,
  4071. pwzArgValue);
  4072. }
  4073. else
  4074. {
  4075. Win32Err = NetDompRemoveTrustObject( rgNetDomArgs,
  4076. TrustingDomain,
  4077. TrustedDomain,
  4078. &TrustingDomainUser,
  4079. &TrustedDomainUser,
  4080. NULL);
  4081. }
  4082. }
  4083. else if ( CmdFlagOn(rgNetDomArgs, eCommReset) )
  4084. {
  4085. //
  4086. // See if a password is specifed
  4087. //
  4088. if (CmdFlagOn(rgNetDomArgs, eTrustPasswordT))
  4089. {
  4090. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4091. eTrustPasswordT,
  4092. &pwzArgValue2);
  4093. if (ERROR_SUCCESS != Win32Err)
  4094. {
  4095. goto HandleTrustExit;
  4096. }
  4097. if (pwzArgValue2)
  4098. {
  4099. Win32Err = NetDompSetMitTrustPW(TrustingDomain,
  4100. TrustedDomain,
  4101. &TrustingDomainUser,
  4102. &TrustedDomainUser,
  4103. pwzArgValue2);
  4104. NetApiBufferFree(pwzArgValue2);
  4105. }
  4106. else
  4107. {
  4108. Win32Err = ERROR_INVALID_PARAMETER;
  4109. }
  4110. }
  4111. else
  4112. {
  4113. Win32Err = NetDompResetTrustPasswords(TrustingDomain,
  4114. TrustedDomain,
  4115. &TrustingDomainUser,
  4116. &TrustedDomainUser);
  4117. }
  4118. }
  4119. else if ( CmdFlagOn(rgNetDomArgs, eCommVerify ) )
  4120. {
  4121. Win32Err = NetDompVerifyTrustObject( rgNetDomArgs,
  4122. TrustingDomain,
  4123. TrustedDomain,
  4124. &TrustingDomainUser,
  4125. &TrustedDomainUser );
  4126. fShowError = false;
  4127. }
  4128. else if ( CmdFlagOn(rgNetDomArgs, eTrustKerberos) )
  4129. {
  4130. Win32Err = NetDompVerifyIndividualTrustKerberos( TrustingDomain,
  4131. TrustedDomain,
  4132. &TrustingDomainUser,
  4133. &TrustedDomainUser );
  4134. }
  4135. else if (CmdFlagOn(rgNetDomArgs, eTrustTransitive))
  4136. {
  4137. //
  4138. // Get the transitivity parameter
  4139. //
  4140. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4141. eTrustTransitive,
  4142. &pwzArgValue);
  4143. if (ERROR_SUCCESS != Win32Err)
  4144. {
  4145. goto HandleTrustExit;
  4146. }
  4147. Win32Err = NetDomTransitivity(pwzArgValue,
  4148. TrustingDomain,
  4149. TrustedDomain,
  4150. &TrustingDomainUser,
  4151. &TrustedDomainUser );
  4152. }
  4153. else if (CmdFlagOn(rgNetDomArgs, eTrustFilterSIDs))
  4154. {
  4155. //
  4156. // Get the transitivity parameter
  4157. //
  4158. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4159. eTrustFilterSIDs,
  4160. &pwzArgValue);
  4161. if (ERROR_SUCCESS != Win32Err)
  4162. {
  4163. goto HandleTrustExit;
  4164. }
  4165. Win32Err = NetDomFilterSID(pwzArgValue,
  4166. TrustingDomain,
  4167. TrustedDomain,
  4168. &TrustingDomainUser,
  4169. &TrustedDomainUser );
  4170. }
  4171. else if (CmdFlagOn(rgNetDomArgs, eTrustNameSuffixes))
  4172. {
  4173. //
  4174. // Get the name of the domain whose name is to be toggled.
  4175. //
  4176. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4177. eTrustNameSuffixes,
  4178. &pwzArgValue);
  4179. if (ERROR_SUCCESS != Win32Err)
  4180. {
  4181. goto HandleTrustExit;
  4182. }
  4183. if (CmdFlagOn(rgNetDomArgs, eTrustToggleSuffixes))
  4184. {
  4185. //
  4186. // Get the number of the name to toggle.
  4187. //
  4188. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4189. eTrustToggleSuffixes,
  4190. &pwzArgValue2);
  4191. if (ERROR_SUCCESS != Win32Err)
  4192. {
  4193. goto HandleTrustExit;
  4194. }
  4195. if (!pwzArgValue2)
  4196. {
  4197. NetDompDisplayMessage(MSG_SUFFIX_INDEX_MISSING);
  4198. Win32Err = ERROR_INVALID_PARAMETER;
  4199. goto HandleTrustExit;
  4200. }
  4201. i = wcstoul(pwzArgValue2, L'\0', 10);
  4202. NetApiBufferFree(pwzArgValue2);
  4203. pwzArgValue2 = NULL;
  4204. if (1 > i)
  4205. {
  4206. NetDompDisplayMessage(MSG_SUFFIX_INDEX_BOUNDS);
  4207. Win32Err = ERROR_INVALID_PARAMETER;
  4208. goto HandleTrustExit;
  4209. }
  4210. Win32Err = NetDomForestSuffix(pwzArgValue,
  4211. i,
  4212. TrustingDomain,
  4213. &TrustingDomainUser);
  4214. }
  4215. else
  4216. {
  4217. Win32Err = NetDomForestSuffix(pwzArgValue,
  4218. 0,
  4219. TrustingDomain,
  4220. &TrustingDomainUser);
  4221. }
  4222. }
  4223. else if ( CmdFlagOn(rgNetDomArgs, eTrustResetOneSide) )
  4224. {
  4225. //
  4226. // See if a password is specifed
  4227. //
  4228. if (CmdFlagOn(rgNetDomArgs, eTrustPasswordT))
  4229. {
  4230. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  4231. eTrustPasswordT,
  4232. &pwzArgValue2);
  4233. if (ERROR_SUCCESS != Win32Err)
  4234. {
  4235. goto HandleTrustExit;
  4236. }
  4237. if (pwzArgValue2)
  4238. {
  4239. Win32Err = NetDompResetTrustPWOneSide (TrustingDomain,
  4240. TrustedDomain,
  4241. &TrustingDomainUser,
  4242. &TrustedDomainUser,
  4243. pwzArgValue2);
  4244. NetApiBufferFree(pwzArgValue2);
  4245. }
  4246. else
  4247. {
  4248. Win32Err = ERROR_INVALID_PARAMETER;
  4249. }
  4250. }
  4251. else
  4252. {
  4253. Win32Err = ERROR_INVALID_PARAMETER;
  4254. }
  4255. }
  4256. else if ( CmdFlagOn(rgNetDomArgs, eTrustTreatAsExternal ) )
  4257. {
  4258. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4259. eTrustTreatAsExternal,
  4260. &pwzArgValue );
  4261. if ( ERROR_SUCCESS != Win32Err )
  4262. {
  4263. goto HandleTrustExit;
  4264. }
  4265. Win32Err = NetDomToggleTrustAttribute( pwzArgValue,
  4266. TrustingDomain,
  4267. TrustedDomain,
  4268. &TrustingDomainUser,
  4269. TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL);
  4270. }
  4271. else if ( CmdFlagOn(rgNetDomArgs, eTrustForestTransitive ) )
  4272. {
  4273. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4274. eTrustForestTransitive,
  4275. &pwzArgValue );
  4276. if ( ERROR_SUCCESS != Win32Err )
  4277. {
  4278. goto HandleTrustExit;
  4279. }
  4280. Win32Err = NetDomToggleTrustAttribute( pwzArgValue,
  4281. TrustingDomain,
  4282. TrustedDomain,
  4283. &TrustingDomainUser,
  4284. TRUST_ATTRIBUTE_FOREST_TRANSITIVE );
  4285. }
  4286. else if ( CmdFlagOn(rgNetDomArgs, eTrustCrossOrganization ) )
  4287. {
  4288. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4289. eTrustCrossOrganization,
  4290. &pwzArgValue );
  4291. if ( ERROR_SUCCESS != Win32Err )
  4292. {
  4293. goto HandleTrustExit;
  4294. }
  4295. Win32Err = NetDomToggleTrustAttribute( pwzArgValue,
  4296. TrustingDomain,
  4297. TrustedDomain,
  4298. &TrustingDomainUser,
  4299. TRUST_ATTRIBUTE_CROSS_ORGANIZATION );
  4300. }
  4301. else if ( CmdFlagOn(rgNetDomArgs, eTrustAddTLN ) )
  4302. {
  4303. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4304. eTrustAddTLN,
  4305. &pwzArgValue );
  4306. if ( ERROR_SUCCESS != Win32Err )
  4307. {
  4308. goto HandleTrustExit;
  4309. }
  4310. Win32Err = NetDomAddRemoveTLN ( TrustingDomain,
  4311. TrustedDomain,
  4312. pwzArgValue,
  4313. TRUE, //Add
  4314. FALSE, //TLN
  4315. &TrustingDomainUser );
  4316. }
  4317. else if ( CmdFlagOn(rgNetDomArgs, eTrustAddTLNEX ) )
  4318. {
  4319. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4320. eTrustAddTLNEX,
  4321. &pwzArgValue );
  4322. if ( ERROR_SUCCESS != Win32Err )
  4323. {
  4324. goto HandleTrustExit;
  4325. }
  4326. Win32Err = NetDomAddRemoveTLN ( TrustingDomain,
  4327. TrustedDomain,
  4328. pwzArgValue,
  4329. TRUE, //Add
  4330. TRUE, //TLNExclusion
  4331. &TrustingDomainUser );
  4332. }
  4333. else if ( CmdFlagOn(rgNetDomArgs, eTrustRemoveTLN ) )
  4334. {
  4335. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4336. eTrustRemoveTLN,
  4337. &pwzArgValue );
  4338. if ( ERROR_SUCCESS != Win32Err )
  4339. {
  4340. goto HandleTrustExit;
  4341. }
  4342. Win32Err = NetDomAddRemoveTLN ( TrustingDomain,
  4343. TrustedDomain,
  4344. pwzArgValue,
  4345. FALSE, //Remove
  4346. FALSE, //TLN
  4347. &TrustingDomainUser );
  4348. }
  4349. else if ( CmdFlagOn(rgNetDomArgs, eTrustRemoveTLNEX ) )
  4350. {
  4351. Win32Err = NetDompGetArgumentString ( rgNetDomArgs,
  4352. eTrustRemoveTLNEX,
  4353. &pwzArgValue );
  4354. if ( ERROR_SUCCESS != Win32Err )
  4355. {
  4356. goto HandleTrustExit;
  4357. }
  4358. Win32Err = NetDomAddRemoveTLN ( TrustingDomain,
  4359. TrustedDomain,
  4360. pwzArgValue,
  4361. FALSE, //Remove
  4362. TRUE, //TLN Exclusion
  4363. &TrustingDomainUser );
  4364. }
  4365. else
  4366. {
  4367. Win32Err = ERROR_INVALID_PARAMETER;
  4368. }
  4369. HandleTrustExit:
  4370. if (pwzArgValue)
  4371. {
  4372. NetApiBufferFree(pwzArgValue);
  4373. }
  4374. NetApiBufferFree( TrustedDomain );
  4375. NetDompFreeAuthIdent( &TrustedDomainUser );
  4376. NetDompFreeAuthIdent( &TrustingDomainUser );
  4377. if (NO_ERROR != Win32Err && fShowError)
  4378. {
  4379. NetDompDisplayErrorMessage(Win32Err);
  4380. }
  4381. return( Win32Err );
  4382. }
  4383. DWORD
  4384. NetDompIsParentChild(
  4385. IN PND5_TRUST_INFO pFirstDomainInfo,
  4386. IN PND5_TRUST_INFO pSecondDomainInfo,
  4387. OUT BOOL * pfParentChild)
  4388. /*++
  4389. Routine Description:
  4390. Is the domain named by the second argument a child or parent of the first argument domain.
  4391. The Parent or Child bits of the trust-info Flags element is set as appropriate.
  4392. --*/
  4393. {
  4394. DWORD Win32Err;
  4395. PDS_DOMAIN_TRUSTS rgDomains = NULL;
  4396. ULONG ulCount = 0, i, ulLocalDomainIdx = (ULONG)-1, ulOtherDomainIdx = (ULONG)-1;
  4397. ULONG ulLocalDomainParent = (ULONG)-1, ulOtherDomainParent = (ULONG)-1;
  4398. PWSTR pwzServer, pwzOtherDomainDnsName, pwzOtherDomainNetbiosName;
  4399. CSafeUnicodeString *psustrOtherDomDnsName = NULL, *psustrOtherDomNetbiosName = NULL;
  4400. BOOL fFirstIsLocal = TRUE;
  4401. *pfParentChild = FALSE;
  4402. // The domain which is used as the starting point for the enumeration is
  4403. // called the "local" domain and the remaining domain is the "other" domain.
  4404. //
  4405. if (pFirstDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  4406. {
  4407. // The first domain does not exist, so use the second domain's server
  4408. // as the starting point for the domain enumeration.
  4409. //
  4410. pwzServer = pSecondDomainInfo->Server;
  4411. ASSERT(!(pSecondDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND));
  4412. psustrOtherDomDnsName = new CSafeUnicodeString ( *( pFirstDomainInfo->DomainName ) );
  4413. if ( !psustrOtherDomDnsName )
  4414. return ERROR_NOT_ENOUGH_MEMORY;
  4415. pwzOtherDomainDnsName = (PWSTR) (*psustrOtherDomDnsName);
  4416. psustrOtherDomNetbiosName = new CSafeUnicodeString ( *( pFirstDomainInfo->DomainName ) );
  4417. if ( !psustrOtherDomNetbiosName )
  4418. {
  4419. delete psustrOtherDomDnsName;
  4420. return ERROR_NOT_ENOUGH_MEMORY;
  4421. }
  4422. pwzOtherDomainNetbiosName = (PWSTR) ( *psustrOtherDomNetbiosName);
  4423. fFirstIsLocal = FALSE;
  4424. }
  4425. else
  4426. {
  4427. // The first domain exists, so use its server as the starting point
  4428. // for the domain enumeration.
  4429. //
  4430. pwzServer = pFirstDomainInfo->Server;
  4431. psustrOtherDomDnsName = new CSafeUnicodeString ( *( pSecondDomainInfo->DomainName ) );
  4432. if ( !psustrOtherDomDnsName )
  4433. return ERROR_NOT_ENOUGH_MEMORY;
  4434. pwzOtherDomainDnsName = (PWSTR) (*psustrOtherDomDnsName);
  4435. psustrOtherDomNetbiosName = new CSafeUnicodeString ( (pSecondDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) ?
  4436. ( *( pSecondDomainInfo->DomainName ) ): ( *( pSecondDomainInfo->FlatName )) );
  4437. if ( !psustrOtherDomNetbiosName )
  4438. {
  4439. delete psustrOtherDomDnsName;
  4440. return ERROR_NOT_ENOUGH_MEMORY;
  4441. }
  4442. pwzOtherDomainNetbiosName = (PWSTR) ( *psustrOtherDomNetbiosName );
  4443. }
  4444. ASSERT(pwzServer);
  4445. // Specifying DS_DOMAIN_IN_FOREST will eliminate any external trusts
  4446. // in the result set.
  4447. //
  4448. Win32Err = DsEnumerateDomainTrusts(pwzServer,
  4449. DS_DOMAIN_IN_FOREST,
  4450. &rgDomains,
  4451. &ulCount);
  4452. if (Win32Err != ERROR_SUCCESS)
  4453. {
  4454. return Win32Err;
  4455. }
  4456. for (i = 0; i < ulCount; i++)
  4457. {
  4458. ASSERT(rgDomains[i].TrustType & TRUST_TYPE_UPLEVEL);
  4459. if (rgDomains[i].Flags & DS_DOMAIN_PRIMARY)
  4460. {
  4461. ulLocalDomainIdx = i;
  4462. DBG_VERBOSE(("%2d: Local domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  4463. if (!(rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT))
  4464. {
  4465. DBG_VERBOSE(("\tParent index of above domain: %d\n", rgDomains[i].ParentIndex))
  4466. ulLocalDomainParent = rgDomains[i].ParentIndex;
  4467. }
  4468. else
  4469. {
  4470. DBG_VERBOSE(("\tThis domain is a tree root\n"))
  4471. }
  4472. continue;
  4473. }
  4474. #if DBG == 1
  4475. DBG_VERBOSE(("%2d: Domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  4476. if (rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT) DBG_VERBOSE(("\tThis domain is a tree root\n"))
  4477. else DBG_VERBOSE(("\tParent index of above domain: %d\n", rgDomains[i].ParentIndex))
  4478. #endif
  4479. if ((rgDomains[i].NetbiosDomainName && _wcsicmp(rgDomains[i].NetbiosDomainName, pwzOtherDomainNetbiosName) == 0) ||
  4480. (rgDomains[i].DnsDomainName && _wcsicmp(rgDomains[i].DnsDomainName, pwzOtherDomainDnsName) == 0))
  4481. {
  4482. ulOtherDomainIdx = i;
  4483. DBG_VERBOSE(("\tThis domain is the second domain\n"))
  4484. if (!(rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT))
  4485. {
  4486. ulOtherDomainParent = rgDomains[i].ParentIndex;
  4487. }
  4488. continue;
  4489. }
  4490. #if DBG == 1
  4491. if (!(rgDomains[i].Flags & DS_DOMAIN_DIRECT_OUTBOUND))
  4492. {
  4493. DBG_VERBOSE(("%2d: Indirectly trusted domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  4494. }
  4495. #endif
  4496. }
  4497. delete psustrOtherDomNetbiosName;
  4498. delete psustrOtherDomDnsName;
  4499. if (rgDomains)
  4500. {
  4501. NetApiBufferFree(rgDomains);
  4502. }
  4503. // Determine the relationship between the two domains. One of three
  4504. // situations will apply:
  4505. // 1. The local domain is the parent of the other domain. If true, then
  4506. // the parent index of the other domain will point to the local domain.
  4507. // In addition, the other domain cannot be a tree root.
  4508. // 2. The local domain is the child of the other domain. If true, then
  4509. // the parent index of the local domain will point to the other domain.
  4510. // The local domain then cannot be a tree root.
  4511. // 3. The two domains don't have a parent-child relationship. It must be
  4512. // a shortcut or external trust.
  4513. //
  4514. if (ulOtherDomainIdx == (ULONG)-1)
  4515. {
  4516. // Other domain not found, it must be an external trust (case 3 above).
  4517. //
  4518. DBG_VERBOSE(("\n"))
  4519. return ERROR_SUCCESS;
  4520. }
  4521. if (ulLocalDomainParent == ulOtherDomainIdx)
  4522. {
  4523. // Case 2, the local domain is the child of the other domain.
  4524. //
  4525. if (fFirstIsLocal)
  4526. {
  4527. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  4528. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  4529. }
  4530. else
  4531. {
  4532. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  4533. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  4534. }
  4535. *pfParentChild = TRUE;
  4536. DBG_VERBOSE(("\tpfParentChild set to TRUE\n\n"))
  4537. }
  4538. else if ( ulOtherDomainParent == ulLocalDomainIdx )
  4539. {
  4540. //
  4541. // Case 1 above, the local domain is the parent of the other domain.
  4542. //
  4543. if (fFirstIsLocal)
  4544. {
  4545. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  4546. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  4547. }
  4548. else
  4549. {
  4550. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  4551. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  4552. }
  4553. *pfParentChild = TRUE;
  4554. DBG_VERBOSE(("\tpfParentChild set to TRUE\n\n"))
  4555. }
  4556. else
  4557. {
  4558. // This is a shortcut trust Case 3 above
  4559. DBG_VERBOSE(("\n"))
  4560. *pfParentChild = FALSE;
  4561. }
  4562. return ERROR_SUCCESS;
  4563. }