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.
781 lines
21 KiB
781 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1987-1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ftinfo.c
|
|
|
|
Abstract:
|
|
|
|
Utilities routine to manage the forest trust info list
|
|
|
|
Author:
|
|
|
|
27-Jul-00 (cliffv)
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
Contains NT-specific code.
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// Common include files.
|
|
//
|
|
|
|
#include "logonsrv.h" // Include files common to entire service
|
|
#pragma hdrstop
|
|
#include <ftnfoctx.h>
|
|
|
|
|
|
|
|
NTSTATUS
|
|
NlpUpdateFtinfo(
|
|
IN PDOMAIN_INFO DomainInfo,
|
|
IN LPWSTR TrustedDomainName,
|
|
IN BOOLEAN ImpersonateCaller,
|
|
IN PLSA_FOREST_TRUST_INFORMATION NewForestTrustInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function write the specified NewForestTrustInfo onto the named TDO.
|
|
|
|
The NewForestTrustInfo is merged with the exsiting information using the following algorithm:
|
|
|
|
The FTinfo records written are described in the NetpMergeFTinfo routine.
|
|
|
|
Arguments:
|
|
|
|
DomainInfo - Hosted Domain that trusts the domain to query.
|
|
|
|
TrustedDomainName - Trusted domain that is to be updated. This domain must have the
|
|
TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set.
|
|
|
|
ImpersonateCaller - TRUE if the caller is to be impersonated.
|
|
FALSE, if the trusted policy handle should be used to write the local LSA.
|
|
|
|
NewForestTrustInfo - Specified the new array of FTinfo records as returned from the
|
|
trusted domain.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS: Success.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
LSAPR_HANDLE PolicyHandle = NULL;
|
|
|
|
UNICODE_STRING TrustedDomainNameString;
|
|
|
|
//
|
|
// Open a handle to the LSA.
|
|
//
|
|
|
|
if ( ImpersonateCaller ) {
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
//
|
|
// Get some handle to LSA. Note that this
|
|
// handle will not be trusted even though
|
|
// we open it as LocalSystem.
|
|
//
|
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
|
|
|
Status = LsarOpenPolicy( NULL, // local server
|
|
(PLSAPR_OBJECT_ATTRIBUTES) &ObjectAttributes,
|
|
POLICY_TRUST_ADMIN,
|
|
&PolicyHandle );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
NlPrint(( NL_CRITICAL,
|
|
"NlpUpdateTdo: %ws: Cannot LsarOpenPolicy 0x%lx\n",
|
|
TrustedDomainName,
|
|
Status ));
|
|
goto Cleanup;
|
|
}
|
|
|
|
} else {
|
|
PolicyHandle = DomainInfo->DomLsaPolicyHandle;
|
|
}
|
|
|
|
//
|
|
// Set FTINFO
|
|
//
|
|
// Note that, if ImpersonateCaller is TRUE, the handle
|
|
// we pass is not trusted. In this case, the LSA will
|
|
// impersonate the caller and do the access check.
|
|
//
|
|
|
|
RtlInitUnicodeString( &TrustedDomainNameString, TrustedDomainName );
|
|
|
|
Status = LsaIUpdateForestTrustInformation(
|
|
PolicyHandle,
|
|
&TrustedDomainNameString,
|
|
NewForestTrustInfo
|
|
);
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( PolicyHandle != NULL ) {
|
|
|
|
if ( ImpersonateCaller ) {
|
|
(VOID) LsarClose( &PolicyHandle );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
NlpGetForestTrustInfoHigher(
|
|
IN PCLIENT_SESSION ClientSession,
|
|
IN DWORD Flags,
|
|
IN BOOLEAN ImpersonateCaller,
|
|
IN BOOLEAN SessionAlreadyAuthenticated,
|
|
OUT PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
This function is the client side stub for getting the forest trust info from a
|
|
trusted forest.
|
|
|
|
Arguments:
|
|
|
|
ClientSession - Trusted domain that is to be queried. This domain must have the
|
|
TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set.
|
|
|
|
Flags - Specifies a set of bits that modify the behavior of the API.
|
|
Valid bits are:
|
|
|
|
DS_GFTI_UPDATE_TDO - If this bit is set, the API will update
|
|
the FTinfo attribute of the TDO named by the ClientSession
|
|
parameter.
|
|
The caller must have access to modify the FTinfo attribute or
|
|
ERROR_ACCESS_DENIED will be returned. The algorithm describing
|
|
how the FTinfo from the trusted domain is merged with the FTinfo
|
|
from the TDO is described below.
|
|
|
|
This bit in only valid if ServerName specifies the PDC of its domain.
|
|
|
|
ImpersonateCaller - TRUE if the caller is to be impersonated.
|
|
FALSE, if the trusted policy handle should be used to write the local LSA.
|
|
|
|
SessionAlreadyAuthenticated - If TRUE, the caller already authenticated
|
|
the session, so there is no need to check or to reauthenticate.
|
|
|
|
ForestTrustInfo - Returns a pointer to a structure containing a count and an
|
|
array of FTInfo records describing the namespaces claimed by the
|
|
domain specified by ClientSession. The Accepted field and Time
|
|
field of all returned records will be zero. The buffer should be freed
|
|
by calling NetApiBufferFree.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS: Message successfully sent
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
NETLOGON_AUTHENTICATOR OurAuthenticator;
|
|
NETLOGON_AUTHENTICATOR ReturnAuthenticator;
|
|
SESSION_INFO SessionInfo;
|
|
BOOLEAN FirstTry = TRUE;
|
|
|
|
NlAssert( ClientSession->CsReferenceCount > 0 );
|
|
NlAssert( ClientSession->CsFlags & CS_WRITER );
|
|
|
|
//
|
|
// Only allow TDO update on the PDC.
|
|
//
|
|
|
|
if ( (Flags & DS_GFTI_UPDATE_TDO) != 0 &&
|
|
ClientSession->CsDomainInfo->DomRole != RolePrimary ) {
|
|
Status = STATUS_BACKUP_CONTROLLER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ensure the F bit is set.
|
|
//
|
|
|
|
if ( (ClientSession->CsTrustAttributes & TRUST_ATTRIBUTE_FOREST_TRANSITIVE) == 0 ) {
|
|
NlPrintCs((NL_CRITICAL, ClientSession,
|
|
"NlpGetForestTrustInfoHigher: trust isn't marked as cross forest trust: 0x%lX\n",
|
|
ClientSession->CsTrustAttributes ));
|
|
|
|
Status = STATUS_NO_SUCH_DOMAIN;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If the session isn't authenticated,
|
|
// do so now.
|
|
//
|
|
|
|
FirstTryFailed:
|
|
|
|
if ( !SessionAlreadyAuthenticated ) {
|
|
Status = NlEnsureSessionAuthenticated( ClientSession, 0 );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
SessionInfo.SessionKey = ClientSession->CsSessionKey;
|
|
SessionInfo.NegotiatedFlags = ClientSession->CsNegotiatedFlags;
|
|
|
|
//
|
|
// If the DC doesn't support the new function,
|
|
// fail now.
|
|
//
|
|
|
|
if ( (SessionInfo.NegotiatedFlags & NETLOGON_SUPPORTS_CROSS_FOREST) == 0 ) {
|
|
NlPrintCs((NL_CRITICAL, ClientSession,
|
|
"NlpGetForestTrustInfoHigher: remote DC doesn't support this function.\n" ));
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Build the Authenticator for this request to the PDC.
|
|
//
|
|
|
|
NlBuildAuthenticator(
|
|
&ClientSession->CsAuthenticationSeed,
|
|
&ClientSession->CsSessionKey,
|
|
&OurAuthenticator);
|
|
|
|
|
|
//
|
|
// Remote the request to the trusted DC.
|
|
//
|
|
|
|
NL_API_START( Status, ClientSession, TRUE ) {
|
|
|
|
NlAssert( ClientSession->CsUncServerName != NULL );
|
|
Status = I_NetGetForestTrustInformation(
|
|
ClientSession->CsUncServerName,
|
|
ClientSession->CsDomainInfo->DomUnicodeComputerNameString.Buffer,
|
|
&OurAuthenticator,
|
|
&ReturnAuthenticator,
|
|
0, // No flags yet
|
|
ForestTrustInfo );
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
NlPrintRpcDebug( "I_NetGetForestTrustInformation", Status );
|
|
}
|
|
|
|
// NOTE: This call may drop the secure channel behind our back
|
|
} NL_API_ELSE( Status, ClientSession, TRUE ) {
|
|
|
|
//
|
|
// We might have been called from NlSessionSetup,
|
|
// So we have to indicate the failure to our caller.
|
|
//
|
|
|
|
if ( NT_SUCCESS(Status) ) {
|
|
Status = ClientSession->CsConnectionStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
} NL_API_END;
|
|
|
|
|
|
//
|
|
// Now verify authenticator and update our seed
|
|
//
|
|
|
|
if ( NlpDidDcFail( Status ) ||
|
|
!NlUpdateSeed( &ClientSession->CsAuthenticationSeed,
|
|
&ReturnAuthenticator.Credential,
|
|
&ClientSession->CsSessionKey) ) {
|
|
|
|
NlPrintCs(( NL_CRITICAL, ClientSession,
|
|
"NlpDidDcFail: denying access after status: 0x%lx\n",
|
|
Status ));
|
|
|
|
//
|
|
// Preserve any status indicating a communication error.
|
|
//
|
|
|
|
if ( NT_SUCCESS(Status) ) {
|
|
Status = STATUS_ACCESS_DENIED;
|
|
}
|
|
NlSetStatusClientSession( ClientSession, Status );
|
|
|
|
//
|
|
// Perhaps the netlogon service on the server has just restarted.
|
|
// Try just once to set up a session to the server again.
|
|
// However, if the caller set up the session, there is
|
|
// no need for a new session setup.
|
|
//
|
|
|
|
if ( FirstTry && !SessionAlreadyAuthenticated ) {
|
|
FirstTry = FALSE;
|
|
goto FirstTryFailed;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Handle failures
|
|
//
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Handle updating the FTINFO on the TDO
|
|
//
|
|
|
|
if ( (Flags & DS_GFTI_UPDATE_TDO) != 0 ) {
|
|
|
|
LOCK_TRUST_LIST( ClientSession->CsDomainInfo );
|
|
Status = NlpUpdateFtinfo( ClientSession->CsDomainInfo,
|
|
ClientSession->CsDnsDomainName.Buffer,
|
|
ImpersonateCaller,
|
|
*ForestTrustInfo );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
UNLOCK_TRUST_LIST( ClientSession->CsDomainInfo );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Set the FTInfo refresh timestamp
|
|
//
|
|
|
|
NlQuerySystemTime( &ClientSession->CsLastFtInfoRefreshTime );
|
|
UNLOCK_TRUST_LIST( ClientSession->CsDomainInfo );
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Common exit
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
NlPrintCs((NL_CRITICAL, ClientSession,
|
|
"NlpGetForestTrustInfoHigher: failed %lX\n",
|
|
Status));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
DsrGetForestTrustInformation (
|
|
IN LPWSTR ServerName OPTIONAL,
|
|
IN LPWSTR TrustedDomainName OPTIONAL,
|
|
IN ULONG Flags,
|
|
OUT PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the server side stub for DsGetForestTrustInformationW. See that routine
|
|
for documentation.
|
|
|
|
Arguments:
|
|
|
|
See DsGetForestTrustInformationW
|
|
|
|
Return Value:
|
|
|
|
|
|
See DsGetForestTrustInformationW
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
PDOMAIN_INFO DomainInfo = NULL;
|
|
PCLIENT_SESSION ClientSession = NULL;
|
|
BOOLEAN AmWriter = FALSE;
|
|
|
|
//
|
|
// Perform access validation on the caller
|
|
//
|
|
|
|
NetStatus = NetpAccessCheck(
|
|
NlGlobalNetlogonSecurityDescriptor, // Security descriptor
|
|
NETLOGON_FTINFO_ACCESS, // Desired access
|
|
&NlGlobalNetlogonInfoMapping ); // Generic mapping
|
|
|
|
if ( NetStatus != NERR_Success) {
|
|
NetStatus = ERROR_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// This API is not supported on workstations.
|
|
//
|
|
|
|
if ( NlGlobalMemberWorkstation ) {
|
|
NetStatus = ERROR_NOT_SUPPORTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Validate the Flags parameter
|
|
//
|
|
|
|
if ((Flags & ~DS_GFTI_VALID_FLAGS) != 0 ) {
|
|
NetStatus = ERROR_INVALID_FLAGS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Find the referenced domain
|
|
//
|
|
|
|
DomainInfo = NlFindDomainByServerName( ServerName ); // Primary domain
|
|
|
|
if ( DomainInfo == NULL ) {
|
|
// Default to primary domain to handle the case where the ComputerName
|
|
// is an IP address.
|
|
|
|
DomainInfo = NlFindNetbiosDomain( NULL, TRUE );
|
|
|
|
if ( DomainInfo == NULL ) {
|
|
NetStatus = ERROR_INVALID_COMPUTERNAME;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
NlPrintDom((NL_SESSION_SETUP, DomainInfo,
|
|
"DsrGetForestTrustInformation: %ws called: 0x%lx\n", TrustedDomainName, Flags ));
|
|
|
|
|
|
|
|
//
|
|
// Get the ForestTrustInformation for a particular TDO
|
|
//
|
|
|
|
if ( TrustedDomainName != NULL &&
|
|
*TrustedDomainName != L'\0' ) {
|
|
|
|
NTSTATUS Status;
|
|
UNICODE_STRING TrustedDomainNameString;
|
|
|
|
//
|
|
// Only allow TDO update on the PDC.
|
|
//
|
|
|
|
if ( (Flags & DS_GFTI_UPDATE_TDO) != 0 &&
|
|
DomainInfo->DomRole != RolePrimary ) {
|
|
NetStatus = NERR_NotPrimary;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Find the client session to the trusted domain.
|
|
//
|
|
|
|
|
|
RtlInitUnicodeString(&TrustedDomainNameString, TrustedDomainName );
|
|
|
|
ClientSession = NlFindNamedClientSession( DomainInfo,
|
|
&TrustedDomainNameString,
|
|
NL_DIRECT_TRUST_REQUIRED,
|
|
NULL );
|
|
|
|
if( ClientSession == NULL ) {
|
|
NlPrintDom((NL_CRITICAL, DomainInfo,
|
|
"DsrGetForestTrustInformation: %ws: can't find the client structure of the domain specified.\n",
|
|
TrustedDomainName ));
|
|
|
|
NetStatus = ERROR_NO_SUCH_DOMAIN;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Become a Writer of the ClientSession.
|
|
//
|
|
|
|
if ( !NlTimeoutSetWriterClientSession( ClientSession, WRITER_WAIT_PERIOD ) ) {
|
|
NlPrintCs((NL_CRITICAL, ClientSession,
|
|
"NlpGetForestTrustInfoHigher: Can't become writer of client session.\n" ));
|
|
|
|
Status = STATUS_NO_LOGON_SERVERS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
AmWriter = TRUE;
|
|
|
|
|
|
//
|
|
// Call the DC in the trusted domain.
|
|
//
|
|
|
|
Status = NlpGetForestTrustInfoHigher( ClientSession,
|
|
Flags,
|
|
TRUE, // Impersonate caller
|
|
FALSE, // We didn't set up the session
|
|
ForestTrustInfo );
|
|
|
|
if ( !NT_SUCCESS(Status ) ) {
|
|
NetStatus = NetpNtStatusToApiStatus( Status );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the local ForestTrustInformation.
|
|
//
|
|
|
|
} else {
|
|
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Don't allow an Update TDO request if there is no TDO.
|
|
//
|
|
|
|
if ( Flags & DS_GFTI_UPDATE_TDO ) {
|
|
NetStatus = ERROR_INVALID_FLAGS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Simply grab the local ForestTrustInformation
|
|
//
|
|
|
|
Status = LsaIGetForestTrustInformation( ForestTrustInfo );
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
|
|
NetStatus = NetpNtStatusToApiStatus( Status );
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
NetStatus = NO_ERROR;
|
|
|
|
Cleanup:
|
|
if ( ClientSession != NULL ) {
|
|
if ( AmWriter ) {
|
|
NlResetWriterClientSession( ClientSession );
|
|
}
|
|
NlUnrefClientSession( ClientSession );
|
|
}
|
|
|
|
NlPrintDom(( NL_SESSION_SETUP, DomainInfo,
|
|
"DsrGetForestTrustInformation: %ws returns %ld\n",
|
|
TrustedDomainName,
|
|
NetStatus ));
|
|
|
|
if ( DomainInfo != NULL ) {
|
|
NlDereferenceDomain( DomainInfo );
|
|
}
|
|
return NetStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NetrGetForestTrustInformation (
|
|
IN LPWSTR ServerName OPTIONAL,
|
|
IN LPWSTR ComputerName,
|
|
IN PNETLOGON_AUTHENTICATOR Authenticator,
|
|
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
|
|
IN DWORD Flags,
|
|
OUT PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The server side of the secure channel version of DsGetForestTrustInformation.
|
|
|
|
The inbound secure channel identified by ComputerName must be for an interdomain trust
|
|
and the inbound TDO must have the TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set.
|
|
|
|
|
|
Arguments:
|
|
|
|
ServerName - The name of the domain controller this API is remoted to.
|
|
|
|
ComputerName -- Name of the DC server making the call.
|
|
|
|
Authenticator -- supplied by the server.
|
|
|
|
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
|
|
|
|
Flags - Specifies a set of bits that modify the behavior of the API.
|
|
No values are currently defined. The caller should pass zero.
|
|
|
|
ForestTrustInfo - Returns a pointer to a structure containing a count and an
|
|
array of FTInfo records describing the namespaces claimed by the
|
|
domain specified by TrustedDomainName. The Accepted field and Time
|
|
field of all returned records will be zero. The buffer should be freed
|
|
by calling NetApiBufferFree.
|
|
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS -- The function completed successfully.
|
|
|
|
STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
|
|
the PDC.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
NET_API_STATUS NetStatus;
|
|
|
|
PDOMAIN_INFO DomainInfo = NULL;
|
|
PSERVER_SESSION ServerSession;
|
|
NETLOGON_SECURE_CHANNEL_TYPE SecureChannelType;
|
|
|
|
|
|
//
|
|
// Lookup which domain this call pertains to.
|
|
//
|
|
*ForestTrustInfo = NULL;
|
|
|
|
DomainInfo = NlFindDomainByServerName( ServerName );
|
|
|
|
NlPrintDom((NL_SESSION_SETUP, DomainInfo,
|
|
"NetrGetForestTrustInformation: %ws called: 0x%lx\n", ComputerName, Flags ));
|
|
|
|
if ( DomainInfo == NULL ) {
|
|
Status = STATUS_INVALID_COMPUTER_NAME;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// This API is not supported on workstations.
|
|
//
|
|
|
|
if ( NlGlobalMemberWorkstation ) {
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Find the server session entry for this secure channel.
|
|
//
|
|
|
|
LOCK_SERVER_SESSION_TABLE( DomainInfo );
|
|
ServerSession = NlFindNamedServerSession( DomainInfo, ComputerName );
|
|
|
|
if (ServerSession == NULL) {
|
|
UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
|
|
Status = STATUS_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Now verify the Authenticator and update seed if OK
|
|
//
|
|
|
|
Status = NlCheckAuthenticator(
|
|
ServerSession,
|
|
Authenticator,
|
|
ReturnAuthenticator);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
|
|
goto Cleanup;
|
|
}
|
|
|
|
SecureChannelType = ServerSession->SsSecureChannelType;
|
|
|
|
//
|
|
// This call is only valid on FOREST_TRANSITIVE trusts
|
|
//
|
|
|
|
if ( (ServerSession->SsFlags & SS_FOREST_TRANSITIVE) == 0 ) {
|
|
UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
|
|
|
|
NlPrintDom((NL_SESSION_SETUP, DomainInfo,
|
|
"NetrGetForestTrustInformation: %ws failed because F bit isn't set on the TDO\n",
|
|
ComputerName ));
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
|
|
|
|
if ( !IsDomainSecureChannelType( SecureChannelType ) ) {
|
|
|
|
NlPrintDom((NL_SESSION_SETUP, DomainInfo,
|
|
"NetrGetForestTrustInformation: %ws failed because secure channel isn't a domain secure channel\n",
|
|
ComputerName ));
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the forest trust information for the local machine
|
|
//
|
|
|
|
Status = LsaIGetForestTrustInformation( ForestTrustInfo );
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// If the request failed, be carefull to not leak authentication
|
|
// information.
|
|
//
|
|
|
|
if ( Status == STATUS_ACCESS_DENIED ) {
|
|
if ( ReturnAuthenticator != NULL ) {
|
|
RtlSecureZeroMemory( ReturnAuthenticator, sizeof(*ReturnAuthenticator) );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NlPrintDom(( NL_SESSION_SETUP, DomainInfo,
|
|
"NetrGetForestTrustInformation: %ws returns %lX\n",
|
|
ComputerName,
|
|
Status ));
|
|
|
|
if ( DomainInfo != NULL ) {
|
|
NlDereferenceDomain( DomainInfo );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|