Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

603 lines
17 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows 2000 Active Directory Service domain trust verification WMI provider
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 2000
  7. //
  8. // File: domain.cpp
  9. //
  10. // Contents: domain class implementation
  11. //
  12. // Classes: CDomainInfo
  13. //
  14. // History: 27-Mar-00 EricB created
  15. //
  16. //-----------------------------------------------------------------------------
  17. #include <stdafx.h>
  18. PCWSTR CSTR_PROP_LOCAL_DNS_NAME = L"DNSname"; // String
  19. PCWSTR CSTR_PROP_LOCAL_FLAT_NAME = L"FlatName"; // String
  20. PCWSTR CSTR_PROP_LOCAL_SID = L"SID"; // String
  21. PCWSTR CSTR_PROP_LOCAL_TREE_NAME = L"TreeName"; // String
  22. PCWSTR CSTR_PROP_LOCAL_DC_NAME = L"DCname"; // String
  23. // TODO: string property listing the FSMOs owned by this DC?
  24. //Implementaion of CDomainInfo class
  25. //+----------------------------------------------------------------------------
  26. //
  27. // Class: CDomainInfo
  28. //
  29. //-----------------------------------------------------------------------------
  30. CDomainInfo::CDomainInfo()
  31. {
  32. TRACE(L"CDomainInfo::CDomainInfo\n");
  33. m_liLastEnumed.QuadPart = 0;
  34. }
  35. CDomainInfo::~CDomainInfo()
  36. {
  37. TRACE(L"CDomainInfo::~CDomainInfo\n");
  38. Reset();
  39. }
  40. //+----------------------------------------------------------------------------
  41. //
  42. // Method: CDomainInfo::Init
  43. //
  44. // Synopsis: Initializes the CDomainInfo object.
  45. //
  46. //-----------------------------------------------------------------------------
  47. HRESULT
  48. CDomainInfo::Init(IWbemClassObject * pClassDef)
  49. {
  50. TRACE(L"CDomainInfo::Init\n");
  51. NTSTATUS Status = STATUS_SUCCESS;
  52. OBJECT_ATTRIBUTES objectAttributes;
  53. CSmartPolicyHandle chPolicy;
  54. m_sipClassDefLocalDomain = pClassDef;
  55. InitializeObjectAttributes(&objectAttributes, NULL, 0L, NULL, NULL);
  56. // Get Local policy
  57. Status = LsaOpenPolicy(NULL, // Local server
  58. &objectAttributes,
  59. MAXIMUM_ALLOWED, // Needed for Rediscover
  60. &chPolicy);
  61. if (!NT_SUCCESS(Status))
  62. {
  63. TRACE(L"LsaOpenPolicy failed with error %d\n", Status);
  64. return HRESULT_FROM_WIN32(LsaNtStatusToWinError(Status));
  65. }
  66. PPOLICY_DNS_DOMAIN_INFO pDnsDomainInfo;
  67. Status = LsaQueryInformationPolicy(chPolicy,
  68. PolicyDnsDomainInformation,
  69. (PVOID *)&pDnsDomainInfo);
  70. if (!NT_SUCCESS(Status))
  71. {
  72. TRACE(L"LsaQueryInformationPolicy failed with error %d\n", Status);
  73. return HRESULT_FROM_WIN32(LsaNtStatusToWinError(Status));
  74. }
  75. m_strDomainFlatName = pDnsDomainInfo->Name.Buffer;
  76. m_strDomainDnsName = pDnsDomainInfo->DnsDomainName.Buffer;
  77. m_strForestName = pDnsDomainInfo->DnsForestName.Buffer;
  78. if (!SetSid(pDnsDomainInfo->Sid))
  79. {
  80. ASSERT(false);
  81. LsaFreeMemory(pDnsDomainInfo);
  82. return E_OUTOFMEMORY;
  83. }
  84. LsaFreeMemory(pDnsDomainInfo);
  85. DWORD dwBufSize = MAX_COMPUTERNAME_LENGTH + 1;
  86. if (!GetComputerName(m_strDcName.GetBuffer(dwBufSize), &dwBufSize))
  87. {
  88. DWORD dwErr = GetLastError();
  89. TRACE(L"GetComputerName failed with error %d\n", dwErr);
  90. return HRESULT_FROM_WIN32(dwErr);
  91. }
  92. m_strDcName.ReleaseBuffer();
  93. return S_OK;
  94. }
  95. //+----------------------------------------------------------------------------
  96. //
  97. // Method: CDomainInfo::Reset
  98. //
  99. // Synopsis: Free the contents of the trust array and re-initialize it.
  100. //
  101. //-----------------------------------------------------------------------------
  102. void
  103. CDomainInfo::Reset(void)
  104. {
  105. TRACE(L"CDomainInfo::Reset\n");
  106. CTrustInfo * pTrustInfo = NULL;
  107. if (IsEnumerated())
  108. {
  109. // Empty cache
  110. for (UINT i = 0; i < m_vectTrustInfo.size(); ++i)
  111. {
  112. pTrustInfo = m_vectTrustInfo[i];
  113. if (pTrustInfo)
  114. delete pTrustInfo;
  115. }
  116. m_vectTrustInfo.clear();
  117. }
  118. }
  119. //+----------------------------------------------------------------------------
  120. //
  121. // Method: CDomainInfo::SetSid
  122. //
  123. //-----------------------------------------------------------------------------
  124. BOOL
  125. CDomainInfo::SetSid(PSID pSid)
  126. {
  127. if (!pSid)
  128. {
  129. return TRUE;
  130. }
  131. #if !defined(NT4_BUILD)
  132. PWSTR buffer;
  133. BOOL fRet = ConvertSidToStringSid(pSid, &buffer);
  134. if (fRet)
  135. {
  136. m_strSid = buffer;
  137. LocalFree(buffer);
  138. }
  139. return fRet;
  140. #else
  141. // TODO: Code for NT4 ??
  142. #endif
  143. }
  144. //+----------------------------------------------------------------------------
  145. //
  146. // Method: CDomainInfo::EnumerateTrusts
  147. //
  148. // Synopsis: List the trusts for this domain.
  149. //
  150. //-----------------------------------------------------------------------------
  151. #if !defined(NT4_BUILD)
  152. HRESULT
  153. CDomainInfo::EnumerateTrusts(void)
  154. {
  155. TRACE(L"CDomainInfo::EnumerateTrusts\n");
  156. DWORD dwRet = ERROR_SUCCESS;
  157. CTrustInfo * pTrustInfo = NULL;
  158. PDS_DOMAIN_TRUSTS rgTrusts = NULL;
  159. ULONG nTrustCount = 0;
  160. Reset();
  161. dwRet = DsEnumerateDomainTrusts(NULL,
  162. DS_DOMAIN_DIRECT_OUTBOUND |
  163. DS_DOMAIN_DIRECT_INBOUND,
  164. &rgTrusts,
  165. &nTrustCount);
  166. if (ERROR_SUCCESS != dwRet)
  167. {
  168. TRACE(L"DsEnumerateDomainTrusts failed with error %d\n", dwRet);
  169. return HRESULT_FROM_WIN32(dwRet);
  170. }
  171. for (ULONG i = 0; i < nTrustCount; i++)
  172. {
  173. pTrustInfo = new CTrustInfo();
  174. if (!pTrustInfo)
  175. {
  176. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  177. break;
  178. }
  179. if (rgTrusts[i].DnsDomainName)
  180. {
  181. // Downlevel domains don't have a DNS name.
  182. //
  183. pTrustInfo->SetTrustedDomain(rgTrusts[i].DnsDomainName);
  184. }
  185. else
  186. {
  187. // So use the flat name instead.
  188. //
  189. pTrustInfo->SetTrustedDomain(rgTrusts[i].NetbiosDomainName);
  190. }
  191. pTrustInfo->SetFlatName(rgTrusts[i].NetbiosDomainName);
  192. if (!pTrustInfo->SetSid(rgTrusts[i].DomainSid))
  193. {
  194. // NTRAID#NTBUG9-582047-2002/05/15-ericb
  195. delete pTrustInfo;
  196. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  197. break;
  198. }
  199. pTrustInfo->SetTrustType(rgTrusts[i].TrustType);
  200. pTrustInfo->SetTrustDirectionFromFlags(rgTrusts[i].Flags);
  201. pTrustInfo->SetTrustAttributes(rgTrusts[i].TrustAttributes);
  202. pTrustInfo->SetFlags(rgTrusts[i].Flags);
  203. // NTRAID#NTBUG9-582047-2002/05/15-ericb
  204. try
  205. {
  206. m_vectTrustInfo.push_back(pTrustInfo);
  207. }
  208. catch (...)
  209. {
  210. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  211. delete pTrustInfo;
  212. break;
  213. }
  214. pTrustInfo = NULL;
  215. }
  216. if (rgTrusts)
  217. {
  218. NetApiBufferFree(rgTrusts);
  219. }
  220. if (ERROR_SUCCESS == dwRet)
  221. {
  222. SYSTEMTIME st;
  223. GetSystemTime(&st);
  224. SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
  225. }
  226. return HRESULT_FROM_WIN32(dwRet);
  227. }
  228. #else // NT4_BUILD
  229. HRESULT
  230. CDomainInfo::EnumerateTrusts(void)
  231. {
  232. TRACE(L"CDomainInfo::EnumerateTrusts\n");
  233. NTSTATUS Status = STATUS_SUCCESS;
  234. DWORD dwErr = ERROR_SUCCESS;
  235. ULONG i = 0;
  236. CTrustInfo * pTrustInfo = NULL;
  237. Reset();
  238. LSA_ENUMERATION_HANDLE hEnumContext = NULL;
  239. ULONG nTrustCount = 0;
  240. ULONG nTotalCount = 0;
  241. ULONG j = 0;
  242. PLSA_TRUST_INFORMATION pTrustDomainInfo = NULL;
  243. DWORD hResumeHandle = 0;
  244. LPUSER_INFO_0 pUserList = NULL;
  245. CTrustInfo * pTempTrustInfo = NULL;
  246. LPWSTR Lop = NULL;
  247. CSmartPolicyHandle chPolicy;
  248. OBJECT_ATTRIBUTES objectAttributes;
  249. InitializeObjectAttributes(&objectAttributes, NULL, 0L, NULL, NULL);
  250. //
  251. // We'll have to do this the old fashioned way. That means that we'll enumerate all of
  252. // the trust directly, save them off in a list, and then go through and enumerate all
  253. // of the interdomain trust accounts and merge those into the list.
  254. //
  255. do
  256. {
  257. Status = LsaOpenPolicy(NULL, // Local server
  258. &objectAttributes,
  259. MAXIMUM_ALLOWED, // Needed for Rediscover
  260. &chPolicy);
  261. Status = LsaEnumerateTrustedDomains(chPolicy,
  262. &hEnumContext,
  263. (void**)&pTrustDomainInfo,
  264. ULONG_MAX,
  265. &nTrustCount );
  266. if (NT_SUCCESS(Status) || Status == STATUS_MORE_ENTRIES)
  267. {
  268. dwErr = ERROR_SUCCESS;
  269. for ( i = 0; i < nTrustCount; i++ )
  270. {
  271. pTrustInfo = new CTrustInfo();
  272. CHECK_NULL( pTrustInfo, CLEAN_RETURN );
  273. pTrustInfo->SetTrustedDomain( pTrustDomainInfo[i].Name.Buffer );
  274. pTrustInfo->SetFlatName( pTrustDomainInfo[i].Name.Buffer );
  275. pTrustInfo->SetSid( pTrustDomainInfo[i].Sid ); // SetSid currently not implemented for NT4
  276. pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
  277. pTrustInfo->SetTrustDirection( TRUST_DIRECTION_OUTBOUND );
  278. // NTRAID#NTBUG9-582047-2002/05/15-ericb
  279. try
  280. {
  281. m_vectTrustInfo.push_back( pTrustInfo );
  282. }
  283. catch (...)
  284. {
  285. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  286. delete pTrustInfo;
  287. goto CLEAN_RETURN;
  288. }
  289. pTrustInfo = NULL;
  290. }
  291. LsaFreeMemory( pTrustDomainInfo );
  292. pTrustDomainInfo = NULL;
  293. }
  294. else
  295. dwErr = LsaNtStatusToWinError(Status);
  296. } while (Status == STATUS_MORE_ENTRIES);
  297. if( Status == STATUS_NO_MORE_ENTRIES )
  298. dwErr = ERROR_SUCCESS;
  299. //
  300. // Now, let's add in the user accounts
  301. //
  302. if ( dwErr == ERROR_SUCCESS )
  303. {
  304. do
  305. {
  306. nTrustCount = 0;
  307. nTotalCount = 0;
  308. dwErr = NetUserEnum(NULL,
  309. 0,
  310. FILTER_INTERDOMAIN_TRUST_ACCOUNT,
  311. (LPBYTE *)&pUserList,
  312. MAX_PREFERRED_LENGTH,
  313. &nTrustCount,
  314. &nTotalCount,
  315. &hResumeHandle);
  316. if ( dwErr == ERROR_SUCCESS || dwErr == ERROR_MORE_DATA )
  317. {
  318. dwErr = ERROR_SUCCESS;
  319. for ( i = 0; i < nTrustCount; i++ )
  320. {
  321. Lop = wcsrchr( pUserList[ i ].usri0_name, L'$' );
  322. if ( Lop )
  323. {
  324. *Lop = UNICODE_NULL;
  325. }
  326. for ( j = 0; j < m_vectTrustInfo.size(); j++ )
  327. {
  328. pTempTrustInfo = m_vectTrustInfo[j];
  329. if ( _wcsicmp( pUserList[ i ].usri0_name, pTempTrustInfo->GetTrustedDomain() ) == 0 )
  330. {
  331. pTempTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND );
  332. break;
  333. }
  334. }
  335. // If it wasn't found, add it...
  336. if ( j == m_vectTrustInfo.size() )
  337. {
  338. pTrustInfo = new CTrustInfo();
  339. CHECK_NULL( pTrustInfo, CLEAN_RETURN );
  340. pTrustInfo->SetTrustedDomain( pUserList[ i ].usri0_name );
  341. pTrustInfo->SetFlatName( pUserList[ i ].usri0_name );
  342. pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
  343. pTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND );
  344. // NTRAID#NTBUG9-582047-2002/05/15-ericb
  345. try
  346. {
  347. m_vectTrustInfo.push_back( pTrustInfo );
  348. }
  349. catch (...)
  350. {
  351. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  352. delete pTrustInfo;
  353. goto CLEAN_RETURN;
  354. }
  355. pTrustInfo = NULL;
  356. }
  357. if ( Lop )
  358. {
  359. *Lop = L'$';
  360. }
  361. }
  362. NetApiBufferFree( pUserList );
  363. pUserList = NULL;
  364. }
  365. } while ( dwErr == ERROR_MORE_DATA );
  366. }
  367. CLEAN_RETURN:
  368. if( pUserList )
  369. NetApiBufferFree( pUserList );
  370. if( pTrustDomainInfo )
  371. LsaFreeMemory( pTrustDomainInfo );
  372. if (ERROR_SUCCESS == dwErr)
  373. {
  374. SYSTEMTIME st;
  375. GetSystemTime(&st);
  376. SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
  377. }
  378. return HRESULT_FROM_WIN32(dwErr);
  379. }
  380. #endif // NT4_BUILD
  381. //+----------------------------------------------------------------------------
  382. //
  383. // Method: CDomainInfo::FindTrust
  384. //
  385. // Synopsis: Find a trust by trusted Domain Name
  386. //
  387. //-----------------------------------------------------------------------------
  388. CTrustInfo *
  389. CDomainInfo::FindTrust(PCWSTR pwzTrust)
  390. {
  391. TRACE(L"CDomainInfo::FindTrust\n");
  392. TRACE(L"\nlooking for domain %s\n", pwzTrust);
  393. ASSERT(IsEnumerated());
  394. ULONG i = 0;
  395. for( i = 0; i < m_vectTrustInfo.size(); ++i )
  396. {
  397. int nStrComp = CompareString(LOCALE_SYSTEM_DEFAULT,
  398. NORM_IGNORECASE,
  399. (m_vectTrustInfo[i])->GetTrustedDomain(), -1,
  400. pwzTrust, -1 );
  401. ASSERT( nStrComp );
  402. if( CSTR_EQUAL == nStrComp )
  403. {
  404. TRACE(L"Trust found!\n");
  405. return m_vectTrustInfo[i];
  406. }
  407. }
  408. return NULL; // Not Found
  409. }
  410. //+----------------------------------------------------------------------------
  411. //
  412. // Method: CDomainInfo::GetTrustByIndex
  413. //
  414. // Synopsis: Get trust info by Index
  415. //
  416. //-----------------------------------------------------------------------------
  417. CTrustInfo *
  418. CDomainInfo::GetTrustByIndex(size_t index)
  419. {
  420. ASSERT(IsEnumerated());
  421. if (index < Size())
  422. {
  423. return m_vectTrustInfo[index];
  424. }
  425. else
  426. {
  427. ASSERT(FALSE);
  428. return NULL;
  429. }
  430. }
  431. //+----------------------------------------------------------------------------
  432. //
  433. // Method: CDomainInfo::IsTrustListStale
  434. //
  435. // Synopsis: Checks to see if the last emumeration time is older than the
  436. // passed in criteria.
  437. //
  438. // Returns: TRUE if older.
  439. //
  440. // Notes: If the trusts haven't been enumerated (m_liLastEnumed == 0),
  441. // then the enumeration is defined to be stale.
  442. //
  443. //-----------------------------------------------------------------------------
  444. BOOL
  445. CDomainInfo::IsTrustListStale(LARGE_INTEGER liMaxAge)
  446. {
  447. TRACE(L"CDomainInfo::IsTrustListStale(0x%08x), MaxAge = %d\n",
  448. this, liMaxAge.QuadPart / TRUSTMON_FILETIMES_PER_MINUTE);
  449. BOOL fStale = FALSE;
  450. LARGE_INTEGER liCurrentTime;
  451. SYSTEMTIME st;
  452. GetSystemTime(&st);
  453. SystemTimeToFileTime(&st, (LPFILETIME)&liCurrentTime);
  454. fStale = (m_liLastEnumed.QuadPart + liMaxAge.QuadPart) < liCurrentTime.QuadPart;
  455. return fStale;
  456. }
  457. //+----------------------------------------------------------------------------
  458. //
  459. // Method: CDomainInfo::CreateAndSendInst
  460. //
  461. // Synopsis: Returns a copy of the current instance back to WMI
  462. //
  463. //-----------------------------------------------------------------------------
  464. HRESULT
  465. CDomainInfo::CreateAndSendInst(IWbemObjectSink * pResponseHandler)
  466. {
  467. TRACE(L"CDomainInfo::CreateAndSendInst\n");
  468. HRESULT hr = WBEM_S_NO_ERROR;
  469. do
  470. {
  471. CComPtr<IWbemClassObject> ipNewInst;
  472. CComVariant var;
  473. //
  474. // Create a new instance of the WMI class object
  475. //
  476. hr = m_sipClassDefLocalDomain->SpawnInstance(0, &ipNewInst);
  477. BREAK_ON_FAIL;
  478. // Set the DNS property value
  479. var = GetDnsName();
  480. hr = ipNewInst->Put(CSTR_PROP_LOCAL_DNS_NAME, 0, &var, 0);
  481. TRACE(L"\tCreating instance %s\n", var.bstrVal);
  482. BREAK_ON_FAIL;
  483. // Set the flat name property value
  484. var = GetFlatName();
  485. hr = ipNewInst->Put(CSTR_PROP_LOCAL_FLAT_NAME, 0, &var, 0);
  486. TRACE(L"\twith flat name %s\n", var.bstrVal);
  487. BREAK_ON_FAIL;
  488. // Set the SID property value
  489. var = GetSid();
  490. hr = ipNewInst->Put(CSTR_PROP_LOCAL_SID, 0, &var, 0);
  491. TRACE(L"\twith SID %s\n", var.bstrVal);
  492. BREAK_ON_FAIL;
  493. // Set the forest name property value
  494. var = GetForestName();
  495. hr = ipNewInst->Put(CSTR_PROP_LOCAL_TREE_NAME, 0, &var, 0);
  496. TRACE(L"\twith forest name %s\n", var.bstrVal);
  497. BREAK_ON_FAIL;
  498. // Set the DC name property value
  499. var = GetDcName();
  500. hr = ipNewInst->Put(CSTR_PROP_LOCAL_DC_NAME, 0, &var, 0);
  501. TRACE(L"\ton DC %s\n", var.bstrVal);
  502. BREAK_ON_FAIL;
  503. //
  504. // Send the object to the caller
  505. //
  506. // [In] param, no need to addref.
  507. IWbemClassObject * pNewInstance = ipNewInst;
  508. hr = pResponseHandler->Indicate(1, &pNewInstance);
  509. BREAK_ON_FAIL;
  510. } while(FALSE);
  511. return hr;
  512. }