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.

1467 lines
46 KiB

  1. // Trust.cpp : Implementation of CTrustMgrApp and DLL registration.
  2. #include "stdafx.h"
  3. //#import "\bin\McsVarSetMin.tlb" no_namespace, named_guids
  4. #import "VarSet.tlb" no_namespace, named_guids rename("property", "aproperty")
  5. #include "TrustMgr.h"
  6. #include "Trust.h"
  7. #include "Common.hpp"
  8. #include "UString.hpp"
  9. #include "ResStr.h"
  10. #include "ErrDct.hpp"
  11. #include "EaLen.hpp"
  12. #include "LSAUtils.h"
  13. #include <lm.h>
  14. #include <dsgetdc.h>
  15. #include <iads.h>
  16. #include <adshlp.h>
  17. #include "ntsecapi.h"
  18. #include "SecPI.h"
  19. #include "cipher.hpp"
  20. #ifndef TRUST_ATTRIBUTE_FOREST_TRANSITIVE
  21. #define TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0x00000008 // This link may contain forest trust information
  22. #endif
  23. StringLoader gString;
  24. TErrorDct err;
  25. // This method is called by the dispatcher to verify that this is a valid plug-in
  26. // Only valid plug-ins will be sent out with the agents
  27. // The purpose of this check is to make it more difficult for unauthorized parties
  28. // to use our plug-in interface, since it is currently undocumented.
  29. STDMETHODIMP CTrust::Verify(/*[in,out]*/ULONG * pData,/*[in]*/ULONG size)
  30. {
  31. McsChallenge * pMcsChallenge;
  32. long lTemp1;
  33. long lTemp2;
  34. if( size == sizeof(McsChallenge) )
  35. {
  36. pMcsChallenge = (McsChallenge*)(pData);
  37. SimpleCipher((LPBYTE)pMcsChallenge,size);
  38. pMcsChallenge->MCS[0] = 'M';
  39. pMcsChallenge->MCS[1] = 'C';
  40. pMcsChallenge->MCS[2] = 'S';
  41. pMcsChallenge->MCS[3] = 0;
  42. lTemp1 = pMcsChallenge->lRand1 + pMcsChallenge->lRand2;
  43. lTemp2 = pMcsChallenge->lRand2 - pMcsChallenge->lRand1;
  44. pMcsChallenge->lRand1 = lTemp1;
  45. pMcsChallenge->lRand2 = lTemp2;
  46. pMcsChallenge->lTime += 100;
  47. SimpleCipher((LPBYTE)pMcsChallenge,size);
  48. }
  49. else
  50. return E_FAIL;
  51. return S_OK;
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. //
  55. STDMETHODIMP CTrust::QueryTrust(BSTR domTrusting, BSTR domTrusted, IUnknown **pVarSet)
  56. {
  57. HRESULT hr = S_OK;
  58. return hr;
  59. }
  60. STDMETHODIMP CTrust::CreateTrust(BSTR domTrusting, BSTR domTrusted, BOOL bBidirectional)
  61. {
  62. HRESULT hr = S_OK;
  63. hr = CheckAndCreate(domTrusting,domTrusted,NULL,NULL,NULL,NULL,NULL,NULL,TRUE,bBidirectional);
  64. return HRESULT_FROM_WIN32(hr);
  65. }
  66. STDMETHODIMP
  67. CTrust::CreateTrustWithCreds(
  68. BSTR domTrusting,
  69. BSTR domTrusted,
  70. BSTR credTrustingDomain,
  71. BSTR credTrustingAccount,
  72. BSTR credTrustingPassword,
  73. BSTR credTrustedDomain,
  74. BSTR credTrustedAccount,
  75. BSTR credTrustedPassword,
  76. BOOL bBidirectional
  77. )
  78. {
  79. HRESULT hr = S_OK;
  80. hr = CheckAndCreate(domTrusting,domTrusted,credTrustingDomain,credTrustingAccount,credTrustingPassword,
  81. credTrustedDomain,credTrustedAccount,credTrustedPassword,TRUE,bBidirectional);
  82. return hr;
  83. }
  84. STDMETHODIMP CTrust::GetRegisterableFiles(/* [out] */SAFEARRAY ** pArray)
  85. {
  86. SAFEARRAYBOUND bound[1] = { 0, 0 };
  87. // this plug-in runs locally, no files to distribute
  88. (*pArray) = SafeArrayCreate(VT_BSTR,1,bound);
  89. return S_OK;
  90. }
  91. STDMETHODIMP CTrust::GetRequiredFiles(/* [out] */SAFEARRAY ** pArray)
  92. {
  93. SAFEARRAYBOUND bound[1] = { 0, 0 };
  94. // this plug-in runs locally, no files to distribute
  95. (*pArray) = SafeArrayCreate(VT_BSTR,1,bound);
  96. return S_OK;
  97. }
  98. STDMETHODIMP CTrust::GetDescription(/* [out] */ BSTR * description)
  99. {
  100. (*description) = SysAllocString(L"Sets up needed trusts between domains.");
  101. return S_OK;
  102. }
  103. BOOL IsDownLevel(WCHAR * sComputer)
  104. {
  105. BOOL bDownlevel = TRUE;
  106. WKSTA_INFO_100 * pInfo;
  107. long rc = NetWkstaGetInfo(sComputer,100,(LPBYTE*)&pInfo);
  108. if ( ! rc )
  109. {
  110. if ( pInfo->wki100_ver_major >= 5 )
  111. {
  112. bDownlevel = FALSE;
  113. }
  114. NetApiBufferFree(pInfo);
  115. }
  116. return bDownlevel;
  117. }
  118. // Helper function that finds a trusts in our varset list
  119. LONG CTrust::FindInboundTrust(IVarSet * pVarSet,WCHAR * sName,LONG max)
  120. {
  121. LONG ndx = -1;
  122. LONG curr = 0;
  123. WCHAR key[100];
  124. _bstr_t tName;
  125. for ( curr = 0 ; curr < max ; curr++ )
  126. {
  127. swprintf(key,L"Trusts.%ld",curr);
  128. tName = pVarSet->get(key);
  129. if ( ! UStrICmp(tName,sName) )
  130. {
  131. // found it!
  132. ndx = curr;
  133. break;
  134. }
  135. }
  136. return ndx;
  137. }
  138. HRESULT
  139. CTrust::CheckAndCreateTrustingSide(
  140. WCHAR * trustingDomain,
  141. WCHAR * trustedDomain,
  142. WCHAR * trustingComp,
  143. WCHAR * trustedComp,
  144. WCHAR * trustedDNSName,
  145. BYTE * trustedSid,
  146. BOOL bCreate,
  147. BOOL bBidirectional
  148. )
  149. {
  150. DWORD rc = S_OK;
  151. // if credentials are specified, use them
  152. LSA_HANDLE hTrusting = NULL;
  153. NTSTATUS status;
  154. LSA_AUTH_INFORMATION curr;
  155. LSA_AUTH_INFORMATION prev;
  156. WCHAR password[] = L"password";
  157. if ( ! rc && bCreate )
  158. {
  159. status = OpenPolicy(trustingComp,POLICY_VIEW_LOCAL_INFORMATION
  160. | POLICY_TRUST_ADMIN | POLICY_CREATE_SECRET,&hTrusting);
  161. rc = LsaNtStatusToWinError(status);
  162. if ( ! rc )
  163. {
  164. // set up the auth information for the trust relationship
  165. curr.AuthInfo = (LPBYTE)password;
  166. curr.AuthInfoLength = UStrLen(password) * sizeof(WCHAR);
  167. curr.AuthType = TRUST_AUTH_TYPE_CLEAR;
  168. curr.LastUpdateTime.QuadPart = 0;
  169. prev.AuthInfo = (LPBYTE)password;
  170. prev.AuthInfoLength = UStrLen(password) * sizeof(WCHAR);
  171. prev.AuthType = TRUST_AUTH_TYPE_CLEAR;
  172. prev.LastUpdateTime.QuadPart = 0;
  173. // set up the trusting side of the relationship
  174. if ( IsDownLevel(trustingComp) )
  175. {
  176. TRUSTED_DOMAIN_NAME_INFO nameInfo;
  177. InitLsaString(&nameInfo.Name,const_cast<WCHAR*>(trustedDomain));
  178. status = LsaSetTrustedDomainInformation(hTrusting,trustedSid,TrustedDomainNameInformation,&nameInfo);
  179. rc = LsaNtStatusToWinError(status);
  180. if ( ! rc || rc == ERROR_ALREADY_EXISTS )
  181. {
  182. // set the password for the new trust
  183. TRUSTED_PASSWORD_INFO pwdInfo;
  184. InitLsaString(&pwdInfo.Password,password);
  185. InitLsaString(&pwdInfo.OldPassword,NULL);
  186. status = LsaSetTrustedDomainInformation(hTrusting,trustedSid,TrustedPasswordInformation,&pwdInfo);
  187. rc = LsaNtStatusToWinError(status);
  188. }
  189. }
  190. else
  191. {
  192. // for Win2K domain, use LsaCreateTrustedDomainEx
  193. // to create the trustedDomain object.
  194. LSA_UNICODE_STRING sTemp;
  195. TRUSTED_DOMAIN_INFORMATION_EX trustedInfo;
  196. TRUSTED_DOMAIN_AUTH_INFORMATION trustAuth;
  197. InitLsaString(&sTemp, const_cast<WCHAR*>(trustedDomain));
  198. trustedInfo.FlatName = sTemp;
  199. InitLsaString(&sTemp, trustedDNSName);
  200. trustedInfo.Name = sTemp;
  201. trustedInfo.Sid = trustedSid;
  202. if ( IsDownLevel(trustedComp) )
  203. {
  204. trustedInfo.TrustAttributes = TRUST_TYPE_DOWNLEVEL;
  205. }
  206. else
  207. {
  208. trustedInfo.TrustAttributes = 0;
  209. }
  210. if ( bBidirectional )
  211. trustedInfo.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  212. else
  213. trustedInfo.TrustDirection = TRUST_DIRECTION_OUTBOUND;
  214. trustedInfo.TrustType = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  215. trustAuth.IncomingAuthInfos = bBidirectional ? 1 : 0;
  216. trustAuth.OutgoingAuthInfos = 1;
  217. trustAuth.IncomingAuthenticationInformation = bBidirectional ? &curr : NULL;
  218. trustAuth.IncomingPreviousAuthenticationInformation = NULL;
  219. trustAuth.OutgoingAuthenticationInformation = &curr;
  220. trustAuth.OutgoingPreviousAuthenticationInformation = NULL;
  221. LSA_HANDLE hTemp = NULL;
  222. status = LsaCreateTrustedDomainEx( hTrusting, &trustedInfo, &trustAuth, 0, &hTemp );
  223. rc = LsaNtStatusToWinError(status);
  224. // if the trust already exists, update its password
  225. if ( status == STATUS_OBJECT_NAME_COLLISION )
  226. {
  227. TRUSTED_DOMAIN_INFORMATION_EX * pTrustedInfo = NULL;
  228. status = LsaQueryTrustedDomainInfo(hTrusting,trustedSid,TrustedDomainInformationEx,(LPVOID*)&pTrustedInfo);
  229. if ( ! status )
  230. {
  231. pTrustedInfo->TrustDirection |= trustedInfo.TrustDirection;
  232. status = LsaSetTrustedDomainInfoByName(hTrusting,&trustedInfo.Name,TrustedDomainInformationEx,(LPVOID*)pTrustedInfo);
  233. if ( ! status )
  234. {
  235. status = LsaSetTrustedDomainInfoByName(hTrusting,&trustedInfo.Name,TrustedDomainAuthInformation,(LPVOID*)&trustAuth);
  236. }
  237. }
  238. rc = LsaNtStatusToWinError(status);
  239. }
  240. if( ! rc )
  241. {
  242. if (hTemp)
  243. LsaClose(hTemp);
  244. }
  245. }
  246. }
  247. }
  248. if ( hTrusting )
  249. LsaClose(hTrusting);
  250. return rc;
  251. }
  252. HRESULT
  253. CTrust::CheckAndCreateTrustedSide(
  254. WCHAR * trustingDomain,
  255. WCHAR * trustedDomain,
  256. WCHAR * trustingComp,
  257. WCHAR * trustedComp,
  258. WCHAR * trustingDNSName,
  259. BYTE * trustingSid,
  260. BOOL bCreate,
  261. BOOL bBidirectional
  262. )
  263. {
  264. DWORD rc = S_OK;
  265. LSA_HANDLE hTrusted = NULL;
  266. LSA_HANDLE hTrusting = NULL;
  267. NTSTATUS status;
  268. LSA_AUTH_INFORMATION curr;
  269. LSA_AUTH_INFORMATION prev;
  270. WCHAR password[] = L"password";
  271. // if credentials are specified, use them
  272. // open an LSA handle to the trusted domain
  273. status = OpenPolicy(trustedComp,POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN | POLICY_CREATE_SECRET,&hTrusted);
  274. rc = LsaNtStatusToWinError(status);
  275. if ( ! rc )
  276. {
  277. // set up the auth information for the trust relationship
  278. curr.AuthInfo = (LPBYTE)password;
  279. curr.AuthInfoLength = UStrLen(password) * sizeof(WCHAR);
  280. curr.AuthType = TRUST_AUTH_TYPE_CLEAR;
  281. curr.LastUpdateTime.QuadPart = 0;
  282. prev.AuthInfo = (LPBYTE)password;
  283. prev.AuthInfoLength = UStrLen(password) * sizeof(WCHAR);
  284. prev.AuthType = TRUST_AUTH_TYPE_CLEAR;
  285. prev.LastUpdateTime.QuadPart = 0;
  286. // set up the trusted side of the relationship
  287. if ( IsDownLevel(trustedComp) )
  288. {
  289. // create an inter-domain trust account for the trusting domain on the trusted domain
  290. USER_INFO_1 uInfo;
  291. DWORD parmErr;
  292. WCHAR name[LEN_Account];
  293. memset(&uInfo,0,(sizeof uInfo));
  294. UStrCpy(name,trustingDomain);
  295. name[UStrLen(name) + 1] = 0;
  296. name[UStrLen(name)] = L'$';
  297. if ( ! bCreate )
  298. {
  299. USER_INFO_1 * tempInfo = NULL;
  300. rc = NetUserGetInfo(trustedComp,name,1,(LPBYTE*)&tempInfo);
  301. if ( ! rc )
  302. {
  303. // the trust exists
  304. NetApiBufferFree(tempInfo);
  305. rc = NERR_UserExists;
  306. }
  307. else
  308. {
  309. if ( rc != NERR_UserNotFound )
  310. {
  311. err.SysMsgWrite(ErrE,rc,DCT_MSG_TRUSTING_DOM_GETINFO_FAILED_SSD,trustingDomain,trustedComp,rc);
  312. }
  313. }
  314. }
  315. else
  316. {
  317. // this creates the trust account if it doesn't already exist
  318. // if the account does exist, reset its password
  319. uInfo.usri1_flags = UF_SCRIPT | UF_INTERDOMAIN_TRUST_ACCOUNT;
  320. uInfo.usri1_name = name;
  321. uInfo.usri1_password = password;
  322. uInfo.usri1_priv = 1;
  323. rc = NetUserAdd(trustedComp,1,(LPBYTE)&uInfo,&parmErr);
  324. if ( rc && rc != NERR_UserExists )
  325. {
  326. err.SysMsgWrite(ErrE,rc,DCT_MSG_TRUSTING_DOM_CREATE_FAILED_SSD,trustingDomain,trustedDomain,rc);
  327. }
  328. else if ( rc == NERR_UserExists )
  329. {
  330. // reset the password for the existing trust account
  331. USER_INFO_1003 pwdInfo;
  332. DWORD parmErr;
  333. pwdInfo.usri1003_password = password;
  334. rc = NetUserSetInfo(trustedComp,name,1003,(LPBYTE)&pwdInfo,&parmErr);
  335. }
  336. }
  337. }
  338. else
  339. {
  340. // Win2K, all trusts exist as trusted domain objects
  341. // Create the trustedDomain object.
  342. LSA_UNICODE_STRING sTemp;
  343. TRUSTED_DOMAIN_INFORMATION_EX trustedInfo;
  344. TRUSTED_DOMAIN_AUTH_INFORMATION trustAuth;
  345. InitLsaString(&sTemp, const_cast<WCHAR*>(trustingDomain));
  346. trustedInfo.FlatName = sTemp;
  347. InitLsaString(&sTemp, trustingDNSName);
  348. trustedInfo.Name = sTemp;
  349. trustedInfo.Sid = trustingSid;
  350. if ( IsDownLevel(trustingComp) )
  351. {
  352. trustedInfo.TrustAttributes = TRUST_TYPE_DOWNLEVEL;
  353. }
  354. else
  355. {
  356. trustedInfo.TrustAttributes = 0;
  357. }
  358. if ( bBidirectional )
  359. trustedInfo.TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
  360. else
  361. trustedInfo.TrustDirection = TRUST_DIRECTION_INBOUND;
  362. trustedInfo.TrustType = TRUST_ATTRIBUTE_NON_TRANSITIVE;
  363. trustAuth.IncomingAuthInfos = 1;
  364. trustAuth.OutgoingAuthInfos = bBidirectional ? 1 : 0;
  365. trustAuth.OutgoingAuthenticationInformation = bBidirectional ? &curr : NULL;
  366. trustAuth.OutgoingPreviousAuthenticationInformation = NULL;
  367. trustAuth.IncomingAuthenticationInformation = &curr;
  368. trustAuth.IncomingPreviousAuthenticationInformation = NULL;
  369. if ( bCreate )
  370. {
  371. status = LsaCreateTrustedDomainEx( hTrusted, &trustedInfo, &trustAuth, POLICY_VIEW_LOCAL_INFORMATION |
  372. POLICY_TRUST_ADMIN | POLICY_CREATE_SECRET, &hTrusting );
  373. if ( status == STATUS_OBJECT_NAME_COLLISION )
  374. {
  375. TRUSTED_DOMAIN_INFORMATION_EX * pTrustedInfo = NULL;
  376. // Get the old information
  377. status = LsaQueryTrustedDomainInfoByName(hTrusted,&sTemp,TrustedDomainInformationEx,(LPVOID*)&pTrustedInfo);
  378. if ( ! status )
  379. {
  380. pTrustedInfo->TrustAttributes |= trustedInfo.TrustAttributes;
  381. pTrustedInfo->TrustDirection |= trustedInfo.TrustDirection;
  382. status = LsaSetTrustedDomainInfoByName(hTrusted,&sTemp,TrustedDomainInformationEx,pTrustedInfo);
  383. if (! status )
  384. {
  385. status = LsaSetTrustedDomainInfoByName(hTrusted,&sTemp,TrustedDomainAuthInformation,&trustAuth);
  386. }
  387. LsaFreeMemory(pTrustedInfo);
  388. }
  389. }
  390. }
  391. else
  392. {
  393. TRUSTED_DOMAIN_INFORMATION_EX * pTrustedInfo = NULL;
  394. status = LsaQueryTrustedDomainInfoByName(hTrusted,&sTemp,TrustedDomainInformationEx,(LPVOID*)&pTrustedInfo);
  395. if ( ! status )
  396. {
  397. LsaFreeMemory(pTrustedInfo);
  398. }
  399. }
  400. rc = LsaNtStatusToWinError(status);
  401. if ( ! rc )
  402. {
  403. LsaClose(hTrusting);
  404. hTrusting = NULL;
  405. }
  406. }
  407. if ( bCreate && bBidirectional && IsDownLevel(trustingComp) )
  408. {
  409. // set up the trust account for the other side of the relationship
  410. // For Win2K, both sides of the bidirectional trust are handled together,
  411. // but NT4 bidirectional trusts require 2 separate actions
  412. USER_INFO_1 uInfo;
  413. DWORD parmErr;
  414. WCHAR name2[LEN_Account];
  415. memset(&uInfo,0,(sizeof uInfo));
  416. UStrCpy(name2,trustedDomain);
  417. name2[UStrLen(name2) + 1] = 0;
  418. name2[UStrLen(name2)] = L'$';
  419. uInfo.usri1_flags = UF_SCRIPT | UF_INTERDOMAIN_TRUST_ACCOUNT;
  420. uInfo.usri1_name = name2;
  421. uInfo.usri1_password = password;
  422. uInfo.usri1_priv = 1;
  423. rc = NetUserAdd(trustingComp,1,(LPBYTE)&uInfo,&parmErr);
  424. if ( rc == NERR_UserExists )
  425. {
  426. LPUSER_INFO_1 puInfo;
  427. rc = NetUserGetInfo(trustingComp, name2, 1, (LPBYTE*)&puInfo);
  428. if ( !rc )
  429. {
  430. puInfo->usri1_flags &= UF_INTERDOMAIN_TRUST_ACCOUNT;
  431. puInfo->usri1_password = password;
  432. rc = NetUserSetInfo(trustingComp,name2,1,(LPBYTE)puInfo,&parmErr);
  433. NetApiBufferFree(puInfo);
  434. }
  435. else
  436. {
  437. err.MsgWrite(0, DCT_MSG_INVALID_ACCOUNT_S, name2);
  438. }
  439. }
  440. else if ( rc )
  441. {
  442. err.SysMsgWrite(ErrE,rc,DCT_MSG_TRUSTING_DOM_CREATE_FAILED_SSD,trustingDomain,trustedDomain,rc);
  443. }
  444. }
  445. }
  446. else
  447. {
  448. err.SysMsgWrite(ErrE,rc,DCT_MSG_LSA_OPEN_FAILED_SD,trustedComp,rc);
  449. }
  450. if( hTrusted )
  451. LsaClose(hTrusted);
  452. return rc;
  453. }
  454. // Helper function that gets DNS and NETBIOS domain names
  455. void GetDnsAndNetbiosFromName(WCHAR const * name,WCHAR * netBios, WCHAR * dns)
  456. {
  457. IADs * pDomain = NULL;
  458. WCHAR strText[1000];
  459. _bstr_t distinguishedName;
  460. // try to connect to the AD, using the specified name
  461. swprintf(strText,L"LDAP://%ls",name);
  462. netBios[0] = 0;
  463. dns[0] = 0;
  464. HRESULT hr = ADsGetObject(strText,IID_IADs,(void**)&pDomain);
  465. if ( SUCCEEDED(hr) )
  466. {
  467. _variant_t var;
  468. // get the DNS name from the LDAP provider
  469. hr = pDomain->Get(L"distinguishedName",&var);
  470. if ( SUCCEEDED(hr) )
  471. {
  472. WCHAR * dn = (WCHAR*)var.bstrVal;
  473. WCHAR * curr = dns;
  474. distinguishedName = dn;
  475. if ( !UStrICmp(dn,L"DC=",3) )
  476. {
  477. // for each ",DC=" in the name, replace it with a .
  478. for ( curr = dns, dn = dn+3 ; // skip the leading "DC="
  479. *dn ; // until the end of the string is reached
  480. curr++ //
  481. )
  482. {
  483. if ( (L',' == *dn) && (L'D' == *(dn+1)) && (L'C' == *(dn+2)) && (L'=' == *(dn+3)) )
  484. {
  485. (*curr) = L'.';
  486. dn+=4;
  487. }
  488. else
  489. {
  490. // just copy the character
  491. (*curr) = (*dn);
  492. dn++;
  493. }
  494. }
  495. *(curr) = 0;
  496. }
  497. // get the NETBIOS name from the LDAP provider
  498. hr = pDomain->Get(L"nETBIOSName",&var);
  499. if ( SUCCEEDED(hr) )
  500. {
  501. UStrCpy(netBios,(WCHAR*)var.bstrVal);
  502. }
  503. else
  504. {
  505. // currently, the netbiosName property is not filled in
  506. // so we will use a different method to get the flat-name for the domain
  507. // Here is our strategy to get the netbios name:
  508. // Enumerate the partitions container under the configuration container
  509. // look for a CrossRef object whose nCName property matches the distinguished name
  510. // we have for the domain. This object's CN property is the flat-name for the domain
  511. // get the name of the configuration container
  512. IADs * pDSE = NULL;
  513. swprintf(strText,L"LDAP://%ls/RootDSE",name);
  514. hr = ADsGetObject(strText,IID_IADs,(void**)&pDSE);
  515. if ( SUCCEEDED(hr) )
  516. {
  517. hr = pDSE->Get(L"configurationNamingContext",&var);
  518. if ( SUCCEEDED(hr) )
  519. {
  520. IADsContainer * pPart = NULL;
  521. swprintf(strText,L"LDAP://%ls/CN=Partitions,%ls",name,var.bstrVal);
  522. hr = ADsGetObject(strText,IID_IADsContainer,(void**)&pPart);
  523. if ( SUCCEEDED(hr) )
  524. {
  525. IUnknown * pUnk = NULL;
  526. IEnumVARIANT * pEnum = NULL;
  527. IADs * pItem = NULL;
  528. ULONG lFetch = 0;
  529. // enumerate the contents of the Partitions container
  530. hr = pPart->get__NewEnum(&pUnk);
  531. if ( SUCCEEDED(hr) )
  532. {
  533. hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
  534. pUnk->Release();
  535. }
  536. if ( SUCCEEDED(hr) )
  537. {
  538. hr = pEnum->Next(1,&var,&lFetch);
  539. }
  540. while ( hr == S_OK )
  541. {
  542. if (lFetch == 1 )
  543. {
  544. IDispatch * pDisp = V_DISPATCH(&var);
  545. BSTR bstr;
  546. if ( pDisp )
  547. {
  548. hr = pDisp->QueryInterface(IID_IADs, (void**)&pItem);
  549. pDisp->Release();
  550. if ( SUCCEEDED(hr) )
  551. {
  552. hr = pItem->get_Class(&bstr);
  553. if ( !UStrICmp(bstr,L"crossRef") )
  554. {
  555. // see if this is the one we are looking for
  556. hr = pItem->Get(L"nCName",&var);
  557. if ( SUCCEEDED(hr) )
  558. {
  559. if ( !UStrICmp(var.bstrVal,(WCHAR*)distinguishedName) )
  560. {
  561. // this is the one we want!
  562. hr = pItem->Get(L"cn",&var);
  563. if ( SUCCEEDED(hr) )
  564. {
  565. UStrCpy(netBios,var.bstrVal);
  566. pItem->Release();
  567. SysFreeString(bstr);
  568. break;
  569. }
  570. }
  571. }
  572. }
  573. SysFreeString(bstr);
  574. pItem->Release();
  575. }
  576. }
  577. }
  578. hr = pEnum->Next(1, &var, &lFetch);
  579. }
  580. pPart->Release();
  581. if ( pEnum )
  582. pEnum->Release();
  583. }
  584. }
  585. pDSE->Release();
  586. }
  587. }
  588. }
  589. pDomain->Release();
  590. }
  591. else
  592. {
  593. // default to using the specified name as both DNS and NETBIOS
  594. // this will work for NT 4 domains
  595. UStrCpy(netBios,name);
  596. UStrCpy(dns,name);
  597. }
  598. if ( ! (*netBios) )
  599. {
  600. UStrCpy(netBios,name);
  601. WCHAR * temp = wcschr(netBios,L'.');
  602. if ( temp )
  603. *temp = 0;
  604. }
  605. if (! (*dns) )
  606. {
  607. UStrCpy(dns,name);
  608. }
  609. }
  610. // Main function used to create trusts
  611. HRESULT
  612. CTrust::CheckAndCreate(
  613. WCHAR * trustingDomain,
  614. WCHAR * trustedDomain,
  615. WCHAR * credDomainTrusting,
  616. WCHAR * credAccountTrusting,
  617. WCHAR * credPasswordTrusting,
  618. WCHAR * credDomainTrusted,
  619. WCHAR * credAccountTrusted,
  620. WCHAR * credPasswordTrusted,
  621. BOOL bCreate,
  622. BOOL bBidirectional
  623. )
  624. {
  625. // HRESULT hr = S_OK;
  626. DWORD rc = 0;
  627. WCHAR trustingDom[LEN_Domain];
  628. WCHAR trustedDom[LEN_Domain];
  629. WCHAR trustingComp[LEN_Computer];
  630. WCHAR trustedComp[LEN_Computer];
  631. WCHAR trustingDNSName[LEN_Path];
  632. WCHAR trustedDNSName[LEN_Path];
  633. BYTE trustingSid[200];
  634. BYTE trustedSid[200];
  635. WCHAR name[LEN_Account];
  636. DWORD lenName = DIM(name);
  637. DWORD lenSid = DIM(trustingSid);
  638. SID_NAME_USE snu;
  639. DOMAIN_CONTROLLER_INFO * pInfo;
  640. WCHAR * curr = NULL;
  641. BOOL bConnectTrusted = FALSE;
  642. BOOL bConnectTrusting = FALSE;
  643. // Get the DC names, and domain SIDs for the source and target domains
  644. GetDnsAndNetbiosFromName(trustingDomain,trustingDom,trustingDNSName);
  645. GetDnsAndNetbiosFromName(trustedDomain,trustedDom,trustedDNSName);
  646. // make sure the NETBIOS domain names are in lower case
  647. for ( curr = trustingDom ; *curr ; curr++ )
  648. {
  649. (*curr) = towupper(*curr);
  650. }
  651. for ( curr = trustedDom ; *curr ; curr++ )
  652. {
  653. (*curr) = towupper(*curr);
  654. }
  655. rc = DsGetDcName(NULL, trustingDom, NULL, NULL, DS_PDC_REQUIRED, &pInfo);
  656. if ( !rc )
  657. {
  658. wcscpy(trustingComp,pInfo->DomainControllerName);
  659. //wcscpy(trustingDNSName,pInfo->DomainName);
  660. NetApiBufferFree(pInfo);
  661. }
  662. else
  663. {
  664. err.SysMsgWrite(ErrE,rc,DCT_MSG_GET_DCNAME_FAILED_SD,trustingDom,rc);
  665. }
  666. if ( ! rc )
  667. {
  668. rc = DsGetDcName(NULL, trustedDom, NULL, NULL, DS_PDC_REQUIRED, &pInfo);
  669. if ( !rc )
  670. {
  671. wcscpy(trustedComp,pInfo->DomainControllerName);
  672. // wcscpy(trustedDNSName,pInfo->DomainName);
  673. NetApiBufferFree(pInfo);
  674. }
  675. else
  676. {
  677. err.SysMsgWrite(ErrE,rc,DCT_MSG_GET_DCNAME_FAILED_SD,trustedDom,rc);
  678. }
  679. }
  680. if ( credAccountTrusted && *credAccountTrusted )
  681. {
  682. if ( EstablishSession(trustedComp,credDomainTrusted,credAccountTrusted,credPasswordTrusted,TRUE) )
  683. {
  684. bConnectTrusted = TRUE;
  685. }
  686. else
  687. {
  688. rc = GetLastError();
  689. }
  690. }
  691. if ( credAccountTrusting && *credAccountTrusting )
  692. {
  693. if ( EstablishSession(trustingComp,credDomainTrusting,credAccountTrusting,credPasswordTrusting,TRUE) )
  694. {
  695. bConnectTrusting = TRUE;
  696. }
  697. else
  698. {
  699. rc = GetLastError();
  700. }
  701. }
  702. // Need to get the computer name and the SIDs for the domains.
  703. if ( ! rc && ! LookupAccountName(trustingComp,trustingDom,trustingSid,&lenSid,name,&lenName,&snu) )
  704. {
  705. rc = GetLastError();
  706. err.SysMsgWrite(ErrE,rc,DCT_MSG_GET_DOMAIN_SID_FAILED_1,trustingDom,rc);
  707. }
  708. lenSid = DIM(trustedSid);
  709. lenName = DIM(name);
  710. if (! rc && ! LookupAccountName(trustedComp,trustedDom,trustedSid,&lenSid,name,&lenName,&snu) )
  711. {
  712. rc = GetLastError();
  713. err.SysMsgWrite(ErrE,rc,DCT_MSG_GET_DOMAIN_SID_FAILED_1,trustedDom,rc);
  714. }
  715. // check the trusted side of the trust first
  716. if ( ! rc )
  717. {
  718. rc = CheckAndCreateTrustedSide(trustingDom,trustedDom,trustingComp,trustedComp,trustingDNSName,trustingSid,
  719. bCreate,bBidirectional);
  720. }
  721. if ( ! rc )
  722. {
  723. rc = CheckAndCreateTrustingSide(trustingDom,trustedDom,trustingComp,trustedComp,trustedDNSName,trustedSid,
  724. bCreate,bBidirectional);
  725. }
  726. if ( bConnectTrusted )
  727. {
  728. EstablishSession(trustedComp,credDomainTrusted,credAccountTrusted,credPasswordTrusted,FALSE);
  729. }
  730. if ( bConnectTrusting )
  731. {
  732. EstablishSession(trustingComp,credDomainTrusting,credAccountTrusting,credPasswordTrusting,FALSE);
  733. }
  734. return HRESULT_FROM_WIN32(rc);
  735. }
  736. long CTrust::EnumerateTrustedDomains(WCHAR * domain,BOOL bIsTarget,IVarSet * pVarSet,long ndxStart)
  737. {
  738. DWORD rcOs; // OS return code
  739. LSA_HANDLE hPolicy;
  740. NTSTATUS status;
  741. WCHAR computer[LEN_Computer];
  742. DOMAIN_CONTROLLER_INFO * pInfo;
  743. WCHAR sName[LEN_Domain];
  744. WCHAR key[100];
  745. long ndxTrust = ndxStart;
  746. /* PDS_DOMAIN_TRUSTS *ChildDomains;
  747. ULONG numChilds;
  748. */
  749. err.MsgWrite(0,DCT_MSG_ENUMERATING_TRUSTED_DOMAINS_S,domain);
  750. // open a handle to the source domain
  751. rcOs = DsGetDcName(NULL, domain, NULL, NULL, 0, &pInfo);
  752. if ( !rcOs )
  753. {
  754. wcscpy(computer,pInfo->DomainControllerName);
  755. NetApiBufferFree(pInfo);
  756. }
  757. else
  758. {
  759. err.SysMsgWrite(ErrE,rcOs,DCT_MSG_GET_DCNAME_FAILED_SD,domain,rcOs);
  760. }
  761. if ( ! rcOs )
  762. {
  763. if ( IsDownLevel(computer) )
  764. {
  765. //Enumerate the trusted domains until there are no more to return.
  766. status = OpenPolicy(computer,POLICY_ALL_ACCESS | POLICY_VIEW_LOCAL_INFORMATION ,&hPolicy);
  767. if ( status == STATUS_SUCCESS )
  768. {
  769. LSA_ENUMERATION_HANDLE lsaEnumHandle=0; // start an enum
  770. PLSA_TRUST_INFORMATION trustInfo = NULL;
  771. ULONG ulReturned; // number of items returned
  772. NTSTATUS status;
  773. DWORD rc;
  774. do {
  775. status = LsaEnumerateTrustedDomains(
  776. hPolicy, // open policy handle
  777. &lsaEnumHandle, // enumeration tracker
  778. (void**)&trustInfo, // buffer to receive data
  779. 32000, // recommended buffer size
  780. &ulReturned // number of items returned
  781. );
  782. //Check the return status for error.
  783. rc = LsaNtStatusToWinError(status);
  784. if( (rc != ERROR_SUCCESS) &&
  785. (rc != ERROR_MORE_DATA) &&
  786. (rc != ERROR_NO_MORE_ITEMS)
  787. )
  788. {
  789. err.SysMsgWrite(ErrE,rcOs,DCT_MSG_TRUSTED_ENUM_FAILED_SD,domain,rcOs);
  790. }
  791. else
  792. {
  793. // . . . Code to use the Trusted Domain information
  794. for ( ULONG ndx = 0 ; ndx < ulReturned ; ndx++ )
  795. {
  796. _bstr_t direction;
  797. UStrCpy(sName,trustInfo[ndx].Name.Buffer, ( trustInfo[ndx].Name.Length / (sizeof WCHAR)) + 1);
  798. TRUSTED_DOMAIN_INFORMATION_EX * pTrustedInfo = NULL;
  799. status = LsaQueryTrustedDomainInfo(hPolicy,trustInfo[ndx].Sid,TrustedDomainInformationEx,(LPVOID*)&pTrustedInfo);
  800. if ( ! status )
  801. {
  802. switch ( pTrustedInfo->TrustDirection )
  803. {
  804. case TRUST_DIRECTION_DISABLED:
  805. direction = GET_BSTR(IDS_TRUST_DIRECTION_DISABLED);
  806. break;
  807. case TRUST_DIRECTION_INBOUND:
  808. direction = GET_BSTR(IDS_TRUST_DIRECTION_INBOUND);
  809. break;
  810. case TRUST_DIRECTION_OUTBOUND:
  811. direction = GET_BSTR(IDS_TRUST_DIRECTION_OUTBOUND);
  812. break;
  813. case TRUST_DIRECTION_BIDIRECTIONAL:
  814. direction = GET_BSTR(IDS_TRUST_DIRECTION_BIDIRECTIONAL);
  815. break;
  816. default:
  817. break;
  818. };
  819. if ( ! bIsTarget )
  820. {
  821. swprintf(key,L"Trusts.%ld.Type",ndxTrust);
  822. pVarSet->put(key, GET_BSTR(IDS_TRUST_RELATION_EXTERNAL));
  823. }
  824. LsaFreeMemory(pTrustedInfo);
  825. }
  826. else
  827. {
  828. rcOs = LsaNtStatusToWinError(status);
  829. // My logic here is that we are checking Trusted domains here so this is atleast true
  830. // check whether this trust is already listed as an inbound trust
  831. //* direction = L"Outbound";
  832. direction = GET_BSTR(IDS_TRUST_DIRECTION_OUTBOUND);
  833. }
  834. if ( ! bIsTarget )
  835. {
  836. swprintf(key,L"Trusts.%ld",ndxTrust);
  837. pVarSet->put(key,sName);
  838. swprintf(key,L"Trusts.%ld.Direction",ndxTrust);
  839. pVarSet->put(key,direction);
  840. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndxTrust);
  841. //* pVarSet->put(key,L"No");
  842. pVarSet->put(key,GET_BSTR(IDS_No));
  843. err.MsgWrite(0,DCT_MSG_SOURCE_TRUSTS_THIS_SS,sName,domain);
  844. }
  845. long ndx2 = FindInboundTrust(pVarSet,sName,ndxTrust);
  846. if ( ndx2 != -1 )
  847. {
  848. if ( ! bIsTarget )
  849. {
  850. // we've already seen this trust as an inbound trust
  851. // update the existing record!
  852. WCHAR key2[1000];
  853. swprintf(key2,L"Trusts.%ld.Direction",ndx2);
  854. //* pVarSet->put(key2,L"Bidirectional");
  855. pVarSet->put(key2,GET_BSTR(IDS_TRUST_DIRECTION_BIDIRECTIONAL));
  856. continue; // don't update the trust entry index, since we used the existing
  857. // entry instead of creating a new one
  858. }
  859. else
  860. {
  861. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndx2);
  862. //* pVarSet->put(key,L"Yes");
  863. pVarSet->put(key,GET_BSTR(IDS_YES));
  864. err.MsgWrite(0,DCT_MSG_TARGET_TRUSTS_THIS_SS,domain,sName);
  865. }
  866. }
  867. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndxTrust);
  868. // check the trusted domain, to see if the target already trusts it
  869. //if ( UStrICmp(sName,target) )
  870. // {
  871. // continue;
  872. // }
  873. if ( ! bIsTarget )
  874. ndxTrust++;
  875. }
  876. // Free the buffer.
  877. LsaFreeMemory(trustInfo);
  878. }
  879. } while (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA );
  880. LsaClose(hPolicy);
  881. }
  882. }
  883. else
  884. {
  885. ULONG ulCount;
  886. PDS_DOMAIN_TRUSTS pDomainTrusts;
  887. DWORD dwError = DsEnumerateDomainTrusts(
  888. computer,
  889. DS_DOMAIN_IN_FOREST|DS_DOMAIN_DIRECT_INBOUND|DS_DOMAIN_DIRECT_OUTBOUND,
  890. &pDomainTrusts,
  891. &ulCount
  892. );
  893. if (dwError == NO_ERROR)
  894. {
  895. ULONG ulIndex;
  896. ULONG ulDomainIndex = (ULONG)-1L;
  897. ULONG ulParentIndex = (ULONG)-1L;
  898. // find local domain
  899. for (ulIndex = 0; ulIndex < ulCount; ulIndex++)
  900. {
  901. if (pDomainTrusts[ulIndex].Flags & DS_DOMAIN_PRIMARY)
  902. {
  903. ulDomainIndex = ulIndex;
  904. if (!(pDomainTrusts[ulIndex].Flags & DS_DOMAIN_TREE_ROOT))
  905. {
  906. ulParentIndex = pDomainTrusts[ulIndex].ParentIndex;
  907. }
  908. break;
  909. }
  910. }
  911. for (ulIndex = 0; ulIndex < ulCount; ulIndex++)
  912. {
  913. DS_DOMAIN_TRUSTS& rDomainTrust = pDomainTrusts[ulIndex];
  914. // filter out indirect trusts
  915. if (!(rDomainTrust.Flags & (DS_DOMAIN_DIRECT_INBOUND|DS_DOMAIN_DIRECT_OUTBOUND)))
  916. {
  917. continue;
  918. }
  919. // trusted or trusting domain name
  920. _bstr_t bstrName(rDomainTrust.NetbiosDomainName);
  921. // trust direction
  922. _bstr_t bstrDirection;
  923. switch (rDomainTrust.Flags & (DS_DOMAIN_DIRECT_INBOUND|DS_DOMAIN_DIRECT_OUTBOUND))
  924. {
  925. case DS_DOMAIN_DIRECT_INBOUND:
  926. bstrDirection = GET_BSTR(IDS_TRUST_DIRECTION_INBOUND);
  927. break;
  928. case DS_DOMAIN_DIRECT_OUTBOUND:
  929. bstrDirection = GET_BSTR(IDS_TRUST_DIRECTION_OUTBOUND);
  930. break;
  931. case DS_DOMAIN_DIRECT_INBOUND|DS_DOMAIN_DIRECT_OUTBOUND:
  932. bstrDirection = GET_BSTR(IDS_TRUST_DIRECTION_BIDIRECTIONAL);
  933. break;
  934. default:
  935. // bstrDirection = ;
  936. break;
  937. }
  938. // trust relationship
  939. _bstr_t bstrRelationship;
  940. if (ulIndex == ulParentIndex)
  941. {
  942. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_PARENT);
  943. }
  944. else if (rDomainTrust.Flags & DS_DOMAIN_IN_FOREST)
  945. {
  946. if (rDomainTrust.ParentIndex == ulDomainIndex)
  947. {
  948. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_CHILD);
  949. }
  950. else if ((rDomainTrust.Flags & DS_DOMAIN_TREE_ROOT) && (pDomainTrusts[ulDomainIndex].Flags & DS_DOMAIN_TREE_ROOT))
  951. {
  952. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_ROOT);
  953. }
  954. else
  955. {
  956. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_SHORTCUT);
  957. }
  958. }
  959. else
  960. {
  961. switch (rDomainTrust.TrustType)
  962. {
  963. case TRUST_TYPE_DOWNLEVEL:
  964. case TRUST_TYPE_UPLEVEL:
  965. bstrRelationship = (rDomainTrust.TrustAttributes & TRUST_ATTRIBUTE_FOREST_TRANSITIVE) ? GET_BSTR(IDS_TRUST_RELATION_FOREST) : GET_BSTR(IDS_TRUST_RELATION_EXTERNAL);
  966. break;
  967. case TRUST_TYPE_MIT:
  968. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_MIT);
  969. break;
  970. case TRUST_TYPE_DCE:
  971. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_DCE);
  972. break;
  973. default:
  974. bstrRelationship = GET_BSTR(IDS_TRUST_RELATION_UNKNOWN);
  975. break;
  976. }
  977. }
  978. if (bIsTarget)
  979. {
  980. // if same trust was found on source domain and the trust
  981. // directions match update exists for target to yes
  982. LONG lSourceIndex = FindInboundTrust(pVarSet, bstrName, ndxTrust);
  983. if (lSourceIndex >= 0)
  984. {
  985. // get source trust direction
  986. swprintf(key, L"Trusts.%ld.Direction", lSourceIndex);
  987. _bstr_t bstrSourceDirection = pVarSet->get(key);
  988. // if target trust direction is bi-directional or
  989. // target trust direction equals source trust direction
  990. // then set exists for target to yes
  991. bool bExists = false;
  992. if (bstrDirection == GET_BSTR(IDS_TRUST_DIRECTION_BIDIRECTIONAL))
  993. {
  994. bExists = true;
  995. }
  996. else if (bstrDirection == bstrSourceDirection)
  997. {
  998. bExists = true;
  999. }
  1000. if (bExists)
  1001. {
  1002. swprintf(key, L"Trusts.%ld.ExistsForTarget", lSourceIndex);
  1003. pVarSet->put(key, GET_BSTR(IDS_YES));
  1004. // write trust directions to log
  1005. if (rDomainTrust.Flags & DS_DOMAIN_DIRECT_OUTBOUND)
  1006. {
  1007. err.MsgWrite(0, DCT_MSG_TARGET_TRUSTS_THIS_SS, domain, (LPCTSTR)bstrName);
  1008. }
  1009. if (rDomainTrust.Flags & DS_DOMAIN_DIRECT_INBOUND)
  1010. {
  1011. err.MsgWrite(0, DCT_MSG_TARGET_TRUSTED_BY_THIS_SS, domain, (LPCTSTR)bstrName);
  1012. }
  1013. }
  1014. }
  1015. }
  1016. else
  1017. {
  1018. // domain name
  1019. swprintf(key, L"Trusts.%ld", ndxTrust);
  1020. pVarSet->put(key, bstrName);
  1021. // trust direction
  1022. swprintf(key, L"Trusts.%ld.Direction", ndxTrust);
  1023. pVarSet->put(key, bstrDirection);
  1024. // trust relationship
  1025. if (bstrRelationship.length() > 0)
  1026. {
  1027. swprintf(key, L"Trusts.%ld.Type", ndxTrust);
  1028. pVarSet->put(key, bstrRelationship);
  1029. }
  1030. // trust exists on target
  1031. // initially set to no until target domain is enumerated
  1032. swprintf(key, L"Trusts.%ld.ExistsForTarget", ndxTrust);
  1033. pVarSet->put(key, GET_BSTR(IDS_No));
  1034. // write trust directions to log
  1035. if (rDomainTrust.Flags & DS_DOMAIN_DIRECT_OUTBOUND)
  1036. {
  1037. err.MsgWrite(0, DCT_MSG_SOURCE_TRUSTS_THIS_SS, (LPCTSTR)bstrName, domain);
  1038. }
  1039. if (rDomainTrust.Flags & DS_DOMAIN_DIRECT_INBOUND)
  1040. {
  1041. err.MsgWrite(0, DCT_MSG_SOURCE_IS_TRUSTED_BY_THIS_SS, (LPCTSTR)bstrName, domain);
  1042. }
  1043. ++ndxTrust;
  1044. }
  1045. }
  1046. NetApiBufferFree(pDomainTrusts);
  1047. }
  1048. else
  1049. {
  1050. err.SysMsgWrite(ErrE, dwError, DCT_MSG_TRUSTED_ENUM_FAILED_SD, domain, dwError);
  1051. }
  1052. }
  1053. }
  1054. if ( bIsTarget )
  1055. {
  1056. // make sure we have "Yes" for the target domain itself
  1057. long ndx2 = FindInboundTrust(pVarSet,domain,ndxTrust);
  1058. if ( ndx2 != -1 )
  1059. {
  1060. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndx2);
  1061. //* pVarSet->put(key,L"Yes");
  1062. pVarSet->put(key,GET_BSTR(IDS_YES));
  1063. }
  1064. }
  1065. return ndxTrust;
  1066. }
  1067. long CTrust::EnumerateTrustingDomains(WCHAR * domain,BOOL bIsTarget,IVarSet * pVarSet,long ndxStart)
  1068. {
  1069. DWORD rcOs; // OS return code
  1070. DWORD hEnum=0; // enumeration handle
  1071. USER_INFO_1 * pNetUsers=NULL; // NetUserEnum array buffer
  1072. USER_INFO_1 * pNetUser; // NetUserEnum array item
  1073. DWORD nRead; // Entries read.
  1074. DWORD nTotal; // Entries total.
  1075. WCHAR sName[LEN_Domain]; // Domain name
  1076. WCHAR * pNameEnd; // Null at end
  1077. WCHAR computer[LEN_Computer];
  1078. DOMAIN_CONTROLLER_INFO * pInfo;
  1079. long ndx = ndxStart;
  1080. WCHAR key[100];
  1081. err.MsgWrite(0,DCT_MSG_ENUMERATING_TRUSTING_DOMAINS_S,domain);
  1082. do
  1083. {
  1084. rcOs = DsGetDcName(NULL, domain, NULL, NULL, 0, &pInfo);
  1085. if ( !rcOs )
  1086. {
  1087. wcscpy(computer,pInfo->DomainControllerName);
  1088. NetApiBufferFree(pInfo);
  1089. }
  1090. else
  1091. {
  1092. break;
  1093. }
  1094. // get the trusting domains for the NT 4 domain
  1095. // for Win2K domains, the trusting domains will be listed as Incoming in the Trusted Domain enumeration
  1096. if ( IsDownLevel(computer) )
  1097. {
  1098. nRead = 0;
  1099. nTotal = 0;
  1100. rcOs = NetUserEnum(
  1101. computer,
  1102. 1,
  1103. FILTER_INTERDOMAIN_TRUST_ACCOUNT,
  1104. (BYTE **) &pNetUsers,
  1105. 10240,
  1106. &nRead,
  1107. &nTotal,
  1108. &hEnum );
  1109. switch ( rcOs )
  1110. {
  1111. case 0:
  1112. case ERROR_MORE_DATA:
  1113. for ( pNetUser = pNetUsers;
  1114. pNetUser < pNetUsers + nRead;
  1115. pNetUser++ )
  1116. {
  1117. // skip trust accounts whose password age is older than 30 days to avoid
  1118. // delays caused by trying to enumerate defunct trusts
  1119. if ( pNetUser->usri1_password_age > 60 * 60 * 24 * 30 ) // 30 days (age is in seconds)
  1120. {
  1121. err.MsgWrite(0,DCT_MSG_SKIPPING_OLD_TRUST_SD,pNetUser->usri1_name,
  1122. pNetUser->usri1_password_age / ( 60*60*24) );
  1123. continue;
  1124. }
  1125. safecopy( sName, pNetUser->usri1_name );
  1126. pNameEnd = sName + UStrLen( sName );
  1127. if ( (pNameEnd > sName) && (pNameEnd[-1] == L'$') )
  1128. {
  1129. pNameEnd[-1] = L'\0';
  1130. }
  1131. if ( *sName )
  1132. {
  1133. // Found a (probably) valid trust!
  1134. if ( ! bIsTarget )
  1135. {
  1136. // for the source domain, simply add the trusts to the list in the varset
  1137. swprintf(key,L"Trusts.%ld",ndx);
  1138. pVarSet->put(key,sName);
  1139. swprintf(key,L"Trusts.%ld.Direction",ndx);
  1140. //* pVarSet->put(key,L"Inbound");
  1141. pVarSet->put(key,GET_BSTR(IDS_TRUST_DIRECTION_INBOUND));
  1142. swprintf(key,L"Trusts.%ld.Type",ndx);
  1143. pVarSet->put(key, GET_BSTR(IDS_TRUST_RELATION_EXTERNAL));
  1144. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndx);
  1145. //* pVarSet->put(key,L"No");
  1146. pVarSet->put(key,GET_BSTR(IDS_No));
  1147. err.MsgWrite(0,DCT_MSG_SOURCE_IS_TRUSTED_BY_THIS_SS,sName,domain);
  1148. ndx++;
  1149. }
  1150. else
  1151. {
  1152. // for the target domain, look for this trust in the varset
  1153. // and if it is there, mark that it exists on the target
  1154. long ndxTemp = FindInboundTrust(pVarSet,sName,ndxStart);
  1155. if ( ndxTemp != -1 )
  1156. {
  1157. swprintf(key,L"Trusts.%ld.ExistsForTarget",ndxTemp);
  1158. //* pVarSet->put(key,L"Yes");
  1159. pVarSet->put(key,GET_BSTR(IDS_YES));
  1160. err.MsgWrite(0,DCT_MSG_TARGET_TRUSTS_THIS_SS,sName,domain);
  1161. }
  1162. }
  1163. }
  1164. }
  1165. break;
  1166. default:
  1167. break;
  1168. }
  1169. if ( pNetUsers )
  1170. {
  1171. NetApiBufferFree( pNetUsers );
  1172. pNetUsers = NULL;
  1173. }
  1174. }
  1175. else // if IsDownLevel()
  1176. {
  1177. // Win2K domain, don't need to enumerate the trusting domains here - they will all be included in the
  1178. // trusted domain enum
  1179. break;
  1180. }
  1181. } while ( rcOs == ERROR_MORE_DATA );
  1182. return ndx;
  1183. }
  1184. /*void CheckProc(void * arg,void * data)
  1185. {
  1186. CTrust * tr = (CTrust*)arg;
  1187. }*/
  1188. STDMETHODIMP CTrust::PreMigrationTask(/* [in] */IUnknown * pVarSet)
  1189. {
  1190. /* IVarSetPtr pVS = pVarSet;
  1191. BOOL bCreate;
  1192. _bstr_t source = pVS->get(GET_BSTR(DCTVS_Options_SourceDomain));
  1193. _bstr_t target = pVS->get(GET_BSTR(DCTVS_Options_TargetDomain));
  1194. _bstr_t logfile = pVS->get(GET_BSTR(DCTVS_Options_Logfile));
  1195. _bstr_t localOnly = pVS->get(GET_BSTR(DCTVS_Options_LocalProcessingOnly));
  1196. _bstr_t docreate = pVS->get(L"Options.CreateTrusts");
  1197. if ( !UStrICmp(localOnly,GET_STRING(IDS_YES)) )
  1198. {
  1199. // don't do anything in local agent mode
  1200. return S_OK;
  1201. }
  1202. if ( !UStrICmp(docreate,GET_STRING(IDS_YES)) )
  1203. {
  1204. bCreate = TRUE;
  1205. }
  1206. else
  1207. {
  1208. bCreate = FALSE;
  1209. }
  1210. pVS->put(GET_BSTR(DCTVS_CurrentOperation),L"Verifying trust relationships");
  1211. err.LogOpen(logfile,1);
  1212. err.LevelBeepSet(1000);
  1213. err.LogClose();
  1214. */
  1215. return S_OK;
  1216. }
  1217. STDMETHODIMP CTrust::PostMigrationTask(/* [in] */IUnknown * pVarSet)
  1218. {
  1219. return S_OK;
  1220. }
  1221. STDMETHODIMP CTrust::GetName(/* [out] */BSTR * name)
  1222. {
  1223. (*name) = SysAllocString(L"Trust Manager");
  1224. return S_OK;
  1225. }
  1226. STDMETHODIMP CTrust::GetResultString(/* [in] */IUnknown * pVarSet,/* [out] */ BSTR * text)
  1227. {
  1228. WCHAR buffer[100] = L"";
  1229. IVarSetPtr pVS;
  1230. pVS = pVarSet;
  1231. (*text) = SysAllocString(buffer);
  1232. return S_OK;
  1233. }
  1234. STDMETHODIMP CTrust::StoreResults(/* [in] */IUnknown * pVarSet)
  1235. {
  1236. return S_OK;
  1237. }
  1238. STDMETHODIMP CTrust::ConfigureSettings(/*[in]*/IUnknown * pVarSet)
  1239. {
  1240. return S_OK;
  1241. }
  1242. STDMETHODIMP CTrust::QueryTrusts(BSTR domainSource,BSTR domainTarget, BSTR sLogFile, IUnknown **pVarSet)
  1243. {
  1244. HRESULT hr = S_OK;
  1245. IVarSetPtr pVS(CLSID_VarSet);
  1246. long ndx;
  1247. _bstr_t sFile = sLogFile;
  1248. err.LogOpen((WCHAR*) sFile, 1);
  1249. err.LevelBeepSet(1000);
  1250. hr = pVS.QueryInterface(IID_IUnknown,(long**)pVarSet);
  1251. // Add a blank line to help differentiate different runs
  1252. err.MsgWrite(0,DCT_MSG_GENERIC_S,L"");
  1253. ndx = EnumerateTrustingDomains(domainSource,FALSE,pVS,0);
  1254. EnumerateTrustingDomains(domainTarget,TRUE,pVS,0);
  1255. ndx = EnumerateTrustedDomains(domainSource,FALSE,pVS,ndx);
  1256. EnumerateTrustedDomains(domainTarget,TRUE,pVS,ndx);
  1257. //err.LogClose();
  1258. pVS->put(L"Trusts",ndx);
  1259. return hr;
  1260. }