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.

563 lines
16 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. BREAK_ON_NULL(pTrustInfo);
  175. if (rgTrusts[i].DnsDomainName)
  176. {
  177. // Downlevel domains don't have a DNS name.
  178. //
  179. pTrustInfo->SetTrustedDomain(rgTrusts[i].DnsDomainName);
  180. }
  181. else
  182. {
  183. // So use the flat name instead.
  184. //
  185. pTrustInfo->SetTrustedDomain(rgTrusts[i].NetbiosDomainName);
  186. }
  187. pTrustInfo->SetFlatName(rgTrusts[i].NetbiosDomainName);
  188. BREAK_ON_NULL(pTrustInfo->SetSid(rgTrusts[i].DomainSid));
  189. pTrustInfo->SetTrustType(rgTrusts[i].TrustType);
  190. pTrustInfo->SetTrustDirectionFromFlags(rgTrusts[i].Flags);
  191. pTrustInfo->SetTrustAttributes(rgTrusts[i].TrustAttributes);
  192. pTrustInfo->SetFlags(rgTrusts[i].Flags);
  193. m_vectTrustInfo.push_back(pTrustInfo);
  194. pTrustInfo = NULL;
  195. }
  196. if (rgTrusts)
  197. {
  198. NetApiBufferFree(rgTrusts);
  199. }
  200. if (ERROR_SUCCESS == dwRet)
  201. {
  202. SYSTEMTIME st;
  203. GetSystemTime(&st);
  204. SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
  205. }
  206. return HRESULT_FROM_WIN32(dwRet);
  207. }
  208. #else // NT4_BUILD
  209. HRESULT
  210. CDomainInfo::EnumerateTrusts(void)
  211. {
  212. TRACE(L"CDomainInfo::EnumerateTrusts\n");
  213. NTSTATUS Status = STATUS_SUCCESS;
  214. DWORD dwErr = ERROR_SUCCESS;
  215. ULONG i = 0;
  216. CTrustInfo * pTrustInfo = NULL;
  217. Reset();
  218. LSA_ENUMERATION_HANDLE hEnumContext = NULL;
  219. ULONG nTrustCount = 0;
  220. ULONG nTotalCount = 0;
  221. ULONG j = 0;
  222. PLSA_TRUST_INFORMATION pTrustDomainInfo = NULL;
  223. DWORD hResumeHandle = 0;
  224. LPUSER_INFO_0 pUserList = NULL;
  225. CTrustInfo * pTempTrustInfo = NULL;
  226. LPWSTR Lop = NULL;
  227. CSmartPolicyHandle chPolicy;
  228. OBJECT_ATTRIBUTES objectAttributes;
  229. InitializeObjectAttributes(&objectAttributes, NULL, 0L, NULL, NULL);
  230. //
  231. // We'll have to do this the old fashioned way. That means that we'll enumerate all of
  232. // the trust directly, save them off in a list, and then go through and enumerate all
  233. // of the interdomain trust accounts and merge those into the list.
  234. //
  235. do
  236. {
  237. Status = LsaOpenPolicy(NULL, // Local server
  238. &objectAttributes,
  239. MAXIMUM_ALLOWED, // Needed for Rediscover
  240. &chPolicy);
  241. Status = LsaEnumerateTrustedDomains(chPolicy,
  242. &hEnumContext,
  243. (void**)&pTrustDomainInfo,
  244. ULONG_MAX,
  245. &nTrustCount );
  246. if (NT_SUCCESS(Status) || Status == STATUS_MORE_ENTRIES)
  247. {
  248. dwErr = ERROR_SUCCESS;
  249. for ( i = 0; i < nTrustCount; i++ )
  250. {
  251. pTrustInfo = new CTrustInfo();
  252. CHECK_NULL( pTrustInfo, CLEAN_RETURN );
  253. pTrustInfo->SetTrustedDomain( pTrustDomainInfo[i].Name.Buffer );
  254. pTrustInfo->SetFlatName( pTrustDomainInfo[i].Name.Buffer );
  255. pTrustInfo->SetSid( pTrustDomainInfo[i].Sid );
  256. pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
  257. pTrustInfo->SetTrustDirection( TRUST_DIRECTION_OUTBOUND );
  258. m_vectTrustInfo.push_back( pTrustInfo );
  259. pTrustInfo = NULL;
  260. }
  261. LsaFreeMemory( pTrustDomainInfo );
  262. pTrustDomainInfo = NULL;
  263. }
  264. else
  265. dwErr = LsaNtStatusToWinError(Status);
  266. } while (Status == STATUS_MORE_ENTRIES);
  267. if( Status == STATUS_NO_MORE_ENTRIES )
  268. dwErr = ERROR_SUCCESS;
  269. //
  270. // Now, let's add in the user accounts
  271. //
  272. if ( dwErr == ERROR_SUCCESS )
  273. {
  274. do
  275. {
  276. nTrustCount = 0;
  277. nTotalCount = 0;
  278. dwErr = NetUserEnum(NULL,
  279. 0,
  280. FILTER_INTERDOMAIN_TRUST_ACCOUNT,
  281. (LPBYTE *)&pUserList,
  282. MAX_PREFERRED_LENGTH,
  283. &nTrustCount,
  284. &nTotalCount,
  285. &hResumeHandle);
  286. if ( dwErr == ERROR_SUCCESS || dwErr == ERROR_MORE_DATA )
  287. {
  288. dwErr = ERROR_SUCCESS;
  289. for ( i = 0; i < nTrustCount; i++ )
  290. {
  291. Lop = wcsrchr( pUserList[ i ].usri0_name, L'$' );
  292. if ( Lop )
  293. {
  294. *Lop = UNICODE_NULL;
  295. }
  296. for ( j = 0; j < m_vectTrustInfo.size(); j++ )
  297. {
  298. pTempTrustInfo = m_vectTrustInfo[j];
  299. if ( _wcsicmp( pUserList[ i ].usri0_name, pTempTrustInfo->GetTrustedDomain() ) == 0 )
  300. {
  301. pTempTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND );
  302. break;
  303. }
  304. }
  305. // If it wasn't found, add it...
  306. if ( j == m_vectTrustInfo.size() )
  307. {
  308. pTrustInfo = new CTrustInfo();
  309. CHECK_NULL( pTrustInfo, CLEAN_RETURN );
  310. pTrustInfo->SetTrustedDomain( pUserList[ i ].usri0_name );
  311. pTrustInfo->SetFlatName( pUserList[ i ].usri0_name );
  312. pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
  313. pTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND );
  314. m_vectTrustInfo.push_back( pTrustInfo );
  315. pTrustInfo = NULL;
  316. }
  317. if ( Lop )
  318. {
  319. *Lop = L'$';
  320. }
  321. }
  322. NetApiBufferFree( pUserList );
  323. pUserList = NULL;
  324. }
  325. } while ( dwErr == ERROR_MORE_DATA );
  326. }
  327. CLEAN_RETURN:
  328. if( pUserList )
  329. NetApiBufferFree( pUserList );
  330. if( pTrustDomainInfo )
  331. LsaFreeMemory( pTrustDomainInfo );
  332. if (ERROR_SUCCESS == dwErr)
  333. {
  334. SYSTEMTIME st;
  335. GetSystemTime(&st);
  336. SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
  337. }
  338. return HRESULT_FROM_WIN32(dwErr);
  339. }
  340. #endif // NT4_BUILD
  341. //+----------------------------------------------------------------------------
  342. //
  343. // Method: CDomainInfo::FindTrust
  344. //
  345. // Synopsis: Find a trust by trusted Domain Name
  346. //
  347. //-----------------------------------------------------------------------------
  348. CTrustInfo *
  349. CDomainInfo::FindTrust(PCWSTR pwzTrust)
  350. {
  351. TRACE(L"CDomainInfo::FindTrust\n");
  352. TRACE(L"\nlooking for domain %s\n", pwzTrust);
  353. ASSERT(IsEnumerated());
  354. ULONG i = 0;
  355. for( i = 0; i < m_vectTrustInfo.size(); ++i )
  356. {
  357. int nStrComp = CompareString(LOCALE_SYSTEM_DEFAULT,
  358. NORM_IGNORECASE,
  359. (m_vectTrustInfo[i])->GetTrustedDomain(), -1,
  360. pwzTrust, -1 );
  361. ASSERT( nStrComp );
  362. if( CSTR_EQUAL == nStrComp )
  363. {
  364. TRACE(L"Trust found!\n");
  365. return m_vectTrustInfo[i];
  366. }
  367. }
  368. return NULL; // Not Found
  369. }
  370. //+----------------------------------------------------------------------------
  371. //
  372. // Method: CDomainInfo::GetTrustByIndex
  373. //
  374. // Synopsis: Get trust info by Index
  375. //
  376. //-----------------------------------------------------------------------------
  377. CTrustInfo *
  378. CDomainInfo::GetTrustByIndex(size_t index)
  379. {
  380. ASSERT(IsEnumerated());
  381. if (index < Size())
  382. {
  383. return m_vectTrustInfo[index];
  384. }
  385. else
  386. {
  387. ASSERT(FALSE);
  388. return NULL;
  389. }
  390. }
  391. //+----------------------------------------------------------------------------
  392. //
  393. // Method: CDomainInfo::IsTrustListStale
  394. //
  395. // Synopsis: Checks to see if the last emumeration time is older than the
  396. // passed in criteria.
  397. //
  398. // Returns: TRUE if older.
  399. //
  400. // Notes: If the trusts haven't been enumerated (m_liLastEnumed == 0),
  401. // then the enumeration is defined to be stale.
  402. //
  403. //-----------------------------------------------------------------------------
  404. BOOL
  405. CDomainInfo::IsTrustListStale(LARGE_INTEGER liMaxAge)
  406. {
  407. TRACE(L"CDomainInfo::IsTrustListStale(0x%08x), MaxAge = %d\n",
  408. this, liMaxAge.QuadPart / TRUSTMON_FILETIMES_PER_MINUTE);
  409. BOOL fStale = FALSE;
  410. LARGE_INTEGER liCurrentTime;
  411. SYSTEMTIME st;
  412. GetSystemTime(&st);
  413. SystemTimeToFileTime(&st, (LPFILETIME)&liCurrentTime);
  414. fStale = (m_liLastEnumed.QuadPart + liMaxAge.QuadPart) < liCurrentTime.QuadPart;
  415. return fStale;
  416. }
  417. //+----------------------------------------------------------------------------
  418. //
  419. // Method: CDomainInfo::CreateAndSendInst
  420. //
  421. // Synopsis: Returns a copy of the current instance back to WMI
  422. //
  423. //-----------------------------------------------------------------------------
  424. HRESULT
  425. CDomainInfo::CreateAndSendInst(IWbemObjectSink * pResponseHandler)
  426. {
  427. TRACE(L"CDomainInfo::CreateAndSendInst\n");
  428. HRESULT hr = WBEM_S_NO_ERROR;
  429. do
  430. {
  431. CComPtr<IWbemClassObject> ipNewInst;
  432. CComVariant var;
  433. //
  434. // Create a new instance of the WMI class object
  435. //
  436. hr = m_sipClassDefLocalDomain->SpawnInstance(0, &ipNewInst);
  437. BREAK_ON_FAIL;
  438. // Set the DNS property value
  439. var = GetDnsName();
  440. hr = ipNewInst->Put(CSTR_PROP_LOCAL_DNS_NAME, 0, &var, 0);
  441. TRACE(L"\tCreating instance %s\n", var.bstrVal);
  442. BREAK_ON_FAIL;
  443. // Set the flat name property value
  444. var = GetFlatName();
  445. hr = ipNewInst->Put(CSTR_PROP_LOCAL_FLAT_NAME, 0, &var, 0);
  446. TRACE(L"\twith flat name %s\n", var.bstrVal);
  447. BREAK_ON_FAIL;
  448. // Set the SID property value
  449. var = GetSid();
  450. hr = ipNewInst->Put(CSTR_PROP_LOCAL_SID, 0, &var, 0);
  451. TRACE(L"\twith SID %s\n", var.bstrVal);
  452. BREAK_ON_FAIL;
  453. // Set the forest name property value
  454. var = GetForestName();
  455. hr = ipNewInst->Put(CSTR_PROP_LOCAL_TREE_NAME, 0, &var, 0);
  456. TRACE(L"\twith forest name %s\n", var.bstrVal);
  457. BREAK_ON_FAIL;
  458. // Set the DC name property value
  459. var = GetDcName();
  460. hr = ipNewInst->Put(CSTR_PROP_LOCAL_DC_NAME, 0, &var, 0);
  461. TRACE(L"\ton DC %s\n", var.bstrVal);
  462. BREAK_ON_FAIL;
  463. //
  464. // Send the object to the caller
  465. //
  466. // [In] param, no need to addref.
  467. IWbemClassObject * pNewInstance = ipNewInst;
  468. hr = pResponseHandler->Indicate(1, &pNewInstance);
  469. BREAK_ON_FAIL;
  470. } while(FALSE);
  471. return hr;
  472. }