windows-nt/Source/XPSP1/NT/termsrv/winsta/server/setuinfo.c
2020-09-26 16:20:57 +08:00

386 lines
14 KiB
C

/*************************************************************************
*
* setuinfo.c
*
* Sets user logon information.
*
* Copyright Microsoft Corporation, 1998
*
*
*************************************************************************/
#include "precomp.h"
#include "tsremdsk.h"
#pragma hdrstop
// global vars
extern POLICY_TS_MACHINE g_MachinePolicy;
/*****************************************************************************
*
* MergeUserConfigData
*
* This is the final step in updating a Winstation's USERCONFIG data, which is the final merge of
* settings from 5 different sources of data, in the following precedence where top most has the highest
* precedence overriding all below it:
* Machine Policy
* User Policy
* TSCC
* TsUserEx
* Client preference settings
*
* By the time this call is made, the Client preference and TsUserEX data is already merged, where
* the result of that merge is in pWinstation's USERCONFIGW struct.
*
* The final call happens when user has logged in, and user policy data is present. When this func is called from
* RpcWinStationUpdateUserConfig, any user policy data that is not already overriden by machine policy will be
* set in USERCONFIG.
*
* The User policy has the following items which ARE repeated in Machine policy, and hence, Machine Policy takes precedence
* Remote Control Settings ( SHADOW)
* Start up program
* Session time out:
* time out for disconnected session
* time limit for active session
* time limit for idle session
* allow reconnect from oirginal client only
* terminate session when time limits are reaced (instead of disconnect).
*
* None of the session-time-out and start-up-program USER policies are relevant to
* sesion 0, or any session that is physically connected on the console.
*
* ENTRY:
* pWinStation
* Pointer to WINSTATION structure
* pPolicy
* TS user policy flags, could be NULL
* pPolicyData
* policy data if pPolicy is not NULL, otherwise, can be NULL
* pUserConfig
* Pointer to USERCONFIG structure, can be NULL if pWinstation already has user conifig data from SAM
*
* EXIT:
* STATUS_SUCCESS - no error
*
* USAGE
* fn( pWinstation, NULL, NULL, pUserConfig) will do a legacy merge of user data into pWinstation.
* Legacy merge means that data set by TSCC could override user data.
*
* fn( pWinstation, pPolicy, pPolicyData, NULL ) would override pWinstation data of user by per user data
* from group policy
*
****************************************************************************/
VOID
MergeUserConfigData( PWINSTATION pWinStation,
PPOLICY_TS_USER pPolicy,
PUSERCONFIGW pPolicyData,
PUSERCONFIG pUserConfig )
{
PUSERCONFIG pWSConfig;
PPOLICY_TS_MACHINE pMachinePolicy;
BOOLEAN dontApplySomePolicy ;
BOOL bValidHelpSessionLogin;
pWSConfig = & pWinStation->Config.Config.User;
pMachinePolicy = & g_MachinePolicy;
// active console ID is the ID of the session that is physically connected to the real video drivers at this time.
dontApplySomePolicy = ( pWinStation->LogonId == 0 ) || (pWinStation->LogonId == (USER_SHARED_DATA->ActiveConsoleId) );
// None of the session-time-out and start-up-program USER policies are relevant to
// sesion 0, or any session that is physically connected on the console.
if (! dontApplySomePolicy )
{
// if sessions0, or if sessions is the phisical console, then we do not want to apply certain policies at all.
if ( ! pMachinePolicy->fPolicyInitialProgram ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyInitialProgram )
{
wcscpy( pWSConfig->InitialProgram, pPolicyData->InitialProgram );
wcscpy( pWSConfig->WorkDirectory, pPolicyData->WorkDirectory );
pWSConfig->fInheritInitialProgram = FALSE;
}
else if (pUserConfig)
{
/*
* Use initial program/working directory from user config if WinStation
* config says inherit and user config does NOT say inherit from client.
*/
if ( pWSConfig->fInheritInitialProgram &&
!pUserConfig->fInheritInitialProgram ) {
/*
* Always copy the user config info in this case, plugs security hole.
*/
wcscpy( pWSConfig->InitialProgram, pUserConfig->InitialProgram );
wcscpy( pWSConfig->WorkDirectory, pUserConfig->WorkDirectory );
}
}
}
if ( ! pMachinePolicy->fPolicyResetBroken ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyResetBroken )
{
pWSConfig->fResetBroken = pPolicyData->fResetBroken;
pWSConfig->fInheritResetBroken = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritResetBroken )
pWSConfig->fResetBroken = pUserConfig->fResetBroken;
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyReconnectSame ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyReconnectSame )
{
pWSConfig->fReconnectSame = pPolicyData->fReconnectSame;
pWSConfig->fInheritReconnectSame = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritReconnectSame )
pWSConfig->fReconnectSame = pUserConfig->fReconnectSame;
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyMaxSessionTime ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyMaxSessionTime )
{
pWSConfig->MaxConnectionTime = pPolicyData->MaxConnectionTime;
pWSConfig->fInheritMaxSessionTime = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritMaxSessionTime )
pWSConfig->MaxConnectionTime = pUserConfig->MaxConnectionTime;
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyMaxDisconnectionTime ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyMaxDisconnectionTime )
{
pWSConfig->MaxDisconnectionTime = pPolicyData->MaxDisconnectionTime;
pWSConfig->fInheritMaxDisconnectionTime = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritMaxDisconnectionTime )
pWSConfig->MaxDisconnectionTime = pUserConfig->MaxDisconnectionTime;
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyMaxIdleTime ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyMaxIdleTime )
{
pWSConfig->MaxIdleTime = pPolicyData->MaxIdleTime;
pWSConfig->fInheritMaxIdleTime = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritMaxIdleTime )
pWSConfig->MaxIdleTime = pUserConfig->MaxIdleTime;
}
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyShadow ) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyShadow )
{
pWSConfig->Shadow = pPolicyData->Shadow;
pWSConfig->fInheritShadow = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritShadow )
pWSConfig->Shadow = pUserConfig->Shadow;
}
}
// ----------------------------------------------
// we don't have a machine policy for this item, which does not even have a UI for user policy...
// if ( ! pMachinePolicy->fPolicyCallback )
//
{
if ( pPolicy && pPolicy->fPolicyCallback )
{
pWSConfig->Callback = pPolicyData->Callback;
pWSConfig->fInheritCallback = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritCallback )
pWSConfig->Callback = pUserConfig->Callback;
}
}
// ----------------------------------------------
// we don't have a machine policy for this item, which does not even have a UI for user policy...
// if ( ! pMachinePolicy->fPolicyCallbackNumber )
//
{
if ( pPolicy && pPolicy->fPolicyCallbackNumber )
{
wcscpy( pWSConfig->CallbackNumber, pPolicyData->CallbackNumber );
pWSConfig->fInheritCallbackNumber = FALSE;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritCallbackNumber )
wcscpy( pWSConfig->CallbackNumber, pUserConfig->CallbackNumber );
}
}
// ----------------------------------------------
// we don't have a machine policy for this item. Policy forces a state, does not configure a preferance.
// if ( ! pMachinePolicy->fPolicyAutoClientDrives )
//
{
if ( pPolicy && pPolicy->fPolicyAutoClientDrives)
{
pWSConfig->fAutoClientDrives = pPolicyData->fAutoClientDrives;
// In case other items such as
// lpt or def-printer are set to be inherited, such an
// inheritance of bits would continue for those items
// pWSConfig->fInheritAutoClient = FALSE;
//
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritAutoClient )
{
pWSConfig->fAutoClientDrives = pUserConfig->fAutoClientDrives;
}
}
}
// ----------------------------------------------
// we don't have a machine policy for this item. Policy forces a state, does not configure a preferance.
// if ( ! pMachinePolicy->fPolicyAutoClientLpts )
//
{
if ( pPolicy && pPolicy->fPolicyAutoClientLpts )
{
pWSConfig->fAutoClientLpts = pPolicyData->fAutoClientLpts;
}
else if (pUserConfig)
{
if (pWSConfig->fInheritAutoClient)
{
pWSConfig->fAutoClientLpts = pUserConfig->fAutoClientLpts;
}
}
}
// ----------------------------------------------
if ( ! pMachinePolicy->fPolicyForceClientLptDef) // if we don't have a machine policy for this, then it is ok to use User policy
{
if ( pPolicy && pPolicy->fPolicyForceClientLptDef )
{
pWSConfig->fForceClientLptDef = pPolicyData->fForceClientLptDef;
}
else if (pUserConfig)
{
if ( pWSConfig->fInheritAutoClient )
{
pWSConfig->fForceClientLptDef = pUserConfig->fForceClientLptDef;
}
}
}
if( TSIsSessionHelpSession( pWinStation, &bValidHelpSessionLogin ) )
{
// We disconnected RA if ticket is invalid.
ASSERT( TRUE == bValidHelpSessionLogin );
// Reset initial program.
pWSConfig->fInheritInitialProgram = FALSE;
//
// our string is still less than 256 (INITIALPROGRAM_LENGTH),
// need to revisit this if ever increase ticket ID and password length
//
_snwprintf(
pWSConfig->InitialProgram,
INITIALPROGRAM_LENGTH,
L"%s %s",
SALEMRDSADDINNAME,
pWinStation->Client.WorkDirectory
);
pWSConfig->WorkDirectory[0] = 0;
// reset winstation when connection is broken
pWSConfig->fInheritResetBroken = FALSE;
pWSConfig->fResetBroken = TRUE;
//
// No re-direction
//
pWSConfig->fInheritAutoClient = FALSE;
pWSConfig->fAutoClientDrives = FALSE;
pWSConfig->fAutoClientLpts = FALSE;
pWSConfig->fForceClientLptDef = FALSE;
}
// Cache the original shadow setting so we can reset shadow setting
// at the end of shadow call, we don't to look it up from registry again
// as winstion shadow setting might change, in addition, a common
// winstation configuration for more than one NIC might get split
// into different winstation, in that case, we will spend a lot time
// figure out which winstation to use.
// We do this here to pick up new value from RpcWinStationUpdateUserConfig
//
pWinStation->OriginalShadowClass = pWSConfig->Shadow;
}
/*****************************************************************************
*
* ResetUserConfigData
*
* ENTRY:
* pWinStation
* Pointer to WINSTATION structure
*
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
VOID
ResetUserConfigData( PWINSTATION pWinStation )
{
PUSERCONFIG pWSConfig = &pWinStation->Config.Config.User;
if ( pWSConfig->fInheritInitialProgram ) {
pWSConfig->InitialProgram[0] = 0;
pWSConfig->WorkDirectory[0] = 0;
}
}