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

4446 lines
136 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. if ( !DomainController ) {
  80. if ( ManageTrust ) {
  81. DsGetDcOptions |= DS_WRITABLE_REQUIRED;
  82. }
  83. if (TrustInfo->Flags & NETDOM_TRUST_PDC_REQUIRED)
  84. {
  85. DsGetDcOptions |= DS_PDC_REQUIRED;
  86. }
  87. Win32Err = DsGetDcName( NULL,
  88. Domain,
  89. NULL,
  90. NULL,
  91. DsGetDcOptions,
  92. &DcInfo );
  93. if ( Win32Err == ERROR_SUCCESS ) {
  94. DomainController = DcInfo->DomainControllerName;
  95. }
  96. }
  97. //
  98. // Save off the server name
  99. //
  100. if ( Win32Err == ERROR_SUCCESS ) {
  101. Win32Err = NetApiBufferAllocate( ( wcslen( DomainController ) + 1 ) * sizeof( WCHAR ),
  102. (PVOID*)&( TrustInfo->Server ) );
  103. if ( Win32Err == ERROR_SUCCESS ) {
  104. wcscpy( TrustInfo->Server, DomainController );
  105. }
  106. }
  107. //
  108. // Connect to the machine
  109. //
  110. if ( Win32Err == ERROR_SUCCESS ) {
  111. LOG_VERBOSE(( MSG_VERBOSE_ESTABLISH_SESSION, DomainController ));
  112. Win32Err = NetpManageIPCConnect( DomainController,
  113. (fUseNullSession) ? L"" : AuthInfo->User,
  114. (fUseNullSession) ? L"" : AuthInfo->Password,
  115. (fUseNullSession) ?
  116. NETSETUPP_NULL_SESSION_IPC : NETSETUPP_CONNECT_IPC);
  117. if ( Win32Err == ERROR_SUCCESS ) {
  118. TrustInfo->Connected = TRUE;
  119. }
  120. if (ERROR_SESSION_CREDENTIAL_CONFLICT == Win32Err)
  121. {
  122. if (fUseNullSession)
  123. {
  124. // Ignore conflict of creds.
  125. //
  126. Win32Err = ERROR_SUCCESS;
  127. }
  128. else
  129. {
  130. NetDompDisplayMessage(MSG_ALREADY_CONNECTED, DomainController);
  131. }
  132. }
  133. if (ERROR_LOGON_FAILURE == Win32Err)
  134. {
  135. NetApiBufferFree( DcInfo );
  136. return Win32Err;
  137. }
  138. }
  139. //
  140. // Get the domain information
  141. //
  142. if ( Win32Err == ERROR_SUCCESS ) {
  143. RtlInitUnicodeString( &ServerU, DomainController );
  144. InitializeObjectAttributes( &OA, NULL, 0, NULL, NULL );
  145. LOG_VERBOSE(( MSG_VERBOSE_GET_LSA ));
  146. LsaOptions = POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES;
  147. if ( ManageTrust ) {
  148. LsaOptions |= POLICY_CREATE_SECRET | POLICY_TRUST_ADMIN;
  149. }
  150. Status = LsaOpenPolicy( &ServerU,
  151. &OA,
  152. LsaOptions,
  153. &( TrustInfo->LsaHandle ) );
  154. if ( NT_SUCCESS( Status ) ) {
  155. Status = LsaQueryInformationPolicy( TrustInfo->LsaHandle,
  156. PolicyDnsDomainInformation,
  157. ( PVOID * )&PolicyDDI );
  158. if ( NT_SUCCESS( Status ) ) {
  159. TrustInfo->DomainName = &PolicyDDI->DnsDomainName;
  160. TrustInfo->FlatName = &PolicyDDI->Name;
  161. TrustInfo->Sid = PolicyDDI->Sid;
  162. TrustInfo->BlobToFree = ( PVOID )PolicyDDI;
  163. TrustInfo->Uplevel = TRUE;
  164. TrustInfo->fWasDownlevel = FALSE;
  165. } else if ( Status == RPC_NT_PROCNUM_OUT_OF_RANGE ) {
  166. Status = LsaQueryInformationPolicy( TrustInfo->LsaHandle,
  167. PolicyPrimaryDomainInformation,
  168. ( PVOID * )&PolicyPDI );
  169. if ( NT_SUCCESS( Status ) ) {
  170. TrustInfo->DomainName = &PolicyPDI->Name;
  171. TrustInfo->FlatName = &PolicyPDI->Name;
  172. TrustInfo->Sid = PolicyPDI->Sid;
  173. TrustInfo->BlobToFree = ( PVOID )PolicyPDI;
  174. TrustInfo->Uplevel = TrustInfo->fWasDownlevel = FALSE;
  175. }
  176. }
  177. }
  178. Win32Err = RtlNtStatusToDosError( Status );
  179. if ( Win32Err != ERROR_SUCCESS ) {
  180. LOG_VERBOSE(( MSG_VERBOSE_DELETE_SESSION, DomainController ));
  181. NetpManageIPCConnect( DomainController,
  182. NULL,
  183. NULL,
  184. NETSETUPP_DISCONNECT_IPC );
  185. TrustInfo->Connected = FALSE;
  186. }
  187. } else if (fForce) {
  188. LOG_VERBOSE(( MSG_VERBOSE_DOMAIN_NOT_FOUND, Domain ));
  189. TrustInfo->Flags = NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND;
  190. // Allocate space to save the user-entered domain name.
  191. Win32Err = NetApiBufferAllocate((wcslen(Domain) + 1) * sizeof(WCHAR), (PVOID*)&pwzDomainName);
  192. if ( Win32Err == ERROR_SUCCESS ) {
  193. Win32Err = NetApiBufferAllocate(sizeof(UNICODE_STRING), (PVOID*)&TrustInfo->DomainName);
  194. if ( Win32Err == ERROR_SUCCESS ) {
  195. wcscpy( pwzDomainName, Domain );
  196. RtlInitUnicodeString( TrustInfo->DomainName, pwzDomainName );
  197. TrustInfo->FlatName = TrustInfo->DomainName;
  198. }
  199. }
  200. }
  201. else
  202. {
  203. LOG_VERBOSE((MSG_DOMAIN_NOT_FOUND, Domain));
  204. }
  205. NetApiBufferFree( DcInfo );
  206. return( Win32Err );
  207. }
  208. DWORD
  209. NetDompTrustRemoveIncomingDownlevelObject(
  210. IN PND5_TRUST_INFO TrustingInfo,
  211. IN PND5_TRUST_INFO TrustedInfo
  212. )
  213. /*++
  214. Routine Description:
  215. This function removes the interdomain trust account object on
  216. the trusted domain.
  217. Arguments:
  218. TrustingInfo - Info on the trusting domain
  219. TrustedInfo - Info on the trusted domain
  220. Return Value:
  221. ERROR_INVALID_PARAMETER - No object name was supplied
  222. --*/
  223. {
  224. DWORD Win32Err = ERROR_SUCCESS;
  225. WCHAR AccountName[ UNLEN + 1 ];
  226. PWSTR FullServer = NULL;
  227. if ( TrustingInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  228. return( ERROR_INVALID_DOMAINNAME );
  229. }
  230. if ( TrustedInfo->Server && *( TrustedInfo->Server ) != L'\\' ) {
  231. Win32Err = NetApiBufferAllocate( ( wcslen( TrustedInfo->Server ) + 3 ) * sizeof( WCHAR ),
  232. ( PVOID * )&FullServer );
  233. if ( Win32Err == ERROR_SUCCESS ) {
  234. swprintf( FullServer, L"\\\\%ws", TrustedInfo->Server );
  235. }
  236. } else {
  237. FullServer = TrustedInfo->Server;
  238. }
  239. //
  240. // Build the account name...
  241. //
  242. if ( Win32Err == ERROR_SUCCESS ) {
  243. swprintf( AccountName, L"%ws$", TrustingInfo->FlatName->Buffer );
  244. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TACCT, AccountName ));
  245. Win32Err = NetUserDel( FullServer,
  246. AccountName );
  247. }
  248. if ( FullServer != TrustedInfo->Server ) {
  249. NetApiBufferFree( FullServer );
  250. }
  251. return( Win32Err );
  252. }
  253. DWORD
  254. NetDompTrustRemoveOutgoingDownlevelObject(
  255. IN PND5_TRUST_INFO TrustingInfo,
  256. IN PND5_TRUST_INFO TrustedInfo
  257. )
  258. /*++
  259. Routine Description:
  260. This function deletes the trust object/secret on the trusting domain.
  261. Arguments:
  262. TrustingInfo - Info on the trusting domain
  263. TrustedInfo - Info on the trusted domain
  264. Return Value:
  265. ERROR_INVALID_PARAMETER - No object name was supplied
  266. --*/
  267. {
  268. DWORD Win32Err = ERROR_SUCCESS;
  269. WCHAR SecretName[ DNLEN + 4 ];
  270. LSA_HANDLE TrustedDomain, SecretHandle;
  271. NTSTATUS Status;
  272. UNICODE_STRING Secret;
  273. if ( TrustedInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  274. return( ERROR_INVALID_DOMAINNAME );
  275. }
  276. if ( !TrustedInfo->Sid ) {
  277. // Must be an orphaned trust, nothing we can do.
  278. return NO_ERROR;
  279. }
  280. //
  281. // Build the secret name
  282. //
  283. swprintf( SecretName, L"%ws$%ws", LSA_GLOBAL_SECRET_PREFIX, TrustedInfo->FlatName->Buffer );
  284. //
  285. // Ok, first, delete the trust object. It's ok if the trust object is deleted but the
  286. // secret is not
  287. //
  288. LOG_VERBOSE(( MSG_VERBOSE_OPEN_TRUST, TrustedInfo->DomainName->Buffer ));
  289. Status = LsaOpenTrustedDomain( TrustingInfo->LsaHandle,
  290. TrustedInfo->Sid,
  291. DELETE,
  292. &TrustedDomain );
  293. if ( NT_SUCCESS( Status ) ) {
  294. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, TrustedInfo->DomainName->Buffer ));
  295. Status = LsaDelete( TrustedDomain );
  296. if ( !NT_SUCCESS( Status ) ) {
  297. LsaClose( TrustedDomain );
  298. }
  299. }
  300. //
  301. // Now, the same with the secret
  302. //
  303. if ( NT_SUCCESS( Status ) ) {
  304. RtlInitUnicodeString( &Secret, SecretName );
  305. LOG_VERBOSE(( MSG_VERBOSE_OPEN_SECRET, Secret.Buffer ));
  306. Status = LsaOpenSecret( TrustingInfo->LsaHandle,
  307. &Secret,
  308. DELETE,
  309. &SecretHandle );
  310. if ( NT_SUCCESS( Status ) ) {
  311. LOG_VERBOSE(( MSG_VERBOSE_DELETE_SECRET, Secret.Buffer ));
  312. Status = LsaDelete( SecretHandle );
  313. if ( !NT_SUCCESS( Status ) ) {
  314. LsaClose( SecretHandle );
  315. }
  316. }
  317. }
  318. Win32Err = RtlNtStatusToDosError( Status );
  319. return( Win32Err );
  320. }
  321. DWORD
  322. NetDompTrustSetPasswordSam(
  323. IN PWSTR Server,
  324. IN PWSTR AccountName,
  325. IN PWSTR Password
  326. )
  327. /*++
  328. Routine Description:
  329. This function will set the password on a SAM trust object
  330. Arguments:
  331. Server - Server that holds the account object
  332. AccountName - Name of the account
  333. Password - Password to set
  334. Return Value:
  335. ERROR_SUCCESS - The function succeeded
  336. --*/
  337. {
  338. DWORD Win32Err = ERROR_SUCCESS;
  339. USER_INFO_1 UI1, *ReadUI1 = NULL;
  340. PWSTR FullServer = NULL;
  341. if ( Server && *( Server ) != L'\\' ) {
  342. Win32Err = NetApiBufferAllocate( ( wcslen( Server ) + 3 ) * sizeof( WCHAR ),
  343. ( PVOID * )&FullServer );
  344. if ( Win32Err == ERROR_SUCCESS ) {
  345. swprintf( FullServer, L"\\\\%ws", Server );
  346. }
  347. } else {
  348. FullServer = Server;
  349. }
  350. if ( Win32Err == ERROR_SUCCESS ) {
  351. Win32Err = NetUserGetInfo( FullServer,
  352. AccountName,
  353. 1,
  354. ( LPBYTE * )&ReadUI1 );
  355. if ( Win32Err == ERROR_SUCCESS ) {
  356. if ( !FLAG_ON( ReadUI1->usri1_flags, UF_INTERDOMAIN_TRUST_ACCOUNT ) ) {
  357. Win32Err = ERROR_SPECIAL_ACCOUNT;
  358. } else {
  359. ReadUI1->usri1_password = Password;
  360. ReadUI1->usri1_flags = UF_INTERDOMAIN_TRUST_ACCOUNT | UF_SCRIPT;
  361. Win32Err = NetUserSetInfo( FullServer,
  362. AccountName,
  363. 1,
  364. ( LPBYTE )ReadUI1,
  365. NULL );
  366. }
  367. NetApiBufferFree( ReadUI1 );
  368. }
  369. }
  370. if ( FullServer != Server ) {
  371. NetApiBufferFree( FullServer );
  372. }
  373. return( Win32Err );
  374. }
  375. DWORD
  376. NetDompTrustAddIncomingDownlevelObject(
  377. IN PND5_TRUST_INFO TrustingInfo,
  378. IN PND5_TRUST_INFO TrustedInfo,
  379. IN PWSTR TrustPassword,
  380. IN ULONG PasswordLength
  381. )
  382. /*++
  383. Routine Description:
  384. This function creates the interdomain trust account object on
  385. the trusted domain.
  386. Arguments:
  387. TrustingInfo - Info on the trusting domain
  388. TrustedInfo - Info on the trusted domain
  389. Return Value:
  390. ERROR_INVALID_PARAMETER - No object name was supplied
  391. --*/
  392. {
  393. DWORD Win32Err = ERROR_SUCCESS;
  394. WCHAR AccountName[ UNLEN + 1 ];
  395. USER_INFO_1 UI1;
  396. PWSTR FullServer = NULL;
  397. if ( TrustingInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  398. return( ERROR_INVALID_DOMAINNAME );
  399. }
  400. //
  401. // Build the account name...
  402. //
  403. swprintf( AccountName, L"%ws$", TrustingInfo->FlatName->Buffer );
  404. LOG_VERBOSE(( MSG_VERBOSE_ADD_TACCT, AccountName ));
  405. UI1.usri1_name = AccountName;
  406. UI1.usri1_password = TrustPassword;
  407. UI1.usri1_password_age = 0;
  408. UI1.usri1_priv = USER_PRIV_USER;
  409. UI1.usri1_home_dir = NULL;
  410. UI1.usri1_comment = NULL;
  411. UI1.usri1_flags = UF_INTERDOMAIN_TRUST_ACCOUNT | UF_SCRIPT;
  412. UI1.usri1_script_path = NULL;
  413. if ( TrustedInfo->Server && *( TrustedInfo->Server ) != L'\\' ) {
  414. Win32Err = NetApiBufferAllocate( ( wcslen( TrustedInfo->Server ) + 3 ) * sizeof( WCHAR ),
  415. ( PVOID * )&FullServer );
  416. if ( Win32Err == ERROR_SUCCESS ) {
  417. swprintf( FullServer, L"\\\\%ws", TrustedInfo->Server );
  418. }
  419. } else {
  420. FullServer = TrustedInfo->Server;
  421. }
  422. if ( Win32Err == ERROR_SUCCESS ) {
  423. Win32Err = NetUserAdd( FullServer,
  424. 1,
  425. ( LPBYTE )&UI1,
  426. NULL );
  427. if ( Win32Err == NERR_UserExists ) {
  428. Win32Err = NetDompTrustSetPasswordSam( FullServer,
  429. AccountName,
  430. TrustPassword );
  431. }
  432. }
  433. if ( FullServer != TrustedInfo->Server ) {
  434. NetApiBufferFree( FullServer );
  435. }
  436. return( Win32Err );
  437. }
  438. DWORD
  439. NetDompTrustAddOutgoingDownlevelObject(
  440. IN PND5_TRUST_INFO TrustingInfo,
  441. IN PND5_TRUST_INFO TrustedInfo,
  442. IN PWSTR TrustPassword,
  443. IN ULONG PasswordLength
  444. )
  445. /*++
  446. Routine Description:
  447. This function creates the trust secret on the trusting domain.
  448. Arguments:
  449. TrustingInfo - Info on the trusting domain
  450. TrustedInfo - Info on the trusted domain
  451. Return Value:
  452. ERROR_INVALID_PARAMETER - No object name was supplied
  453. --*/
  454. {
  455. DWORD Win32Err = ERROR_SUCCESS;
  456. WCHAR SecretName[ DNLEN + 4 ];
  457. LSA_HANDLE TrustedDomain = NULL, SecretHandle = NULL;
  458. NTSTATUS Status;
  459. UNICODE_STRING Secret, Password;
  460. BOOL DeleteSecret = FALSE;
  461. LSA_TRUST_INFORMATION TrustInfo;
  462. if ( TrustedInfo->FlatName->Length > DNLEN * sizeof( WCHAR ) ) {
  463. return( ERROR_INVALID_DOMAINNAME );
  464. }
  465. //
  466. // Build the secret name
  467. //
  468. swprintf( SecretName, L"%ws$%ws", LSA_GLOBAL_SECRET_PREFIX, TrustedInfo->FlatName->Buffer );
  469. //
  470. // Ok, first, create the secret, It's ok if the secret is created but the
  471. // trust object is not
  472. //
  473. RtlInitUnicodeString( &Secret, SecretName );
  474. LOG_VERBOSE(( MSG_VERBOSE_CREATE_SECRET, Secret.Buffer ));
  475. Status = LsaCreateSecret( TrustingInfo->LsaHandle,
  476. &Secret,
  477. SECRET_SET_VALUE,
  478. &SecretHandle );
  479. if ( NT_SUCCESS( Status ) ) {
  480. DeleteSecret = TRUE;
  481. } else if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  482. LOG_VERBOSE(( MSG_VERBOSE_OPEN_SECRET, Secret.Buffer ));
  483. Status = LsaOpenSecret( TrustingInfo->LsaHandle,
  484. &Secret,
  485. SECRET_SET_VALUE,
  486. &SecretHandle );
  487. }
  488. if ( NT_SUCCESS( Status ) ) {
  489. RtlInitUnicodeString( &Password, TrustPassword );
  490. Status = LsaSetSecret( SecretHandle,
  491. &Password,
  492. NULL );
  493. }
  494. //
  495. // Ok, now create the trust object
  496. //
  497. if ( NT_SUCCESS( Status ) ) {
  498. TrustInfo.Sid = TrustedInfo->Sid;
  499. RtlCopyMemory( &TrustInfo.Name, TrustedInfo->FlatName, sizeof( UNICODE_STRING ) );
  500. LOG_VERBOSE(( MSG_VERBOSE_CREATE_TRUST, TrustInfo.Name.Buffer ));
  501. Status = LsaCreateTrustedDomain( TrustingInfo->LsaHandle,
  502. &TrustInfo,
  503. TRUSTED_QUERY_DOMAIN_NAME,
  504. &TrustedDomain );
  505. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  506. Status = STATUS_SUCCESS;
  507. }
  508. }
  509. if ( !NT_SUCCESS( Status ) && DeleteSecret ) {
  510. LsaDelete( SecretHandle );
  511. SecretHandle = NULL;
  512. }
  513. Win32Err = RtlNtStatusToDosError( Status );
  514. if ( SecretHandle ) {
  515. LsaClose( SecretHandle );
  516. }
  517. if ( TrustedDomain ) {
  518. LsaClose( TrustedDomain );
  519. }
  520. return( Win32Err );
  521. }
  522. DWORD
  523. NetDompAddOnTrustingSide(
  524. IN PND5_TRUST_INFO TrustedInfo,
  525. IN PND5_TRUST_INFO TrustingInfo,
  526. IN PWSTR TrustPassword,
  527. IN ULONG Direction,
  528. IN BOOL Mit
  529. )
  530. /*++
  531. Routine Description:
  532. This function creates the trust object on the trusting domain.
  533. Arguments:
  534. TrustedInfo - Info on the trusted domain
  535. TrustingInfo - Info on the trusting domain
  536. Direction - The direction of the trust
  537. Mit - If true, this is an MIT style trust
  538. Return Value:
  539. ERROR_INVALID_PARAMETER - No object name was supplied
  540. --*/
  541. {
  542. DWORD Win32Err = ERROR_SUCCESS;
  543. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  544. PTRUSTED_DOMAIN_FULL_INFORMATION pFullInfo;
  545. TRUSTED_DOMAIN_AUTH_INFORMATION TDAI;
  546. LSA_AUTH_INFORMATION AuthData;
  547. ULONG PasswordLength = wcslen(TrustPassword);
  548. NTSTATUS Status;
  549. BOOL fSidSet = FALSE;
  550. PLSA_UNICODE_STRING pName;
  551. if (TrustingInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  552. {
  553. if (Mit)
  554. {
  555. return ERROR_SUCCESS;
  556. }
  557. else
  558. {
  559. return ERROR_INVALID_PARAMETER;
  560. }
  561. }
  562. if ( TrustingInfo->Uplevel ) {
  563. RtlCopyMemory( &TDIEx.Name, TrustedInfo->DomainName, sizeof( UNICODE_STRING ) );
  564. TDIEx.Sid = TrustedInfo->Sid;
  565. TDIEx.TrustDirection = Direction;
  566. if ( Mit ) {
  567. TDIEx.TrustType = TRUST_TYPE_MIT;
  568. TDIEx.TrustAttributes = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  569. RtlCopyMemory( &TDIEx.FlatName, TrustedInfo->DomainName, sizeof( UNICODE_STRING ) );
  570. } else {
  571. TDIEx.TrustType = TrustedInfo->Uplevel ? TRUST_TYPE_UPLEVEL : TRUST_TYPE_DOWNLEVEL;
  572. TDIEx.TrustAttributes = 0;
  573. RtlCopyMemory( &TDIEx.FlatName, TrustedInfo->FlatName, sizeof( UNICODE_STRING ) );
  574. }
  575. Status = NtQuerySystemTime( &AuthData.LastUpdateTime );
  576. if ( NT_SUCCESS( Status ) ) {
  577. AuthData.AuthType = TRUST_AUTH_TYPE_CLEAR;
  578. AuthData.AuthInfoLength = PasswordLength * sizeof( WCHAR );
  579. AuthData.AuthInfo = ( PUCHAR )TrustPassword;
  580. TDAI.OutgoingAuthInfos = 1;
  581. TDAI.OutgoingAuthenticationInformation = &AuthData;
  582. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  583. if ( FLAG_ON( Direction, TRUST_DIRECTION_INBOUND ) ) {
  584. TDAI.IncomingAuthInfos = 1;
  585. TDAI.IncomingAuthenticationInformation = &AuthData;
  586. TDAI.IncomingPreviousAuthenticationInformation = NULL;
  587. } else {
  588. TDAI.IncomingAuthInfos = 0;
  589. TDAI.IncomingAuthenticationInformation = NULL;
  590. TDAI.IncomingPreviousAuthenticationInformation = NULL;
  591. }
  592. Status = LsaCreateTrustedDomainEx( TrustingInfo->LsaHandle,
  593. &TDIEx,
  594. &TDAI,
  595. TRUSTED_ALL_ACCESS,
  596. &( TrustingInfo->TrustHandle ) );
  597. //
  598. // If the object already exists, morph our info into it.
  599. //
  600. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  601. pName = &TDIEx.Name;
  602. Status = LsaQueryTrustedDomainInfoByName(TrustingInfo->LsaHandle,
  603. pName,
  604. TrustedDomainFullInformation,
  605. (PVOID*)&pFullInfo);
  606. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  607. {
  608. // Now try by flat name; can get here if a downlevel domain
  609. // is upgraded to NT5. The name used above was the DNS name
  610. // but the TDO would be named after the flat name.
  611. //
  612. pName = TrustingInfo->FlatName;
  613. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  614. pName,
  615. TrustedDomainFullInformation,
  616. (PVOID*)&pFullInfo);
  617. }
  618. if ( NT_SUCCESS( Status ) ) {
  619. if ( pFullInfo->Information.TrustDirection == Direction ) {
  620. Status = STATUS_OBJECT_NAME_COLLISION;
  621. } else {
  622. pFullInfo->Information.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  623. pFullInfo->AuthInformation.OutgoingAuthInfos = 1;
  624. pFullInfo->AuthInformation.OutgoingAuthenticationInformation = &AuthData;
  625. pFullInfo->AuthInformation.OutgoingPreviousAuthenticationInformation = NULL;
  626. // Check for a NULL domain SID. The SID can be NULL if the
  627. // trust was created when the domain was still NT4.
  628. //
  629. if (!pFullInfo->Information.Sid)
  630. {
  631. pFullInfo->Information.Sid = TrustedInfo->Sid;
  632. fSidSet = TRUE;
  633. }
  634. Status = LsaSetTrustedDomainInfoByName(TrustingInfo->LsaHandle,
  635. pName,
  636. TrustedDomainFullInformation,
  637. pFullInfo);
  638. }
  639. }
  640. if (fSidSet)
  641. {
  642. // Sid memory is owned by the TrustingInfo struct, so don't free
  643. // it here.
  644. //
  645. pFullInfo->Information.Sid = NULL;
  646. }
  647. LsaFreeMemory( pFullInfo );
  648. }
  649. }
  650. Win32Err = RtlNtStatusToDosError( Status );
  651. } else {
  652. //
  653. // Doing downlevel
  654. //
  655. if ( Mit ) {
  656. Win32Err = ERROR_INVALID_PARAMETER;
  657. } else {
  658. Win32Err = NetDompTrustAddOutgoingDownlevelObject( TrustingInfo,
  659. TrustedInfo,
  660. TrustPassword,
  661. PasswordLength );
  662. if ( Win32Err == ERROR_SUCCESS &&
  663. Direction == TRUST_DIRECTION_BIDIRECTIONAL ) {
  664. Win32Err = NetDompTrustAddIncomingDownlevelObject( TrustedInfo,
  665. TrustingInfo,
  666. TrustPassword,
  667. PasswordLength );
  668. if ( Win32Err != ERROR_SUCCESS ) {
  669. Win32Err = NetDompTrustRemoveOutgoingDownlevelObject( TrustingInfo,
  670. TrustedInfo );
  671. }
  672. }
  673. }
  674. }
  675. if (ERROR_SUCCESS == Win32Err)
  676. {
  677. LOG_VERBOSE((MSG_VERBOSE_CREATED_TRUST, TrustedInfo->DomainName->Buffer,
  678. TrustingInfo->DomainName->Buffer));
  679. }
  680. return( Win32Err );
  681. }
  682. DWORD
  683. NetDompAddOnTrustedSide(
  684. IN PND5_TRUST_INFO TrustedInfo,
  685. IN PND5_TRUST_INFO TrustingInfo,
  686. IN PWSTR TrustPassword,
  687. IN ULONG Direction,
  688. IN BOOL Mit
  689. )
  690. /*++
  691. Routine Description:
  692. This function creates the trust object on the trusted domain.
  693. Arguments:
  694. TrustedInfo - Info on the trusted domain
  695. TrustingInfo - Info on the trusting domain
  696. Direction - The direction of the trust
  697. Mit - If true, this is an MIT style trust
  698. Return Value:
  699. ERROR_INVALID_PARAMETER - No object name was supplied
  700. --*/
  701. {
  702. DWORD Win32Err = ERROR_SUCCESS;
  703. TRUSTED_DOMAIN_INFORMATION_EX TDIEx;
  704. PTRUSTED_DOMAIN_FULL_INFORMATION pFullInfo;
  705. LSA_AUTH_INFORMATION AuthData;
  706. TRUSTED_DOMAIN_AUTH_INFORMATION TDAI;
  707. ULONG PasswordLength = wcslen(TrustPassword);
  708. NTSTATUS Status;
  709. BOOL fSidSet = FALSE;
  710. PLSA_UNICODE_STRING pName;
  711. if (TrustedInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  712. {
  713. if (Mit)
  714. {
  715. return ERROR_SUCCESS;
  716. }
  717. else
  718. {
  719. return ERROR_INVALID_PARAMETER;
  720. }
  721. }
  722. if ( TrustedInfo->Uplevel) {
  723. RtlCopyMemory( &TDIEx.Name, TrustingInfo->DomainName, sizeof( UNICODE_STRING ) );
  724. TDIEx.Sid = TrustingInfo->Sid;
  725. TDIEx.TrustDirection = Direction;
  726. if ( Mit ) {
  727. TDIEx.TrustType = TRUST_TYPE_MIT;
  728. TDIEx.TrustAttributes = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  729. RtlCopyMemory( &TDIEx.FlatName, TrustingInfo->DomainName, sizeof( UNICODE_STRING ) );
  730. } else {
  731. TDIEx.TrustType = TrustingInfo->Uplevel ? TRUST_TYPE_UPLEVEL : TRUST_TYPE_DOWNLEVEL;
  732. TDIEx.TrustAttributes = 0;
  733. RtlCopyMemory( &TDIEx.FlatName, TrustingInfo->FlatName, sizeof( UNICODE_STRING ) );
  734. }
  735. Status = NtQuerySystemTime( &AuthData.LastUpdateTime );
  736. if ( NT_SUCCESS( Status ) ) {
  737. AuthData.AuthType = TRUST_AUTH_TYPE_CLEAR;
  738. AuthData.AuthInfoLength = PasswordLength * sizeof( WCHAR );
  739. AuthData.AuthInfo = ( PUCHAR )TrustPassword;
  740. TDAI.IncomingAuthInfos = 1;
  741. TDAI.IncomingAuthenticationInformation = &AuthData;
  742. TDAI.IncomingPreviousAuthenticationInformation = &AuthData;
  743. if ( FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  744. TDAI.OutgoingAuthInfos = 1;
  745. TDAI.OutgoingAuthenticationInformation = &AuthData;
  746. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  747. } else {
  748. TDAI.OutgoingAuthInfos = 0;
  749. TDAI.OutgoingAuthenticationInformation = NULL;
  750. TDAI.OutgoingPreviousAuthenticationInformation = NULL;
  751. }
  752. Status = LsaCreateTrustedDomainEx( TrustedInfo->LsaHandle,
  753. &TDIEx,
  754. &TDAI,
  755. TRUSTED_ALL_ACCESS,
  756. &( TrustedInfo->TrustHandle ) );
  757. //
  758. // If the object already exists, morph our info into it.
  759. //
  760. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  761. pName = &TDIEx.Name;
  762. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  763. pName,
  764. TrustedDomainFullInformation,
  765. (PVOID*)&pFullInfo);
  766. if (STATUS_OBJECT_NAME_NOT_FOUND == Status)
  767. {
  768. // Now try by flat name; can get here if a downlevel domain
  769. // is upgraded to NT5. The name used above was the DNS name
  770. // but the TDO would be named after the flat name.
  771. //
  772. pName = TrustingInfo->FlatName;
  773. Status = LsaQueryTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  774. pName,
  775. TrustedDomainFullInformation,
  776. (PVOID*)&pFullInfo);
  777. }
  778. if ( NT_SUCCESS( Status ) ) {
  779. if ( pFullInfo->Information.TrustDirection == Direction ) {
  780. Status = STATUS_OBJECT_NAME_COLLISION;
  781. } else {
  782. pFullInfo->Information.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  783. pFullInfo->AuthInformation.IncomingAuthInfos = 1;
  784. pFullInfo->AuthInformation.IncomingAuthenticationInformation = &AuthData;
  785. pFullInfo->AuthInformation.IncomingPreviousAuthenticationInformation = NULL;
  786. // Check for a NULL domain SID. The SID can be NULL if the
  787. // trust was created when the domain was still NT4.
  788. //
  789. if (!pFullInfo->Information.Sid)
  790. {
  791. pFullInfo->Information.Sid = TrustingInfo->Sid;
  792. fSidSet = TRUE;
  793. }
  794. Status = LsaSetTrustedDomainInfoByName(TrustedInfo->LsaHandle,
  795. pName,
  796. TrustedDomainFullInformation,
  797. pFullInfo);
  798. }
  799. }
  800. if (fSidSet)
  801. {
  802. // Sid memory is owned by the TrustingInfo struct, so don't free
  803. // it here.
  804. //
  805. pFullInfo->Information.Sid = NULL;
  806. }
  807. LsaFreeMemory( pFullInfo );
  808. }
  809. }
  810. Win32Err = RtlNtStatusToDosError( Status );
  811. } else {
  812. //
  813. // Doing downlevel
  814. //
  815. if ( Mit ) {
  816. Win32Err = ERROR_INVALID_PARAMETER;
  817. } else {
  818. Win32Err = NetDompTrustAddIncomingDownlevelObject( TrustingInfo,
  819. TrustedInfo,
  820. TrustPassword,
  821. PasswordLength );
  822. if ( Win32Err == ERROR_SUCCESS &&
  823. FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  824. Win32Err = NetDompTrustAddOutgoingDownlevelObject( TrustedInfo,
  825. TrustingInfo,
  826. TrustPassword,
  827. PasswordLength );
  828. if ( Win32Err != ERROR_SUCCESS ) {
  829. Win32Err = NetDompTrustRemoveIncomingDownlevelObject( TrustingInfo,
  830. TrustedInfo );
  831. }
  832. }
  833. }
  834. }
  835. if (ERROR_SUCCESS == Win32Err)
  836. {
  837. LOG_VERBOSE((MSG_VERBOSE_CREATED_TRUST, TrustingInfo->DomainName->Buffer,
  838. TrustedInfo->DomainName->Buffer));
  839. }
  840. return( Win32Err );
  841. }
  842. DWORD
  843. NetDompResetTrustSC(
  844. IN PND5_TRUST_INFO TrustingInfo,
  845. IN PND5_TRUST_INFO TrustedInfo
  846. )
  847. /*++
  848. Routine Description:
  849. This function will reset the secure channel between two domains
  850. Arguments:
  851. TrustingInfo - Information on the trusting side of the domain
  852. TrustedInfo - Information on the trusted side of the domain
  853. Return Value:
  854. ERROR_SUCCESS - The function succeeded
  855. --*/
  856. {
  857. DWORD Win32Err = ERROR_SUCCESS;
  858. PWSTR ScDomain = NULL;
  859. PNETLOGON_INFO_2 NetlogonInfo2 = NULL;
  860. PWSTR FullServer = NULL, pwzDomName = NULL;
  861. if (!TrustingInfo->Server)
  862. {
  863. return ERROR_INVALID_PARAMETER;
  864. }
  865. Win32Err = NetApiBufferAllocate( TrustedInfo->DomainName->Length + sizeof( WCHAR ) +
  866. ( wcslen( TrustedInfo->Server ) * sizeof( WCHAR ) ) +
  867. sizeof( WCHAR ),
  868. (PVOID*)&ScDomain );
  869. if (ERROR_SUCCESS != Win32Err)
  870. {
  871. return Win32Err;
  872. }
  873. if (*(TrustingInfo->Server) == L'\\')
  874. {
  875. FullServer = TrustingInfo->Server;
  876. }
  877. else
  878. {
  879. Win32Err = NetApiBufferAllocate((wcslen(TrustingInfo->Server) + 3) * sizeof(WCHAR),
  880. (PVOID *)&FullServer);
  881. if (ERROR_SUCCESS != Win32Err)
  882. {
  883. return Win32Err;
  884. }
  885. swprintf(FullServer, L"\\\\%ws", TrustingInfo->Server);
  886. }
  887. if (TrustedInfo->fWasDownlevel)
  888. {
  889. pwzDomName = TrustedInfo->FlatName->Buffer;
  890. }
  891. else
  892. {
  893. pwzDomName = TrustedInfo->DomainName->Buffer;
  894. }
  895. if (*(TrustedInfo->Server) == L'\\')
  896. {
  897. swprintf(ScDomain, L"%ws%ws", pwzDomName, TrustedInfo->Server + 1);
  898. }
  899. else
  900. {
  901. swprintf(ScDomain, L"%ws\\%ws", pwzDomName, TrustedInfo->Server);
  902. }
  903. if ( Win32Err == ERROR_SUCCESS ) {
  904. LOG_VERBOSE(( MSG_VERBOSE_RESET_SC, ScDomain ));
  905. Win32Err = I_NetLogonControl2( FullServer,
  906. NETLOGON_CONTROL_REDISCOVER,
  907. 2,
  908. ( LPBYTE )&ScDomain,
  909. ( LPBYTE *)&NetlogonInfo2 );
  910. if ( Win32Err == ERROR_NO_SUCH_DOMAIN || Win32Err == ERROR_INVALID_PARAMETER ) {
  911. LOG_VERBOSE(( MSG_VERBOSE_RETRY_RESET_SC, ScDomain, TrustedInfo->DomainName->Buffer ));
  912. //
  913. // Must be using an downlevel domain, so try it again with out the server
  914. //
  915. Win32Err = I_NetLogonControl2( FullServer,
  916. NETLOGON_CONTROL_REDISCOVER,
  917. 2,
  918. ( LPBYTE )&( TrustedInfo->DomainName->Buffer ),
  919. ( LPBYTE *)&NetlogonInfo2 );
  920. if ( Win32Err == ERROR_SUCCESS ) {
  921. LOG_VERBOSE(( MSG_VERBOSE_RESET_NOT_NAMED, TrustedInfo->Server ));
  922. }
  923. }
  924. }
  925. NetApiBufferFree( ScDomain );
  926. if (FullServer != TrustingInfo->Server)
  927. {
  928. NetApiBufferFree(FullServer);
  929. }
  930. return( Win32Err );
  931. }
  932. DWORD
  933. NetDompTrustRemoveObject(
  934. IN PND5_TRUST_INFO LocalDomainInfo,
  935. IN PND5_TRUST_INFO TrustDomainInfo,
  936. IN ULONG Direction,
  937. IN BOOL fForce,
  938. IN PND5_AUTH_INFO pAuthInfo
  939. )
  940. /*++
  941. Routine Description:
  942. This function removes the specified trust
  943. Arguments:
  944. LocalDomainInfo - Info on the domain where the operation is being performed
  945. TrustDomainInfo - Info on the trusted/trusting domain
  946. Direction - The direction of the trust
  947. fForce - If true, remove even if a child.
  948. Return Value:
  949. ERROR_INVALID_PARAMETER - No object name was supplied
  950. --*/
  951. {
  952. DWORD Win32Err = ERROR_SUCCESS;
  953. NTSTATUS Status = STATUS_SUCCESS;
  954. PTRUSTED_DOMAIN_INFORMATION_EX ReadTDIEx = NULL;
  955. BOOL fChild = (TrustDomainInfo->Flags & NETDOM_TRUST_FLAG_CHILD);
  956. PLDAP pLdap;
  957. HANDLE hDS;
  958. PWSTR pwzConfigPath, pwzPartitionsPath, pwzFSMORoleOwner, pwzServerPath,
  959. pwzServerDNSname, pwzDomainName, pwzNcName, pwzServerObjDN, pwzSettingsDN,
  960. pwzFilter;
  961. WCHAR wzPartition[] = L"CN=Partitions,";
  962. WCHAR wzFilterFormat[] = L"(&(objectClass=nTDSDSA)(hasMasterNCs=%s))";
  963. RPC_AUTH_IDENTITY_HANDLE AuthHandle;
  964. PDS_NAME_RESULT pNameResult;
  965. LDAPMessage *Message = NULL, *Entry;
  966. PWSTR Attrib[2] = {
  967. L"foo",
  968. NULL
  969. };
  970. ASSERT(!(fChild && !fForce));
  971. ASSERT(!(TrustDomainInfo->Flags & NETDOM_TRUST_FLAG_PARENT));
  972. if ( LocalDomainInfo->Uplevel ) {
  973. LOG_VERBOSE(( MSG_VERBOSE_OPEN_TRUST, TrustDomainInfo->DomainName->Buffer ));
  974. if ( !LocalDomainInfo->TrustHandle ) {
  975. Status = LsaOpenTrustedDomainByName( LocalDomainInfo->LsaHandle,
  976. TrustDomainInfo->DomainName,
  977. TRUSTED_ALL_ACCESS, // DELETE | TRUSTED_QUERY_DOMAIN_NAME,
  978. &( LocalDomainInfo->TrustHandle ) );
  979. }
  980. if (STATUS_OBJECT_NAME_NOT_FOUND == Status && TrustDomainInfo->Uplevel) {
  981. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  982. // have a flat name.
  983. //
  984. TrustDomainInfo->fWasDownlevel = TRUE;
  985. Status = LsaOpenTrustedDomainByName( LocalDomainInfo->LsaHandle,
  986. TrustDomainInfo->FlatName,
  987. TRUSTED_ALL_ACCESS, // DELETE | TRUSTED_QUERY_DOMAIN_NAME,
  988. &( LocalDomainInfo->TrustHandle ) );
  989. }
  990. if ( NT_SUCCESS( Status ) ) {
  991. if ( Direction == TRUST_DIRECTION_BIDIRECTIONAL ) {
  992. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, TrustDomainInfo->DomainName->Buffer ));
  993. Status = LsaDelete( LocalDomainInfo->TrustHandle );
  994. if ( NT_SUCCESS( Status ) ) {
  995. LocalDomainInfo->TrustHandle = NULL;
  996. }
  997. } else {
  998. LOG_VERBOSE(( MSG_VERBOSE_GET_TRUST, TrustDomainInfo->DomainName->Buffer ));
  999. Status = LsaQueryInfoTrustedDomain( LocalDomainInfo->TrustHandle,
  1000. TrustedDomainInformationEx,
  1001. (PVOID*)&ReadTDIEx );
  1002. if ( NT_SUCCESS( Status ) ) {
  1003. ReadTDIEx->TrustDirection &= ~Direction;
  1004. if ( 0 == ReadTDIEx->TrustDirection ) {
  1005. LOG_VERBOSE(( MSG_VERBOSE_DELETE_TRUST, TrustDomainInfo->DomainName->Buffer ));
  1006. Status = LsaDelete( LocalDomainInfo->TrustHandle );
  1007. if ( NT_SUCCESS( Status ) ) {
  1008. LocalDomainInfo->TrustHandle = NULL;
  1009. }
  1010. }
  1011. else {
  1012. LOG_VERBOSE(( MSG_VERBOSE_SET_TRUST, TrustDomainInfo->DomainName->Buffer ));
  1013. Status = LsaSetInformationTrustedDomain( LocalDomainInfo->TrustHandle,
  1014. TrustedDomainInformationEx,
  1015. ReadTDIEx );
  1016. }
  1017. LsaFreeMemory( ReadTDIEx );
  1018. }
  1019. }
  1020. }
  1021. else {
  1022. if (STATUS_OBJECT_NAME_NOT_FOUND == Status) {
  1023. LOG_VERBOSE(( MSG_VERBOSE_TDO_NOT_FOUND, TrustDomainInfo->DomainName->Buffer ));
  1024. }
  1025. }
  1026. Win32Err = LsaNtStatusToWinError(Status);
  1027. DBG_VERBOSE(("Return code from LsaOpen: %d (LSA: %x)\n", Win32Err, Status));
  1028. if (fChild) {
  1029. // Remove the cross ref object. To do that, locate and bind to the naming
  1030. // FSMO DC.
  1031. //
  1032. LOG_VERBOSE((MSG_VERBOSE_DELETE_CROSS_REF, TrustDomainInfo->DomainName->Buffer));
  1033. Win32Err = NetDompLdapBind(LocalDomainInfo->Server + 2, // skip the backslashes
  1034. (pAuthInfo->pwzUsersDomain) ?
  1035. pAuthInfo->pwzUsersDomain : NULL,
  1036. (pAuthInfo->pwzUserWoDomain) ?
  1037. pAuthInfo->pwzUserWoDomain : pAuthInfo->User,
  1038. pAuthInfo->Password,
  1039. LDAP_AUTH_SSPI,
  1040. &pLdap);
  1041. if (Win32Err != ERROR_SUCCESS)
  1042. {
  1043. return Win32Err;
  1044. }
  1045. DBG_VERBOSE(("bind succeeded\n"));
  1046. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1047. NULL, //L"RootDSE",
  1048. L"configurationNamingContext",
  1049. &pwzConfigPath);
  1050. if (Win32Err != ERROR_SUCCESS)
  1051. {
  1052. NetDompLdapUnbind(pLdap);
  1053. return Win32Err;
  1054. }
  1055. Win32Err = NetApiBufferAllocate((wcslen(pwzConfigPath) + wcslen(wzPartition) + 1) * sizeof(WCHAR),
  1056. (PVOID*)&pwzPartitionsPath);
  1057. if (Win32Err != ERROR_SUCCESS)
  1058. {
  1059. NetApiBufferFree(pwzConfigPath);
  1060. NetDompLdapUnbind(pLdap);
  1061. return Win32Err;
  1062. }
  1063. wsprintf(pwzPartitionsPath, L"%s%s", wzPartition, pwzConfigPath);
  1064. DBG_VERBOSE(("path: %ws\n", pwzPartitionsPath));
  1065. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1066. pwzPartitionsPath,
  1067. L"fSMORoleOwner",
  1068. &pwzFSMORoleOwner);
  1069. NetApiBufferFree(pwzPartitionsPath);
  1070. if (Win32Err != ERROR_SUCCESS)
  1071. {
  1072. NetApiBufferFree(pwzConfigPath);
  1073. NetDompLdapUnbind(pLdap);
  1074. return Win32Err;
  1075. }
  1076. DBG_VERBOSE(("fSMORoleOwner: %ws\n", pwzFSMORoleOwner));
  1077. pwzServerPath = wcschr(pwzFSMORoleOwner, L',');
  1078. if (!pwzServerPath)
  1079. {
  1080. NetApiBufferFree(pwzConfigPath);
  1081. NetApiBufferFree(pwzFSMORoleOwner);
  1082. NetDompLdapUnbind(pLdap);
  1083. return ERROR_INVALID_DATA;
  1084. }
  1085. pwzServerPath++;
  1086. Win32Err = NetDompLdapReadOneAttribute(pLdap,
  1087. pwzServerPath,
  1088. L"dNSHostName",
  1089. &pwzServerDNSname);
  1090. NetApiBufferFree(pwzFSMORoleOwner);
  1091. if (Win32Err != ERROR_SUCCESS)
  1092. {
  1093. NetApiBufferFree(pwzConfigPath);
  1094. NetDompLdapUnbind(pLdap);
  1095. return Win32Err;
  1096. }
  1097. DBG_VERBOSE(("Role owner server DNS name: %ws\n", pwzServerDNSname));
  1098. Win32Err = DsMakePasswordCredentials((pAuthInfo->pwzUserWoDomain) ?
  1099. pAuthInfo->pwzUserWoDomain : pAuthInfo->User,
  1100. (pAuthInfo->pwzUsersDomain) ?
  1101. pAuthInfo->pwzUsersDomain : NULL,
  1102. pAuthInfo->Password,
  1103. &AuthHandle);
  1104. if (Win32Err != ERROR_SUCCESS)
  1105. {
  1106. NetApiBufferFree(pwzConfigPath);
  1107. NetApiBufferFree(pwzServerDNSname);
  1108. return Win32Err;
  1109. }
  1110. Win32Err = DsBindWithCred(pwzServerDNSname, NULL, AuthHandle, &hDS);
  1111. NetApiBufferFree(pwzServerDNSname);
  1112. DsFreePasswordCredentials(AuthHandle);
  1113. if (Win32Err != ERROR_SUCCESS)
  1114. {
  1115. NetApiBufferFree(pwzConfigPath);
  1116. return Win32Err;
  1117. }
  1118. DBG_VERBOSE(("DsBind Succeeded, getting domain NC name.\n"));
  1119. Win32Err = NetApiBufferAllocate((wcslen(TrustDomainInfo->DomainName->Buffer) + 2) * sizeof(WCHAR),
  1120. (PVOID*)&pwzDomainName);
  1121. if (Win32Err != ERROR_SUCCESS)
  1122. {
  1123. NetApiBufferFree(pwzConfigPath);
  1124. NetDompLdapUnbind(pLdap);
  1125. DsUnBind(&hDS);
  1126. return Win32Err;
  1127. }
  1128. //
  1129. // Get the domain Naming Context DN to use for the removal of the cross-ref.
  1130. // On the first try to get the domain NC DN, assume that the domain name is
  1131. // an NT4 flat name. A backslash must be appended.
  1132. //
  1133. wcscpy(pwzDomainName, TrustDomainInfo->DomainName->Buffer);
  1134. wcscat(pwzDomainName, L"\\");
  1135. DBG_VERBOSE(("Name passed to DsCrackNames is %ws.\n", pwzDomainName));
  1136. Win32Err = DsCrackNames(hDS,
  1137. DS_NAME_NO_FLAGS,
  1138. DS_NT4_ACCOUNT_NAME,
  1139. DS_FQDN_1779_NAME,
  1140. 1,
  1141. &pwzDomainName,
  1142. &pNameResult);
  1143. if (Win32Err != ERROR_SUCCESS)
  1144. {
  1145. NetApiBufferFree(pwzConfigPath);
  1146. NetApiBufferFree(pwzDomainName);
  1147. NetDompLdapUnbind(pLdap);
  1148. DsUnBind(&hDS);
  1149. return Win32Err;
  1150. }
  1151. ASSERT(pNameResult);
  1152. ASSERT(pNameResult->cItems == 1);
  1153. if (DS_NAME_NO_ERROR != pNameResult->rItems->status)
  1154. {
  1155. // Try again, this time assume that it might be a DNS name. Replace
  1156. // the back slash with a forward slash.
  1157. //
  1158. pwzDomainName[wcslen(pwzDomainName) -1] = L'/';
  1159. DsFreeNameResultW(pNameResult);
  1160. DBG_VERBOSE(("Try again, name passed to DsCrackNames is %ws.\n", pwzDomainName));
  1161. Win32Err = DsCrackNames(hDS,
  1162. DS_NAME_NO_FLAGS,
  1163. DS_CANONICAL_NAME,
  1164. DS_FQDN_1779_NAME,
  1165. 1,
  1166. &pwzDomainName,
  1167. &pNameResult);
  1168. if (Win32Err != ERROR_SUCCESS)
  1169. {
  1170. NetApiBufferFree(pwzConfigPath);
  1171. NetApiBufferFree(pwzDomainName);
  1172. NetDompLdapUnbind(pLdap);
  1173. DsUnBind(&hDS);
  1174. return Win32Err;
  1175. }
  1176. ASSERT(pNameResult);
  1177. ASSERT(pNameResult->cItems == 1);
  1178. }
  1179. NetApiBufferFree(pwzDomainName);
  1180. if (DS_NAME_NO_ERROR != pNameResult->rItems->status)
  1181. {
  1182. NetApiBufferFree(pwzConfigPath);
  1183. DsFreeNameResultW(pNameResult);
  1184. NetDompLdapUnbind(pLdap);
  1185. DsUnBind(&hDS);
  1186. return ERROR_NO_SUCH_DOMAIN;
  1187. }
  1188. //
  1189. // Delete the Server object for the domain. Get the name of the server
  1190. // object by searching for the NTDS-Settings object that references the
  1191. // domain NC.
  1192. //
  1193. Win32Err = NetApiBufferAllocate((wcslen(wzFilterFormat) + wcslen(pNameResult->rItems->pName) + 1) * sizeof(WCHAR),
  1194. (PVOID*)&pwzFilter);
  1195. if (Win32Err != ERROR_SUCCESS)
  1196. {
  1197. DsFreeNameResultW(pNameResult);
  1198. NetApiBufferFree(pwzConfigPath);
  1199. NetDompLdapUnbind(pLdap);
  1200. DsUnBind(&hDS);
  1201. return Win32Err;
  1202. }
  1203. swprintf(pwzFilter, wzFilterFormat, pNameResult->rItems->pName);
  1204. DBG_VERBOSE(("search filter: %ws\n", pwzFilter));
  1205. Win32Err = LdapMapErrorToWin32(ldap_search_s(pLdap,
  1206. pwzConfigPath,
  1207. LDAP_SCOPE_SUBTREE,
  1208. pwzFilter,
  1209. Attrib,
  1210. 0,
  1211. &Message));
  1212. if (Win32Err != ERROR_SUCCESS)
  1213. {
  1214. DBG_VERBOSE(("search for Settings object failed with error %d\n", Win32Err));
  1215. NetApiBufferFree(pwzConfigPath);
  1216. DsFreeNameResultW(pNameResult);
  1217. NetDompLdapUnbind(pLdap);
  1218. DsUnBind(&hDS);
  1219. return Win32Err;
  1220. }
  1221. Entry = ldap_first_entry(pLdap, Message);
  1222. if (Entry) {
  1223. pwzSettingsDN = ldap_get_dnW(pLdap, Entry);
  1224. DBG_VERBOSE(("NTDS Settings object DN: %ws\n", pwzSettingsDN));
  1225. if (pwzSettingsDN) {
  1226. pwzServerObjDN = wcschr(pwzSettingsDN, L',');
  1227. if (pwzServerObjDN) {
  1228. pwzServerObjDN++;
  1229. Win32Err = DsRemoveDsServerW(hDS,
  1230. pwzServerObjDN,
  1231. NULL,
  1232. NULL,
  1233. TRUE);
  1234. if (Win32Err == ERROR_SUCCESS)
  1235. {
  1236. LOG_VERBOSE((MSG_VERBOSE_NTDSDSA_DELETED, pwzServerObjDN));
  1237. }
  1238. else
  1239. {
  1240. DBG_VERBOSE(("DsRemoveDsServer failed with error %d\n", Win32Err));
  1241. LOG_VERBOSE((MSG_VERBOSE_NTDSDSA_NOT_REMOVED, pwzServerObjDN));
  1242. }
  1243. }
  1244. }
  1245. ldap_memfree(pwzSettingsDN);
  1246. } else {
  1247. Win32Err = LdapMapErrorToWin32(pLdap->ld_errno);
  1248. DBG_VERBOSE(("search results for Settings object failed with error %d\n", Win32Err));
  1249. }
  1250. ldap_msgfree(Message);
  1251. NetDompLdapUnbind(pLdap); // add to error returns above.
  1252. NetApiBufferFree(pwzConfigPath);
  1253. //
  1254. // Now remove the cross-ref object.
  1255. //
  1256. DBG_VERBOSE(("About to remove the cross-ref for NC %ws.\n", pNameResult->rItems->pName));
  1257. Win32Err = DsRemoveDsDomainW(hDS, pNameResult->rItems->pName);
  1258. if (Win32Err == ERROR_SUCCESS)
  1259. {
  1260. LOG_VERBOSE((MSG_VERBOSE_CROSS_REF_DELETED, pNameResult->rItems->pName));
  1261. }
  1262. else
  1263. {
  1264. DBG_VERBOSE(("DsRemoveDsDomain returned %d.\n", Win32Err));
  1265. if (ERROR_DS_NO_CROSSREF_FOR_NC == Win32Err)
  1266. {
  1267. LOG_VERBOSE((MSG_VERBOSE_CROSS_REF_NOT_FOUND, pNameResult->rItems->pName));
  1268. }
  1269. }
  1270. DsFreeNameResultW(pNameResult);
  1271. DsUnBind(&hDS);
  1272. }
  1273. } else {
  1274. if ( FLAG_ON( Direction, TRUST_DIRECTION_INBOUND ) ) {
  1275. Win32Err = NetDompTrustRemoveIncomingDownlevelObject( TrustDomainInfo,
  1276. LocalDomainInfo );
  1277. if ( Win32Err == NERR_UserNotFound ) {
  1278. Win32Err = ERROR_SUCCESS;
  1279. }
  1280. }
  1281. if ( Win32Err == ERROR_SUCCESS && FLAG_ON( Direction, TRUST_DIRECTION_OUTBOUND ) ) {
  1282. Win32Err = NetDompTrustRemoveOutgoingDownlevelObject( LocalDomainInfo,
  1283. TrustDomainInfo );
  1284. }
  1285. }
  1286. return( Win32Err );
  1287. }
  1288. DWORD
  1289. NetDompCreateTrustObject(
  1290. IN ARG_RECORD * rgNetDomArgs,
  1291. IN PWSTR TrustingDomain,
  1292. IN PWSTR TrustedDomain,
  1293. IN PND5_AUTH_INFO pTrustingCreds,
  1294. IN PND5_AUTH_INFO pTrustedCreds,
  1295. IN PWSTR pwzTrustPW,
  1296. IN PWSTR pwzWhichSide
  1297. )
  1298. /*++
  1299. Routine Description:
  1300. This function will handle the adding of a trusted domain object
  1301. Arguments:
  1302. rgNetDomArgs - List of arguments present in the Args list
  1303. TrustingDomain - Trusting side of the trust
  1304. TrustedDomain - Trusted side of the trust
  1305. pTrustingCreds - Credentials to use when connecting to a domain controller in the
  1306. trusting domain
  1307. pTrustedCreds - Credentials to use when connecting to a domain controller in the
  1308. trusted domain
  1309. pwzTrustPW - Required for creating MIT trust.
  1310. pwzWhichSide - Required for creating one-side-only, names the side.
  1311. Return Value:
  1312. ERROR_INVALID_PARAMETER - No object name was supplied
  1313. --*/
  1314. {
  1315. DWORD Win32Err = ERROR_SUCCESS;
  1316. ND5_TRUST_INFO TrustingInfo, TrustedInfo;
  1317. WCHAR TrustPassword[ LM20_PWLEN + 1 ];
  1318. PWSTR pwzPW = NULL;
  1319. WCHAR wzTrusted[NETDOM_STR_LEN], wzTrusting[NETDOM_STR_LEN];
  1320. BOOL fCreateOnTrusted = FALSE, fCreateOnTrusting = FALSE;
  1321. RtlZeroMemory( &TrustingInfo, sizeof( TrustingInfo ) );
  1322. RtlZeroMemory( &TrustedInfo, sizeof( TrustedInfo ) );
  1323. if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  1324. {
  1325. if (!LoadString(g_hInstance, IDS_ONESIDE_TRUSTED, wzTrusted, NETDOM_STR_LEN) ||
  1326. !LoadString(g_hInstance, IDS_ONESIDE_TRUSTING, wzTrusting, NETDOM_STR_LEN))
  1327. {
  1328. printf("LoadString FAILED!\n");
  1329. return ERROR_RESOURCE_NAME_NOT_FOUND;
  1330. }
  1331. // Determine on which domain the trust should be created.
  1332. //
  1333. if (_wcsicmp(pwzWhichSide, wzTrusted) == 0)
  1334. {
  1335. fCreateOnTrusted = TRUE;
  1336. }
  1337. else if (_wcsicmp(pwzWhichSide, wzTrusting) == 0)
  1338. {
  1339. fCreateOnTrusting = TRUE;
  1340. }
  1341. else
  1342. {
  1343. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  1344. return ERROR_INVALID_PARAMETER;
  1345. }
  1346. }
  1347. Win32Err = NetDompTrustGetDomInfo( TrustingDomain,
  1348. NULL,
  1349. pTrustingCreds,
  1350. &TrustingInfo,
  1351. !fCreateOnTrusted,
  1352. CmdFlagOn(rgNetDomArgs, eTrustRealm),
  1353. fCreateOnTrusted);
  1354. if ( Win32Err == ERROR_SUCCESS ) {
  1355. Win32Err = NetDompTrustGetDomInfo( TrustedDomain,
  1356. NULL,
  1357. pTrustedCreds,
  1358. &TrustedInfo,
  1359. !fCreateOnTrusting,
  1360. CmdFlagOn(rgNetDomArgs, eTrustRealm),
  1361. fCreateOnTrusting);
  1362. }
  1363. if ( Win32Err != ERROR_SUCCESS ) {
  1364. goto TrustAddExit;
  1365. }
  1366. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  1367. {
  1368. if (!(TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  1369. !(TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  1370. {
  1371. // Both domains found (both are Windows domains), can't establish an MIT trust.
  1372. //
  1373. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  1374. Win32Err = ERROR_INVALID_PARAMETER;
  1375. goto TrustAddExit;
  1376. }
  1377. pwzPW = pwzTrustPW;
  1378. }
  1379. else if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  1380. {
  1381. // Create the trust on only one of the two domains.
  1382. //
  1383. if (fCreateOnTrusted)
  1384. {
  1385. Win32Err = NetDompAddOnTrustedSide(&TrustedInfo,
  1386. &TrustingInfo,
  1387. pwzTrustPW,
  1388. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1389. TRUST_DIRECTION_BIDIRECTIONAL :
  1390. TRUST_DIRECTION_INBOUND,
  1391. FALSE);
  1392. }
  1393. else
  1394. {
  1395. Win32Err = NetDompAddOnTrustingSide(&TrustedInfo,
  1396. &TrustingInfo,
  1397. pwzTrustPW,
  1398. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1399. TRUST_DIRECTION_BIDIRECTIONAL :
  1400. TRUST_DIRECTION_OUTBOUND,
  1401. FALSE);
  1402. }
  1403. goto TrustAddExit;
  1404. }
  1405. else
  1406. {
  1407. Win32Err = NetDompGenerateRandomPassword( TrustPassword,
  1408. LM20_PWLEN );
  1409. if ( Win32Err != ERROR_SUCCESS ) {
  1410. goto TrustAddExit;
  1411. }
  1412. pwzPW = TrustPassword;
  1413. }
  1414. //
  1415. // Ok, now that we have the password, let's create the trust
  1416. //
  1417. Win32Err = NetDompAddOnTrustedSide( &TrustedInfo,
  1418. &TrustingInfo,
  1419. pwzPW,
  1420. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1421. TRUST_DIRECTION_BIDIRECTIONAL :
  1422. TRUST_DIRECTION_INBOUND,
  1423. CmdFlagOn(rgNetDomArgs, eTrustRealm));
  1424. if ( Win32Err == ERROR_SUCCESS ) {
  1425. Win32Err = NetDompAddOnTrustingSide( &TrustedInfo,
  1426. &TrustingInfo,
  1427. pwzPW,
  1428. CmdFlagOn(rgNetDomArgs, eTrustTwoWay) ?
  1429. TRUST_DIRECTION_BIDIRECTIONAL :
  1430. TRUST_DIRECTION_OUTBOUND,
  1431. CmdFlagOn(rgNetDomArgs, eTrustRealm));
  1432. }
  1433. TrustAddExit:
  1434. NetDompFreeDomInfo( &TrustedInfo );
  1435. NetDompFreeDomInfo( &TrustingInfo );
  1436. return( Win32Err );
  1437. }
  1438. DWORD
  1439. NetDompRemoveTrustObject(
  1440. IN ARG_RECORD * rgNetDomArgs,
  1441. IN PWSTR TrustingDomain,
  1442. IN PWSTR TrustedDomain,
  1443. IN PND5_AUTH_INFO pTrustingCreds,
  1444. IN PND5_AUTH_INFO pTrustedCreds
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. This function will handle the removal of a trusted domain object
  1449. Arguments:
  1450. rgNetDomArgs - List of arguments present in the Args list
  1451. TrustingDomain - Trusting side of the trust
  1452. TrustedDomain - Trusted side of the trust
  1453. pTrustingCreds - Credentials to use when connecting to a domain controller in the
  1454. trusting domain
  1455. pTrustedCreds - Credentials to use when connecting to a domain controller in the
  1456. trusted domain
  1457. Return Value:
  1458. ERROR_INVALID_PARAMETER - No object name was supplied
  1459. --*/
  1460. {
  1461. DWORD Win32Err = ERROR_SUCCESS;
  1462. ND5_TRUST_INFO TrustingInfo, TrustedInfo;
  1463. BOOL fForce = CmdFlagOn(rgNetDomArgs, eCommForce);
  1464. BOOL TwoWay = CmdFlagOn(rgNetDomArgs, eTrustTwoWay);
  1465. BOOL fParentChild = FALSE, fVerifyChildDelete = FALSE;
  1466. RtlZeroMemory( &TrustingInfo, sizeof( TrustingInfo ) );
  1467. RtlZeroMemory( &TrustedInfo, sizeof( TrustedInfo ) );
  1468. Win32Err = NetDompTrustGetDomInfo( TrustingDomain,
  1469. NULL,
  1470. pTrustingCreds,
  1471. &TrustingInfo,
  1472. TRUE,
  1473. fForce, FALSE );
  1474. if ( Win32Err == ERROR_SUCCESS ) {
  1475. Win32Err = NetDompTrustGetDomInfo( TrustedDomain,
  1476. NULL,
  1477. pTrustedCreds,
  1478. &TrustedInfo,
  1479. TRUE,
  1480. fForce, FALSE );
  1481. }
  1482. if ( Win32Err != ERROR_SUCCESS ) {
  1483. if (ERROR_NO_SUCH_DOMAIN == Win32Err) {
  1484. NetDompDisplayMessage(MSG_TRUST_DOMAIN_NOT_FOUND);
  1485. }
  1486. goto TrustRemoveExit;
  1487. }
  1488. Win32Err = NetDompIsParentChild(&TrustingInfo,
  1489. &TrustedInfo,
  1490. &fParentChild);
  1491. if ( Win32Err != ERROR_SUCCESS ) {
  1492. goto TrustRemoveExit;
  1493. }
  1494. if (fParentChild)
  1495. {
  1496. // Enforce rules for parent-child trust.
  1497. //
  1498. if (TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1499. {
  1500. if (TrustingInfo.Flags & NETDOM_TRUST_FLAG_PARENT)
  1501. {
  1502. // The domain that wasn't found was the parent, deletion not allowed.
  1503. //
  1504. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT);
  1505. printf("\n");
  1506. Win32Err = ERROR_NOT_SUPPORTED;
  1507. goto TrustRemoveExit;
  1508. }
  1509. else
  1510. {
  1511. if (!fForce)
  1512. {
  1513. // Force flag required to delete non-existant child.
  1514. //
  1515. NetDompDisplayMessage(MSG_DELETE_CHILD_FORCE_REQ);
  1516. printf("\n");
  1517. Win32Err = ERROR_NOT_SUPPORTED;
  1518. goto TrustRemoveExit;
  1519. }
  1520. else
  1521. {
  1522. fVerifyChildDelete = TRUE;
  1523. }
  1524. }
  1525. }
  1526. else {
  1527. if (TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1528. {
  1529. if (TrustedInfo.Flags & NETDOM_TRUST_FLAG_PARENT)
  1530. {
  1531. // The domain that wasn't found was the parent, deletion not allowed.
  1532. //
  1533. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT);
  1534. printf("\n");
  1535. Win32Err = ERROR_NOT_SUPPORTED;
  1536. goto TrustRemoveExit;
  1537. }
  1538. else
  1539. {
  1540. if (!fForce)
  1541. {
  1542. // Force flag required to delete non-existant child.
  1543. //
  1544. NetDompDisplayMessage(MSG_DELETE_CHILD_FORCE_REQ);
  1545. printf("\n");
  1546. Win32Err = ERROR_NOT_SUPPORTED;
  1547. goto TrustRemoveExit;
  1548. }
  1549. else
  1550. {
  1551. fVerifyChildDelete = TRUE;
  1552. }
  1553. }
  1554. }
  1555. else
  1556. {
  1557. // Both domains were found, don't allow deletion.
  1558. //
  1559. NetDompDisplayMessage(MSG_CANT_DELETE_PARENT_CHILD);
  1560. printf("\n");
  1561. Win32Err = ERROR_NOT_SUPPORTED;
  1562. goto TrustRemoveExit;
  1563. }
  1564. }
  1565. }
  1566. if (fVerifyChildDelete)
  1567. {
  1568. // Put up a message box asking for confirmation of the deletion.
  1569. //
  1570. PWSTR pwzDomain = (TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) ?
  1571. TrustingInfo.DomainName->Buffer :
  1572. TrustedInfo.DomainName->Buffer;
  1573. if (!NetDompGetUserConfirmation(IDS_PROMPT_DEL_TRUST, pwzDomain))
  1574. {
  1575. goto TrustRemoveExit;
  1576. }
  1577. }
  1578. if (!(TrustingInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  1579. {
  1580. Win32Err = NetDompTrustRemoveObject( &TrustingInfo,
  1581. &TrustedInfo,
  1582. (TwoWay || fForce) ?
  1583. TRUST_DIRECTION_BIDIRECTIONAL :
  1584. TRUST_DIRECTION_OUTBOUND,
  1585. fForce,
  1586. pTrustingCreds );
  1587. }
  1588. if ((Win32Err == ERROR_SUCCESS && !CmdFlagOn(rgNetDomArgs, eTrustRealm)) &&
  1589. !(TrustedInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)) {
  1590. Win32Err = NetDompTrustRemoveObject( &TrustedInfo,
  1591. &TrustingInfo,
  1592. (TwoWay || fForce) ?
  1593. TRUST_DIRECTION_BIDIRECTIONAL :
  1594. TRUST_DIRECTION_INBOUND,
  1595. fForce,
  1596. pTrustedCreds );
  1597. }
  1598. TrustRemoveExit:
  1599. NetDompFreeDomInfo( &TrustedInfo );
  1600. NetDompFreeDomInfo( &TrustingInfo );
  1601. return( Win32Err );
  1602. }
  1603. DWORD
  1604. NetDompSetTrustPW(
  1605. IN PND5_TRUST_INFO pDomain1Info,
  1606. IN PND5_TRUST_INFO pDomain2Info,
  1607. IN PWSTR pwzNewTrustPW,
  1608. OUT PDWORD pDirection
  1609. )
  1610. /*++
  1611. Routine Description:
  1612. This function will set the trust password on Domain1.
  1613. Arguments:
  1614. pDomain1Info - Domain on which to set the trust passwords
  1615. pDomain2Info - Domain whose TDO should be set.
  1616. pwzNewTrustPW - new trust password to use.
  1617. Return Value:
  1618. ERROR_INVALID_PARAMETER - No object name was supplied
  1619. --*/
  1620. {
  1621. DWORD Win32Err = ERROR_SUCCESS;
  1622. PTRUSTED_DOMAIN_FULL_INFORMATION pOldDomain1TDFInfo = NULL;
  1623. TRUSTED_DOMAIN_FULL_INFORMATION NewDomain1TDFInfo;
  1624. LSA_AUTH_INFORMATION NewAuthInfo;
  1625. LARGE_INTEGER ft;
  1626. NTSTATUS Status = STATUS_SUCCESS;
  1627. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, pDomain1Info->DomainName->Buffer));
  1628. if (pDomain2Info->Sid)
  1629. {
  1630. Status = LsaQueryTrustedDomainInfo(pDomain1Info->LsaHandle,
  1631. pDomain2Info->Sid,
  1632. TrustedDomainFullInformation,
  1633. (PVOID *)&pOldDomain1TDFInfo);
  1634. }
  1635. else
  1636. {
  1637. Status = LsaQueryTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1638. pDomain2Info->DomainName,
  1639. TrustedDomainFullInformation,
  1640. (PVOID *)&pOldDomain1TDFInfo);
  1641. }
  1642. Win32Err = LsaNtStatusToWinError(Status);
  1643. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  1644. if (pDirection)
  1645. {
  1646. *pDirection = pOldDomain1TDFInfo->Information.TrustDirection;
  1647. }
  1648. GetSystemTimeAsFileTime((PFILETIME)&ft);
  1649. //
  1650. // Set the current password data.
  1651. //
  1652. NewAuthInfo.LastUpdateTime = ft;
  1653. NewAuthInfo.AuthType = TRUST_AUTH_TYPE_CLEAR;
  1654. NewAuthInfo.AuthInfoLength = wcslen(pwzNewTrustPW) * sizeof(WCHAR);
  1655. NewAuthInfo.AuthInfo = (PUCHAR)pwzNewTrustPW;
  1656. ZeroMemory(&NewDomain1TDFInfo, sizeof(TRUSTED_DOMAIN_FULL_INFORMATION));
  1657. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_INBOUND)
  1658. {
  1659. NewDomain1TDFInfo.AuthInformation.IncomingAuthInfos = 1;
  1660. NewDomain1TDFInfo.AuthInformation.IncomingAuthenticationInformation = &NewAuthInfo;
  1661. NewDomain1TDFInfo.AuthInformation.IncomingPreviousAuthenticationInformation = NULL;
  1662. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  1663. }
  1664. if (pOldDomain1TDFInfo->Information.TrustDirection & TRUST_DIRECTION_OUTBOUND)
  1665. {
  1666. NewDomain1TDFInfo.AuthInformation.OutgoingAuthInfos = 1;
  1667. NewDomain1TDFInfo.AuthInformation.OutgoingAuthenticationInformation = &NewAuthInfo;
  1668. NewDomain1TDFInfo.AuthInformation.OutgoingPreviousAuthenticationInformation = NULL;
  1669. NewDomain1TDFInfo.Information = pOldDomain1TDFInfo->Information;
  1670. }
  1671. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, pDomain1Info->DomainName->Buffer));
  1672. // Save changes.
  1673. //
  1674. Status = LsaSetTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1675. pDomain2Info->DomainName,
  1676. TrustedDomainFullInformation,
  1677. &NewDomain1TDFInfo);
  1678. if (STATUS_OBJECT_NAME_NOT_FOUND == Status && pDomain2Info->Uplevel)
  1679. {
  1680. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  1681. // have a flat name.
  1682. //
  1683. pDomain2Info->fWasDownlevel = TRUE;
  1684. Status = LsaSetTrustedDomainInfoByName(pDomain1Info->LsaHandle,
  1685. pDomain2Info->FlatName,
  1686. TrustedDomainFullInformation,
  1687. &NewDomain1TDFInfo);
  1688. }
  1689. Win32Err = LsaNtStatusToWinError(Status);
  1690. CHECK_WIN32(Win32Err, goto TrustPwSetExit);
  1691. TrustPwSetExit:
  1692. if (pOldDomain1TDFInfo)
  1693. LsaFreeMemory(pOldDomain1TDFInfo);
  1694. return Win32Err;
  1695. }
  1696. DWORD
  1697. NetDompResetTrustPasswords(
  1698. IN PWSTR pwzDomain1,
  1699. IN PWSTR pwzDomain2,
  1700. IN PND5_AUTH_INFO pDomain1Creds,
  1701. IN PND5_AUTH_INFO pDomain2Creds
  1702. )
  1703. /*++
  1704. Routine Description:
  1705. This function will handle the password reset of the trusted domain objects
  1706. Arguments:
  1707. pwzDomain1, pwzDomain2 - Names of domains with trust.
  1708. pDomain1Creds, pDomain2Creds - Credentials to use when connecting to a domain controller
  1709. in the domain
  1710. --*/
  1711. {
  1712. DWORD Win32Err = ERROR_SUCCESS;
  1713. NTSTATUS Status = STATUS_SUCCESS;
  1714. ND5_TRUST_INFO Domain1Info, Domain2Info;
  1715. WCHAR wzNewPw[MAX_COMPUTERNAME_LENGTH];
  1716. ULONG Length, i;
  1717. LARGE_INTEGER ft;
  1718. DWORD Direction;
  1719. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  1720. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  1721. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  1722. NULL,
  1723. pDomain1Creds,
  1724. &Domain1Info,
  1725. TRUE,
  1726. FALSE, FALSE );
  1727. if (Win32Err == ERROR_SUCCESS)
  1728. {
  1729. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  1730. NULL,
  1731. pDomain2Creds,
  1732. &Domain2Info,
  1733. TRUE,
  1734. FALSE, FALSE );
  1735. }
  1736. CHECK_WIN32(Win32Err, goto TrustResetExit);
  1737. if (Domain1Info.Uplevel && Domain2Info.Uplevel)
  1738. {
  1739. NetDompDisplayMessage(MSG_RESET_TRUST_STARTING, pwzDomain1, pwzDomain2);
  1740. }
  1741. else
  1742. {
  1743. NetDompDisplayMessage(MSG_RESET_TRUST_NOT_UPLEVEL);
  1744. goto TrustResetExit;
  1745. }
  1746. //
  1747. // Build a random password
  1748. //
  1749. CDGenerateRandomBits((PUCHAR)wzNewPw, sizeof(wzNewPw));
  1750. // Terminate the password
  1751. Length = MAX_COMPUTERNAME_LENGTH;
  1752. Length--;
  1753. wzNewPw[Length] = L'\0';
  1754. // Make sure there aren't any NULL's in the password
  1755. for (i = 0; i < Length; i++)
  1756. {
  1757. if (wzNewPw[i] == L'\0')
  1758. {
  1759. // arbitrary letter
  1760. wzNewPw[i] = L'c';
  1761. }
  1762. }
  1763. Win32Err = NetDompSetTrustPW(&Domain1Info,
  1764. &Domain2Info,
  1765. wzNewPw,
  1766. &Direction);
  1767. CHECK_WIN32(Win32Err, goto TrustResetExit);
  1768. Win32Err = NetDompSetTrustPW(&Domain2Info,
  1769. &Domain1Info,
  1770. wzNewPw,
  1771. NULL);
  1772. CHECK_WIN32(Win32Err, goto TrustResetExit);
  1773. //
  1774. // Verify the repaired trust.
  1775. //
  1776. if (Direction & TRUST_DIRECTION_OUTBOUND)
  1777. {
  1778. Win32Err = NetDompResetTrustSC( &Domain1Info, &Domain2Info );
  1779. CHECK_WIN32(Win32Err, goto TrustResetExit);
  1780. }
  1781. if (Direction & TRUST_DIRECTION_INBOUND)
  1782. {
  1783. Win32Err = NetDompResetTrustSC( &Domain2Info, &Domain1Info );
  1784. CHECK_WIN32(Win32Err, goto TrustResetExit);
  1785. }
  1786. NetDompDisplayMessage(MSG_RESET_TRUST_OK, pwzDomain1, pwzDomain2);
  1787. TrustResetExit:
  1788. NetDompFreeDomInfo( &Domain2Info );
  1789. NetDompFreeDomInfo( &Domain1Info );
  1790. return( Win32Err );
  1791. }
  1792. DWORD
  1793. NetDompSetMitTrustPW(
  1794. IN PWSTR pwzDomain1,
  1795. IN PWSTR pwzDomain2,
  1796. IN PND5_AUTH_INFO pDomain1Creds,
  1797. IN PND5_AUTH_INFO pDomain2Creds,
  1798. IN PWSTR pwzNewTrustPW
  1799. )
  1800. /*++
  1801. Routine Description:
  1802. This function will handle the password reset of an MIT trusted domain object
  1803. Arguments:
  1804. pwzDomain1, pwzDomain2 - Trusted domains
  1805. pDomain1Creds - Credentials to use when connecting to a domain controller in
  1806. domain21
  1807. pDomain2Creds - Credentials to use when connecting to a domain controller in
  1808. domain 2
  1809. pwzNewTrustPW - new trust password to use.
  1810. Return Value:
  1811. ERROR_INVALID_PARAMETER - No object name was supplied
  1812. --*/
  1813. {
  1814. DWORD Win32Err = ERROR_SUCCESS;
  1815. ND5_TRUST_INFO Domain1Info, Domain2Info;
  1816. PND5_TRUST_INFO pDomFoundInfo, pMitDomInfo;
  1817. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  1818. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  1819. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  1820. NULL,
  1821. pDomain1Creds,
  1822. &Domain1Info,
  1823. TRUE,
  1824. TRUE, FALSE );
  1825. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  1826. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  1827. NULL,
  1828. pDomain2Creds,
  1829. &Domain2Info,
  1830. TRUE,
  1831. TRUE, FALSE );
  1832. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  1833. if ((Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  1834. (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  1835. {
  1836. // at least one must be found.
  1837. //
  1838. Win32Err = ERROR_NO_SUCH_DOMAIN;
  1839. goto MitTrustPwSetExit;
  1840. }
  1841. if (Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1842. {
  1843. pMitDomInfo = &Domain1Info;
  1844. pDomFoundInfo = &Domain2Info;
  1845. }
  1846. else
  1847. {
  1848. if (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1849. {
  1850. pMitDomInfo = &Domain2Info;
  1851. pDomFoundInfo = &Domain1Info;
  1852. }
  1853. else
  1854. {
  1855. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  1856. Win32Err = ERROR_INVALID_PARAMETER;
  1857. goto MitTrustPwSetExit;
  1858. }
  1859. }
  1860. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_STARTING, pDomFoundInfo->DomainName->Buffer,
  1861. pMitDomInfo->DomainName->Buffer);
  1862. Win32Err = NetDompSetTrustPW(pDomFoundInfo,
  1863. pMitDomInfo,
  1864. pwzNewTrustPW,
  1865. NULL);
  1866. CHECK_WIN32(Win32Err, goto MitTrustPwSetExit);
  1867. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_OK, pMitDomInfo->DomainName->Buffer);
  1868. MitTrustPwSetExit:
  1869. NetDompFreeDomInfo( &Domain2Info );
  1870. NetDompFreeDomInfo( &Domain1Info );
  1871. return( Win32Err );
  1872. }
  1873. DWORD
  1874. NetDomTransitivity(PWSTR pwzTransArg,
  1875. PWSTR pwzDomain1,
  1876. PWSTR pwzDomain2,
  1877. PND5_AUTH_INFO pDomain1Creds,
  1878. PND5_AUTH_INFO pDomain2Creds)
  1879. /*++
  1880. Routine Description:
  1881. This routine will display or change the transitivity of a trust.
  1882. Arguments:
  1883. pwzTransArg -- Either blank (display the transitivity) or one of
  1884. yes or no (change the transitivity).
  1885. pwzDomain1 -- Name of one domain
  1886. pwzDomain2 -- Name of the other domain
  1887. pDomain1Creds -- Credentials of the user of domain1
  1888. pDomain2Creds -- Credentials of the user of domain2
  1889. Return Value:
  1890. STATUS_SUCCESS -- Success
  1891. --*/
  1892. {
  1893. DWORD Win32Err = ERROR_SUCCESS;
  1894. NTSTATUS Status = STATUS_SUCCESS;
  1895. BOOL fDisplayOnly = FALSE;
  1896. BOOL fTransOn = FALSE;
  1897. ND5_TRUST_INFO Domain1Info, Domain2Info;
  1898. PND5_TRUST_INFO pDomFoundInfo, pMitDomInfo;
  1899. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  1900. WCHAR wzYes[NETDOM_STR_LEN], wzNo[NETDOM_STR_LEN];
  1901. RtlZeroMemory( &Domain1Info, sizeof( Domain1Info ) );
  1902. RtlZeroMemory( &Domain2Info, sizeof( Domain2Info ) );
  1903. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  1904. NULL,
  1905. pDomain1Creds,
  1906. &Domain1Info,
  1907. TRUE,
  1908. TRUE, FALSE );
  1909. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  1910. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  1911. NULL,
  1912. pDomain2Creds,
  1913. &Domain2Info,
  1914. TRUE,
  1915. TRUE, FALSE );
  1916. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  1917. if ((Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) &&
  1918. (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND))
  1919. {
  1920. // at least one must be found.
  1921. //
  1922. Win32Err = ERROR_NO_SUCH_DOMAIN;
  1923. goto TrustSetTransExit;
  1924. }
  1925. if (Domain1Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1926. {
  1927. pMitDomInfo = &Domain1Info;
  1928. pDomFoundInfo = &Domain2Info;
  1929. }
  1930. else
  1931. {
  1932. if (Domain2Info.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  1933. {
  1934. pMitDomInfo = &Domain2Info;
  1935. pDomFoundInfo = &Domain1Info;
  1936. }
  1937. else
  1938. {
  1939. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  1940. Win32Err = ERROR_INVALID_PARAMETER;
  1941. goto TrustSetTransExit;
  1942. }
  1943. }
  1944. if (NULL == pwzTransArg)
  1945. {
  1946. fDisplayOnly = TRUE;
  1947. }
  1948. else
  1949. {
  1950. if (!LoadString(g_hInstance, IDS_YES, wzYes, NETDOM_STR_LEN) ||
  1951. !LoadString(g_hInstance, IDS_NO, wzNo, NETDOM_STR_LEN))
  1952. {
  1953. printf("LoadString FAILED!\n");
  1954. Win32Err = ERROR_RESOURCE_NAME_NOT_FOUND;
  1955. goto TrustSetTransExit;
  1956. }
  1957. if (_wcsicmp(wzYes, pwzTransArg) == 0)
  1958. {
  1959. fTransOn = TRUE;
  1960. }
  1961. else
  1962. {
  1963. if (_wcsicmp(wzNo, pwzTransArg) != 0)
  1964. {
  1965. fDisplayOnly = TRUE;
  1966. }
  1967. }
  1968. }
  1969. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, pDomFoundInfo->DomainName->Buffer));
  1970. if (pMitDomInfo->Sid)
  1971. {
  1972. Status = LsaQueryTrustedDomainInfo(pDomFoundInfo->LsaHandle,
  1973. pMitDomInfo->Sid,
  1974. TrustedDomainInformationEx,
  1975. (PVOID *)&pTDIx);
  1976. }
  1977. else
  1978. {
  1979. Status = LsaQueryTrustedDomainInfoByName(pDomFoundInfo->LsaHandle,
  1980. pMitDomInfo->DomainName,
  1981. TrustedDomainInformationEx,
  1982. (PVOID *)&pTDIx);
  1983. }
  1984. Win32Err = LsaNtStatusToWinError(Status);
  1985. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  1986. if (TRUST_TYPE_MIT != pTDIx->TrustType)
  1987. {
  1988. NetDompDisplayMessage(MSG_RESET_MIT_TRUST_NOT_MIT);
  1989. Win32Err = ERROR_INVALID_PARAMETER;
  1990. goto TrustSetTransExit;
  1991. }
  1992. if (fDisplayOnly)
  1993. {
  1994. NetDompDisplayMessage((pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE) ?
  1995. MSG_TRUST_NON_TRANSITIVE : MSG_TRUST_TRANSITIVE);
  1996. goto TrustSetTransExit;
  1997. }
  1998. if (fTransOn)
  1999. {
  2000. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE)
  2001. {
  2002. NetDompDisplayMessage(MSG_TRUST_SET_TRANSITIVE);
  2003. pTDIx->TrustAttributes &= ~(TRUST_ATTRIBUTE_NON_TRANSITIVE);
  2004. }
  2005. else
  2006. {
  2007. NetDompDisplayMessage(MSG_TRUST_ALREADY_TRANSITIVE);
  2008. goto TrustSetTransExit;
  2009. }
  2010. }
  2011. else
  2012. {
  2013. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_NON_TRANSITIVE)
  2014. {
  2015. NetDompDisplayMessage(MSG_TRUST_ALREADY_NON_TRANSITIVE);
  2016. goto TrustSetTransExit;
  2017. }
  2018. else
  2019. {
  2020. NetDompDisplayMessage(MSG_TRUST_SET_NON_TRANSITIVE);
  2021. pTDIx->TrustAttributes |= TRUST_ATTRIBUTE_NON_TRANSITIVE;
  2022. }
  2023. }
  2024. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, pDomFoundInfo->DomainName->Buffer));
  2025. Status = LsaSetTrustedDomainInfoByName(pDomFoundInfo->LsaHandle,
  2026. pMitDomInfo->DomainName,
  2027. TrustedDomainInformationEx,
  2028. pTDIx);
  2029. Win32Err = LsaNtStatusToWinError(Status);
  2030. CHECK_WIN32(Win32Err, goto TrustSetTransExit);
  2031. TrustSetTransExit:
  2032. NetDompFreeDomInfo( &Domain2Info );
  2033. NetDompFreeDomInfo( &Domain1Info );
  2034. if (pTDIx)
  2035. LsaFreeMemory(pTDIx);
  2036. return Win32Err;
  2037. }
  2038. DWORD
  2039. NetDomFilterSID(PWSTR pwzFilterArg,
  2040. PWSTR pwzTrustingDomain,
  2041. PWSTR pwzTrustedDomain,
  2042. PND5_AUTH_INFO pTrustingDomainCreds,
  2043. PND5_AUTH_INFO pDomain2Creds)
  2044. /*++
  2045. Routine Description:
  2046. This routine will display or change the SID filtering state of a trust.
  2047. Arguments:
  2048. pwzFilterArg -- Either blank (display the filtering state) or one of
  2049. yes or no (change the filtering state).
  2050. pwzTrustingDomain -- Name of the trusting domain domain
  2051. pwzTrustedDomain -- Name of the trusted domain
  2052. pTrustingDomainCreds -- Credentials of the user of the trusting domain
  2053. pDomain2Creds -- Credentials of the user of domain2 BUGBUG not needed?
  2054. Return Value:
  2055. STATUS_SUCCESS -- Success
  2056. --*/
  2057. {
  2058. DWORD Win32Err = ERROR_SUCCESS;
  2059. NTSTATUS Status = STATUS_SUCCESS;
  2060. BOOL fDisplayOnly = FALSE;
  2061. BOOL fFilterOn = FALSE;
  2062. ND5_TRUST_INFO TrustingDomainInfo, TrustedDomainInfo;
  2063. PTRUSTED_DOMAIN_INFORMATION_EX pTDIx = NULL;
  2064. WCHAR wzYes[NETDOM_STR_LEN], wzNo[NETDOM_STR_LEN];
  2065. RtlZeroMemory(&TrustingDomainInfo, sizeof(TrustingDomainInfo));
  2066. RtlZeroMemory(&TrustedDomainInfo, sizeof(TrustedDomainInfo));
  2067. Win32Err = NetDompTrustGetDomInfo(pwzTrustingDomain,
  2068. NULL,
  2069. pTrustingDomainCreds,
  2070. &TrustingDomainInfo,
  2071. TRUE,
  2072. FALSE, FALSE);
  2073. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2074. Win32Err = NetDompTrustGetDomInfo(pwzTrustedDomain,
  2075. NULL,
  2076. NULL,
  2077. &TrustedDomainInfo,
  2078. FALSE,
  2079. TRUE, TRUE);
  2080. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2081. if (TrustingDomainInfo.Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  2082. {
  2083. Win32Err = ERROR_NO_SUCH_DOMAIN;
  2084. goto TrustSetFilterExit;
  2085. }
  2086. if (NULL == pwzFilterArg)
  2087. {
  2088. fDisplayOnly = TRUE;
  2089. }
  2090. else
  2091. {
  2092. if (!LoadString(g_hInstance, IDS_YES, wzYes, NETDOM_STR_LEN) ||
  2093. !LoadString(g_hInstance, IDS_NO, wzNo, NETDOM_STR_LEN))
  2094. {
  2095. printf("LoadString FAILED!\n");
  2096. Win32Err = ERROR_RESOURCE_NAME_NOT_FOUND;
  2097. NetApiBufferFree(pwzFilterArg);
  2098. goto TrustSetFilterExit;
  2099. }
  2100. if (_wcsicmp(wzYes, pwzFilterArg) == 0)
  2101. {
  2102. fFilterOn = TRUE;
  2103. }
  2104. else
  2105. {
  2106. if (_wcsicmp(wzNo, pwzFilterArg) != 0)
  2107. {
  2108. fDisplayOnly = TRUE;
  2109. }
  2110. }
  2111. NetApiBufferFree(pwzFilterArg);
  2112. }
  2113. LOG_VERBOSE((MSG_VERBOSE_GET_TRUST, TrustingDomainInfo.DomainName->Buffer));
  2114. if (TrustedDomainInfo.Sid)
  2115. {
  2116. Status = LsaQueryTrustedDomainInfo(TrustingDomainInfo.LsaHandle,
  2117. TrustedDomainInfo.Sid,
  2118. TrustedDomainInformationEx,
  2119. (PVOID *)&pTDIx);
  2120. }
  2121. else
  2122. {
  2123. Status = LsaQueryTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2124. TrustedDomainInfo.DomainName,
  2125. TrustedDomainInformationEx,
  2126. (PVOID *)&pTDIx);
  2127. }
  2128. Win32Err = LsaNtStatusToWinError(Status);
  2129. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2130. if (!(pTDIx->TrustDirection & TRUST_DIRECTION_OUTBOUND))
  2131. {
  2132. NetDompDisplayMessage(MSG_TRUST_FILTER_SIDS_WRONG_DIR, pwzTrustingDomain);
  2133. goto TrustSetFilterExit;
  2134. }
  2135. if (fDisplayOnly)
  2136. {
  2137. NetDompDisplayMessage((pTDIx->TrustAttributes & TRUST_ATTRIBUTE_FILTER_SIDS) ?
  2138. MSG_TRUST_FILTER_SIDS : MSG_TRUST_DONT_FILTER_SIDS);
  2139. goto TrustSetFilterExit;
  2140. }
  2141. if (fFilterOn)
  2142. {
  2143. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_FILTER_SIDS)
  2144. {
  2145. NetDompDisplayMessage(MSG_TRUST_ALREADY_FILTER_SIDS);
  2146. goto TrustSetFilterExit;
  2147. }
  2148. else
  2149. {
  2150. NetDompDisplayMessage(MSG_TRUST_SET_FILTER_SIDS);
  2151. pTDIx->TrustAttributes |= TRUST_ATTRIBUTE_FILTER_SIDS;
  2152. }
  2153. }
  2154. else
  2155. {
  2156. if (pTDIx->TrustAttributes & TRUST_ATTRIBUTE_FILTER_SIDS)
  2157. {
  2158. NetDompDisplayMessage(MSG_TRUST_SET_DONT_FILTER_SIDS);
  2159. pTDIx->TrustAttributes &= ~(TRUST_ATTRIBUTE_FILTER_SIDS);
  2160. }
  2161. else
  2162. {
  2163. NetDompDisplayMessage(MSG_TRUST_ALREADY_DONT_FILTER_SIDS);
  2164. goto TrustSetFilterExit;
  2165. }
  2166. }
  2167. LOG_VERBOSE((MSG_VERBOSE_SET_TRUST, TrustingDomainInfo.DomainName->Buffer));
  2168. Status = LsaSetTrustedDomainInfoByName(TrustingDomainInfo.LsaHandle,
  2169. TrustedDomainInfo.DomainName,
  2170. TrustedDomainInformationEx,
  2171. pTDIx);
  2172. Win32Err = LsaNtStatusToWinError(Status);
  2173. CHECK_WIN32(Win32Err, goto TrustSetFilterExit);
  2174. TrustSetFilterExit:
  2175. NetDompFreeDomInfo( &TrustedDomainInfo );
  2176. NetDompFreeDomInfo( &TrustingDomainInfo );
  2177. if (pTDIx)
  2178. LsaFreeMemory(pTDIx);
  2179. return Win32Err;
  2180. }
  2181. typedef INT_PTR (*DSPROP_DumpFTInfos)(PCWSTR pwzDcName, PCWSTR pwzTrust,
  2182. PCWSTR pwzUser, PCWSTR pwzPw);
  2183. typedef INT_PTR (*DSPROP_ToggleFTName)(PCWSTR pwzLocalDc, PWSTR pwzTrust, ULONG iSel,
  2184. PCWSTR pwzUser, PCWSTR pwzPW);
  2185. DWORD
  2186. NetDomForestSuffix(PWSTR pwzTrustPartnerArg,
  2187. ULONG iSel,
  2188. PWSTR pwzLocalDomain,
  2189. PND5_AUTH_INFO pLocalDomainCreds)
  2190. /*++
  2191. Routine Description:
  2192. This routine will toggle the status of a name suffix claimed by a forest trust domain
  2193. or if iSel is zero will display the name suffixes claimed by a forest trust domain.
  2194. Arguments:
  2195. pwzTrustPartnerArg -- the domain whose TDO will be read for the name suffixes
  2196. attribute (ms-DS-Trust-Forest-Trust-Info).
  2197. iSel -- the one-based index of the name to toggle (if zero, display the names).
  2198. pwzLocalDomain -- Name of the domain on which the TDO resides.
  2199. pLocalDomainCreds -- Credentials of the user of the local domain
  2200. Return Value:
  2201. STATUS_SUCCESS -- Success
  2202. --*/
  2203. {
  2204. DWORD Win32Err = ERROR_SUCCESS;
  2205. PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
  2206. PWSTR pwzDcName = NULL;
  2207. NTSTATUS Status = STATUS_SUCCESS;
  2208. HMODULE hm = NULL;
  2209. DSPROP_DumpFTInfos pDumpFTInfos = NULL;
  2210. DSPROP_ToggleFTName pToggleFTName = NULL;
  2211. ASSERT(pwzTrustPartnerArg && pwzLocalDomain && pLocalDomainCreds);
  2212. Win32Err = DsGetDcName(NULL,
  2213. pwzLocalDomain,
  2214. NULL,
  2215. NULL,
  2216. DS_PDC_REQUIRED,
  2217. &pDcInfo );
  2218. CHECK_WIN32(Win32Err, return Win32Err);
  2219. ASSERT(pDcInfo);
  2220. pwzDcName = pDcInfo->DomainControllerName;
  2221. hm = LoadLibrary(L"adprop.dll");
  2222. if (!hm)
  2223. {
  2224. Win32Err = GetLastError();
  2225. NetApiBufferFree(pDcInfo);
  2226. return Win32Err;
  2227. }
  2228. if (0 == iSel)
  2229. {
  2230. pDumpFTInfos = (DSPROP_DumpFTInfos)GetProcAddress(hm, "DSPROP_DumpFTInfos");
  2231. }
  2232. else
  2233. {
  2234. pToggleFTName = (DSPROP_ToggleFTName)GetProcAddress(hm, "DSPROP_ToggleFTName");
  2235. }
  2236. if (!pDumpFTInfos && !pToggleFTName)
  2237. {
  2238. Win32Err = GetLastError();
  2239. NetApiBufferFree(pDcInfo);
  2240. NetDompDisplayMessage(MSG_WRONG_DSPROP_DLL);
  2241. return Win32Err;
  2242. }
  2243. if (0 == iSel)
  2244. {
  2245. Win32Err = (DWORD)(*pDumpFTInfos)(pwzDcName, pwzTrustPartnerArg,
  2246. pLocalDomainCreds->User, pLocalDomainCreds->Password);
  2247. }
  2248. else
  2249. {
  2250. Win32Err = (DWORD)(*pToggleFTName)(pwzDcName, pwzTrustPartnerArg, iSel,
  2251. pLocalDomainCreds->User, pLocalDomainCreds->Password);
  2252. }
  2253. NetApiBufferFree(pDcInfo);
  2254. return Win32Err;
  2255. }
  2256. DWORD
  2257. NetDompVerifyIndividualTrustKerberos(
  2258. IN PWSTR TrustingDomain,
  2259. IN PWSTR TrustedDomain,
  2260. IN PND5_AUTH_INFO pTrustingCreds,
  2261. IN PND5_AUTH_INFO pTrustedCreds
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. This routine will verify a single trust in the one direction only.
  2266. Arguments:
  2267. TrustingDomain -- Name of the domain on the outbound side
  2268. TrustedDomain -- Name of the domain on the inbound side
  2269. pTrustingCreds -- Credentials of the user on the outbound side
  2270. pTrustedCreds -- Credentials of the user on the inbound side
  2271. Return Value:
  2272. STATUS_SUCCESS -- Success
  2273. --*/
  2274. {
  2275. //
  2276. // Copy the relevant info into local pointers so that I don't have
  2277. // to rewrite the rest of the function.
  2278. //
  2279. PWSTR PackageName = NULL;
  2280. PWSTR UserNameU = pTrustedCreds->pwzUserWoDomain;
  2281. PWSTR DomainNameU = pTrustedCreds->pwzUsersDomain;
  2282. PWSTR PasswordU = pTrustedCreds->Password;
  2283. PWSTR ServerUserNameU = pTrustingCreds->pwzUserWoDomain;
  2284. PWSTR ServerDomainNameU = pTrustingCreds->pwzUsersDomain;
  2285. PWSTR ServerPasswordU = pTrustingCreds->Password;
  2286. ULONG ContextReq = 0;
  2287. ULONG CredFlags = 0;
  2288. SECURITY_STATUS SecStatus;
  2289. SECURITY_STATUS AcceptStatus;
  2290. SECURITY_STATUS InitStatus;
  2291. CredHandle CredentialHandle2;
  2292. CtxtHandle ClientContextHandle;
  2293. CtxtHandle ServerContextHandle;
  2294. TimeStamp Lifetime;
  2295. ULONG ContextAttributes;
  2296. ULONG PackageCount;
  2297. PSecPkgInfo PackageInfo = NULL;
  2298. ULONG ClientFlags;
  2299. ULONG ServerFlags;
  2300. BOOLEAN AcquiredServerCred = FALSE;
  2301. LPWSTR DomainName = NULL;
  2302. LPWSTR UserName = NULL;
  2303. TCHAR TargetName[256];
  2304. PSEC_WINNT_AUTH_IDENTITY_EXW AuthIdentity = NULL;
  2305. PSEC_WINNT_AUTH_IDENTITY_W ServerAuthIdentity = NULL;
  2306. PUCHAR Where;
  2307. ULONG CredSize;
  2308. SecBufferDesc NegotiateDesc;
  2309. SecBuffer NegotiateBuffer;
  2310. SecBufferDesc ChallengeDesc;
  2311. SecBuffer ChallengeBuffer;
  2312. SecBufferDesc AuthenticateDesc;
  2313. SecBuffer AuthenticateBuffer;
  2314. SecPkgCredentials_Names CredNames;
  2315. CredHandle ServerCredHandleStorage;
  2316. PCredHandle ServerCredHandle = NULL;
  2317. //
  2318. // Set the package to wide-char
  2319. //
  2320. if (PackageName == NULL)
  2321. {
  2322. PackageName = MICROSOFT_KERBEROS_NAME_W;
  2323. }
  2324. //
  2325. // Allocate the Authentication Identity for the outbound trust
  2326. //
  2327. if ((UserNameU != NULL) || (DomainNameU != NULL) || (PasswordU != NULL) || (CredFlags != 0))
  2328. {
  2329. CredSize = (((UserNameU != NULL) ? wcslen(UserNameU) + 1 : 0) +
  2330. ((DomainNameU != NULL) ? wcslen(DomainNameU) + 1 : 0 ) +
  2331. ((PasswordU != NULL) ? wcslen(PasswordU) + 1 : 0) ) * sizeof(WCHAR) +
  2332. sizeof(SEC_WINNT_AUTH_IDENTITY_EXW);
  2333. AuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_EXW) LocalAlloc(LMEM_ZEROINIT,CredSize);
  2334. if (!AuthIdentity)
  2335. {
  2336. return ERROR_NOT_ENOUGH_MEMORY;
  2337. }
  2338. AuthIdentity->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
  2339. Where = (PUCHAR) (AuthIdentity + 1);
  2340. if (UserNameU != NULL)
  2341. {
  2342. AuthIdentity->UserLength = wcslen(UserNameU);
  2343. AuthIdentity->User = (LPWSTR) Where;
  2344. wcscpy(
  2345. (LPWSTR) Where,
  2346. UserNameU
  2347. );
  2348. Where += (wcslen(UserNameU) + 1) * sizeof(WCHAR);
  2349. }
  2350. if (DomainNameU != NULL)
  2351. {
  2352. AuthIdentity->DomainLength = wcslen(DomainNameU);
  2353. AuthIdentity->Domain = (LPWSTR) Where;
  2354. wcscpy(
  2355. (LPWSTR) Where,
  2356. DomainNameU
  2357. );
  2358. Where += (wcslen(DomainNameU) + 1) * sizeof(WCHAR);
  2359. }
  2360. if (PasswordU != NULL)
  2361. {
  2362. AuthIdentity->PasswordLength = wcslen(PasswordU);
  2363. AuthIdentity->Password = (LPWSTR) Where;
  2364. wcscpy(
  2365. (LPWSTR) Where,
  2366. PasswordU
  2367. );
  2368. Where += (wcslen(PasswordU) + 1) * sizeof(WCHAR);
  2369. }
  2370. AuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | CredFlags;
  2371. }
  2372. //
  2373. // Allocate the Authentication Identity for the outbound trust
  2374. //
  2375. if ((ServerUserNameU != NULL) || (ServerDomainNameU != NULL) || (ServerPasswordU != NULL))
  2376. {
  2377. CredSize = (((ServerUserNameU != NULL) ? wcslen(ServerUserNameU) + 1 : 0) +
  2378. ((ServerDomainNameU != NULL) ? wcslen(ServerDomainNameU) + 1 : 0 ) +
  2379. ((ServerPasswordU != NULL) ? wcslen(ServerPasswordU) + 1 : 0) ) * sizeof(WCHAR) +
  2380. sizeof(SEC_WINNT_AUTH_IDENTITY);
  2381. ServerAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_W) LocalAlloc(LMEM_ZEROINIT,CredSize);
  2382. if (!ServerAuthIdentity)
  2383. {
  2384. return ERROR_NOT_ENOUGH_MEMORY;
  2385. }
  2386. Where = (PUCHAR) (ServerAuthIdentity + 1);
  2387. if (ServerUserNameU != NULL)
  2388. {
  2389. ServerAuthIdentity->UserLength = wcslen(ServerUserNameU);
  2390. ServerAuthIdentity->User = (LPWSTR) Where;
  2391. wcscpy(
  2392. (LPWSTR) Where,
  2393. ServerUserNameU
  2394. );
  2395. Where += (wcslen(ServerUserNameU) + 1) * sizeof(WCHAR);
  2396. }
  2397. if (ServerDomainNameU != NULL)
  2398. {
  2399. ServerAuthIdentity->DomainLength = wcslen(ServerDomainNameU);
  2400. ServerAuthIdentity->Domain = (LPWSTR) Where;
  2401. wcscpy(
  2402. (LPWSTR) Where,
  2403. ServerDomainNameU
  2404. );
  2405. Where += (wcslen(ServerDomainNameU) + 1) * sizeof(WCHAR);
  2406. }
  2407. if (ServerPasswordU != NULL)
  2408. {
  2409. ServerAuthIdentity->PasswordLength = wcslen(ServerPasswordU);
  2410. ServerAuthIdentity->Password = (LPWSTR) Where;
  2411. wcscpy(
  2412. (LPWSTR) Where,
  2413. ServerPasswordU
  2414. );
  2415. Where += (wcslen(ServerPasswordU) + 1) * sizeof(WCHAR);
  2416. }
  2417. ServerAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | SEC_WINNT_AUTH_IDENTITY_MARSHALLED;
  2418. }
  2419. CredNames.sUserName = NULL;
  2420. NegotiateBuffer.pvBuffer = NULL;
  2421. ChallengeBuffer.pvBuffer = NULL;
  2422. AuthenticateBuffer.pvBuffer = NULL;
  2423. DomainName = _wgetenv(L"USERDOMAIN");
  2424. UserName = _wgetenv(L"USERNAME");
  2425. //
  2426. // Get info about the security packages.
  2427. //
  2428. SecStatus = EnumerateSecurityPackages( &PackageCount, &PackageInfo );
  2429. if ( SecStatus != STATUS_SUCCESS )
  2430. {
  2431. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2432. TrustingDomain,
  2433. TrustedDomain );
  2434. return SecStatus;
  2435. }
  2436. //
  2437. // Get info about the security packages.
  2438. //
  2439. SecStatus = QuerySecurityPackageInfo( PackageName, &PackageInfo );
  2440. if ( SecStatus != STATUS_SUCCESS )
  2441. {
  2442. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2443. TrustingDomain,
  2444. TrustedDomain );
  2445. return SecStatus;
  2446. }
  2447. //
  2448. // Acquire a credential handle for the server side
  2449. //
  2450. if (ServerCredHandle == NULL)
  2451. {
  2452. ServerCredHandle = &ServerCredHandleStorage;
  2453. AcquiredServerCred = TRUE;
  2454. SecStatus = AcquireCredentialsHandle(
  2455. NULL,
  2456. PackageName,
  2457. SECPKG_CRED_INBOUND,
  2458. NULL,
  2459. ServerAuthIdentity,
  2460. NULL,
  2461. NULL,
  2462. ServerCredHandle,
  2463. &Lifetime );
  2464. if ( SecStatus != STATUS_SUCCESS )
  2465. {
  2466. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2467. TrustingDomain,
  2468. TrustedDomain );
  2469. return SecStatus;
  2470. }
  2471. }
  2472. //
  2473. // Acquire a credential handle for the client side
  2474. //
  2475. SecStatus = AcquireCredentialsHandle(
  2476. NULL, // New principal
  2477. PackageName,
  2478. SECPKG_CRED_OUTBOUND,
  2479. NULL,
  2480. AuthIdentity,
  2481. NULL,
  2482. NULL,
  2483. &CredentialHandle2,
  2484. &Lifetime );
  2485. if ( SecStatus != STATUS_SUCCESS )
  2486. {
  2487. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2488. TrustingDomain,
  2489. TrustedDomain );
  2490. return SecStatus;
  2491. }
  2492. //
  2493. // Query some cred attributes
  2494. //
  2495. SecStatus = QueryCredentialsAttributes(
  2496. &CredentialHandle2,
  2497. SECPKG_CRED_ATTR_NAMES,
  2498. &CredNames );
  2499. if ( SecStatus != STATUS_SUCCESS )
  2500. {
  2501. if ( !NT_SUCCESS(SecStatus) )
  2502. {
  2503. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2504. TrustingDomain,
  2505. TrustedDomain );
  2506. return SecStatus;
  2507. }
  2508. }
  2509. else
  2510. {
  2511. FreeContextBuffer(CredNames.sUserName);
  2512. }
  2513. //
  2514. // Do the same for the client
  2515. //
  2516. SecStatus = QueryCredentialsAttributes(
  2517. ServerCredHandle,
  2518. SECPKG_CRED_ATTR_NAMES,
  2519. &CredNames );
  2520. if ( SecStatus != STATUS_SUCCESS )
  2521. {
  2522. if ( !NT_SUCCESS(SecStatus) )
  2523. {
  2524. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2525. TrustingDomain,
  2526. TrustedDomain );
  2527. return SecStatus;
  2528. }
  2529. }
  2530. else
  2531. {
  2532. FreeContextBuffer(CredNames.sUserName);
  2533. }
  2534. //
  2535. // Get the NegotiateMessage (ClientSide)
  2536. //
  2537. NegotiateDesc.ulVersion = 0;
  2538. NegotiateDesc.cBuffers = 1;
  2539. NegotiateDesc.pBuffers = &NegotiateBuffer;
  2540. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  2541. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  2542. NegotiateBuffer.pvBuffer = LocalAlloc( 0, NegotiateBuffer.cbBuffer );
  2543. if ( NegotiateBuffer.pvBuffer == NULL )
  2544. {
  2545. DWORD dwError = GetLastError();
  2546. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2547. TrustingDomain,
  2548. TrustedDomain );
  2549. return dwError;
  2550. }
  2551. if (ContextReq == 0)
  2552. {
  2553. 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;
  2554. }
  2555. else
  2556. {
  2557. ClientFlags = ContextReq;
  2558. }
  2559. if (ServerUserNameU != NULL && ServerDomainNameU != NULL)
  2560. {
  2561. wcscpy(
  2562. TargetName,
  2563. ServerUserNameU
  2564. );
  2565. wcscat(
  2566. TargetName,
  2567. L"@"
  2568. );
  2569. wcscat(
  2570. TargetName,
  2571. ServerDomainNameU
  2572. );
  2573. }
  2574. InitStatus = InitializeSecurityContext(
  2575. &CredentialHandle2,
  2576. NULL, // No Client context yet
  2577. TargetName, // Faked target name
  2578. ClientFlags,
  2579. 0, // Reserved 1
  2580. SECURITY_NATIVE_DREP,
  2581. NULL, // No initial input token
  2582. 0, // Reserved 2
  2583. &ClientContextHandle,
  2584. &NegotiateDesc,
  2585. &ContextAttributes,
  2586. &Lifetime );
  2587. if ( InitStatus != STATUS_SUCCESS )
  2588. {
  2589. if ( !NT_SUCCESS(InitStatus) )
  2590. {
  2591. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2592. TrustingDomain,
  2593. TrustedDomain );
  2594. return InitStatus;
  2595. }
  2596. }
  2597. //
  2598. // Get the ChallengeMessage (ServerSide)
  2599. //
  2600. NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
  2601. ChallengeDesc.ulVersion = 0;
  2602. ChallengeDesc.cBuffers = 1;
  2603. ChallengeDesc.pBuffers = &ChallengeBuffer;
  2604. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  2605. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  2606. ChallengeBuffer.pvBuffer = LocalAlloc( 0, ChallengeBuffer.cbBuffer );
  2607. if ( ChallengeBuffer.pvBuffer == NULL )
  2608. {
  2609. DWORD dwError = GetLastError();
  2610. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2611. TrustingDomain,
  2612. TrustedDomain );
  2613. return dwError;
  2614. }
  2615. ServerFlags = ASC_REQ_EXTENDED_ERROR;
  2616. AcceptStatus = AcceptSecurityContext(
  2617. ServerCredHandle,
  2618. NULL, // No Server context yet
  2619. &NegotiateDesc,
  2620. ServerFlags,
  2621. SECURITY_NATIVE_DREP,
  2622. &ServerContextHandle,
  2623. &ChallengeDesc,
  2624. &ContextAttributes,
  2625. &Lifetime );
  2626. if ( AcceptStatus != STATUS_SUCCESS )
  2627. {
  2628. if ( !NT_SUCCESS(AcceptStatus) )
  2629. {
  2630. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2631. TrustingDomain,
  2632. TrustedDomain );
  2633. return AcceptStatus;
  2634. }
  2635. }
  2636. while (InitStatus != STATUS_SUCCESS)
  2637. {
  2638. //
  2639. // Get the AuthenticateMessage (ClientSide)
  2640. //
  2641. ChallengeBuffer.BufferType |= SECBUFFER_READONLY;
  2642. AuthenticateDesc.ulVersion = 0;
  2643. AuthenticateDesc.cBuffers = 1;
  2644. AuthenticateDesc.pBuffers = &AuthenticateBuffer;
  2645. AuthenticateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  2646. AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
  2647. if (AuthenticateBuffer.pvBuffer == NULL)
  2648. {
  2649. AuthenticateBuffer.pvBuffer = LocalAlloc( 0, AuthenticateBuffer.cbBuffer );
  2650. if ( AuthenticateBuffer.pvBuffer == NULL )
  2651. {
  2652. DWORD dwError = GetLastError();
  2653. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2654. TrustingDomain,
  2655. TrustedDomain );
  2656. return dwError;
  2657. }
  2658. }
  2659. InitStatus = InitializeSecurityContext(
  2660. NULL,
  2661. &ClientContextHandle,
  2662. TargetName,
  2663. ClientFlags,
  2664. 0, // Reserved 1
  2665. SECURITY_NATIVE_DREP,
  2666. &ChallengeDesc,
  2667. 0, // Reserved 2
  2668. &ClientContextHandle,
  2669. &AuthenticateDesc,
  2670. &ContextAttributes,
  2671. &Lifetime );
  2672. if ( InitStatus != STATUS_SUCCESS )
  2673. {
  2674. if ( !NT_SUCCESS(InitStatus) )
  2675. {
  2676. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2677. TrustingDomain,
  2678. TrustedDomain );
  2679. return InitStatus;
  2680. }
  2681. }
  2682. if (AcceptStatus != STATUS_SUCCESS)
  2683. {
  2684. //
  2685. // Finally authenticate the user (ServerSide)
  2686. //
  2687. AuthenticateBuffer.BufferType |= SECBUFFER_READONLY;
  2688. ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
  2689. ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
  2690. AcceptStatus = AcceptSecurityContext(
  2691. NULL,
  2692. &ServerContextHandle,
  2693. &AuthenticateDesc,
  2694. ServerFlags,
  2695. SECURITY_NATIVE_DREP,
  2696. &ServerContextHandle,
  2697. &ChallengeDesc,
  2698. &ContextAttributes,
  2699. &Lifetime );
  2700. if ( AcceptStatus != STATUS_SUCCESS )
  2701. {
  2702. if ( !NT_SUCCESS(AcceptStatus) )
  2703. {
  2704. NetDompDisplayMessage( MSG_KERBEROS_TRUST_FAILED,
  2705. TrustingDomain,
  2706. TrustedDomain );
  2707. return AcceptStatus;
  2708. }
  2709. }
  2710. }
  2711. }
  2712. NetDompDisplayMessage( MSG_KERBEROS_TRUST_SUCCEEDED, TrustedDomain, TrustingDomain );
  2713. return AcceptStatus;
  2714. }
  2715. DWORD
  2716. NetDompVerifyTrust(
  2717. IN PND5_TRUST_INFO pTrustingInfo, // outbound
  2718. IN PND5_TRUST_INFO pTrustedInfo, // inbound
  2719. BOOL fShowResults
  2720. )
  2721. /*++
  2722. Routine Description:
  2723. This function will verify a trust connection
  2724. Arguments:
  2725. TrustingInfo - Information on the trusting (outbound) side of the domain
  2726. TrustedInfo - Information on the trusted (inbound) side of the domain
  2727. Return Value:
  2728. ERROR_SUCCESS - The function succeeded
  2729. --*/
  2730. {
  2731. NTSTATUS Status = STATUS_SUCCESS;
  2732. DWORD SidBuff[ sizeof( SID ) / sizeof( DWORD ) + 5 ];
  2733. PSID DomAdminSid = ( PSID )SidBuff;
  2734. PLSA_REFERENCED_DOMAIN_LIST Domains = NULL;
  2735. PLSA_TRANSLATED_NAME Names = NULL;
  2736. NET_API_STATUS NetStatus;
  2737. PNETLOGON_INFO_2 NetlogonInfo2 = NULL;
  2738. PWSTR pwzDomSvr = pTrustedInfo->DomainName->Buffer;
  2739. PWSTR pwzTrustedDomain = pTrustedInfo->DomainName->Buffer;
  2740. BOOL fBufferAlloced = FALSE;
  2741. ASSERT( RtlValidSid( pTrustedInfo->Sid ) );
  2742. if ( !RtlValidSid( pTrustedInfo->Sid ) ) {
  2743. return( ERROR_INVALID_SID );
  2744. }
  2745. if (!pTrustingInfo->Uplevel)
  2746. {
  2747. pwzTrustedDomain = pwzDomSvr = pTrustedInfo->FlatName->Buffer;
  2748. }
  2749. //
  2750. // Check netlogon's secure channel
  2751. //
  2752. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  2753. NETLOGON_CONTROL_TC_VERIFY,
  2754. 2,
  2755. (LPBYTE)&pwzTrustedDomain,
  2756. (LPBYTE *)&NetlogonInfo2);
  2757. if (ERROR_NO_SUCH_DOMAIN == NetStatus && pTrustingInfo->Uplevel)
  2758. {
  2759. // Pre-existing TDOs for domains upgraded from NT4 to NT5 will continue to
  2760. // have a flat name.
  2761. //
  2762. pwzTrustedDomain = pwzDomSvr = pTrustedInfo->FlatName->Buffer;
  2763. pTrustedInfo->fWasDownlevel = TRUE;
  2764. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  2765. NETLOGON_CONTROL_TC_VERIFY,
  2766. 2,
  2767. (LPBYTE)&pwzTrustedDomain,
  2768. (LPBYTE *)&NetlogonInfo2);
  2769. }
  2770. if (ERROR_NOT_SUPPORTED == NetStatus)
  2771. {
  2772. // Must be remoted to a Win2k/NT4 DC that doesn't support SC verify.
  2773. //
  2774. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  2775. NETLOGON_CONTROL_TC_QUERY,
  2776. 2,
  2777. (LPBYTE)&pwzTrustedDomain,
  2778. (LPBYTE *)&NetlogonInfo2);
  2779. }
  2780. if (NERR_Success == NetStatus)
  2781. {
  2782. NetStatus = NetlogonInfo2->netlog2_tc_connection_status;
  2783. if (NERR_Success == NetStatus)
  2784. {
  2785. if (pTrustingInfo->Uplevel)
  2786. {
  2787. // Form the name domain\DC so a reset can done against the same
  2788. // DC that is currently being used for the secure channel.
  2789. //
  2790. NetStatus = NetApiBufferAllocate((wcslen(NetlogonInfo2->netlog2_trusted_dc_name) +
  2791. wcslen(pwzTrustedDomain) + 1) * sizeof(WCHAR),
  2792. (PVOID*)&pwzDomSvr);
  2793. if (NERR_Success != NetStatus)
  2794. {
  2795. NetApiBufferFree( NetlogonInfo2 );
  2796. return ERROR_NOT_ENOUGH_MEMORY;
  2797. }
  2798. fBufferAlloced = TRUE;
  2799. wsprintf(pwzDomSvr, L"%s\\%s", pwzTrustedDomain,
  2800. (L'\\' == *NetlogonInfo2->netlog2_trusted_dc_name) ?
  2801. NetlogonInfo2->netlog2_trusted_dc_name + 2 :
  2802. NetlogonInfo2->netlog2_trusted_dc_name);
  2803. }
  2804. }
  2805. else
  2806. {
  2807. if (fShowResults)
  2808. {
  2809. // Report Query failure.
  2810. //
  2811. NetDompDisplayMessage(MSG_VERIFY_TRUST_QUERY_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  2812. NetDompDisplayErrorMessage(NetStatus);
  2813. }
  2814. }
  2815. NetApiBufferFree( NetlogonInfo2 );
  2816. }
  2817. else
  2818. {
  2819. if (fShowResults)
  2820. {
  2821. // Report I_NetLogonControl2 error.
  2822. //
  2823. NetDompDisplayMessage(MSG_VERIFY_TRUST_NLQUERY_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  2824. NetDompDisplayErrorMessage(NetStatus);
  2825. return NetStatus;
  2826. }
  2827. }
  2828. NetStatus = I_NetLogonControl2(pTrustingInfo->Server,
  2829. NETLOGON_CONTROL_REDISCOVER,
  2830. 2,
  2831. (LPBYTE)&pwzDomSvr,
  2832. (LPBYTE *)&NetlogonInfo2 );
  2833. if (fBufferAlloced)
  2834. {
  2835. NetApiBufferFree(pwzDomSvr);
  2836. }
  2837. if (NERR_Success == NetStatus)
  2838. {
  2839. NetStatus = NetlogonInfo2->netlog2_tc_connection_status;
  2840. if (NERR_Success != NetStatus)
  2841. {
  2842. if (fShowResults)
  2843. {
  2844. // Report Reset failure.
  2845. //
  2846. NetDompDisplayMessage(MSG_VERIFY_TRUST_RESET_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  2847. NetDompDisplayErrorMessage(NetStatus);
  2848. }
  2849. NetApiBufferFree( NetlogonInfo2 );
  2850. return NetStatus;
  2851. }
  2852. NetApiBufferFree( NetlogonInfo2 );
  2853. }
  2854. else
  2855. {
  2856. if (fShowResults)
  2857. {
  2858. // Report failure
  2859. //
  2860. NetDompDisplayMessage(MSG_VERIFY_TRUST_NLRESET_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  2861. NetDompDisplayErrorMessage(NetStatus);
  2862. }
  2863. return NetStatus;
  2864. }
  2865. //
  2866. // Now, try a lookup
  2867. //
  2868. if (ERROR_SUCCESS == NetStatus)
  2869. {
  2870. //
  2871. // Build the domain admins sid for the inbound side of the trust
  2872. //
  2873. RtlCopyMemory( DomAdminSid,
  2874. pTrustedInfo->Sid,
  2875. RtlLengthSid( pTrustedInfo->Sid ) );
  2876. ( ( PISID )( DomAdminSid ) )->SubAuthorityCount++;
  2877. *( RtlSubAuthoritySid( DomAdminSid,
  2878. *( RtlSubAuthorityCountSid( pTrustedInfo->Sid ) ) ) ) =
  2879. DOMAIN_GROUP_RID_ADMINS;
  2880. //
  2881. // Now, we'll simply do a remote lookup, and ensure that we get back success
  2882. //
  2883. Status = LsaLookupSids( pTrustingInfo->LsaHandle,
  2884. 1,
  2885. &DomAdminSid,
  2886. &Domains,
  2887. &Names );
  2888. if ( NT_SUCCESS( Status ) )
  2889. {
  2890. LsaFreeMemory( Domains );
  2891. LsaFreeMemory( Names );
  2892. NetStatus = ERROR_SUCCESS;
  2893. }
  2894. else
  2895. {
  2896. if ( Status == STATUS_NONE_MAPPED )
  2897. {
  2898. NetStatus = ERROR_TRUSTED_DOMAIN_FAILURE;
  2899. }
  2900. else
  2901. {
  2902. NetStatus = RtlNtStatusToDosError( Status );
  2903. }
  2904. if (fShowResults)
  2905. {
  2906. // Report failure
  2907. //
  2908. NetDompDisplayMessage(MSG_VERIFY_TRUST_LOOKUP_FAILED, pTrustingInfo->Server, pwzTrustedDomain);
  2909. NetDompDisplayErrorMessage(NetStatus);
  2910. }
  2911. }
  2912. }
  2913. return NetStatus;
  2914. }
  2915. DWORD
  2916. NetDompVerifyTrustObject(
  2917. IN ARG_RECORD * rgNetDomArgs,
  2918. IN PWSTR pwzDomain1,
  2919. IN PWSTR pwzDomain2,
  2920. IN PND5_AUTH_INFO pDomain1Creds,
  2921. IN PND5_AUTH_INFO pDomain2Creds
  2922. )
  2923. /*++
  2924. Routine Description:
  2925. This function will handle the adding of a trusted domain object
  2926. Arguments:
  2927. rgNetDomArgs - List of arguments present in the Args list
  2928. pwzDomain1, pwzDomain2 - domains with trust
  2929. pDomain1Creds, pDomain2Creds - Credentials to use when connecting to
  2930. the domain controllers
  2931. Return Value:
  2932. ERROR_INVALID_PARAMETER - No object name was supplied
  2933. --*/
  2934. {
  2935. DWORD Win32Err, Win32Err1;
  2936. ND5_TRUST_INFO TrustInfo1, TrustInfo2;
  2937. PND5_TRUST_INFO pTrustInfoUplevel, pTrustInfoOther;
  2938. DWORD Direction;
  2939. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  2940. {
  2941. return ERROR_INVALID_PARAMETER;
  2942. }
  2943. RtlZeroMemory( &TrustInfo1, sizeof( TrustInfo1 ) );
  2944. RtlZeroMemory( &TrustInfo2, sizeof( TrustInfo2 ) );
  2945. Win32Err = NetDompTrustGetDomInfo( pwzDomain1,
  2946. NULL,
  2947. pDomain1Creds,
  2948. &TrustInfo1,
  2949. TRUE,
  2950. FALSE, FALSE );
  2951. if (ERROR_SUCCESS == Win32Err) {
  2952. Win32Err = NetDompTrustGetDomInfo( pwzDomain2,
  2953. NULL,
  2954. pDomain2Creds,
  2955. &TrustInfo2,
  2956. TRUE,
  2957. FALSE, FALSE );
  2958. }
  2959. if (ERROR_SUCCESS != Win32Err)
  2960. {
  2961. goto TrustVerifyExit;
  2962. }
  2963. Win32Err = NetDompGetTrustDirection(&TrustInfo1,
  2964. &TrustInfo2,
  2965. &Direction);
  2966. if (ERROR_SUCCESS != Win32Err)
  2967. {
  2968. goto TrustVerifyExit;
  2969. }
  2970. if (TRUST_DIRECTION_DISABLED == Direction)
  2971. {
  2972. NetDompDisplayMessage(MSG_VERIFY_TRUST_DISABLED);
  2973. goto TrustVerifyExit;
  2974. }
  2975. if (Direction & TRUST_DIRECTION_OUTBOUND)
  2976. {
  2977. LOG_VERBOSE((MSG_VERBOSE_VERIFY_TRUST, pwzDomain1, pwzDomain2));
  2978. Win32Err = NetDompVerifyTrust(&TrustInfo1,
  2979. &TrustInfo2,
  2980. TRUE);
  2981. }
  2982. if (Direction & TRUST_DIRECTION_INBOUND)
  2983. {
  2984. LOG_VERBOSE((MSG_VERBOSE_VERIFY_TRUST, pwzDomain2, pwzDomain1));
  2985. Win32Err1 = NetDompVerifyTrust(&TrustInfo2,
  2986. &TrustInfo1,
  2987. TRUE);
  2988. }
  2989. if (ERROR_SUCCESS == Win32Err && ERROR_SUCCESS == Win32Err1)
  2990. {
  2991. NetDompDisplayMessage(MSG_VERIFY_TRUST_OK, pwzDomain1, pwzDomain2);
  2992. }
  2993. TrustVerifyExit:
  2994. NetDompFreeDomInfo( &TrustInfo2 );
  2995. NetDompFreeDomInfo( &TrustInfo1 );
  2996. return( Win32Err );
  2997. }
  2998. DWORD
  2999. NetDompHandleTrust(ARG_RECORD * rgNetDomArgs)
  3000. /*++
  3001. Routine Description:
  3002. This function manages inter-domain trust
  3003. Arguments:
  3004. Args - List of command line arguments
  3005. Return Value:
  3006. ERROR_INVALID_PARAMETER - No object name was supplied
  3007. --*/
  3008. {
  3009. DWORD Win32Err = ERROR_SUCCESS;
  3010. ULONG Ops = 0, i;
  3011. NETDOM_ARG_ENUM BadOp = eArgBegin;
  3012. PWSTR TrustedDomain = NULL, pwzArgValue = NULL, pwzArgValue2 = NULL;
  3013. ND5_AUTH_INFO TrustedDomainUser, TrustingDomainUser;
  3014. RtlZeroMemory( &TrustedDomainUser, sizeof( ND5_AUTH_INFO ) );
  3015. RtlZeroMemory( &TrustingDomainUser, sizeof( ND5_AUTH_INFO ) );
  3016. PWSTR TrustingDomain = rgNetDomArgs[eObject].strValue;
  3017. if ( !TrustingDomain ) {
  3018. DisplayHelp(ePriTrust);
  3019. return( ERROR_INVALID_PARAMETER );
  3020. }
  3021. Win32Err = NetDompValidateSecondaryArguments(rgNetDomArgs,
  3022. eObject,
  3023. eCommDomain,
  3024. eCommUserNameO,
  3025. eCommPasswordO,
  3026. eCommUserNameD,
  3027. eCommPasswordD,
  3028. eTrustRealm,
  3029. eTrustPasswordT,
  3030. eCommAdd,
  3031. eCommRemove,
  3032. eTrustTwoWay,
  3033. eTrustKerberos,
  3034. eTrustTransitive,
  3035. eTrustOneSide,
  3036. eTrustNameSuffixes,
  3037. eTrustToggleSuffixes,
  3038. eTrustFilterSIDs,
  3039. eCommVerify,
  3040. eCommReset,
  3041. eCommForce,
  3042. eCommVerbose,
  3043. eArgEnd);
  3044. if ( Win32Err != ERROR_SUCCESS ) {
  3045. DisplayHelp(ePriTrust);
  3046. return Win32Err;
  3047. }
  3048. //
  3049. // See if we are doing an add, remove, or verify
  3050. //
  3051. if ( CmdFlagOn(rgNetDomArgs, eCommAdd) ) {
  3052. Ops++;
  3053. if (CmdFlagOn(rgNetDomArgs, eTrustTransitive))
  3054. {
  3055. BadOp = eTrustTransitive;
  3056. }
  3057. }
  3058. if ( CmdFlagOn(rgNetDomArgs, eCommRemove) ) {
  3059. if ( Ops ) {
  3060. BadOp = eCommRemove;
  3061. } else {
  3062. Ops++;
  3063. }
  3064. if ( CmdFlagOn(rgNetDomArgs, eTrustRealm) ) {
  3065. BadOp = eTrustRealm;
  3066. }
  3067. }
  3068. if ( CmdFlagOn(rgNetDomArgs, eCommVerify) ) {
  3069. if ( Ops ) {
  3070. BadOp = eCommVerify;
  3071. } else {
  3072. Ops++;
  3073. }
  3074. }
  3075. if (BadOp != eArgBegin) {
  3076. Win32Err = ERROR_INVALID_PARAMETER;
  3077. NetDompDisplayUnexpectedParameter(rgNetDomArgs[BadOp].strArg1);
  3078. goto HandleTrustExit;
  3079. }
  3080. if (!CmdFlagOn(rgNetDomArgs, eTrustNameSuffixes)) {
  3081. //
  3082. // Make sure that we have a specified domain (if not listing claimed names).
  3083. //
  3084. Win32Err = NetDompGetDomainForOperation(rgNetDomArgs,
  3085. NULL, // no server specified
  3086. FALSE, // don't default to current domain.
  3087. &TrustedDomain);
  3088. if ( Win32Err != ERROR_SUCCESS ) {
  3089. goto HandleTrustExit;
  3090. }
  3091. }
  3092. //
  3093. // Get the password and user if it exists
  3094. //
  3095. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameD) ) {
  3096. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  3097. eCommUserNameD,
  3098. TrustedDomain,
  3099. &TrustedDomainUser );
  3100. if ( Win32Err != ERROR_SUCCESS ) {
  3101. goto HandleTrustExit;
  3102. }
  3103. }
  3104. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameO) ) {
  3105. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  3106. eCommUserNameO,
  3107. TrustingDomain,
  3108. &TrustingDomainUser );
  3109. if ( Win32Err != ERROR_SUCCESS ) {
  3110. goto HandleTrustExit;
  3111. }
  3112. }
  3113. if ( CmdFlagOn(rgNetDomArgs, eCommAdd) ) {
  3114. if (CmdFlagOn(rgNetDomArgs, eTrustRealm))
  3115. {
  3116. // Get the trust PW.
  3117. //
  3118. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3119. eTrustPasswordT,
  3120. &pwzArgValue2);
  3121. if (ERROR_SUCCESS != Win32Err)
  3122. {
  3123. goto HandleTrustExit;
  3124. }
  3125. if (pwzArgValue2)
  3126. {
  3127. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  3128. TrustingDomain,
  3129. TrustedDomain,
  3130. &TrustingDomainUser,
  3131. &TrustedDomainUser,
  3132. pwzArgValue2,
  3133. NULL);
  3134. NetApiBufferFree(pwzArgValue2);
  3135. }
  3136. else
  3137. {
  3138. NetDompDisplayMessage(MSG_TRUST_PW_MISSING);
  3139. Win32Err = ERROR_INVALID_PARAMETER;
  3140. }
  3141. }
  3142. else if (CmdFlagOn(rgNetDomArgs, eTrustOneSide))
  3143. {
  3144. // Get the trust PW.
  3145. //
  3146. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3147. eTrustPasswordT,
  3148. &pwzArgValue2);
  3149. if (ERROR_SUCCESS != Win32Err)
  3150. {
  3151. goto HandleTrustExit;
  3152. }
  3153. if (!pwzArgValue2)
  3154. {
  3155. NetDompDisplayMessage(MSG_TRUST_PW_MISSING);
  3156. Win32Err = ERROR_INVALID_PARAMETER;
  3157. goto HandleTrustExit;
  3158. }
  3159. // Get the side on which to create the trust.
  3160. //
  3161. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3162. eTrustOneSide,
  3163. &pwzArgValue);
  3164. if (ERROR_SUCCESS != Win32Err)
  3165. {
  3166. NetApiBufferFree(pwzArgValue2);
  3167. goto HandleTrustExit;
  3168. }
  3169. if (!pwzArgValue)
  3170. {
  3171. NetDompDisplayMessage(MSG_ONESIDE_ARG_STRING);
  3172. Win32Err = ERROR_INVALID_PARAMETER;
  3173. NetApiBufferFree(pwzArgValue2);
  3174. goto HandleTrustExit;
  3175. }
  3176. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  3177. TrustingDomain,
  3178. TrustedDomain,
  3179. &TrustingDomainUser,
  3180. &TrustedDomainUser,
  3181. pwzArgValue2,
  3182. pwzArgValue);
  3183. NetApiBufferFree(pwzArgValue2);
  3184. }
  3185. else
  3186. {
  3187. Win32Err = NetDompCreateTrustObject( rgNetDomArgs,
  3188. TrustingDomain,
  3189. TrustedDomain,
  3190. &TrustingDomainUser,
  3191. &TrustedDomainUser,
  3192. NULL, NULL);
  3193. }
  3194. } else if ( CmdFlagOn(rgNetDomArgs, eCommRemove) ) {
  3195. Win32Err = NetDompRemoveTrustObject( rgNetDomArgs,
  3196. TrustingDomain,
  3197. TrustedDomain,
  3198. &TrustingDomainUser,
  3199. &TrustedDomainUser );
  3200. } else if ( CmdFlagOn(rgNetDomArgs, eCommReset) ) {
  3201. //
  3202. // See if a password is specifed
  3203. //
  3204. if (CmdFlagOn(rgNetDomArgs, eTrustPasswordT))
  3205. {
  3206. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3207. eTrustPasswordT,
  3208. &pwzArgValue2);
  3209. if (ERROR_SUCCESS != Win32Err)
  3210. {
  3211. goto HandleTrustExit;
  3212. }
  3213. if (pwzArgValue2)
  3214. {
  3215. Win32Err = NetDompSetMitTrustPW(TrustingDomain,
  3216. TrustedDomain,
  3217. &TrustingDomainUser,
  3218. &TrustedDomainUser,
  3219. pwzArgValue2);
  3220. NetApiBufferFree(pwzArgValue2);
  3221. }
  3222. else
  3223. {
  3224. Win32Err = ERROR_INVALID_PARAMETER;
  3225. }
  3226. }
  3227. else
  3228. {
  3229. Win32Err = NetDompResetTrustPasswords(TrustingDomain,
  3230. TrustedDomain,
  3231. &TrustingDomainUser,
  3232. &TrustedDomainUser);
  3233. }
  3234. } else if ( CmdFlagOn(rgNetDomArgs, eCommVerify ) ) {
  3235. Win32Err = NetDompVerifyTrustObject( rgNetDomArgs,
  3236. TrustingDomain,
  3237. TrustedDomain,
  3238. &TrustingDomainUser,
  3239. &TrustedDomainUser );
  3240. } else if ( CmdFlagOn(rgNetDomArgs, eTrustKerberos) ) {
  3241. Win32Err = NetDompVerifyIndividualTrustKerberos( TrustingDomain,
  3242. TrustedDomain,
  3243. &TrustingDomainUser,
  3244. &TrustedDomainUser );
  3245. } else if (CmdFlagOn(rgNetDomArgs, eTrustTransitive)) {
  3246. //
  3247. // Get the transitivity parameter
  3248. //
  3249. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3250. eTrustTransitive,
  3251. &pwzArgValue);
  3252. if (ERROR_SUCCESS != Win32Err)
  3253. {
  3254. goto HandleTrustExit;
  3255. }
  3256. Win32Err = NetDomTransitivity(pwzArgValue,
  3257. TrustingDomain,
  3258. TrustedDomain,
  3259. &TrustingDomainUser,
  3260. &TrustedDomainUser );
  3261. } else if (CmdFlagOn(rgNetDomArgs, eTrustFilterSIDs)) {
  3262. //
  3263. // Get the transitivity parameter
  3264. //
  3265. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3266. eTrustFilterSIDs,
  3267. &pwzArgValue);
  3268. if (ERROR_SUCCESS != Win32Err)
  3269. {
  3270. goto HandleTrustExit;
  3271. }
  3272. Win32Err = NetDomFilterSID(pwzArgValue,
  3273. TrustingDomain,
  3274. TrustedDomain,
  3275. &TrustingDomainUser,
  3276. &TrustedDomainUser );
  3277. } else if (CmdFlagOn(rgNetDomArgs, eTrustNameSuffixes)) {
  3278. //
  3279. // Get the name of the domain whose name is to be toggled.
  3280. //
  3281. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3282. eTrustNameSuffixes,
  3283. &pwzArgValue);
  3284. if (ERROR_SUCCESS != Win32Err)
  3285. {
  3286. goto HandleTrustExit;
  3287. }
  3288. if (CmdFlagOn(rgNetDomArgs, eTrustToggleSuffixes))
  3289. {
  3290. //
  3291. // Get the number of the name to toggle.
  3292. //
  3293. Win32Err = NetDompGetArgumentString(rgNetDomArgs,
  3294. eTrustToggleSuffixes,
  3295. &pwzArgValue2);
  3296. if (ERROR_SUCCESS != Win32Err)
  3297. {
  3298. goto HandleTrustExit;
  3299. }
  3300. if (!pwzArgValue2)
  3301. {
  3302. NetDompDisplayMessage(MSG_SUFFIX_INDEX_MISSING);
  3303. Win32Err = ERROR_INVALID_PARAMETER;
  3304. goto HandleTrustExit;
  3305. }
  3306. i = wcstoul(pwzArgValue2, L'\0', 10);
  3307. NetApiBufferFree(pwzArgValue2);
  3308. pwzArgValue2 = NULL;
  3309. if (1 > i)
  3310. {
  3311. NetDompDisplayMessage(MSG_SUFFIX_INDEX_BOUNDS);
  3312. Win32Err = ERROR_INVALID_PARAMETER;
  3313. goto HandleTrustExit;
  3314. }
  3315. Win32Err = NetDomForestSuffix(pwzArgValue,
  3316. i,
  3317. TrustingDomain,
  3318. &TrustingDomainUser);
  3319. }
  3320. else
  3321. {
  3322. Win32Err = NetDomForestSuffix(pwzArgValue,
  3323. 0,
  3324. TrustingDomain,
  3325. &TrustingDomainUser);
  3326. }
  3327. } else {
  3328. Win32Err = ERROR_INVALID_PARAMETER;
  3329. }
  3330. HandleTrustExit:
  3331. if (pwzArgValue)
  3332. {
  3333. NetApiBufferFree(pwzArgValue);
  3334. }
  3335. NetApiBufferFree( TrustedDomain );
  3336. NetDompFreeAuthIdent( &TrustedDomainUser );
  3337. NetDompFreeAuthIdent( &TrustingDomainUser );
  3338. if (NO_ERROR != Win32Err)
  3339. {
  3340. NetDompDisplayErrorMessage(Win32Err);
  3341. }
  3342. return( Win32Err );
  3343. }
  3344. DWORD
  3345. NetDompIsParentChild(
  3346. IN PND5_TRUST_INFO pFirstDomainInfo,
  3347. IN PND5_TRUST_INFO pSecondDomainInfo,
  3348. OUT BOOL * pfParentChild)
  3349. /*++
  3350. Routine Description:
  3351. Is the domain named by the second argument a child or parent of the first argument domain.
  3352. The Parent or Child bits of the trust-info Flags element is set as appropriate.
  3353. --*/
  3354. {
  3355. DWORD Win32Err;
  3356. PDS_DOMAIN_TRUSTS rgDomains = NULL;
  3357. ULONG ulCount = 0, i, ulLocalDomainIdx = (ULONG)-1, ulOtherDomainIdx = (ULONG)-1;
  3358. ULONG ulLocalDomainParent = (ULONG)-1, ulOtherDomainParent = (ULONG)-1;
  3359. PWSTR pwzServer, pwzOtherDomainDnsName, pwzOtherDomainNetbiosName;
  3360. BOOL fFirstIsLocal = TRUE;
  3361. *pfParentChild = FALSE;
  3362. // The domain which is used as the starting point for the enumeration is
  3363. // called the "local" domain and the remaining domain is the "other" domain.
  3364. //
  3365. if (pFirstDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND)
  3366. {
  3367. // The first domain does not exist, so use the second domain's server
  3368. // as the starting point for the domain enumeration.
  3369. //
  3370. pwzServer = pSecondDomainInfo->Server;
  3371. ASSERT(!(pSecondDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND));
  3372. pwzOtherDomainDnsName = pFirstDomainInfo->DomainName->Buffer;
  3373. pwzOtherDomainNetbiosName = pFirstDomainInfo->DomainName->Buffer;
  3374. fFirstIsLocal = FALSE;
  3375. }
  3376. else
  3377. {
  3378. // The first domain exists, so use its server as the starting point
  3379. // for the domain enumeration.
  3380. //
  3381. pwzServer = pFirstDomainInfo->Server;
  3382. pwzOtherDomainDnsName = pSecondDomainInfo->DomainName->Buffer;
  3383. pwzOtherDomainNetbiosName = (pSecondDomainInfo->Flags & NETDOM_TRUST_FLAG_DOMAIN_NOT_FOUND) ?
  3384. pSecondDomainInfo->DomainName->Buffer : pSecondDomainInfo->FlatName->Buffer;
  3385. }
  3386. ASSERT(pwzServer);
  3387. // Specifying DS_DOMAIN_IN_FOREST will eliminate any external trusts
  3388. // in the result set.
  3389. //
  3390. Win32Err = DsEnumerateDomainTrusts(pwzServer,
  3391. DS_DOMAIN_IN_FOREST,
  3392. &rgDomains,
  3393. &ulCount);
  3394. if (Win32Err != ERROR_SUCCESS)
  3395. {
  3396. return Win32Err;
  3397. }
  3398. for (i = 0; i < ulCount; i++)
  3399. {
  3400. ASSERT(rgDomains[i].TrustType & TRUST_TYPE_UPLEVEL);
  3401. if (rgDomains[i].Flags & DS_DOMAIN_PRIMARY)
  3402. {
  3403. ulLocalDomainIdx = i;
  3404. DBG_VERBOSE(("%2d: Local domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  3405. if (!(rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT))
  3406. {
  3407. DBG_VERBOSE(("\tParent index of above domain: %d\n", rgDomains[i].ParentIndex))
  3408. ulLocalDomainParent = rgDomains[i].ParentIndex;
  3409. }
  3410. else
  3411. {
  3412. DBG_VERBOSE(("\tThis domain is a tree root\n"))
  3413. }
  3414. continue;
  3415. }
  3416. #if DBG == 1
  3417. DBG_VERBOSE(("%2d: Domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  3418. if (rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT) DBG_VERBOSE(("\tThis domain is a tree root\n"))
  3419. else DBG_VERBOSE(("\tParent index of above domain: %d\n", rgDomains[i].ParentIndex))
  3420. #endif
  3421. if ((rgDomains[i].NetbiosDomainName && _wcsicmp(rgDomains[i].NetbiosDomainName, pwzOtherDomainNetbiosName) == 0) ||
  3422. (rgDomains[i].DnsDomainName && _wcsicmp(rgDomains[i].DnsDomainName, pwzOtherDomainDnsName) == 0))
  3423. {
  3424. ulOtherDomainIdx = i;
  3425. DBG_VERBOSE(("\tThis domain is the second domain\n"))
  3426. if (!(rgDomains[i].Flags & DS_DOMAIN_TREE_ROOT))
  3427. {
  3428. ulOtherDomainParent = rgDomains[i].ParentIndex;
  3429. }
  3430. continue;
  3431. }
  3432. #if DBG == 1
  3433. if (!(rgDomains[i].Flags & DS_DOMAIN_DIRECT_OUTBOUND))
  3434. {
  3435. DBG_VERBOSE(("%2d: Indirectly trusted domain: %ws (%ws)\n", i, rgDomains[i].DnsDomainName, rgDomains[i].NetbiosDomainName))
  3436. }
  3437. #endif
  3438. }
  3439. if (rgDomains)
  3440. {
  3441. NetApiBufferFree(rgDomains);
  3442. }
  3443. // Determine the relationship between the two domains. One of three
  3444. // situations will apply:
  3445. // 1. The local domain is the parent of the other domain. If true, then
  3446. // the parent index of the other domain will point to the local domain.
  3447. // In addition, the other domain cannot be a tree root.
  3448. // 2. The local domain is the child of the other domain. If true, then
  3449. // the parent index of the local domain will point to the other domain.
  3450. // The local domain then cannot be a tree root.
  3451. // 3. The two domains don't have a parent-child relationship. It must be
  3452. // a shortcut or external trust.
  3453. //
  3454. if (ulOtherDomainIdx == (ULONG)-1)
  3455. {
  3456. // Other domain not found, it must be a shortcut trust (case 3 above).
  3457. //
  3458. DBG_VERBOSE(("\n"))
  3459. return ERROR_SUCCESS;
  3460. }
  3461. if (ulLocalDomainParent == ulOtherDomainIdx)
  3462. {
  3463. // Case 2, the local domain is the child of the other domain.
  3464. //
  3465. if (fFirstIsLocal)
  3466. {
  3467. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  3468. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  3469. }
  3470. else
  3471. {
  3472. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  3473. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  3474. }
  3475. }
  3476. else
  3477. {
  3478. //
  3479. // Case 1 above, the local domain is the parent of the other domain.
  3480. //
  3481. if (fFirstIsLocal)
  3482. {
  3483. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  3484. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  3485. }
  3486. else
  3487. {
  3488. pSecondDomainInfo->Flags |= NETDOM_TRUST_FLAG_PARENT;
  3489. pFirstDomainInfo->Flags |= NETDOM_TRUST_FLAG_CHILD;
  3490. }
  3491. }
  3492. *pfParentChild = TRUE;
  3493. DBG_VERBOSE(("\tpfParentChild set to TRUE\n\n"))
  3494. return ERROR_SUCCESS;
  3495. }