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.
 
 
 
 
 
 

554 lines
17 KiB

//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// trust.c
//
// Abstract:
//
// Queries into network drivers
//
// Author:
//
// Anilth - 4-20-1998
//
// Environment:
//
// User mode only.
// Contains NT-specific code.
//
// Revision History:
//
//--
#include "precomp.h"
BOOL DomainSidRight( IN PTESTED_DOMAIN TestedDomain,
NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults
);
HRESULT TrustTest( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
HRESULT hr = S_OK;
PTESTED_DOMAIN Context = pParams->pDomain;
NET_API_STATUS NetStatus;
PNETLOGON_INFO_2 NetlogonInfo2 = NULL;
NET_API_STATUS TrustedNetStatus = 0;
LPWSTR TrustedDomainList = NULL;
PTESTED_DOMAIN TestedDomain = pResults->Global.pMemberDomain;
PLIST_ENTRY ListEntry;
LPBYTE InputDataPtr;
int i;
// validDC is the count of valid Domain Controllers with which secure channel can be set.
int validDC = 0;
InitializeListHead(&pResults->Trust.lmsgOutput);
PrintStatusMessage(pParams, 4, IDS_TRUST_STATUS_MSG);
//
// Only Members and BDCs have trust relationships to their primary domain
//
if (!
(pResults->Global.pPrimaryDomainInfo->MachineRole == DsRole_RoleMemberWorkstation ||
pResults->Global.pPrimaryDomainInfo->MachineRole == DsRole_RoleMemberServer ||
pResults->Global.pPrimaryDomainInfo->MachineRole == DsRole_RoleBackupDomainController )
)
{
PrintStatusMessage(pParams, 0, IDS_GLOBAL_SKIP_NL);
return hr; // not to test standalone
}
pResults->Trust.fPerformed = TRUE;
//
// Check to see that the domain Sid of the primary domain is right.
//
if ( !DomainSidRight( pResults->Global.pMemberDomain, pParams, pResults ) ) {
hr = S_FALSE;
goto L_ERR;
}
//
// Use the secure channel
//
// If some other caller did this in the recent past,
// this doesn't even use the secure channel.
//
// On a BDC, this doesn't use the secure channel.
//
TrustedNetStatus = NetEnumerateTrustedDomains( NULL, &TrustedDomainList );
if ( TrustedNetStatus != NO_ERROR ) {
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_LISTDOMAINS,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetStatusToString(TrustedNetStatus));
}
// Don't complain yet since the real secure channel status is more
// important to the user.
//
// Check the current status of the secure channel.
// (This may still be cached and out of date.)
//
InputDataPtr = (LPBYTE)(pResults->Global.pPrimaryDomainInfo->DomainNameDns ?
pResults->Global.pPrimaryDomainInfo->DomainNameDns :
pResults->Global.pPrimaryDomainInfo->DomainNameFlat);
NetStatus = I_NetLogonControl2(
NULL,
NETLOGON_CONTROL_TC_QUERY,
2, // Query level
(LPBYTE)&(InputDataPtr),
(LPBYTE *)&NetlogonInfo2 );
// put message to message list
if ( NetStatus != NO_ERROR )
{
//IDS_TRUST_FAILED_SECURECHANNEL " Cannot get secure channel status for domain '%ws' from Netlogon. [%s]"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_SECURECHANNEL,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetStatusToString(NetStatus));
hr = S_FALSE;
goto L_ERR;
}
if ( NetlogonInfo2->netlog2_tc_connection_status != NO_ERROR )
{
//IDS_TRUST_CHANNEL_BROKEN " [FATAL] Secure channel to domain '%ws' is broken. [%s]\n"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_CHANNEL_BROKEN,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetStatusToString(NetlogonInfo2->netlog2_tc_connection_status));
hr = S_FALSE;
goto L_ERR;
}
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Verbose, 0,
IDS_TRUST_SECURECHANNEL_TO,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetlogonInfo2->netlog2_trusted_dc_name);
// free the data buffer returned earlies
if ( NetlogonInfo2 != NULL ) {
NetApiBufferFree( NetlogonInfo2 );
NetlogonInfo2 = NULL;
}
// test further
switch(pResults->Global.pPrimaryDomainInfo->MachineRole){
//
// On a backup domain controller,
// only setup a secure channel to the PDC.
//
case DsRole_RoleBackupDomainController:
//
// Check the current status of the secure channel.
// (This may be still cached and out of date.)
//
NetlogonInfo2 = NULL;
InputDataPtr = (LPBYTE)(pResults->Global.pPrimaryDomainInfo->DomainNameDns ?
pResults->Global.pPrimaryDomainInfo->DomainNameDns :
pResults->Global.pPrimaryDomainInfo->DomainNameFlat);
// connect to PDC
NetStatus = I_NetLogonControl2(
NULL,
NETLOGON_CONTROL_REDISCOVER,
2, // Query level
(LPBYTE)&InputDataPtr,
(LPBYTE *)&NetlogonInfo2 );
if (NetStatus == ERROR_ACCESS_DENIED)
{
//IDS_TRUST_NOT_ADMIN " Cannot test secure channel to PDC since you are not an administrator.\n"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_NOT_ADMIN);
goto L_ERR;
}
if(NetStatus != NO_ERROR)
{
//IDS_TRUST_FAILED_CHANNEL_PDC " [FATAL] Cannot set secure channel for domain '%ws' to PDC. [%s]\n"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_CHANNEL_PDC,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetStatusToString(NetStatus));
hr = S_FALSE;
goto L_ERR;
}
if ( NetlogonInfo2->netlog2_tc_connection_status != NO_ERROR )
{
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_CHANNEL_PDC,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetStatusToString(NetStatus));
hr = S_FALSE;
goto L_ERR;
}
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_ReallyVerbose, 0,
IDS_TRUST_SECURECHANNEL_TOPDC,
pResults->Global.pPrimaryDomainInfo->DomainNameFlat,
NetlogonInfo2->netlog2_trusted_dc_name);
if ( NetlogonInfo2 != NULL )
{
NetApiBufferFree( NetlogonInfo2 );
NetlogonInfo2 = NULL;
}
break;
// On a workstation or member server,
// try the secure channel to ever DC in the domain.
//
case DsRole_RoleMemberServer:
case DsRole_RoleMemberWorkstation:
if ( TestedDomain->NetbiosDomainName == NULL ) {
//IDS_TRUST_NO_NBT_DOMAIN " [FATAL] Cannot test secure channel since no netbios domain name '%ws' to DC '%ws'."
AddMessageToList( &pResults->Trust.lmsgOutput, Nd_Quiet, IDS_TRUST_NO_NBT_DOMAIN, TestedDomain->PrintableDomainName );
PrintGuruMessage2(" [FATAL] Cannot test secure channel since no netbios domain name '%ws' to DC '%ws'.", TestedDomain->PrintableDomainName );
PrintGuru( 0, NETLOGON_GURU );
hr = S_FALSE;
goto L_ERR;
}
//
// Ensure secure channel can be set with atleast one DC.
//
for ( ListEntry = TestedDomain->TestedDcs.Flink ;
ListEntry != &TestedDomain->TestedDcs ;
ListEntry = ListEntry->Flink )
{
WCHAR RediscoverName[MAX_PATH+1+MAX_PATH+1];
PTESTED_DC TestedDc;
//
// Loop through the list of DCs in this domain
//
TestedDc = CONTAINING_RECORD( ListEntry, TESTED_DC, Next );
if ( TestedDc->Flags & DC_IS_DOWN ) {
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_ReallyVerbose, 0,
IDS_TRUST_NOTESTASITSDOWN,
TestedDc->ComputerName );
continue;
}
//
// Build the name to rediscover
//
wcscpy( RediscoverName, GetSafeStringW(TestedDomain->DnsDomainName ?
TestedDomain->DnsDomainName :
TestedDomain->NetbiosDomainName));
wcscat( RediscoverName, L"\\" );
wcscat( RediscoverName, GetSafeStringW(TestedDc->ComputerName) );
//
// Check the current status of the secure channel.
// (This may be still cached and out of date.)
//
InputDataPtr = (LPBYTE)RediscoverName;
NetStatus = I_NetLogonControl2(
NULL,
NETLOGON_CONTROL_REDISCOVER,
2, // Query level
(LPBYTE)&InputDataPtr,
(LPBYTE *)&NetlogonInfo2 );
if ( NetStatus != NO_ERROR )
{
if ( ERROR_ACCESS_DENIED == NetStatus )
{
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_TODCS_NOT_ADMIN);
}
else
{
//IDS_TRUST_FAILED_TODCS " Cannot test secure channel for domain '%ws' to DC '%ws'. [%s]\n"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_TODCS,
TestedDomain->PrintableDomainName,
TestedDc->NetbiosDcName,
NetStatusToString(NetStatus));
}
continue;
}
if ( NetlogonInfo2->netlog2_tc_connection_status != NO_ERROR )
{
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_FAILED_CHANNEL_DCS,
TestedDomain->PrintableDomainName,
TestedDc->NetbiosDcName );
continue;
}
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_ReallyVerbose, 0,
IDS_TRUST_CHANNEL_DC,
TestedDomain->PrintableDomainName,
NetlogonInfo2->netlog2_trusted_dc_name );
validDC++;
}
if (validDC == 0)
hr = S_FALSE;
break;
}
L_ERR:
if ( NetlogonInfo2 != NULL ) {
NetApiBufferFree( NetlogonInfo2 );
NetlogonInfo2 = NULL;
}
if ( TrustedDomainList != NULL ) {
NetApiBufferFree( TrustedDomainList );
TrustedDomainList = NULL;
}
PrintStatusMessage(pParams, 0, FHrOK(hr) ? IDS_GLOBAL_PASS_NL : IDS_GLOBAL_FAIL_NL);
pResults->Trust.hr = hr;
return hr;
}
void TrustGlobalPrint(IN NETDIAG_PARAMS *pParams, IN OUT NETDIAG_RESULT *pResults)
{
// print out the test result
if (pParams->fVerbose || !FHrOK(pResults->Trust.hr))
{
PrintNewLine(pParams, 2);
PrintTestTitleResult(pParams, IDS_TRUST_LONG, IDS_TRUST_SHORT, pResults->Trust.fPerformed,
pResults->Trust.hr, 0);
PrintMessageList(pParams, &pResults->Trust.lmsgOutput);
}
}
void TrustPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
IN OUT NETDIAG_RESULT *pResults,
IN INTERFACE_RESULT *pIfResult)
{
// no perinterface information
}
void TrustCleanup(IN NETDIAG_PARAMS *pParams,
IN OUT NETDIAG_RESULT *pResults)
{
MessageListCleanUp(&pResults->Trust.lmsgOutput);
}
BOOL
DomainSidRight(
IN PTESTED_DOMAIN TestedDomain,
NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults
)
/*++
Routine Description:
Determine if the DomainSid field of the TestDomain matches the DomainSid
of the domain.
Arguments:
TestedDomain - Domain to test
Return Value:
TRUE: Test suceeded.
FALSE: Test failed
--*/
{
NET_API_STATUS NetStatus;
NTSTATUS Status;
BOOL RetVal = TRUE;
SAM_HANDLE LocalSamHandle = NULL;
SAM_HANDLE DomainHandle = NULL;
PTESTED_DC pTestedDc;
//
// Initialization
//
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_ReallyVerbose, 0,
IDS_TRUST_ENSURESID,
TestedDomain->PrintableDomainName);
if ( TestedDomain->DomainSid == NULL ) {
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0,
IDS_TRUST_MISSINGSID,
TestedDomain->PrintableDomainName);
RetVal = FALSE;
goto Cleanup;
}
//
// If we don't yet know a DC in the domain,
// find one.
//
if ( TestedDomain->DcInfo == NULL )
{
LPTSTR pszDcType;
if ( TestedDomain->fTriedToFindDcInfo ) {
//IDS_DCLIST_NO_DC " '%ws': Cannot find DC to get DC list from [test skiped].\n"
AddMessageToList( &pResults->Trust.lmsgOutput, Nd_Verbose, IDS_TRUST_NODC, TestedDomain->PrintableDomainName);
goto Cleanup;
}
pszDcType = LoadAndAllocString(IDS_DCTYPE_DC);
NetStatus = DoDsGetDcName( pParams,
pResults,
&pResults->Trust.lmsgOutput,
TestedDomain,
DS_DIRECTORY_SERVICE_PREFERRED,
pszDcType, //"DC",
FALSE,
&TestedDomain->DcInfo );
Free(pszDcType);
TestedDomain->fTriedToFindDcInfo = TRUE;
if ( NetStatus != NO_ERROR ) {
//IDS_TRUST_NODC " '%ws': Cannot find DC to get DC list from [test skiped].\n"
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Verbose, 0,
IDS_TRUST_NODC, TestedDomain->PrintableDomainName);
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Verbose, 4,
IDS_GLOBAL_STATUS, NetStatusToString(NetStatus));
// This isn't fatal.
RetVal = TRUE;
goto Cleanup;
}
}
//
// Get a DC that's UP.
//
pTestedDc = GetUpTestedDc( TestedDomain );
if ( pTestedDc == NULL ) {
AddMessageToList( &pResults->Trust.lmsgOutput, Nd_Verbose,
IDS_TRUST_NODC_UP, TestedDomain->PrintableDomainName);
PrintGuruMessage2(" '%ws': No DCs are up (Cannot run test).\n",
TestedDomain->PrintableDomainName );
PrintGuru( NetStatus, DSGETDC_GURU );
// This isn't fatal.
RetVal = TRUE;
goto Cleanup;
}
//
// Connect to the SAM server
//
Status = NettestSamConnect(
pParams,
pTestedDc->ComputerName,
&LocalSamHandle );
if ( !NT_SUCCESS(Status)) {
if ( Status == STATUS_ACCESS_DENIED ) {
//IDS_TRUST_NO_ACCESS " [WARNING] Don't have access to test your domain sid for domain '%ws'. [Test skipped]\n"
AddMessageToList( &pResults->Trust.lmsgOutput, Nd_Verbose,
IDS_TRUST_NO_ACCESS, TestedDomain->PrintableDomainName );
}
// This isn't fatal.
RetVal = TRUE;
goto Cleanup;
}
//
// Open the domain.
// Ask for no access to avoid access denied.
//
Status = SamOpenDomain( LocalSamHandle,
0,
pResults->Global.pMemberDomain->DomainSid,
&DomainHandle );
if ( Status == STATUS_NO_SUCH_DOMAIN ) {
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0, IDS_TRUST_WRONGSID, TestedDomain->PrintableDomainName );
RetVal = FALSE;
goto Cleanup;
}
if ( !NT_SUCCESS( Status ) ) {
AddIMessageToList(&pResults->Trust.lmsgOutput, Nd_Quiet, 0, IDS_TRUST_FAILED_SAMOPEN, pTestedDc->ComputerName );
RetVal = FALSE;
goto Cleanup;
}
//
// Cleanup locally used resources
//
Cleanup:
if ( DomainHandle != NULL ) {
(VOID) SamCloseHandle( DomainHandle );
}
if ( LocalSamHandle != NULL ) {
(VOID) SamCloseHandle( LocalSamHandle );
}
return RetVal;
}