windows-nt/Source/XPSP1/NT/admin/wmiprov/trustmon/domain.cpp
2020-09-26 16:20:57 +08:00

564 lines
16 KiB
C++

//+----------------------------------------------------------------------------
//
// Windows 2000 Active Directory Service domain trust verification WMI provider
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: domain.cpp
//
// Contents: domain class implementation
//
// Classes: CDomainInfo
//
// History: 27-Mar-00 EricB created
//
//-----------------------------------------------------------------------------
#include <stdafx.h>
PCWSTR CSTR_PROP_LOCAL_DNS_NAME = L"DNSname"; // String
PCWSTR CSTR_PROP_LOCAL_FLAT_NAME = L"FlatName"; // String
PCWSTR CSTR_PROP_LOCAL_SID = L"SID"; // String
PCWSTR CSTR_PROP_LOCAL_TREE_NAME = L"TreeName"; // String
PCWSTR CSTR_PROP_LOCAL_DC_NAME = L"DCname"; // String
// TODO: string property listing the FSMOs owned by this DC?
//Implementaion of CDomainInfo class
//+----------------------------------------------------------------------------
//
// Class: CDomainInfo
//
//-----------------------------------------------------------------------------
CDomainInfo::CDomainInfo()
{
TRACE(L"CDomainInfo::CDomainInfo\n");
m_liLastEnumed.QuadPart = 0;
}
CDomainInfo::~CDomainInfo()
{
TRACE(L"CDomainInfo::~CDomainInfo\n");
Reset();
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::Init
//
// Synopsis: Initializes the CDomainInfo object.
//
//-----------------------------------------------------------------------------
HRESULT
CDomainInfo::Init(IWbemClassObject * pClassDef)
{
TRACE(L"CDomainInfo::Init\n");
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES objectAttributes;
CSmartPolicyHandle chPolicy;
m_sipClassDefLocalDomain = pClassDef;
InitializeObjectAttributes(&objectAttributes, NULL, 0L, NULL, NULL);
// Get Local policy
Status = LsaOpenPolicy(NULL, // Local server
&objectAttributes,
MAXIMUM_ALLOWED, // Needed for Rediscover
&chPolicy);
if (!NT_SUCCESS(Status))
{
TRACE(L"LsaOpenPolicy failed with error %d\n", Status);
return HRESULT_FROM_WIN32(LsaNtStatusToWinError(Status));
}
PPOLICY_DNS_DOMAIN_INFO pDnsDomainInfo;
Status = LsaQueryInformationPolicy(chPolicy,
PolicyDnsDomainInformation,
(PVOID *)&pDnsDomainInfo);
if (!NT_SUCCESS(Status))
{
TRACE(L"LsaQueryInformationPolicy failed with error %d\n", Status);
return HRESULT_FROM_WIN32(LsaNtStatusToWinError(Status));
}
m_strDomainFlatName = pDnsDomainInfo->Name.Buffer;
m_strDomainDnsName = pDnsDomainInfo->DnsDomainName.Buffer;
m_strForestName = pDnsDomainInfo->DnsForestName.Buffer;
if (!SetSid(pDnsDomainInfo->Sid))
{
ASSERT(false);
LsaFreeMemory(pDnsDomainInfo);
return E_OUTOFMEMORY;
}
LsaFreeMemory(pDnsDomainInfo);
DWORD dwBufSize = MAX_COMPUTERNAME_LENGTH + 1;
if (!GetComputerName(m_strDcName.GetBuffer(dwBufSize), &dwBufSize))
{
DWORD dwErr = GetLastError();
TRACE(L"GetComputerName failed with error %d\n", dwErr);
return HRESULT_FROM_WIN32(dwErr);
}
m_strDcName.ReleaseBuffer();
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::Reset
//
// Synopsis: Free the contents of the trust array and re-initialize it.
//
//-----------------------------------------------------------------------------
void
CDomainInfo::Reset(void)
{
TRACE(L"CDomainInfo::Reset\n");
CTrustInfo * pTrustInfo = NULL;
if (IsEnumerated())
{
// Empty cache
for (UINT i = 0; i < m_vectTrustInfo.size(); ++i)
{
pTrustInfo = m_vectTrustInfo[i];
if (pTrustInfo)
delete pTrustInfo;
}
m_vectTrustInfo.clear();
}
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::SetSid
//
//-----------------------------------------------------------------------------
BOOL
CDomainInfo::SetSid(PSID pSid)
{
if (!pSid)
{
return TRUE;
}
#if !defined(NT4_BUILD)
PWSTR buffer;
BOOL fRet = ConvertSidToStringSid(pSid, &buffer);
if (fRet)
{
m_strSid = buffer;
LocalFree(buffer);
}
return fRet;
#else
// TODO: Code for NT4 ??
#endif
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::EnumerateTrusts
//
// Synopsis: List the trusts for this domain.
//
//-----------------------------------------------------------------------------
#if !defined(NT4_BUILD)
HRESULT
CDomainInfo::EnumerateTrusts(void)
{
TRACE(L"CDomainInfo::EnumerateTrusts\n");
DWORD dwRet = ERROR_SUCCESS;
CTrustInfo * pTrustInfo = NULL;
PDS_DOMAIN_TRUSTS rgTrusts = NULL;
ULONG nTrustCount = 0;
Reset();
dwRet = DsEnumerateDomainTrusts(NULL,
DS_DOMAIN_DIRECT_OUTBOUND |
DS_DOMAIN_DIRECT_INBOUND,
&rgTrusts,
&nTrustCount);
if (ERROR_SUCCESS != dwRet)
{
TRACE(L"DsEnumerateDomainTrusts failed with error %d\n", dwRet);
return HRESULT_FROM_WIN32(dwRet);
}
for (ULONG i = 0; i < nTrustCount; i++)
{
pTrustInfo = new CTrustInfo();
BREAK_ON_NULL(pTrustInfo);
if (rgTrusts[i].DnsDomainName)
{
// Downlevel domains don't have a DNS name.
//
pTrustInfo->SetTrustedDomain(rgTrusts[i].DnsDomainName);
}
else
{
// So use the flat name instead.
//
pTrustInfo->SetTrustedDomain(rgTrusts[i].NetbiosDomainName);
}
pTrustInfo->SetFlatName(rgTrusts[i].NetbiosDomainName);
BREAK_ON_NULL(pTrustInfo->SetSid(rgTrusts[i].DomainSid));
pTrustInfo->SetTrustType(rgTrusts[i].TrustType);
pTrustInfo->SetTrustDirectionFromFlags(rgTrusts[i].Flags);
pTrustInfo->SetTrustAttributes(rgTrusts[i].TrustAttributes);
pTrustInfo->SetFlags(rgTrusts[i].Flags);
m_vectTrustInfo.push_back(pTrustInfo);
pTrustInfo = NULL;
}
if (rgTrusts)
{
NetApiBufferFree(rgTrusts);
}
if (ERROR_SUCCESS == dwRet)
{
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
}
return HRESULT_FROM_WIN32(dwRet);
}
#else // NT4_BUILD
HRESULT
CDomainInfo::EnumerateTrusts(void)
{
TRACE(L"CDomainInfo::EnumerateTrusts\n");
NTSTATUS Status = STATUS_SUCCESS;
DWORD dwErr = ERROR_SUCCESS;
ULONG i = 0;
CTrustInfo * pTrustInfo = NULL;
Reset();
LSA_ENUMERATION_HANDLE hEnumContext = NULL;
ULONG nTrustCount = 0;
ULONG nTotalCount = 0;
ULONG j = 0;
PLSA_TRUST_INFORMATION pTrustDomainInfo = NULL;
DWORD hResumeHandle = 0;
LPUSER_INFO_0 pUserList = NULL;
CTrustInfo * pTempTrustInfo = NULL;
LPWSTR Lop = NULL;
CSmartPolicyHandle chPolicy;
OBJECT_ATTRIBUTES objectAttributes;
InitializeObjectAttributes(&objectAttributes, NULL, 0L, NULL, NULL);
//
// We'll have to do this the old fashioned way. That means that we'll enumerate all of
// the trust directly, save them off in a list, and then go through and enumerate all
// of the interdomain trust accounts and merge those into the list.
//
do
{
Status = LsaOpenPolicy(NULL, // Local server
&objectAttributes,
MAXIMUM_ALLOWED, // Needed for Rediscover
&chPolicy);
Status = LsaEnumerateTrustedDomains(chPolicy,
&hEnumContext,
(void**)&pTrustDomainInfo,
ULONG_MAX,
&nTrustCount );
if (NT_SUCCESS(Status) || Status == STATUS_MORE_ENTRIES)
{
dwErr = ERROR_SUCCESS;
for ( i = 0; i < nTrustCount; i++ )
{
pTrustInfo = new CTrustInfo();
CHECK_NULL( pTrustInfo, CLEAN_RETURN );
pTrustInfo->SetTrustedDomain( pTrustDomainInfo[i].Name.Buffer );
pTrustInfo->SetFlatName( pTrustDomainInfo[i].Name.Buffer );
pTrustInfo->SetSid( pTrustDomainInfo[i].Sid );
pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
pTrustInfo->SetTrustDirection( TRUST_DIRECTION_OUTBOUND );
m_vectTrustInfo.push_back( pTrustInfo );
pTrustInfo = NULL;
}
LsaFreeMemory( pTrustDomainInfo );
pTrustDomainInfo = NULL;
}
else
dwErr = LsaNtStatusToWinError(Status);
} while (Status == STATUS_MORE_ENTRIES);
if( Status == STATUS_NO_MORE_ENTRIES )
dwErr = ERROR_SUCCESS;
//
// Now, let's add in the user accounts
//
if ( dwErr == ERROR_SUCCESS )
{
do
{
nTrustCount = 0;
nTotalCount = 0;
dwErr = NetUserEnum(NULL,
0,
FILTER_INTERDOMAIN_TRUST_ACCOUNT,
(LPBYTE *)&pUserList,
MAX_PREFERRED_LENGTH,
&nTrustCount,
&nTotalCount,
&hResumeHandle);
if ( dwErr == ERROR_SUCCESS || dwErr == ERROR_MORE_DATA )
{
dwErr = ERROR_SUCCESS;
for ( i = 0; i < nTrustCount; i++ )
{
Lop = wcsrchr( pUserList[ i ].usri0_name, L'$' );
if ( Lop )
{
*Lop = UNICODE_NULL;
}
for ( j = 0; j < m_vectTrustInfo.size(); j++ )
{
pTempTrustInfo = m_vectTrustInfo[j];
if ( _wcsicmp( pUserList[ i ].usri0_name, pTempTrustInfo->GetTrustedDomain() ) == 0 )
{
pTempTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND );
break;
}
}
// If it wasn't found, add it...
if ( j == m_vectTrustInfo.size() )
{
pTrustInfo = new CTrustInfo();
CHECK_NULL( pTrustInfo, CLEAN_RETURN );
pTrustInfo->SetTrustedDomain( pUserList[ i ].usri0_name );
pTrustInfo->SetFlatName( pUserList[ i ].usri0_name );
pTrustInfo->SetTrustType( TRUST_TYPE_DOWNLEVEL );
pTrustInfo->SetTrustDirection( TRUST_DIRECTION_INBOUND );
m_vectTrustInfo.push_back( pTrustInfo );
pTrustInfo = NULL;
}
if ( Lop )
{
*Lop = L'$';
}
}
NetApiBufferFree( pUserList );
pUserList = NULL;
}
} while ( dwErr == ERROR_MORE_DATA );
}
CLEAN_RETURN:
if( pUserList )
NetApiBufferFree( pUserList );
if( pTrustDomainInfo )
LsaFreeMemory( pTrustDomainInfo );
if (ERROR_SUCCESS == dwErr)
{
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastEnumed);
}
return HRESULT_FROM_WIN32(dwErr);
}
#endif // NT4_BUILD
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::FindTrust
//
// Synopsis: Find a trust by trusted Domain Name
//
//-----------------------------------------------------------------------------
CTrustInfo *
CDomainInfo::FindTrust(PCWSTR pwzTrust)
{
TRACE(L"CDomainInfo::FindTrust\n");
TRACE(L"\nlooking for domain %s\n", pwzTrust);
ASSERT(IsEnumerated());
ULONG i = 0;
for( i = 0; i < m_vectTrustInfo.size(); ++i )
{
int nStrComp = CompareString(LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE,
(m_vectTrustInfo[i])->GetTrustedDomain(), -1,
pwzTrust, -1 );
ASSERT( nStrComp );
if( CSTR_EQUAL == nStrComp )
{
TRACE(L"Trust found!\n");
return m_vectTrustInfo[i];
}
}
return NULL; // Not Found
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::GetTrustByIndex
//
// Synopsis: Get trust info by Index
//
//-----------------------------------------------------------------------------
CTrustInfo *
CDomainInfo::GetTrustByIndex(size_t index)
{
ASSERT(IsEnumerated());
if (index < Size())
{
return m_vectTrustInfo[index];
}
else
{
ASSERT(FALSE);
return NULL;
}
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::IsTrustListStale
//
// Synopsis: Checks to see if the last emumeration time is older than the
// passed in criteria.
//
// Returns: TRUE if older.
//
// Notes: If the trusts haven't been enumerated (m_liLastEnumed == 0),
// then the enumeration is defined to be stale.
//
//-----------------------------------------------------------------------------
BOOL
CDomainInfo::IsTrustListStale(LARGE_INTEGER liMaxAge)
{
TRACE(L"CDomainInfo::IsTrustListStale(0x%08x), MaxAge = %d\n",
this, liMaxAge.QuadPart / TRUSTMON_FILETIMES_PER_MINUTE);
BOOL fStale = FALSE;
LARGE_INTEGER liCurrentTime;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, (LPFILETIME)&liCurrentTime);
fStale = (m_liLastEnumed.QuadPart + liMaxAge.QuadPart) < liCurrentTime.QuadPart;
return fStale;
}
//+----------------------------------------------------------------------------
//
// Method: CDomainInfo::CreateAndSendInst
//
// Synopsis: Returns a copy of the current instance back to WMI
//
//-----------------------------------------------------------------------------
HRESULT
CDomainInfo::CreateAndSendInst(IWbemObjectSink * pResponseHandler)
{
TRACE(L"CDomainInfo::CreateAndSendInst\n");
HRESULT hr = WBEM_S_NO_ERROR;
do
{
CComPtr<IWbemClassObject> ipNewInst;
CComVariant var;
//
// Create a new instance of the WMI class object
//
hr = m_sipClassDefLocalDomain->SpawnInstance(0, &ipNewInst);
BREAK_ON_FAIL;
// Set the DNS property value
var = GetDnsName();
hr = ipNewInst->Put(CSTR_PROP_LOCAL_DNS_NAME, 0, &var, 0);
TRACE(L"\tCreating instance %s\n", var.bstrVal);
BREAK_ON_FAIL;
// Set the flat name property value
var = GetFlatName();
hr = ipNewInst->Put(CSTR_PROP_LOCAL_FLAT_NAME, 0, &var, 0);
TRACE(L"\twith flat name %s\n", var.bstrVal);
BREAK_ON_FAIL;
// Set the SID property value
var = GetSid();
hr = ipNewInst->Put(CSTR_PROP_LOCAL_SID, 0, &var, 0);
TRACE(L"\twith SID %s\n", var.bstrVal);
BREAK_ON_FAIL;
// Set the forest name property value
var = GetForestName();
hr = ipNewInst->Put(CSTR_PROP_LOCAL_TREE_NAME, 0, &var, 0);
TRACE(L"\twith forest name %s\n", var.bstrVal);
BREAK_ON_FAIL;
// Set the DC name property value
var = GetDcName();
hr = ipNewInst->Put(CSTR_PROP_LOCAL_DC_NAME, 0, &var, 0);
TRACE(L"\ton DC %s\n", var.bstrVal);
BREAK_ON_FAIL;
//
// Send the object to the caller
//
// [In] param, no need to addref.
IWbemClassObject * pNewInstance = ipNewInst;
hr = pResponseHandler->Indicate(1, &pNewInstance);
BREAK_ON_FAIL;
} while(FALSE);
return hr;
}