windows-nt/Source/XPSP1/NT/net/config/common/ncbase/ncperms.cpp
2020-09-26 16:20:57 +08:00

1388 lines
37 KiB
C++

//+---------------------------------------------------------------------------
//
// 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 -
//
// Returns: TRUE if the logged on user is a member of the specified group
//
// Author: scottbri 14 Sept 1998
//
// Notes:
//
BOOL FCheckGroupMembership(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 (
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 (
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 (
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(DWORD dw, DWORD dwVal)
{
DWORD dwBit = (1 << dw);
g_dwPermMask = (g_dwPermMask & ~dwBit) | ((0==dwVal) ? 0 : dwBit);
}
inline
BOOL NCPERM_CHECKBIT(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(DWORD dwUserType)
{
return (dwUserType & USER_TYPE_ADMIN);
}
inline
BOOL NCPERM_USER_IS_NETCONFIGOPS(DWORD dwUserType)
{
return (dwUserType & USER_TYPE_NETCONFIGOPS);
}
inline
BOOL NCPERM_USER_IS_POWERUSER(DWORD dwUserType)
{
return (dwUserType & USER_TYPE_POWERUSER);
}
inline
BOOL NCPERM_USER_IS_USER(DWORD dwUserType)
{
return (dwUserType & USER_TYPE_USER);
}
inline
BOOL NCPERM_USER_IS_GUEST(DWORD dwUserType)
{
return (dwUserType & USER_TYPE_GUEST);
}
inline
BOOL NCPERM_APPLIES_TO_CURRENT_USER(DWORD dwUserType, DWORD dwApplyMask)
{
return (dwUserType & dwApplyMask);
}
inline
int NCPERM_FIND_MAP_ENTRY(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(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(ULONG ulPerm, 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.
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_AllowNetBridge_NLA,
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
//
// Returns: BOOL, TRUE if the requested permission is granted to the user
//
BOOL
FHasPermission(ULONG ulPerm, CGroupPolicyBase* pGPBase)
{
TraceFileFunc(ttidDefault);
DWORD dwCurrentUserType;
Assert(static_cast<LONG>(ulPerm) >= NCPERM_Min);
Assert(static_cast<LONG>(ulPerm) <= NCPERM_Max);
g_pNetmanGPNLA = pGPBase;
//if the requested is from a homenet component and we are using DataCenter or
//Advanced Server, than dont 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_ENTERPRISE;
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
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");
g_fPermsInited = TRUE;
RefreshAllPermission();
}
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);
}
BOOL
FHasPermissionFromCache(ULONG ulPerm)
{
Assert(static_cast<LONG>(ulPerm) >= NCPERM_Min);
Assert(static_cast<LONG>(ulPerm) <= NCPERM_Max);
if (!g_fPermsInited)
{
g_fPermsInited = TRUE;
RefreshAllPermission();
}
return NCPERM_CHECKBIT(ulPerm);
}
//+---------------------------------------------------------------------------
//
// 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:
//
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);
bEnabled = (dw) ? TRUE : FALSE;
RegCloseKey(hKey);
}
TraceErrorOptional("FProhibitFromAdmins", hr, (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr));
return bEnabled;
}
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)
//
// 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(
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_ENTERPRISE;
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:
// none.
//
//
// Returns: BOOL.
//
// Author: ckotze 12 Jun 2000
//
// Notes:
//
BOOL FIsPolicyConfigured(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();
}