|
|
/*
* Includes */ #include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntlsa.h>
#include <ntsam.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <lm.h>
#include <winsta.h>
#include <rpc.h>
#include <rpcdce.h>
#include <ntdsapi.h>
// For more info, check out \\index1\src\nt\private\security\tools\delegate\ldap.c
#include "usrprop.h"
#include "regapi.h"
extern "C" { BOOLEAN RegGetUserPolicy( LPWSTR userSID , PPOLICY_TS_USER pPolicy , PUSERCONFIGW pData ); void RegGetMachinePolicy( PPOLICY_TS_MACHINE pPolicy ); void RegMergeMachinePolicy( PPOLICY_TS_MACHINE pPolicy, USERCONFIGW *pMachineConfigData , WINSTATIONCREATE * pCreate ); BOOLEAN RegDenyTSConnectionsPolicy(); DWORD WaitForTSConnectionsPolicyChanges( BOOLEAN bWaitForAccept, HANDLE hExtraEvent);
BOOLEAN RegGetMachinePolicyEx( BOOLEAN forcePolicyRead, FILETIME *pTime , PPOLICY_TS_MACHINE pPolicy ); BOOLEAN RegIsMachineInHelpMode(); BOOLEAN RegIsTimeZoneRedirectionEnabled(); }
extern "C" { //
HKEY g_hTSPolicyKey = NULL;//handle to TS_POLICY_SUB_TREE key
HKEY g_hTSControlKey = NULL;//handle to REG_CONTROL_TSERVER key
}
/******************************************************************
* * * Check to see if the policy is set to stop accepting connections * * * ******************************************************************/ BOOLEAN RegDenyTSConnectionsPolicy() { LONG errorCode = ERROR_SUCCESS; DWORD ValueType; DWORD ValueSize = sizeof(DWORD); DWORD valueData ;
//
// first check the policy tree,
//
if( !g_hTSPolicyKey ) { errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &g_hTSPolicyKey );
//If error code is ERROR_FILE_NOT_FOUND, this is not an error.
if( !g_hTSPolicyKey && errorCode != ERROR_FILE_NOT_FOUND ) { //we could not open policy key for some reason other
//than key not found.
//return TRUE to be on the safe side
return TRUE; } } if ( g_hTSPolicyKey ) { errorCode = RegQueryValueEx( g_hTSPolicyKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType, (LPBYTE) &valueData, &ValueSize ); switch( errorCode ) { case ERROR_SUCCESS : return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
break;
case ERROR_KEY_DELETED: // Group policy must have deleted this key, close it
// Then, below we check for the local machine key
RegCloseKey( g_hTSPolicyKey ); g_hTSPolicyKey = NULL; break;
case ERROR_FILE_NOT_FOUND: // there is no policy from GP, so see (below) what the local machine
// value has.
break;
default: // if we are having any other kind of a problem, claim TRUE and
// stop connections to be on the safe side (a security angle).
return TRUE; break; } }
// if we got this far, then no policy was set. Check the local machine now.
if( !g_hTSControlKey ) { errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0, KEY_READ, &g_hTSControlKey ); }
if ( g_hTSControlKey ) { errorCode = RegQueryValueEx( g_hTSControlKey, POLICY_DENY_TS_CONNECTIONS , NULL, &ValueType, (LPBYTE) &valueData, &ValueSize ); if (errorCode == ERROR_SUCCESS ) { return ( valueData ? TRUE : FALSE ) ; // we have data from the policyKey handle to return
}
}
// if no localKey, gee... the registry is missing data... return TRUE to be on the safe side
return TRUE; }
/******************************************************************
* * * Wait until POLICY_DENY_TS_CONNECTIONS is changed * * * * Parameters: * * bWaitForAccept * * if TRUE, test if connections are accepted and wait for * * them to be accepted if they are not currently accepted. * * if FALSE, test if connections are not accepted and wait * * for them to be denied if they are currently accepted. * * * * hExtraEvent * * optional handle to an event to wait for. * * * * Returns: * * WAIT_OBJECT_0 * * if a change in TS connections policy occurred * * * * WAIT_OBJECT_0 + 1 * * if the extra event is present and signaled * * * ******************************************************************/ //
// Note that opening the global g_hTSControlKey without protection
// can cause the key to be opened twice.
//
// This macro is TRUE if the TS connections are denied
#define TSConnectionsDenied (RegDenyTSConnectionsPolicy() && \
!(RegIsMachinePolicyAllowHelp() && RegIsMachineInHelpMode()))
DWORD WaitForTSConnectionsPolicyChanges( BOOLEAN bWaitForAccept, HANDLE hExtraEvent ) { DWORD errorCode = ERROR_SUCCESS; HKEY hControlKey = NULL; HKEY hPoliciesKey = NULL; HKEY hFipsPolicy = NULL; HANDLE hEvents[4] = { NULL, NULL, NULL, NULL };
//
// Wait for a policy change if
// we want TS connections and they are denied OR
// we don't want TS connections and they are accepted
//
if((bWaitForAccept && TSConnectionsDenied) || (!bWaitForAccept && !TSConnectionsDenied)) { errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0, KEY_READ, &hControlKey ); if( !hControlKey ) { goto error_exit; }
//We cannot wait for g_hTSPolicyKey because it can be deleted and created
//Instead we wait for HKLM\Policies key
errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Policies"), 0, KEY_READ, &hPoliciesKey ); if( !hPoliciesKey ) { goto error_exit; } errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_FIPS_POLICY, 0, KEY_READ, &hFipsPolicy );
hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL); if( !hEvents[0]) { errorCode = GetLastError(); goto error_exit; }
hEvents[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
if( !hEvents[1]) { errorCode = GetLastError(); goto error_exit; }
hEvents[2] = CreateEvent(NULL,FALSE,FALSE,NULL);
if( !hEvents[2]) { errorCode = GetLastError(); goto error_exit; }
hEvents[3] = hExtraEvent;
DWORD whichObject;
errorCode = RegNotifyChangeKeyValue(hControlKey, FALSE,REG_NOTIFY_CHANGE_LAST_SET, hEvents[0], TRUE );
if( errorCode != ERROR_SUCCESS ) { goto error_exit; } errorCode = RegNotifyChangeKeyValue(hPoliciesKey, TRUE,REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME, hEvents[1], TRUE );
if( errorCode != ERROR_SUCCESS ) { goto error_exit; }
errorCode = RegNotifyChangeKeyValue(hFipsPolicy, TRUE,REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME, hEvents[2], TRUE );
if( errorCode != ERROR_SUCCESS ) { goto error_exit; }
if ( hExtraEvent == NULL ) { whichObject = WaitForMultipleObjects(3,hEvents,FALSE,INFINITE); } else { whichObject = WaitForMultipleObjects(4,hEvents,FALSE,INFINITE); } errorCode = GetLastError(); CloseHandle( hEvents[0] ); CloseHandle( hEvents[1] ); CloseHandle( hEvents[2] ); RegCloseKey(hPoliciesKey); RegCloseKey(hControlKey); RegCloseKey(hFipsPolicy);
if(whichObject == WAIT_FAILED) { SetLastError( errorCode ); return WAIT_FAILED; } else { if ( whichObject >= WAIT_OBJECT_0 + 2 ) { return WAIT_OBJECT_0 + 1; } else { return WAIT_OBJECT_0; } } } return WAIT_OBJECT_0;
error_exit:
if(hEvents[0]) { CloseHandle( hEvents[0] ); }
if(hEvents[1]) { CloseHandle( hEvents[1] ); }
if(hEvents[2]) { CloseHandle( hEvents[2] ); } if(hPoliciesKey) { RegCloseKey(hPoliciesKey); }
if(hControlKey) { RegCloseKey(hControlKey); }
if(hFipsPolicy) { RegCloseKey(hFipsPolicy); } SetLastError( errorCode );
return WAIT_FAILED;
}
/********************************************************************************
* * GPGetNumValue() * * Params * [in] policyKey : hkey to the policy reg tree where values are stored * [in] ValueName : name of the value (which is the policy) we are looking for * [out] pValueData: the data for the policy * * Return: * if the policy defined by the passed in valuename is present, then * return TRUE. Else, return FALSE * ********************************************************************************/ BOOLEAN GPGetNumValue( HKEY policyKey, LPWSTR ValueName, DWORD *pValueData ) { LONG Status = ERROR_SUCCESS; DWORD ValueType; DWORD ValueSize = sizeof(DWORD); // init data value to zero, just to get Prefix off our backs. This is a wasted OP
// since unless policy is set, value is not used.
*pValueData = 0;
//
// See if any values are present from the policyKey .
//
if ( policyKey ) { Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType, (LPBYTE) pValueData, &ValueSize ); if (Status == ERROR_SUCCESS ) { return TRUE; // we have data from the policyKey handle to return
} } // else, no key means policy is not set
return FALSE; } /********************************************************************************
* * GPGetStringValue() * * same as GPGetNumValue() but for policies that have a string value * * ********************************************************************************/
BOOLEAN GPGetStringValue( HKEY policyKey, LPWSTR ValueName, LPWSTR pValueData, DWORD MaxValueSize ) { LONG Status; DWORD ValueType; DWORD ValueSize = MaxValueSize << 1;
if (policyKey ) { Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType, (LPBYTE) pValueData, &ValueSize ); if ( Status != ERROR_SUCCESS || ValueSize == sizeof(UNICODE_NULL) ) { return FALSE; // no data found.
} else { if ( ValueType != REG_SZ ) { return FALSE; // bad data, pretend we have no data.
} } // we did get data
return( TRUE ); }
return FALSE;
}
/********************************************************************************
* * GPGetStringValue() * * Variant of the above function that returns false if error happens, but not * when value does not exist. * If the value does not exist it sets bValueExists to FALSE. * * ********************************************************************************/ extern "C" BOOLEAN GPGetStringValue( HKEY policyKey, LPWSTR ValueName, LPWSTR pValueData, DWORD MaxValueSize, BOOLEAN *pbValueExists) { LONG Status; DWORD ValueType; DWORD ValueSize = MaxValueSize << 1; if(!pValueData || !MaxValueSize) { return FALSE; }
*pbValueExists = FALSE; pValueData[0] = 0;
if (policyKey ) { Status = RegQueryValueEx( policyKey, ValueName, NULL, &ValueType, (LPBYTE) pValueData, &ValueSize ); if ( Status == ERROR_FILE_NOT_FOUND || ValueSize == sizeof(UNICODE_NULL) ) { return TRUE; // no data found.
} else { if ( Status != ERROR_SUCCESS || ValueType != REG_SZ ) { return FALSE; // bad data, DO NOT pretend we have no data.
} }
// we did get data
*pbValueExists = TRUE; return( TRUE ); } else { //Policy key may not exist. Now we pretend we have no data!
return TRUE; }
}
/*******************************************************************************
* * GPQueryUserConfig * * query USERCONFIG structure * * Params: * policyKey : hkey to the HKCU policy tree * pPolicy : points to the user policy struct which has flags for any policy * value that is present in the policy tree * pUser : pointer to a userconfigw struct used as a sracth pad to hold the * policy values (if present). * Return: * void * ******************************************************************************/
VOID GPQueryUserConfig( HKEY policyKey, PPOLICY_TS_USER pPolicy , PUSERCONFIGW pUser ) { UCHAR seed; UNICODE_STRING UnicodePassword; WCHAR encPassword[ PASSWORD_LENGTH + 2 ]; DWORD dwTmpValue;
// ----------------
pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM, pUser->InitialProgram, INITIALPROGRAM_LENGTH + 1 ); GPGetStringValue( policyKey, WIN_WORKDIRECTORY, pUser->WorkDirectory, DIRECTORY_LENGTH + 1 );
// ----------------
pPolicy->fPolicyResetBroken = GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue ); pUser->fResetBroken = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyReconnectSame = GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue ); pUser->fReconnectSame = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyShadow = GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue ); pUser->Shadow = (SHADOWCLASS) dwTmpValue;
// ----------------
pPolicy->fPolicyMaxSessionTime = GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue ); pUser->MaxConnectionTime = dwTmpValue;
// ----------------
pPolicy->fPolicyMaxDisconnectionTime = GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue ); pUser->MaxDisconnectionTime = dwTmpValue;
// ----------------
pPolicy->fPolicyMaxIdleTime = GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue ); pUser->MaxIdleTime = dwTmpValue;
// ----------------
pPolicy->fPolicyCallback = GPGetNumValue( policyKey, WIN_CALLBACK, &dwTmpValue ); pUser->Callback = (CALLBACKCLASS ) dwTmpValue;
// ----------------
pPolicy->fPolicyCallbackNumber = GPGetStringValue( policyKey, WIN_CALLBACKNUMBER, pUser->CallbackNumber, CALLBACK_LENGTH + 1 );
// ----------------
pPolicy->fPolicyAutoClientDrives = GPGetNumValue( policyKey,WIN_AUTOCLIENTDRIVES , &dwTmpValue ); pUser->fAutoClientDrives = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyAutoClientLpts = GPGetNumValue( policyKey,WIN_AUTOCLIENTLPTS , &dwTmpValue ); pUser->fAutoClientLpts = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyForceClientLptDef = GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue ); pUser->fForceClientLptDef = (BOOLEAN) dwTmpValue;
}
/*******************************************************************************
* RegGetUserPolicy() * * Params: * [in] userSID : user sid in a text format * [out] pPolicy : user policy struct * [out] pUser : policy values * * Return: * BOOLEAN : TRUE if user policy was found * FALSE if there was a problem getting user policy *******************************************************************************/ BOOLEAN RegGetUserPolicy( LPWSTR userSID , PPOLICY_TS_USER pPolicy, PUSERCONFIGW pUser ) { DWORD status= ERROR_SUCCESS;
HKEY policyKey; WCHAR userHive [MAX_PATH];
if (userSID) // this would never happen, but Master Prefix complains and we must server him!
{ wcscpy(userHive, userSID); wcscat(userHive, L"\\"); wcscat(userHive, TS_POLICY_SUB_TREE ); status = RegOpenKeyEx( HKEY_USERS, userHive , 0, KEY_READ, &policyKey ); if (status == ERROR_SUCCESS ) { GPQueryUserConfig( policyKey, pPolicy, pUser ); RegCloseKey( policyKey );
return TRUE; } }
return FALSE;
}
/*******************************************************************************
* GPQueryMachineConfig() * * Params: * [in] policyKey : key to the policy tree under hklm * [out] pPolicy : pointer to a machine policy data that is filled up by this function * * Return: * void * * * !!! WARNING !!! * * All TS related values MUST be in the flat TS-POLICY-TREE, no sub keys. * This is due to the fact that time-stamp checks by the caller of RegGetMachinePolicyEx() will * check the time stamp on the TS-POLICY key, which is NOT updated when a value in a sub-key is * altered. * * *******************************************************************************/ void GPQueryMachineConfig( HKEY policyKey, PPOLICY_TS_MACHINE pPolicy ) { DWORD dwTmpValue;
// ---------------- SessionDirectoryActive
pPolicy->fPolicySessionDirectoryActive = GPGetNumValue( policyKey,WIN_SESSIONDIRECTORYACTIVE, &dwTmpValue ); pPolicy->SessionDirectoryActive = (BOOLEAN) dwTmpValue;
// ---------------- SessionDirectoryLocation
pPolicy->fPolicySessionDirectoryLocation = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYLOCATION , pPolicy->SessionDirectoryLocation, DIRECTORY_LENGTH + 1 );
// ---------------- SessionDirectoryClusterName
pPolicy->fPolicySessionDirectoryClusterName = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYCLUSTERNAME , pPolicy->SessionDirectoryClusterName, DIRECTORY_LENGTH + 1 );
// ---------------- SessionDirectoryAdditionalParams
pPolicy->fPolicySessionDirectoryAdditionalParams = GPGetStringValue( policyKey, WIN_SESSIONDIRECTORYADDITIONALPARAMS , pPolicy->SessionDirectoryAdditionalParams, DIRECTORY_LENGTH + 1 ); // ---------------- EnableTimeZoneRedirection
pPolicy->fPolicyEnableTimeZoneRedirection = GPGetNumValue( policyKey,POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION , &dwTmpValue ); pPolicy->fEnableTimeZoneRedirection = (BOOLEAN) dwTmpValue;
// ---------------- EncryptRPCTraffic
pPolicy->fPolicyEncryptRPCTraffic = GPGetNumValue( policyKey, POLICY_TS_ENCRYPT_RPC_TRAFFIC , &dwTmpValue ); if(pPolicy->fPolicyEncryptRPCTraffic) { pPolicy->fEncryptRPCTraffic = (BOOLEAN) dwTmpValue; } else { pPolicy->fEncryptRPCTraffic = FALSE; }
// ---------------- Clipboard
pPolicy->fPolicyDisableClip = GPGetNumValue( policyKey,WIN_DISABLECLIP, &dwTmpValue ); pPolicy->fDisableClip = (BOOLEAN) dwTmpValue;
// ---------------- Audio
pPolicy->fPolicyDisableCam = GPGetNumValue( policyKey,WIN_DISABLECAM , &dwTmpValue ); pPolicy->fDisableCam = (BOOLEAN) dwTmpValue;
// ---------------- Comport
pPolicy->fPolicyDisableCcm = GPGetNumValue( policyKey,WIN_DISABLECCM , &dwTmpValue ); pPolicy->fDisableCcm = (BOOLEAN) dwTmpValue;
// ---------------- LPT
pPolicy->fPolicyDisableLPT = GPGetNumValue( policyKey,WIN_DISABLELPT , &dwTmpValue ); pPolicy->fDisableLPT = (BOOLEAN) dwTmpValue;
// ---------------- PRN
pPolicy->fPolicyDisableCpm = GPGetNumValue( policyKey,WIN_DISABLECPM , &dwTmpValue ); pPolicy->fDisableCpm = (BOOLEAN) dwTmpValue;
// ---------------- Password
pPolicy->fPolicyPromptForPassword = GPGetNumValue( policyKey, WIN_PROMPTFORPASSWORD , &dwTmpValue ); pPolicy->fPromptForPassword = (BOOLEAN) dwTmpValue;
// ---------------- Max Instance Count
pPolicy->fPolicyMaxInstanceCount = GPGetNumValue( policyKey,WIN_MAXINSTANCECOUNT , &dwTmpValue ); pPolicy->MaxInstanceCount = dwTmpValue;
// ---------------- Min Encryption Level
pPolicy->fPolicyMinEncryptionLevel = GPGetNumValue( policyKey, WIN_MINENCRYPTIONLEVEL , &dwTmpValue ); pPolicy->MinEncryptionLevel = (BYTE) dwTmpValue;
// ---------------- AutoReconect
pPolicy->fPolicyDisableAutoReconnect = GPGetNumValue( policyKey, WIN_DISABLEAUTORECONNECT , &dwTmpValue ); pPolicy->fDisableAutoReconnect = (BOOLEAN) dwTmpValue;
// New machine wide profile, home dir and home drive
/*
pPolicy->fPolicyWFProfilePath = GPGetStringValue( policyKey, WIN_WFPROFILEPATH, pPolicy ->WFProfilePath, DIRECTORY_LENGTH + 1 ); */ pPolicy->fErrorInvalidProfile = FALSE; BOOLEAN bValueExists;
pPolicy->fErrorInvalidProfile = !GPGetStringValue( policyKey, WIN_WFPROFILEPATH, pPolicy ->WFProfilePath, DIRECTORY_LENGTH + 1, &bValueExists ); pPolicy->fPolicyWFProfilePath = bValueExists; if (!pPolicy->fPolicyWFProfilePath) { pPolicy->WFProfilePath[0]=L'\0'; }
pPolicy->fPolicyWFHomeDir = GPGetStringValue( policyKey, WIN_WFHOMEDIR , pPolicy->WFHomeDir, DIRECTORY_LENGTH + 1 ); if (!pPolicy->fPolicyWFHomeDir) { pPolicy->WFHomeDir[0]=L'\0'; }
pPolicy->fPolicyWFHomeDirDrive =GPGetStringValue( policyKey, WIN_WFHOMEDIRDRIVE, pPolicy->WFHomeDirDrive, 4 ); if(!pPolicy->WFHomeDir[0]) { pPolicy->WFHomeDirDrive[0] = L'\0'; }
// if home dir is of the form "driveletter:\path" (such as c:\foo), null out the dir-drive to
// eliminate any confusion.
if ( pPolicy->WFHomeDir[1] == L':' ) { pPolicy->WFHomeDirDrive[0] = L'\0'; }
// --------------- deny connection policy, this is directly read by RegDenyTSConnectionsPolicy() too
pPolicy->fPolicyDenyTSConnections = GPGetNumValue( policyKey, POLICY_DENY_TS_CONNECTIONS , &dwTmpValue ); pPolicy->fDenyTSConnections = (BOOLEAN) dwTmpValue;
// track the rest of all possivle GP policies
// even thou not all are used by term-srv's USERCONFIGW . A good example is the
// delete tmp folders that Winlogon/wlnotify uses.
// --------------- Per session tmp folders, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
pPolicy->fPolicyTempFoldersPerSession = GPGetNumValue( policyKey, REG_TERMSRV_PERSESSIONTEMPDIR , &dwTmpValue ); pPolicy-> fTempFoldersPerSession = (BOOLEAN) dwTmpValue;
// -------------- delete per session folders on exit, WARNING : GINA reads policy tree directly for the sake of lower overhead during login
pPolicy->fPolicyDeleteTempFoldersOnExit = GPGetNumValue( policyKey, REG_CITRIX_DELETETEMPDIRSONEXIT , &dwTmpValue ); pPolicy->fDeleteTempFoldersOnExit = (BOOLEAN) dwTmpValue;
pPolicy->fPolicyPreventLicenseUpgrade = GPGetNumValue( policyKey, REG_POLICY_PREVENT_LICENSE_UPGRADE , &dwTmpValue ); pPolicy->fPreventLicenseUpgrade = (BOOLEAN) dwTmpValue;
pPolicy->fPolicySecureLicensing = GPGetNumValue( policyKey, REG_POLICY_SECURE_LICENSING , &dwTmpValue ); pPolicy->fSecureLicensing = (BOOLEAN) dwTmpValue;
// -------------- Color Depth
pPolicy->fPolicyColorDepth = GPGetNumValue( policyKey, POLICY_TS_COLOR_DEPTH , &dwTmpValue ); // disabled policy will set value to zero, which we will force it
// to be the min color depth of 8 bits.
if ( dwTmpValue < TS_8BPP_SUPPORT ) { pPolicy->ColorDepth = TS_8BPP_SUPPORT ; } else if ( dwTmpValue == TS_CLIENT_COMPAT_BPP_SUPPORT ) { pPolicy->ColorDepth = TS_24BPP_SUPPORT; // our current max, may change in teh future.
} else { pPolicy->ColorDepth = dwTmpValue; }
// ---------------- TSCC's permissions TAB
pPolicy->fPolicyWritableTSCCPermissionsTAB = GPGetNumValue( policyKey, POLICY_TS_TSCC_PERM_TAB_WRITABLE , &dwTmpValue ); pPolicy->fWritableTSCCPermissionsTAB= (BOOLEAN) dwTmpValue;
// ----------------
// Ritu has folded the user policy into machine policy for the drive re-direction.
pPolicy->fPolicyDisableCdm = GPGetNumValue( policyKey, WIN_DISABLECDM , &dwTmpValue ); pPolicy->fDisableCdm = (BOOLEAN) dwTmpValue;
// ----------------
// fold user config policy into machine config policy
pPolicy->fPolicyForceClientLptDef = GPGetNumValue( policyKey,WIN_FORCECLIENTLPTDEF , &dwTmpValue ); pPolicy->fForceClientLptDef = (BOOLEAN) dwTmpValue;
// for user config policy into machine config policy
// ----------------
pPolicy->fPolicyShadow = GPGetNumValue( policyKey, WIN_SHADOW, &dwTmpValue ); pPolicy->Shadow = (SHADOWCLASS) dwTmpValue;
//
// ---- Sessions Policy
//
// ----------------
pPolicy->fPolicyResetBroken = GPGetNumValue( policyKey,WIN_RESETBROKEN , & dwTmpValue ); pPolicy->fResetBroken = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyReconnectSame = GPGetNumValue( policyKey,WIN_RECONNECTSAME , &dwTmpValue ); pPolicy->fReconnectSame = (BOOLEAN) dwTmpValue;
// ----------------
pPolicy->fPolicyMaxSessionTime = GPGetNumValue( policyKey, WIN_MAXCONNECTIONTIME , &dwTmpValue ); pPolicy->MaxConnectionTime = dwTmpValue;
// ----------------
pPolicy->fPolicyMaxDisconnectionTime = GPGetNumValue( policyKey,WIN_MAXDISCONNECTIONTIME ,&dwTmpValue ); pPolicy->MaxDisconnectionTime = dwTmpValue;
// ----------------
pPolicy->fPolicyMaxIdleTime = GPGetNumValue( policyKey,WIN_MAXIDLETIME , &dwTmpValue ); pPolicy->MaxIdleTime = dwTmpValue;
// ---------------- Start program policy
pPolicy->fPolicyInitialProgram = GPGetStringValue( policyKey, WIN_INITIALPROGRAM, pPolicy->InitialProgram, INITIALPROGRAM_LENGTH + 1 ); GPGetStringValue( policyKey, WIN_WORKDIRECTORY, pPolicy->WorkDirectory, DIRECTORY_LENGTH + 1 );
// ---------------- single session per user
pPolicy->fPolicySingleSessionPerUser= GPGetNumValue( policyKey,POLICY_TS_SINGLE_SESSION_PER_USER, &dwTmpValue ); pPolicy->fSingleSessionPerUser = dwTmpValue;
pPolicy->fPolicySessionDirectoryExposeServerIP = GPGetNumValue( policyKey, REG_TS_SESSDIR_EXPOSE_SERVER_ADDR , &dwTmpValue ); pPolicy->SessionDirectoryExposeServerIP = dwTmpValue;
// policy for disabling wallpaper in remote desktop
pPolicy->fPolicyDisableWallpaper = GPGetNumValue( policyKey, POLICY_TS_NO_REMOTE_DESKTOP_WALLPAPER, &dwTmpValue ); pPolicy->fDisableWallpaper = dwTmpValue;
// policy to enable disable keep alive
pPolicy->fPolicyKeepAlive = GPGetNumValue( policyKey, KEEP_ALIVE_ENABLE_KEY , &dwTmpValue ); pPolicy->fKeepAliveEnable = dwTmpValue; GPGetNumValue( policyKey, KEEP_ALIVE_INTERVAL_KEY , &dwTmpValue ); pPolicy->KeepAliveInterval = dwTmpValue;
// Policy for disabling forcible logoff
pPolicy->fPolicyDisableForcibleLogoff = GPGetNumValue( policyKey, POLICY_TS_DISABLE_FORCIBLE_LOGOFF, &dwTmpValue ); pPolicy->fDisableForcibleLogoff = dwTmpValue; // ---------------- FIPS Encryption Enabled/Disabled
// FIPS policy key is stored separately from the others so we must explicity
// read it in from its location in registry
HKEY hkey; LONG lRet; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TS_FIPS_POLICY, 0, KEY_READ, &hkey);
if (lRet == ERROR_SUCCESS) { // if policy is not set GPGetNumValue returns dwTmpValue = 0
GPGetNumValue(hkey, FIPS_ALGORITH_POLICY, &dwTmpValue); pPolicy->fPolicyFipsEnabled = dwTmpValue; RegCloseKey(hkey); } else pPolicy->fPolicyFipsEnabled = 0; }
/*******************************************************************************
* RegGetMachinePolicy() * * Params: * [out] pPolicy : the machine policy used by ts session's userconfig * * Return: * void * *******************************************************************************/ void RegGetMachinePolicy( PPOLICY_TS_MACHINE pPolicy ) { NTSTATUS status= STATUS_SUCCESS;
HKEY policyKey;
status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &policyKey );
if ( status != ERROR_SUCCESS) { policyKey = NULL; // prefix complains.
}
// ok to call this with policyKey=NULL since func will init pPolicy using default values for the case of NULL key.
GPQueryMachineConfig( policyKey, pPolicy );
if ( policyKey ) { RegCloseKey( policyKey ); }
}
/*******************************************************************************
* RegGetMachinePolicyiEx() * * This func is identical to RegGetMachinePolicy() , and provides the time stampt for * the last write time of the policy key, and if the time of the key is the same as the * time for the last read, then it will not bother with any reads and return false * * Params: * [in ] forcePolicyRead : 1st time around, you want to init all vars so force a read. * [in/out] pTime : caller passes in the last write time for the machine policy key. * if key is missing, then time is set to zero. * On return, this param is updated to reflect the most recent * update time, which could be zero if the policy key was deleted * * [out] pPolicy : the machine policy struct updated * * Return: * TRUE : means there was a real change present * FALSE : means no values had changed. *******************************************************************************/ BOOLEAN RegGetMachinePolicyEx( BOOLEAN forcePolicyRead, FILETIME *pTime , PPOLICY_TS_MACHINE pPolicy ) { HKEY policyKey; HKEY FipsPolicyKey; FILETIME newTime; FILETIME FipsNewTime; NTSTATUS status = STATUS_SUCCESS; BOOLEAN rc = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &policyKey ); if (status != ERROR_SUCCESS) { policyKey = NULL; // prefix complains.
}
// if we have a policy key, get the time for that key
if (policyKey) { RegQueryInfoKey( policyKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &newTime ); }
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TS_FIPS_POLICY, 0, KEY_READ, &FipsPolicyKey); if (status != ERROR_SUCCESS) { FipsPolicyKey = NULL; // prefix complains.
}
// if we have a Fips policy key, get the time for that key
if (FipsPolicyKey) { RegQueryInfoKey(FipsPolicyKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &FipsNewTime); }
// If we got times back for both policies pick the newest
if (policyKey && FipsPolicyKey) { if ( (FipsNewTime.dwHighDateTime > newTime.dwHighDateTime) || ( (FipsNewTime.dwHighDateTime == newTime.dwHighDateTime) && (FipsNewTime.dwLowDateTime > newTime.dwLowDateTime) ) ) { // FipsNewTime is newer, set it as the time to use
newTime = FipsNewTime; } } // If we don't have a time for either policy keys then init time to the current system time
else { SYSTEMTIME currentTimeOnSystemInSystemTimeUnits; GetSystemTime(¤tTimeOnSystemInSystemTimeUnits); SystemTimeToFileTime(¤tTimeOnSystemInSystemTimeUnits, &newTime); }
if ( forcePolicyRead || ( (pTime->dwHighDateTime < newTime.dwHighDateTime ) || ( ( pTime->dwHighDateTime == newTime.dwHighDateTime ) && pTime->dwLowDateTime < newTime.dwLowDateTime ) ) ) { // this call will init struct memebers even if the policy key in null, so it
// is required to make this call on startup, with or without an actual reg key being present
GPQueryMachineConfig( policyKey, pPolicy );
rc = TRUE; }
pTime->dwHighDateTime = newTime.dwHighDateTime; pTime->dwLowDateTime = newTime.dwLowDateTime;
if ( policyKey ) { RegCloseKey( policyKey ); } if ( FipsPolicyKey ) { RegCloseKey( FipsPolicyKey ); }
return rc; }
/*******************************************************************************
* RegMergeMachinePolicy() * * Params: * [in] pPolicy : policy data to use to override userconfig * [in/out] pWSConfig : userconfig data that is modified based on the policy data * * Return: * void * ********************************************************************************/ void RegMergeMachinePolicy( PPOLICY_TS_MACHINE pPolicy, // the policy override data
USERCONFIGW * pWSConfig, // the machine config data represented thru a USERCONFIGW data struct (mostly)
PWINSTATIONCREATE pCreate // some of winstation data is stored here
) { // ---------------------------------------------- Clipboard
if ( pPolicy->fPolicyDisableClip ) { pWSConfig->fDisableClip = pPolicy->fDisableClip; }
// ---------------------------------------------- Audio
if ( pPolicy->fPolicyDisableCam ) { pWSConfig->fDisableCam = pPolicy->fDisableCam; }
// ---------------------------------------------- Comport
if ( pPolicy->fPolicyDisableCcm ) { pWSConfig->fDisableCcm = pPolicy->fDisableCcm; }
// ---------------------------------------------- LPT
if ( pPolicy->fPolicyDisableLPT ) { pWSConfig->fDisableLPT = pPolicy->fDisableLPT; }
// ---------------------------------------------- PRN
if ( pPolicy->fPolicyDisableCpm ) { pWSConfig->fDisableCpm = pPolicy->fDisableCpm; }
// ---------------------------------------------- Password
if ( pPolicy->fPolicyPromptForPassword ) { pWSConfig->fPromptForPassword = pPolicy->fPromptForPassword; }
// ---------------------------------------------- Max Instance
if ( pPolicy->fPolicyMaxInstanceCount ) { pCreate->MaxInstanceCount = pPolicy->MaxInstanceCount; }
// ---------------------------------------------- Min Encryption Level
if ( pPolicy->fPolicyMinEncryptionLevel ) { pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel; }
// ---------------------------------------------- FIPS Enabled/Disabled
if ( pPolicy->fPolicyFipsEnabled ) { pWSConfig->MinEncryptionLevel = (BYTE)REG_FIPS_ENCRYPTION_LEVEL; } // ---------------------------------------------- Auto Reconnect disable
if ( pPolicy->fPolicyDisableAutoReconnect ) { pWSConfig->fDisableAutoReconnect = pPolicy->fDisableAutoReconnect; } //----------------------------------------------- "Invalid Profile" flag
if(pPolicy->fErrorInvalidProfile) { pWSConfig->fErrorInvalidProfile = pPolicy->fErrorInvalidProfile; }
// ---------------------------------------------- Profile Path
if (pPolicy->fPolicyWFProfilePath ) { wcscpy( pWSConfig->WFProfilePath, pPolicy->WFProfilePath ); }
// ---------------------------------------------- Home Directory
if ( pPolicy->fPolicyWFHomeDir ) { wcscpy( pWSConfig->WFHomeDir, pPolicy->WFHomeDir ); }
// ---------------------------------------------- Home Directory Drive
if ( pPolicy->fPolicyWFHomeDirDrive ) { wcscpy( pWSConfig->WFHomeDirDrive, pPolicy->WFHomeDirDrive ); }
// ---------------------------------------------- Color Depth
if ( pPolicy->fPolicyColorDepth) { pWSConfig->ColorDepth = pPolicy->ColorDepth ; pWSConfig->fInheritColorDepth = FALSE; }
//
if ( pPolicy->fPolicyDisableCdm) { pWSConfig->fDisableCdm = pPolicy->fDisableCdm; }
//
if ( pPolicy->fPolicyForceClientLptDef ) { pWSConfig->fForceClientLptDef = pPolicy->fForceClientLptDef; }
// Shadow
if ( pPolicy->fPolicyShadow) { pWSConfig->Shadow = pPolicy->Shadow; pWSConfig->fInheritShadow = FALSE; }
if (pPolicy->fPolicyResetBroken ) { pWSConfig->fResetBroken = pPolicy->fResetBroken; pWSConfig->fInheritResetBroken = FALSE; }
if (pPolicy->fPolicyReconnectSame ) { pWSConfig->fReconnectSame = pPolicy->fReconnectSame; pWSConfig->fInheritReconnectSame = FALSE; }
if (pPolicy->fPolicyMaxSessionTime ) { pWSConfig->MaxConnectionTime = pPolicy->MaxConnectionTime; pWSConfig->fInheritMaxSessionTime = FALSE; }
if (pPolicy->fPolicyMaxDisconnectionTime) { pWSConfig->MaxDisconnectionTime = pPolicy->MaxDisconnectionTime; pWSConfig->fInheritMaxDisconnectionTime = FALSE; }
if (pPolicy->fPolicyMaxIdleTime) { pWSConfig->MaxIdleTime = pPolicy->MaxIdleTime; pWSConfig->fInheritMaxIdleTime = FALSE; }
if (pPolicy->fPolicyInitialProgram) { wcscpy( pWSConfig->InitialProgram, pPolicy->InitialProgram ); wcscpy( pWSConfig->WorkDirectory, pPolicy->WorkDirectory ); pWSConfig->fInheritInitialProgram = FALSE; }
if ( pPolicy->fPolicyDisableWallpaper ) { pWSConfig->fWallPaperDisabled = pPolicy->fDisableWallpaper ; }
// ----------------------------------------------
// There is no UI for setting these... So it's probably never used
//
// if ( pPolicy->fPolicytSecurity )
// {
// pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
// pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
// }
// else
// {
// if ( pWSConfig->fInheritSecurity )
// {
// pWSConfig->fDisableEncryption = pPolicy->fDisableEncryption;
// pWSConfig->MinEncryptionLevel = pPolicy->MinEncryptionLevel;
// }
// }
}
__inline BOOL IsAppServer() { OSVERSIONINFOEX osVersionInfo; DWORDLONG dwlConditionMask = 0; BOOL fIsWTS = FALSE; osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); fIsWTS = GetVersionEx((OSVERSIONINFO *)&osVersionInfo) && (osVersionInfo.wSuiteMask & VER_SUITE_TERMINAL) && !(osVersionInfo.wSuiteMask & VER_SUITE_SINGLEUSERTS);
return fIsWTS; }
/*******************************************************************************
* RegIsTimeZoneRedirectionEnabled() * * Purpose: * Checks the registry settings for Time Zone redirection. * Params: * NONE * * Return: * TRUE if time zone redirection is enabled. * Note: * This function reads the registry only once. So for new settings to take * effect one needs to reboot machine. This is done on purpose, to avoid * confusions when one creates a session having TZ redirection disabled, then * disconnects, enables TZ redirection and reconnects again. ********************************************************************************/ BOOLEAN RegIsTimeZoneRedirectionEnabled() {
LONG errorCode = ERROR_SUCCESS; DWORD ValueType; DWORD ValueSize = sizeof(DWORD); DWORD valueData ; HKEY hKey = NULL; if(!IsAppServer()) { return FALSE; }
//
// first check the policy tree,
//
errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &hKey );
//If error code is ERROR_FILE_NOT_FOUND, this is not an error.
if( !hKey && errorCode != ERROR_FILE_NOT_FOUND ) { return FALSE; }
if ( hKey ) { errorCode = RegQueryValueEx( hKey, POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION, NULL, &ValueType, (LPBYTE) &valueData, &ValueSize ); RegCloseKey(hKey); hKey = NULL;
switch( errorCode ) { case ERROR_SUCCESS : return (valueData != 0); // we have data from the policyKey handle to return
case ERROR_FILE_NOT_FOUND: // there is no policy from GP, so see (below) what the local machine
// value has.
break;
default: // if we are having any other kind of a problem, claim FALSE
//to be on the safe side.
return FALSE; } }
// if we got this far, then no policy was set. Check the local machine now.
errorCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0, KEY_READ, &hKey );
if ( hKey ) { errorCode = RegQueryValueEx( hKey, POLICY_TS_ENABLE_TIME_ZONE_REDIRECTION, NULL, &ValueType, (LPBYTE) &valueData, &ValueSize );
RegCloseKey(hKey); hKey = NULL;
if (errorCode == ERROR_SUCCESS ) { return (valueData != 0); // we have data from the ControlKey handle to return
}
}
return FALSE; }
|