|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997-2001.
//
// File: N C P E R M S . C P P
//
// Contents: Common routines for dealing with permissions.
//
// Notes: Pollute this under penalty of death.
//
// Author: shaunco 20 Sep 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include <ntseapi.h>
#include "ncbase.h"
#include "ncdebug.h"
#include "ncperms.h"
#include "netconp.h"
#include "ncreg.h"
#include "lm.h"
CGroupPolicyBase* g_pNetmanGPNLA = NULL;
#define INITGUID
#include <nmclsid.h>
//+---------------------------------------------------------------------------
//
// Function: FCheckGroupMembership
//
// Purpose: Returns TRUE if the logged on user is a member of the
// specified group.
//
// Arguments:
// dwRID [in] Group RID to check against.
//
// Returns: TRUE if the logged on user is a member of the specified group
//
// Author: scottbri 14 Sept 1998
//
// Notes:
//
BOOL FCheckGroupMembership(IN DWORD dwRID) { SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_NT_AUTHORITY; PSID psid; BOOL fIsMember = FALSE;
// Allocate a SID for the Administrators group and check to see
// if the user is a member.
//
if (AllocateAndInitializeSid (&SidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, dwRID, 0, 0, 0, 0, 0, 0, &psid)) { if (!CheckTokenMembership (NULL, psid, &fIsMember)) { fIsMember = FALSE; TraceLastWin32Error ("FCheckGroupMembership - CheckTokenMemberShip failed."); }
FreeSid (psid); } else { TraceLastWin32Error ("FCheckGroupMembership - AllocateAndInitializeSid failed."); }
return fIsMember; }
//+---------------------------------------------------------------------------
//
// Function: FIsUserAdmin
//
// Purpose: Returns TRUE if the logged on user is a member of the
// Administrators local group.
//
// Arguments:
// (none)
//
// Returns: TRUE if the logged on user is a member of the
// Administrators local group. False otherwise.
//
// Author: shaunco 19 Mar 1998
//
// Notes:
//
BOOL FIsUserAdmin() { BOOL fIsMember;
// Check the administrators group
//
fIsMember = FCheckGroupMembership(DOMAIN_ALIAS_RID_ADMINS);
return fIsMember; }
//#define ALIGN_DWORD(_size) (((_size) + 3) & ~3)
//#define ALIGN_QWORD(_size) (((_size) + 7) & ~7)
#define SIZE_ALIGNED_FOR_TYPE(_size, _type) \
(((_size) + sizeof(_type)-1) & ~(sizeof(_type)-1))
//+---------------------------------------------------------------------------
//
// Function: HrAllocateSecurityDescriptorAllowAccessToWorld
//
// Purpose: Allocate a security descriptor and initialize it to
// allow access to everyone.
//
// Arguments:
// ppSd [out] Returned security descriptor.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 10 Nov 1998
//
// Notes: Free *ppSd with MemFree.
//
HRESULT HrAllocateSecurityDescriptorAllowAccessToWorld ( OUT PSECURITY_DESCRIPTOR* ppSd) { PSECURITY_DESCRIPTOR pSd = NULL; PSID pSid = NULL; PACL pDacl = NULL; DWORD dwErr = NOERROR; DWORD dwAlignSdSize; DWORD dwAlignDaclSize; DWORD dwSidSize; PVOID pvBuffer = NULL;
// Here is the buffer we are building.
//
// |<- a ->|<- b ->|<- c ->|
// +-------+--------+------+
// | p| p| |
// | SD a| DACL a| SID |
// | d| d| |
// +-------+-------+-------+
// ^ ^ ^
// | | |
// | | +--pSid
// | |
// | +--pDacl
// |
// +--pSd (this is returned via *ppSd)
//
// pad is so that pDacl and pSid are aligned properly.
//
// a = dwAlignSdSize
// b = dwAlignDaclSize
// c = dwSidSize
//
// Initialize output parameter.
//
*ppSd = NULL;
// Compute the size of the SID. The SID is the well-known SID for World
// (S-1-1-0).
//
dwSidSize = GetSidLengthRequired(1);
// Compute the size of the DACL. It has an inherent copy of SID within
// it so add enough room for it. It also must sized properly so that
// a pointer to a SID structure can come after it. Hence, we use
// SIZE_ALIGNED_FOR_TYPE.
//
dwAlignDaclSize = SIZE_ALIGNED_FOR_TYPE( sizeof(ACCESS_ALLOWED_ACE) + sizeof(ACL) + dwSidSize, PSID);
// Compute the size of the SD. It must be sized propertly so that a
// pointer to a DACL structure can come after it. Hence, we use
// SIZE_ALIGNED_FOR_TYPE.
//
dwAlignSdSize = SIZE_ALIGNED_FOR_TYPE( sizeof(SECURITY_DESCRIPTOR), PACL);
// Allocate the buffer big enough for all.
//
dwErr = ERROR_OUTOFMEMORY; pvBuffer = MemAlloc(dwSidSize + dwAlignDaclSize + dwAlignSdSize); if (pvBuffer) { SID_IDENTIFIER_AUTHORITY SidIdentifierWorldAuth = SECURITY_WORLD_SID_AUTHORITY; PULONG pSubAuthority;
dwErr = NOERROR;
// Setup the pointers into the buffer.
//
pSd = pvBuffer; pDacl = (PACL)((PBYTE)pvBuffer + dwAlignSdSize); pSid = (PSID)((PBYTE)pDacl + dwAlignDaclSize);
// Initialize pSid as S-1-1-0.
//
if (!InitializeSid( pSid, &SidIdentifierWorldAuth, 1)) // 1 sub-authority
{ dwErr = GetLastError(); goto finish; }
pSubAuthority = GetSidSubAuthority(pSid, 0); *pSubAuthority = SECURITY_WORLD_RID;
// Initialize pDacl.
//
if (!InitializeAcl( pDacl, dwAlignDaclSize, ACL_REVISION)) { dwErr = GetLastError(); goto finish; }
// Add an access-allowed ACE for S-1-1-0 to pDacl.
//
if (!AddAccessAllowedAce( pDacl, ACL_REVISION, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, pSid)) { dwErr = GetLastError(); goto finish; }
// Initialize pSd.
//
if (!InitializeSecurityDescriptor( pSd, SECURITY_DESCRIPTOR_REVISION)) { dwErr = GetLastError(); goto finish; }
// Set pSd to use pDacl.
//
if (!SetSecurityDescriptorDacl( pSd, TRUE, pDacl, FALSE)) { dwErr = GetLastError(); goto finish; }
// Set the owner for pSd.
//
if (!SetSecurityDescriptorOwner( pSd, NULL, FALSE)) { dwErr = GetLastError(); goto finish; }
// Set the group for pSd.
//
if (!SetSecurityDescriptorGroup( pSd, NULL, FALSE)) { dwErr = GetLastError(); goto finish; }
finish: if (!dwErr) { *ppSd = pSd; } else { MemFree(pvBuffer); } }
return HRESULT_FROM_WIN32(dwErr); }
//+--------------------------------------------------------------------------
//
// Function: HrEnablePrivilege
//
// Purpose: Enables the specified privilege for the current process
//
// Arguments:
// pszPrivilegeName [in] The name of the privilege
//
// Returns: HRESULT. S_OK if successful,
// a converted Win32 error code otherwise
//
// Author: billbe 13 Dec 1997
//
// Notes:
//
HRESULT HrEnablePrivilege ( IN PCWSTR pszPrivilegeName) { HANDLE hToken;
// Open the thread token in case it is impersonating
BOOL fWin32Success = OpenThreadToken (GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken);
// If there was no token for the thread, open the process token
//
if (!fWin32Success && (ERROR_NO_TOKEN == GetLastError ())) { // Get token to adjust privileges for this process
fWin32Success = OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); }
if (fWin32Success) { // get the luid that represents the privilege name
LUID luid; fWin32Success = LookupPrivilegeValue(NULL, pszPrivilegeName, &luid);
if (fWin32Success) { // set up the privilege structure
TOKEN_PRIVILEGES tpNewPrivileges; tpNewPrivileges.PrivilegeCount = 1; tpNewPrivileges.Privileges[0].Luid = luid; tpNewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// turn on the privilege
AdjustTokenPrivileges (hToken, FALSE, &tpNewPrivileges, 0, NULL, NULL);
if (ERROR_SUCCESS != GetLastError()) { fWin32Success = FALSE; } }
CloseHandle(hToken); }
HRESULT hr; // Convert any errors to an HRESULT
if (!fWin32Success) { hr = HrFromLastWin32Error(); } else { hr = S_OK; }
TraceError ("HrEnablePrivilege", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrEnableAllPrivileges
//
// Purpose: Enables all privileges for the current process.
//
// Arguments:
// pptpOld [out] Returns the previous state of privileges so that they can
// be restored.
//
// Returns: S_OK if successful, Win32 Error otherwise
//
// Author: danielwe 11 Aug 1997
//
// Notes: The pptpOld parameter should be freed with delete [].
//
HRESULT HrEnableAllPrivileges ( OUT TOKEN_PRIVILEGES** pptpOld) { Assert(pptpOld);
HRESULT hr = S_OK; HANDLE hTok; ULONG cbTok = 4096; BOOL fres;
// Try opening the thread token first in case of impersonation
fres = OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hTok);
if (!fres && (ERROR_NO_TOKEN == GetLastError())) { // If there was no thread token open the process token
fres = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTok); }
if (fres) { PTOKEN_PRIVILEGES ptpNew; hr = E_OUTOFMEMORY; ptpNew = (PTOKEN_PRIVILEGES)MemAlloc(cbTok); if (ptpNew) { hr = S_OK;
fres = GetTokenInformation(hTok, TokenPrivileges, ptpNew, cbTok, &cbTok); if (fres) { //
// Set the state settings so that all privileges are enabled...
//
if (ptpNew->PrivilegeCount > 0) { for (ULONG iPriv = 0; iPriv < ptpNew->PrivilegeCount; iPriv++) { ptpNew->Privileges[iPriv].Attributes = SE_PRIVILEGE_ENABLED; } }
*pptpOld = reinterpret_cast<PTOKEN_PRIVILEGES>(new BYTE[cbTok]);
fres = AdjustTokenPrivileges(hTok, FALSE, ptpNew, cbTok, *pptpOld, &cbTok); }
MemFree(ptpNew); }
CloseHandle(hTok); }
if (!fres) { hr = HrFromLastWin32Error(); }
TraceError("HrEnableAllPrivileges", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrRestorePrivileges
//
// Purpose: Restores the privileges for the current process after they have
// have been modified by HrEnableAllPrivileges().
//
// Arguments:
// ptpRestore [in] Previous state of privileges as returned by
// HrEnableAllPrivileges().
//
// Returns: S_OK if successful, Win32 Error otherwise
//
// Author: danielwe 11 Aug 1997
//
// Notes:
//
HRESULT HrRestorePrivileges ( IN TOKEN_PRIVILEGES* ptpRestore) { HRESULT hr = S_OK; HANDLE hTok = NULL ; BOOL fres = FALSE;
Assert(ptpRestore);
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTok)) { if (AdjustTokenPrivileges(hTok, FALSE, ptpRestore, 0, NULL, NULL)) { fres = TRUE; }
CloseHandle(hTok); }
if (!fres) { hr = HrFromLastWin32Error(); }
TraceError("HrRestorePrivileges", hr); return hr; }
extern const DECLSPEC_SELECTANY WCHAR c_szConnectionsPolicies[] = L"Software\\Policies\\Microsoft\\Windows\\Network Connections";
// User types
const DWORD USER_TYPE_ADMIN = 0x00000001; const DWORD USER_TYPE_NETCONFIGOPS = 0x00000002; const DWORD USER_TYPE_POWERUSER = 0x00000004; const DWORD USER_TYPE_USER = 0x00000008; const DWORD USER_TYPE_GUEST = 0x00000010;
typedef struct { DWORD dwShift; PCWSTR pszValue; DWORD dwApplyMask; } PERM_MAP_STRUCT;
extern const DECLSPEC_SELECTANY PERM_MAP_STRUCT USER_PERM_MAP[] = { {NCPERM_NewConnectionWizard, L"NC_NewConnectionWizard", APPLY_TO_ALL_USERS}, {NCPERM_Statistics, L"NC_Statistics", APPLY_TO_ALL_USERS}, {NCPERM_AddRemoveComponents, L"NC_AddRemoveComponents", APPLY_TO_ADMIN}, {NCPERM_RasConnect, L"NC_RasConnect", APPLY_TO_ALL_USERS}, {NCPERM_LanConnect, L"NC_LanConnect", APPLY_TO_ALL_USERS}, {NCPERM_DeleteConnection, L"NC_DeleteConnection", APPLY_TO_ALL_USERS}, {NCPERM_DeleteAllUserConnection, L"NC_DeleteAllUserConnection", APPLY_TO_ALL_USERS}, {NCPERM_RenameConnection, L"NC_RenameConnection", APPLY_TO_ALL_USERS}, {NCPERM_RenameMyRasConnection, L"NC_RenameMyRasConnection", APPLY_TO_ALL_USERS}, {NCPERM_ChangeBindState, L"NC_ChangeBindState", APPLY_TO_ADMIN}, {NCPERM_AdvancedSettings, L"NC_AdvancedSettings", APPLY_TO_ADMIN}, {NCPERM_DialupPrefs, L"NC_DialupPrefs", APPLY_TO_ALL_USERS}, {NCPERM_LanChangeProperties, L"NC_LanChangeProperties", APPLY_TO_OPS_OR_ADMIN}, {NCPERM_RasChangeProperties, L"NC_RasChangeProperties", APPLY_TO_ALL_USERS}, {NCPERM_LanProperties, L"NC_LanProperties", APPLY_TO_ALL_USERS}, {NCPERM_RasMyProperties, L"NC_RasMyProperties", APPLY_TO_ALL_USERS}, {NCPERM_RasAllUserProperties, L"NC_RasAllUserProperties", APPLY_TO_ALL_USERS}, {NCPERM_ShowSharedAccessUi, L"NC_ShowSharedAccessUi", APPLY_TO_LOCATION}, {NCPERM_AllowAdvancedTCPIPConfig, L"NC_AllowAdvancedTCPIPConfig", APPLY_TO_ALL_USERS}, {NCPERM_PersonalFirewallConfig, L"NC_PersonalFirewallConfig", APPLY_TO_LOCATION}, {NCPERM_AllowNetBridge_NLA, L"NC_AllowNetBridge_NLA", APPLY_TO_LOCATION}, {NCPERM_ICSClientApp, L"NC_ICSClientApp", APPLY_TO_LOCATION}, {NCPERM_EnDisComponentsAllUserRas, L"NC_EnDisComponentsAllUserRas", APPLY_TO_NON_ADMINS}, {NCPERM_EnDisComponentsMyRas, L"NC_EnDisComponentsMyRas", APPLY_TO_NON_ADMINS}, {NCPERM_ChangeMyRasProperties, L"NC_ChangeMyRasProperties", APPLY_TO_NON_ADMINS}, {NCPERM_ChangeAllUserRasProperties, L"NC_ChangeAllUserRasProperties", APPLY_TO_NON_ADMINS}, {NCPERM_RenameLanConnection, L"NC_RenameLanConnection", APPLY_TO_NON_ADMINS}, {NCPERM_RenameAllUserRasConnection, L"NC_RenameAllUserRasConnection", APPLY_TO_NON_ADMINS}, {NCPERM_IpcfgOperation, L"NC_IPConfigOperation", APPLY_TO_ALL_USERS}, {NCPERM_Repair, L"NC_Repair", APPLY_TO_ALL_USERS}, };
extern const DECLSPEC_SELECTANY PERM_MAP_STRUCT MACHINE_PERM_MAP[] = { {NCPERM_ShowSharedAccessUi, L"NC_ShowSharedAccessUi", APPLY_TO_LOCATION}, {NCPERM_PersonalFirewallConfig, L"NC_PersonalFirewallConfig", APPLY_TO_LOCATION}, {NCPERM_ICSClientApp, L"NC_ICSClientApp", APPLY_TO_LOCATION}, {NCPERM_AllowNetBridge_NLA, L"NC_AllowNetBridge_NLA", APPLY_TO_LOCATION} };
extern const LONG NCPERM_Min = NCPERM_NewConnectionWizard; extern const LONG NCPERM_Max = NCPERM_Repair;
// External policies (for now, only explorer has polices that affect our processing
//
extern const WCHAR c_szExplorerPolicies[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
extern const WCHAR c_szNCPolicyForAdministrators[] = L"NC_EnableAdminProhibits";
extern const WCHAR c_szNoNetworkConnectionPolicy[] = L"NoNetworkConnections";
static DWORD g_dwPermMask; static BOOL g_fPermsInited = FALSE;
inline VOID NCPERM_SETBIT(IN DWORD dw, IN DWORD dwVal) { DWORD dwBit = (1 << dw); g_dwPermMask = (g_dwPermMask & ~dwBit) | ((0==dwVal) ? 0 : dwBit); }
inline BOOL NCPERM_CHECKBIT(IN DWORD dw) { #ifdef DBG
if (!FIsPolicyConfigured(dw)) { if (0xFFFFFFFF != g_dwDbgPermissionsFail) { if (FProhibitFromAdmins() || !FIsUserAdmin()) { if ( (1 << dw) & g_dwDbgPermissionsFail) { TraceTag(ttidDefault, "Failing permissions check due to g_dwDbgPermissionsFail set"); return FALSE; } } } } #endif // DBG
return !!(g_dwPermMask & (1 << dw)); }
inline BOOL NCPERM_USER_IS_ADMIN(IN DWORD dwUserType) { return (dwUserType & USER_TYPE_ADMIN); }
inline BOOL NCPERM_USER_IS_NETCONFIGOPS(IN DWORD dwUserType) { return (dwUserType & USER_TYPE_NETCONFIGOPS); }
inline BOOL NCPERM_USER_IS_POWERUSER(IN DWORD dwUserType) { return (dwUserType & USER_TYPE_POWERUSER); }
inline BOOL NCPERM_USER_IS_USER(IN DWORD dwUserType) { return (dwUserType & USER_TYPE_USER); }
inline BOOL NCPERM_USER_IS_GUEST(IN DWORD dwUserType) { return (dwUserType & USER_TYPE_GUEST); }
inline BOOL NCPERM_APPLIES_TO_CURRENT_USER(IN DWORD dwUserType, IN DWORD dwApplyMask) { return (dwUserType & dwApplyMask); }
inline int NCPERM_FIND_MAP_ENTRY(IN ULONG ulPerm) {
for (int i = 0; i < celems(USER_PERM_MAP); i++)
{ if (USER_PERM_MAP[i].dwShift == ulPerm) { return i; } }
return -1; }
inline BOOL NCPERM_APPLIES_TO_LOCATION(IN ULONG ulPerm) { BOOL bAppliesToLocation = FALSE;
int nIdx = NCPERM_FIND_MAP_ENTRY(ulPerm);
if (nIdx != -1) { bAppliesToLocation = (USER_PERM_MAP[nIdx].dwApplyMask & APPLY_TO_LOCATION); } else { bAppliesToLocation = FALSE; } return bAppliesToLocation; }
inline BOOL NCPERM_APPLY_BASED_ON_LOCATION(IN ULONG ulPerm, IN DWORD dwPermission) { DWORD fSameNetwork = FALSE;
if (g_pNetmanGPNLA) { fSameNetwork = g_pNetmanGPNLA->IsSameNetworkAsGroupPolicies(); }
if (!fSameNetwork && NCPERM_APPLIES_TO_LOCATION(ulPerm)) { dwPermission = TRUE; } return dwPermission; }
inline DWORD NCPERM_USER_TYPE() { if (FIsUserAdmin()) { return USER_TYPE_ADMIN; } else if (FIsUserNetworkConfigOps()) { return USER_TYPE_NETCONFIGOPS; } else if (FIsUserPowerUser()) { return USER_TYPE_POWERUSER; } else if (FIsUserGuest()) { return USER_TYPE_GUEST; }
return USER_TYPE_USER; }
inline BOOL IsOsLikePersonal() { OSVERSIONINFOEXW verInfo = {0}; ULONGLONG ConditionMask = 0; static BOOL fChecked = FALSE; static BOOL fOsLikePersonal = FALSE; // Optimization, since OS can't change on the fly. Even a domain join requires a reboot.
// If that ever changes then this logic needs to be revisited.
// ISSUE: Revisit frequently. This may change.
if (fChecked) { return fOsLikePersonal; }
verInfo.dwOSVersionInfoSize = sizeof(verInfo); verInfo.wProductType = VER_NT_WORKSTATION; VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_LESS_EQUAL); if(VerifyVersionInfo(&verInfo, VER_PRODUCT_TYPE, ConditionMask)) { LPWSTR pszDomain; NETSETUP_JOIN_STATUS njs = NetSetupUnknownStatus; if (NERR_Success == NetGetJoinInformation(NULL, &pszDomain, &njs)) { NetApiBufferFree(pszDomain); } if (NetSetupDomainName == njs) { fOsLikePersonal = FALSE; // connected to domain
} else { fOsLikePersonal = TRUE; // Professional, but not a domain member
} } else { fOsLikePersonal = FALSE; }
fChecked = TRUE; return fOsLikePersonal; }
const ULONG c_arrayHomenetPerms[] = { NCPERM_PersonalFirewallConfig, NCPERM_ICSClientApp, NCPERM_ShowSharedAccessUi };
#ifdef DBG
ULONG g_dwDbgPermissionsFail = 0xFFFFFFFF; ULONG g_dwDbgWin2kPoliciesSet = 0xFFFFFFFF; #endif // DBG
//+---------------------------------------------------------------------------
//
// Function: FHasPermission
//
// Purpose: Called to determine if the requested permissions are available
//
// Arguments:
// ulPerm [in] Permission flags (E.g. NCPERM_xxxx)
// pGPBase [in] CGroupPolicyBase - the netman Group Policy Engine. In
// order to check a location aware policy, this must be
// passed in.
//
// Returns: BOOL, TRUE if the requested permission is granted to the user
//
BOOL FHasPermission(IN ULONG ulPerm, IN CGroupPolicyBase* pGPBase) { TraceFileFunc(ttidDefault);
DWORD dwCurrentUserType;
Assert(static_cast<LONG>(ulPerm) >= NCPERM_Min); Assert(static_cast<LONG>(ulPerm) <= NCPERM_Max);
g_pNetmanGPNLA = pGPBase;
//if we are using DataCenter, Back Office,
//Small Business Center, or Blade, then don't grant the permission
for (int i = 0; i < celems(c_arrayHomenetPerms); i++) { if (c_arrayHomenetPerms[i] == ulPerm) { // On IA64, all homenet technologies are unavailable.
#ifndef _WIN64
// Look for the enterprise SKUs
OSVERSIONINFOEXW verInfo = {0}; ULONGLONG ConditionMask = 0;
verInfo.dwOSVersionInfoSize = sizeof(verInfo); verInfo.wSuiteMask = VER_SUITE_DATACENTER | VER_SUITE_BACKOFFICE | VER_SUITE_SMALLBUSINESS_RESTRICTED | VER_SUITE_SMALLBUSINESS | VER_SUITE_BLADE;
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_OR);
if(VerifyVersionInfo(&verInfo, VER_SUITENAME, ConditionMask)) #endif
{ return FALSE; } } }
dwCurrentUserType = NCPERM_USER_TYPE();
if (NCPERM_USER_IS_ADMIN(dwCurrentUserType) && !FProhibitFromAdmins() && !NCPERM_APPLIES_TO_LOCATION(ulPerm)) { // If user is admin and we're not supposed to revoke
// anything from admins and this is not a location aware policy
// then just return TRUE
return TRUE; }
if (!g_fPermsInited) { TraceTag(ttidDefault, "Initializing permissions"); RefreshAllPermission(); g_fPermsInited = TRUE; } else { // update the requested permission only
HRESULT hr = S_OK; HKEY hkey = NULL; DWORD dw = 0;
switch(ulPerm) { case NCPERM_OpenConnectionsFolder: TraceTag(ttidDefault, "Reading OpenConnectionsFolder permissions"); hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szExplorerPolicies, KEY_READ, &hkey);
if (S_OK == hr) { TraceTag(ttidDefault, "Opened explorer policies"); hr = HrRegQueryDword(hkey, c_szNoNetworkConnectionPolicy, &dw); if (SUCCEEDED(hr) && dw) { TraceTag(ttidDefault, "Explorer 'No open connections folder' policy: %d", dw); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 0);
}
RegCloseKey(hkey); hkey = NULL; } break;
default: hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szConnectionsPolicies, KEY_READ, &hkey); if (S_OK == hr) { DWORD dw;
// Read the User Policy
for (UINT nIdx=0; nIdx<celems(USER_PERM_MAP); nIdx++) { if (ulPerm == USER_PERM_MAP[nIdx].dwShift && NCPERM_APPLIES_TO_CURRENT_USER(dwCurrentUserType, USER_PERM_MAP[nIdx].dwApplyMask)) { hr = HrRegQueryDword(hkey, USER_PERM_MAP[nIdx].pszValue, &dw); if (SUCCEEDED(hr)) { NCPERM_SETBIT(USER_PERM_MAP[nIdx].dwShift, dw); } } }
RegCloseKey(hkey); }
// Read the machine policy
//
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szConnectionsPolicies, KEY_READ, &hkey); if (S_OK == hr) { DWORD dw;
for (UINT nIdx=0; nIdx<celems(MACHINE_PERM_MAP); nIdx++) { if (ulPerm == MACHINE_PERM_MAP[nIdx].dwShift) { hr = HrRegQueryDword(hkey, MACHINE_PERM_MAP[nIdx].pszValue, &dw); if (S_OK == hr) { NCPERM_SETBIT(MACHINE_PERM_MAP[nIdx].dwShift, NCPERM_APPLY_BASED_ON_LOCATION(ulPerm, dw)); } } }
RegCloseKey(hkey); } break; } } return NCPERM_CHECKBIT(ulPerm); }
//+---------------------------------------------------------------------------
//
// Function: FHasPermissionFromCache
//
// Purpose: Fast call to determine if the requested permissions are available
//
// Arguments:
// ulPerm [in] Permission flags (E.g. NCPERM_xxxx)
//
// Returns: BOOL, TRUE if the requested permission is granted to the user
//
// NOTE: Cannot be used to check a location aware policy!
//
BOOL FHasPermissionFromCache(IN ULONG ulPerm) { Assert(static_cast<LONG>(ulPerm) >= NCPERM_Min); Assert(static_cast<LONG>(ulPerm) <= NCPERM_Max);
if (!g_fPermsInited) { RefreshAllPermission(); g_fPermsInited = TRUE; }
return NCPERM_CHECKBIT(ulPerm); }
//+---------------------------------------------------------------------------
//
// Function: FProhibitFromAdmins
//
// Purpose: See if group policies should apply to the administrator
//
// Arguments:
//
// Returns: TRUE if it should apply, otherwise false
//
// Author: ckotze 11 Aug 2000
//
// Notes:
//
BOOL FProhibitFromAdmins() { HRESULT hr = S_OK; HKEY hKey; DWORD dw; BOOL bEnabled = FALSE;
#ifdef DBG
if (0xFFFFFFFF != g_dwDbgWin2kPoliciesSet) { return g_dwDbgWin2kPoliciesSet; } #endif // DBG
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szConnectionsPolicies, KEY_READ, &hKey);
if (S_OK == hr) { hr = HrRegQueryDword(hKey, c_szNCPolicyForAdministrators, &dw);
if (SUCCEEDED(hr)) { bEnabled = (dw) ? TRUE : FALSE; } RegCloseKey(hKey); }
TraceErrorOptional("FProhibitFromAdmins", hr, (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr));
return bEnabled; }
//+---------------------------------------------------------------------------
//
// Function: RefreshAllPermission
//
// Purpose: Initializes all permission to the settings from the registry,
// and the ACL list below. Stores these to be used by
// FHasPermissionFromCache
//
// Arguments:
// none
//
// Returns: None
//
VOID RefreshAllPermission() { DWORD dwCurrentUserType; HKEY hkey; HRESULT hr; DWORD dw;
dwCurrentUserType = NCPERM_USER_TYPE();
g_dwPermMask = 0;
// If Admin assume all rights
//
if (NCPERM_USER_IS_ADMIN(dwCurrentUserType)) { // Cheat a little by setting all bits to one
//
g_dwPermMask = 0xFFFFFFFF;
// If this policy is not set, then we don't need to worry about reading the regkeys
// since we can never take anything away from Admins.
} else if (NCPERM_USER_IS_NETCONFIGOPS(dwCurrentUserType)) { NCPERM_SETBIT(NCPERM_NewConnectionWizard, 1); NCPERM_SETBIT(NCPERM_Statistics, 1); NCPERM_SETBIT(NCPERM_RasConnect, 1); NCPERM_SETBIT(NCPERM_DeleteConnection, 1); NCPERM_SETBIT(NCPERM_DeleteAllUserConnection, 1); NCPERM_SETBIT(NCPERM_RenameConnection, 1); NCPERM_SETBIT(NCPERM_RenameMyRasConnection, 1); NCPERM_SETBIT(NCPERM_RenameAllUserRasConnection, 1); NCPERM_SETBIT(NCPERM_RenameLanConnection, 1); NCPERM_SETBIT(NCPERM_DialupPrefs, 1); NCPERM_SETBIT(NCPERM_RasChangeProperties, 1); NCPERM_SETBIT(NCPERM_RasMyProperties, 1); NCPERM_SETBIT(NCPERM_RasAllUserProperties, 1); NCPERM_SETBIT(NCPERM_ChangeAllUserRasProperties, 1); NCPERM_SETBIT(NCPERM_LanProperties, 1); NCPERM_SETBIT(NCPERM_LanChangeProperties, 1); NCPERM_SETBIT(NCPERM_AllowAdvancedTCPIPConfig, 1); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 1); NCPERM_SETBIT(NCPERM_LanConnect, 1); NCPERM_SETBIT(NCPERM_EnDisComponentsAllUserRas, 1); NCPERM_SETBIT(NCPERM_EnDisComponentsMyRas, 1); NCPERM_SETBIT(NCPERM_IpcfgOperation, 1); NCPERM_SETBIT(NCPERM_Repair, 1); } else if (NCPERM_USER_IS_POWERUSER(dwCurrentUserType)) { NCPERM_SETBIT(NCPERM_Repair, 1);
// Rest should be like NCPERM_USER_IS_USER
NCPERM_SETBIT(NCPERM_NewConnectionWizard, 1); NCPERM_SETBIT(NCPERM_Statistics, 1); NCPERM_SETBIT(NCPERM_RasConnect, 1); NCPERM_SETBIT(NCPERM_DeleteConnection, 1); NCPERM_SETBIT(NCPERM_RenameMyRasConnection, 1); NCPERM_SETBIT(NCPERM_DialupPrefs, 1); NCPERM_SETBIT(NCPERM_RasChangeProperties, 1); NCPERM_SETBIT(NCPERM_RasMyProperties, 1); NCPERM_SETBIT(NCPERM_AllowAdvancedTCPIPConfig, 1); NCPERM_SETBIT(NCPERM_LanProperties, 1); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 1); if (IsOsLikePersonal()) { NCPERM_SETBIT(NCPERM_RasAllUserProperties, 1); NCPERM_SETBIT(NCPERM_ChangeAllUserRasProperties, 1); } } else if (NCPERM_USER_IS_USER(dwCurrentUserType)) { NCPERM_SETBIT(NCPERM_NewConnectionWizard, 1); NCPERM_SETBIT(NCPERM_Statistics, 1); NCPERM_SETBIT(NCPERM_RasConnect, 1); NCPERM_SETBIT(NCPERM_DeleteConnection, 1); NCPERM_SETBIT(NCPERM_RenameMyRasConnection, 1); NCPERM_SETBIT(NCPERM_DialupPrefs, 1); NCPERM_SETBIT(NCPERM_RasChangeProperties, 1); NCPERM_SETBIT(NCPERM_RasMyProperties, 1); NCPERM_SETBIT(NCPERM_AllowAdvancedTCPIPConfig, 1); NCPERM_SETBIT(NCPERM_LanProperties, 1); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 1); if (IsOsLikePersonal()) { NCPERM_SETBIT(NCPERM_RasAllUserProperties, 1); NCPERM_SETBIT(NCPERM_ChangeAllUserRasProperties, 1); } } else if (NCPERM_USER_IS_GUEST(dwCurrentUserType)) { NCPERM_SETBIT(NCPERM_Statistics, 1); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 1); }
if (FProhibitFromAdmins() || !NCPERM_USER_IS_ADMIN(dwCurrentUserType)) { // Read folder policy
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szExplorerPolicies, KEY_READ, &hkey); if (S_OK == hr) { TraceTag(ttidDefault, "Opened Explorer Policy reg key");
hr = HrRegQueryDword(hkey, c_szNoNetworkConnectionPolicy, &dw); if (SUCCEEDED(hr) && dw) { TraceTag(ttidDefault, "Explorer 'No open connections folder' policy: %d", dw); NCPERM_SETBIT(NCPERM_OpenConnectionsFolder, 0); }
RegCloseKey(hkey);
hkey = NULL; }
// Read the user policy
//
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szConnectionsPolicies, KEY_READ, &hkey);
if (S_OK == hr) { for (UINT nIdx=0; nIdx<celems(USER_PERM_MAP); nIdx++) { if (NCPERM_APPLIES_TO_CURRENT_USER(dwCurrentUserType, USER_PERM_MAP[nIdx].dwApplyMask)) { hr = HrRegQueryDword(hkey, USER_PERM_MAP[nIdx].pszValue, &dw);
if (SUCCEEDED(hr)) { NCPERM_SETBIT(USER_PERM_MAP[nIdx].dwShift, dw); } } }
RegCloseKey(hkey);
} }
// Read the machine policy
//
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szConnectionsPolicies, KEY_READ, &hkey); if (S_OK == hr) { DWORD dw;
for (UINT nIdx=0; nIdx<celems(MACHINE_PERM_MAP); nIdx++) { hr = HrRegQueryDword(hkey, MACHINE_PERM_MAP[nIdx].pszValue, &dw); if (S_OK == hr) { NCPERM_SETBIT(MACHINE_PERM_MAP[nIdx].dwShift, NCPERM_APPLY_BASED_ON_LOCATION(MACHINE_PERM_MAP[nIdx].dwShift, dw)); } }
RegCloseKey(hkey); } }
//+---------------------------------------------------------------------------
//
// Function: IsHNetAllowed
//
// Purpose: Verify the permission to use/enable (ICS/Firewall and create bridge network)
//
// Arguments: dwPerm [in] Group policy check to make for permission checking
//
// Notes: Checks the following:
//
// Does the architecture / SKU permit the use of homenet technologies?
// Does group policy allow the particular technology?
// Is the user an Admin and are admins allowed access to this technology?
//
// Example scenario. The user is a Admin but ITG disables the right to create bridge this function would return FALSE
//
BOOL IsHNetAllowed( IN DWORD dwPerm ) { #ifndef _WIN64
BOOL fPermission = false; OSVERSIONINFOEXW verInfo = {0}; ULONGLONG ConditionMask = 0;
// Look for the enterprise SKUs
verInfo.dwOSVersionInfoSize = sizeof(verInfo); verInfo.wSuiteMask = VER_SUITE_DATACENTER | VER_SUITE_BACKOFFICE | VER_SUITE_SMALLBUSINESS_RESTRICTED | VER_SUITE_SMALLBUSINESS | VER_SUITE_BLADE;
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
if ( VerifyVersionInfo(&verInfo, VER_SUITENAME, ConditionMask) ) { // Homenet technologies are not available on enterprise SKUs
return FALSE; }
if ( FIsUserAdmin() && !FProhibitFromAdmins() ) { HRESULT hr; INetMachinePolicies* pMachinePolicy;
hr = CoCreateInstance( CLSID_NetGroupPolicies, NULL, CLSCTX_SERVER, IID_INetMachinePolicies, reinterpret_cast<void **>(&pMachinePolicy) );
if ( SUCCEEDED(hr) ) { hr = pMachinePolicy->VerifyPermission(dwPerm, &fPermission); pMachinePolicy->Release(); } }
return fPermission;
#else // #ifndef _WIN64
// On IA64, homenet technologies are not available at all.
return FALSE;
#endif
}
//+---------------------------------------------------------------------------
//
// Function: FIsUserNetworkConfigOps
//
// Purpose: Checks to see if the current user is a NetConfig Operator
//
//
// Arguments:
// none.
//
//
// Returns: BOOL.
//
// Author: ckotze 12 Jun 2000
//
// Notes:
//
BOOL FIsUserNetworkConfigOps() { BOOL fIsMember;
fIsMember = FCheckGroupMembership(DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS);
return fIsMember; }
//+---------------------------------------------------------------------------
//
// Function: FIsUserPowerUser
//
// Purpose: Checks to see if the current user is a Power User
//
//
// Arguments:
// none.
//
//
// Returns: BOOL.
//
// Author: deonb 9 May 2001
//
// Notes:
//
BOOL FIsUserPowerUser() { BOOL fIsMember;
fIsMember = FCheckGroupMembership(DOMAIN_ALIAS_RID_POWER_USERS);
return fIsMember; }
//+---------------------------------------------------------------------------
//
// Function: FIsUserGuest
//
// Purpose: Checks to see if the current user is a Guest
//
//
// Arguments:
// none.
//
//
// Returns: BOOL.
//
// Author: ckotze 12 Jun 2000
//
// Notes:
//
BOOL FIsUserGuest() { BOOL fIsMember; fIsMember = FCheckGroupMembership(DOMAIN_ALIAS_RID_GUESTS); return fIsMember; }
//+---------------------------------------------------------------------------
//
// Function: FIsPolicyConfigured
//
// Purpose: Checks to see if the specific policy is configured
//
//
// Arguments: ulPerm [in] Group policy number from the USER_PERM_MAP
//
//
// Returns: BOOL.
//
// Author: ckotze 12 Jun 2000
//
// Notes:
//
BOOL FIsPolicyConfigured(IN DWORD ulPerm) { HRESULT hr; HKEY hkey; BOOL bConfigured = FALSE;
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, c_szConnectionsPolicies, KEY_READ, &hkey);
if (S_OK == hr) { DWORD dw;
if (ulPerm == USER_PERM_MAP[ulPerm].dwShift) { DWORD dw;
hr = HrRegQueryDword(hkey, USER_PERM_MAP[static_cast<DWORD>(ulPerm)].pszValue, &dw); if (SUCCEEDED(hr)) { bConfigured = TRUE; } }
RegCloseKey(hkey); }
return bConfigured; }
//+---------------------------------------------------------------------------
//
// Function: IsSameNetworkAsGroupPolicies
//
// Purpose: Checks to see if the current network is the same as where the
// Group Policies were assigned from.
//
// Arguments:
// none.
//
//
// Returns: BOOL
//
// Author: ckotze 05 Jan 2001
//
// Notes:
//
BOOL IsSameNetworkAsGroupPolicies() { return g_pNetmanGPNLA->IsSameNetworkAsGroupPolicies(); }
|