415 lines
9.7 KiB
C++
415 lines
9.7 KiB
C++
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
disptrus.c(pp)
|
|
|
|
Author:
|
|
|
|
Scott Field (sfield) 16-Mar-96
|
|
|
|
Revision:
|
|
JonY 16-Apr-96 Modified to .cpp
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include "trstlist.h"
|
|
|
|
|
|
#define RTN_OK 0
|
|
#define RTN_ERROR 13
|
|
|
|
//
|
|
// if you have the ddk, include ntstatus.h
|
|
//
|
|
#ifndef STATUS_SUCCESS
|
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
|
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
|
|
#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
|
|
#endif
|
|
|
|
|
|
#define ELEMENT_COUNT 64 // number of array elements to allocate
|
|
|
|
CTrustList::CTrustList()
|
|
{
|
|
m_dwTrustCount = 0;
|
|
m_ppszTrustList = (LPWSTR *)HeapAlloc(
|
|
GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
ELEMENT_COUNT * sizeof(LPWSTR)
|
|
);
|
|
}
|
|
|
|
CTrustList::~CTrustList()
|
|
{
|
|
//
|
|
// free trust list
|
|
//
|
|
unsigned int i;
|
|
for(i = 0 ; i < m_dwTrustCount ; i++) {
|
|
if(m_ppszTrustList[i] != NULL)
|
|
HeapFree(GetProcessHeap(), 0, m_ppszTrustList[i]);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, m_ppszTrustList);
|
|
|
|
}
|
|
|
|
BOOL
|
|
CTrustList::BuildTrustList(
|
|
LPTSTR Target
|
|
)
|
|
{
|
|
LSA_HANDLE PolicyHandle;
|
|
NTSTATUS Status;
|
|
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomain;
|
|
BOOL bDC;
|
|
NET_API_STATUS nas = NERR_Success; // assume success
|
|
|
|
BOOL bSuccess = FALSE; // assume this function will fail
|
|
|
|
//
|
|
// open the policy on the specified machine
|
|
//
|
|
Status = OpenPolicy(
|
|
Target,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle
|
|
);
|
|
|
|
if(Status != STATUS_SUCCESS) {
|
|
SetLastError( LsaNtStatusToWinError(Status) );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// obtain the AccountDomain, which is common to all three cases
|
|
//
|
|
Status = LsaQueryInformationPolicy(
|
|
PolicyHandle,
|
|
PolicyAccountDomainInformation,
|
|
(LPVOID*)&AccountDomain
|
|
);
|
|
|
|
if(Status != STATUS_SUCCESS)
|
|
goto cleanup;
|
|
|
|
//
|
|
// Note: AccountDomain->DomainSid will contain binary Sid
|
|
//
|
|
AddTrustToList(&AccountDomain->DomainName);
|
|
|
|
//
|
|
// free memory allocated for account domain
|
|
//
|
|
LsaFreeMemory(AccountDomain);
|
|
|
|
//
|
|
// find out if the target machine is a domain controller
|
|
//
|
|
if(!IsDomainController(Target, &bDC)) {
|
|
////
|
|
goto cleanup;
|
|
}
|
|
|
|
if(!bDC) {
|
|
PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain;
|
|
TCHAR* szPrimaryDomainName = NULL;
|
|
TCHAR* DomainController = NULL;
|
|
|
|
//
|
|
// get the primary domain
|
|
//
|
|
Status = LsaQueryInformationPolicy(
|
|
PolicyHandle,
|
|
PolicyPrimaryDomainInformation,
|
|
(LPVOID*)&PrimaryDomain
|
|
);
|
|
|
|
if(Status != STATUS_SUCCESS)
|
|
goto cleanup;
|
|
|
|
//
|
|
// if the primary domain Sid is NULL, we are a non-member, and
|
|
// our work is done.
|
|
//
|
|
if(PrimaryDomain->Sid == NULL) {
|
|
LsaFreeMemory(PrimaryDomain);
|
|
bSuccess = TRUE;
|
|
goto cleanup;
|
|
}
|
|
|
|
AddTrustToList(&PrimaryDomain->Name);
|
|
|
|
//
|
|
// build a copy of what we just added. This is necessary in order
|
|
// to lookup the domain controller for the specified domain.
|
|
// the Domain name must be NULL terminated for NetGetDCName(),
|
|
// and the LSA_UNICODE_STRING buffer is not necessarilly NULL
|
|
// terminated. Note that in a practical implementation, we
|
|
// could just extract the element we added, since it ends up
|
|
// NULL terminated.
|
|
//
|
|
|
|
szPrimaryDomainName = (LPTSTR)HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
PrimaryDomain->Name.Length + sizeof(WCHAR) // existing length + NULL
|
|
);
|
|
|
|
if(szPrimaryDomainName != NULL) {
|
|
//
|
|
// copy the existing buffer to the new storage, appending a NULL
|
|
//
|
|
_tcsncpy(
|
|
szPrimaryDomainName,
|
|
PrimaryDomain->Name.Buffer,
|
|
(PrimaryDomain->Name.Length / 2) + 1
|
|
);
|
|
}
|
|
|
|
LsaFreeMemory(PrimaryDomain);
|
|
|
|
if(szPrimaryDomainName == NULL) goto cleanup;
|
|
|
|
//
|
|
// get the primary domain controller computer name
|
|
//
|
|
nas = NetGetDCName(
|
|
NULL,
|
|
szPrimaryDomainName,
|
|
(LPBYTE *)&DomainController
|
|
);
|
|
|
|
HeapFree(GetProcessHeap(), 0, szPrimaryDomainName);
|
|
|
|
if(nas != NERR_Success)
|
|
goto cleanup;
|
|
|
|
//
|
|
// close the policy handle, because we don't need it anymore
|
|
// for the workstation case, as we open a handle to a DC
|
|
// policy below
|
|
//
|
|
LsaClose(PolicyHandle);
|
|
PolicyHandle = INVALID_HANDLE_VALUE; // invalidate handle value
|
|
|
|
//
|
|
// open the policy on the domain controller
|
|
//
|
|
Status = OpenPolicy(
|
|
DomainController,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle
|
|
);
|
|
|
|
//
|
|
// free the domaincontroller buffer
|
|
//
|
|
NetApiBufferFree(DomainController);
|
|
|
|
if(Status != STATUS_SUCCESS)
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// build additional trusted domain(s) list and indicate if successful
|
|
//
|
|
bSuccess = EnumTrustedDomains(PolicyHandle);
|
|
|
|
cleanup:
|
|
|
|
//
|
|
// close the policy handle
|
|
//
|
|
if(PolicyHandle != INVALID_HANDLE_VALUE)
|
|
LsaClose(PolicyHandle);
|
|
|
|
if(!bSuccess) {
|
|
if(Status != STATUS_SUCCESS)
|
|
SetLastError( LsaNtStatusToWinError(Status) );
|
|
else if(nas != NERR_Success)
|
|
SetLastError( nas );
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CTrustList::EnumTrustedDomains(
|
|
LSA_HANDLE PolicyHandle
|
|
)
|
|
{
|
|
LSA_ENUMERATION_HANDLE lsaEnumHandle=0; // start an enum
|
|
PLSA_TRUST_INFORMATION TrustInfo;
|
|
ULONG ulReturned; // number of items returned
|
|
ULONG ulCounter; // counter for items returned
|
|
NTSTATUS Status;
|
|
|
|
do {
|
|
Status = LsaEnumerateTrustedDomains(
|
|
PolicyHandle, // open policy handle
|
|
&lsaEnumHandle, // enumeration tracker
|
|
(LPVOID*)&TrustInfo, // buffer to receive data
|
|
32000, // recommended buffer size
|
|
&ulReturned // number of items returned
|
|
);
|
|
//
|
|
// get out if an error occurred
|
|
//
|
|
if( (Status != STATUS_SUCCESS) &&
|
|
(Status != STATUS_MORE_ENTRIES) &&
|
|
(Status != STATUS_NO_MORE_ENTRIES)
|
|
) {
|
|
SetLastError( LsaNtStatusToWinError(Status) );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Display results
|
|
// Note: Sids are in TrustInfo[ulCounter].Sid
|
|
//
|
|
for(ulCounter = 0 ; ulCounter < ulReturned ; ulCounter++)
|
|
AddTrustToList(&TrustInfo[ulCounter].Name);
|
|
|
|
//
|
|
// free the buffer
|
|
//
|
|
LsaFreeMemory(TrustInfo);
|
|
|
|
} while (Status != STATUS_NO_MORE_ENTRIES);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CTrustList::IsDomainController(
|
|
LPTSTR Server,
|
|
LPBOOL bDomainController
|
|
)
|
|
{
|
|
PSERVER_INFO_101 si101;
|
|
NET_API_STATUS nas;
|
|
|
|
nas = NetServerGetInfo(
|
|
Server,
|
|
101, // info-level
|
|
(LPBYTE *)&si101
|
|
);
|
|
|
|
if(nas != NERR_Success) {
|
|
SetLastError(nas);
|
|
return FALSE;
|
|
}
|
|
|
|
if( (si101->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
|
|
(si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
|
|
//
|
|
// we are dealing with a DC
|
|
//
|
|
*bDomainController = TRUE;
|
|
} else {
|
|
*bDomainController = FALSE;
|
|
}
|
|
|
|
NetApiBufferFree(si101);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CTrustList::AddTrustToList(
|
|
PLSA_UNICODE_STRING UnicodeString
|
|
)
|
|
{
|
|
if(m_dwTrustCount > ELEMENT_COUNT) return FALSE;
|
|
|
|
//
|
|
// allocate storage for array element
|
|
//
|
|
m_ppszTrustList[m_dwTrustCount] = (LPWSTR)HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
UnicodeString->Length + sizeof(WCHAR) // existing length + NULL
|
|
);
|
|
|
|
if(m_ppszTrustList[m_dwTrustCount] == NULL) return FALSE;
|
|
|
|
//
|
|
// copy the existing buffer to the new storage, appending a NULL
|
|
//
|
|
lstrcpynW(
|
|
m_ppszTrustList[m_dwTrustCount],
|
|
UnicodeString->Buffer,
|
|
(UnicodeString->Length / 2) + 1
|
|
);
|
|
|
|
m_dwTrustCount++; // increment the trust count
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
CTrustList::InitLsaString(
|
|
PLSA_UNICODE_STRING LsaString,
|
|
LPTSTR String
|
|
)
|
|
{
|
|
DWORD StringLength;
|
|
|
|
if (String == NULL) {
|
|
LsaString->Buffer = NULL;
|
|
LsaString->Length = 0;
|
|
LsaString->MaximumLength = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
StringLength = _tcslen(String);
|
|
LsaString->Buffer = String;
|
|
LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
|
|
LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
NTSTATUS
|
|
CTrustList::OpenPolicy(
|
|
LPTSTR ServerName,
|
|
DWORD DesiredAccess,
|
|
PLSA_HANDLE PolicyHandle
|
|
)
|
|
{
|
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LSA_UNICODE_STRING ServerString;
|
|
PLSA_UNICODE_STRING Server;
|
|
|
|
//
|
|
// Always initialize the object attributes to all zeroes
|
|
//
|
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
|
|
|
if(ServerName != NULL) {
|
|
//
|
|
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
|
|
//
|
|
InitLsaString(&ServerString, ServerName);
|
|
|
|
Server = &ServerString;
|
|
} else {
|
|
Server = NULL;
|
|
}
|
|
|
|
//
|
|
// Attempt to open the policy
|
|
//
|
|
return LsaOpenPolicy(
|
|
Server,
|
|
&ObjectAttributes,
|
|
DesiredAccess,
|
|
PolicyHandle
|
|
);
|
|
}
|
|
|
|
|