|
|
/*++
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 ); }
|