//*************************************************************************** // // Copyright (c) 1998-2000 Microsoft Corporation // // SECURITY.CPP // // alanbos 28-Jun-98 Created. // // Defines the implementation of CSWbemSecurity // //*************************************************************************** #include "precomp.h" // Used to protect security calls extern CRITICAL_SECTION g_csSecurity; bool CSWbemSecurity::s_bInitialized = false; bool CSWbemSecurity::s_bIsNT = false; DWORD CSWbemSecurity::s_dwNTMajorVersion = 0; HINSTANCE CSWbemSecurity::s_hAdvapi = NULL; bool CSWbemSecurity::s_bCanRevert = false; WbemImpersonationLevelEnum CSWbemSecurity::s_dwDefaultImpersonationLevel = wbemImpersonationLevelIdentify; // Declarations for function pointers that won't exist on Win9x BOOL (STDAPICALLTYPE *s_pfnDuplicateTokenEx) ( HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE ) = NULL; //*************************************************************************** // // SCODE CSWbemSecurity::Initialize // // DESCRIPTION: // // This static function is caused on DLL attachment to the process; it // sets up the function pointers for advanced API privilege functions. // On Win9x these functions are not supported which is why we need to // indirect through GetProcAddress. // //*************************************************************************** void CSWbemSecurity::Initialize () { EnterCriticalSection (&g_csSecurity); if (!s_bInitialized) { // Get OS info OSVERSIONINFO osVersionInfo; osVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&osVersionInfo); s_bIsNT = (VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId); s_dwNTMajorVersion = osVersionInfo.dwMajorVersion; if (s_bIsNT) { HKEY hKey; // Security values are relevant for NT only - for Win9x leave as default if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WBEMS_RK_SCRIPTING, 0, KEY_QUERY_VALUE, &hKey)) { DWORD dwDummy = 0; // Get revert flag value from registry - NT 4.0 or less only if (s_dwNTMajorVersion <= 4) { DWORD dwEnableForAsp = 0; dwDummy = sizeof (dwEnableForAsp); if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_ENABLEFORASP, NULL, NULL, (BYTE *) &dwEnableForAsp, &dwDummy)) s_bCanRevert = (0 != dwEnableForAsp); } // Get default impersonation level from registry DWORD dwImpLevel = 0; dwDummy = sizeof (dwImpLevel); if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_DEFAULTIMPLEVEL, NULL, NULL, (BYTE *) &dwImpLevel, &dwDummy)) s_dwDefaultImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel; RegCloseKey (hKey); } // Set up security function pointers for NT if (!s_hAdvapi) { TCHAR dllName [] = _T("\\advapi32.dll"); LPTSTR pszSysDir = new TCHAR[ MAX_PATH + _tcslen (dllName) + 1]; if (pszSysDir) { pszSysDir[0] = NULL; UINT uSize = GetSystemDirectory(pszSysDir, MAX_PATH); if(uSize > MAX_PATH) { delete[] pszSysDir; pszSysDir = new TCHAR[ uSize + _tcslen (dllName) + 1]; if (pszSysDir) { pszSysDir[0] = NULL; uSize = GetSystemDirectory(pszSysDir, uSize); } } if (pszSysDir) { _tcscat (pszSysDir, dllName); s_hAdvapi = LoadLibraryEx (pszSysDir, NULL, 0); if (s_hAdvapi) (FARPROC&) s_pfnDuplicateTokenEx = GetProcAddress(s_hAdvapi, "DuplicateTokenEx"); delete [] pszSysDir; } } } } s_bInitialized = true; } LeaveCriticalSection (&g_csSecurity); } //*************************************************************************** // // SCODE CSWbemSecurity::Uninitialize // // DESCRIPTION: // // This static function is caused on DLL detachment to the process; it // unloads the API loaded by Initialize (above) to obtain function pointers. // //*************************************************************************** void CSWbemSecurity::Uninitialize () { EnterCriticalSection (&g_csSecurity); if (s_hAdvapi) { s_pfnDuplicateTokenEx = NULL; FreeLibrary (s_hAdvapi); s_hAdvapi = NULL; } LeaveCriticalSection (&g_csSecurity); } //*************************************************************************** // // SCODE CSWbemSecurity::LookupPrivilegeValue // // DESCRIPTION: // // This static function wraps the Win32 LookupPrivilegeValue function, // allowing us to do some OS-dependent stuff. // // PARAMETERS: // // lpName the privilege name // lpLuid holds the LUID on successful return // // RETURN VALUES: // // true On NT this means we found the privilege. On Win9x we // always return this. // // false On NT this means the privilege is not recognized. This // is never returned on Win9x. // //*************************************************************************** BOOL CSWbemSecurity::LookupPrivilegeValue ( LPCTSTR lpName, PLUID lpLuid ) { // Allows any name to map to 0 LUID on Win9x - this aids script portability if (IsNT ()) return ::LookupPrivilegeValue(NULL, lpName, lpLuid); else return true; } //*************************************************************************** // // SCODE CSWbemSecurity::LookupPrivilegeDisplayName // // DESCRIPTION: // // This static function wraps the Win32 LookupPrivilegeDisplayName function, // allowing us to do some OS-dependent stuff. // // PARAMETERS: // // tName the privilege name // pDisplayName holds the display name on successful return // //*************************************************************************** void CSWbemSecurity::LookupPrivilegeDisplayName (LPCTSTR lpName, BSTR *pDisplayName) { if (pDisplayName) { // Can't return display name on Win9x (no privilege support) if (IsNT ()) { DWORD dwLangID; DWORD dwSize = 1; TCHAR dummy [1]; // Get size of required buffer ::LookupPrivilegeDisplayName (NULL, lpName, dummy, &dwSize, &dwLangID); LPTSTR dname = new TCHAR[dwSize + 1]; if (dname) { if (::LookupPrivilegeDisplayName (_T(""), lpName, dname, &dwSize, &dwLangID)) { // Have a valid name - now copy it to a BSTR #ifdef _UNICODE *pDisplayName = SysAllocString (dname); #else size_t dnameLen = strlen (dname); OLECHAR *nameW = new OLECHAR [dnameLen + 1]; if (nameW) { mbstowcs (nameW, dname, dnameLen); nameW [dnameLen] = NULL; *pDisplayName = SysAllocString (nameW); delete [] nameW; } #endif } delete [] dname; } } // If we failed, just set an empty string if (!(*pDisplayName)) *pDisplayName = SysAllocString (L""); } } //*************************************************************************** // // CSWbemSecurity::CSWbemSecurity // // CONSTRUCTOR // This form of the constructor is used for securing a new WBEM // remoted interface where no previous security has been applied. // It is only used to secure IWbemServices interfaces. // Note that the Locator may have security settings so these are // transferred if present. // //*************************************************************************** CSWbemSecurity::CSWbemSecurity ( IUnknown *pUnk, BSTR bsAuthority , BSTR bsUser, BSTR bsPassword, CWbemLocatorSecurity *pLocatorSecurity) : m_pPrivilegeSet (NULL), m_pProxyCache (NULL), m_pCurProxy (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); m_cRef=1; m_pProxyCache = new CSWbemProxyCache (pUnk, bsAuthority, bsUser, bsPassword, pLocatorSecurity); if (m_pProxyCache) m_pCurProxy = m_pProxyCache->GetInitialProxy (); if (pLocatorSecurity) { // Clone the privilege set CSWbemPrivilegeSet *pPrivilegeSet = pLocatorSecurity->GetPrivilegeSet (); if (pPrivilegeSet) { m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet); pPrivilegeSet->Release (); } } else { // Create a new privilege set m_pPrivilegeSet = new CSWbemPrivilegeSet; } InterlockedIncrement(&g_cObj); } //*************************************************************************** // // CSWbemSecurity::CSWbemSecurity // // CONSTRUCTOR // This form of the constructor is used for securing a new WBEM // remoted interface where no previous security has been applied, // and where the user credentials are expressed in the form of an // encrypted COAUTHIDENTITY plus principal and authority. // It is only used to secure IWbemServices interfaces. // //*************************************************************************** CSWbemSecurity::CSWbemSecurity ( IUnknown *pUnk, COAUTHIDENTITY *pCoAuthIdentity, BSTR bsPrincipal, BSTR bsAuthority) : m_pPrivilegeSet (NULL), m_pProxyCache (NULL), m_pCurProxy (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); m_cRef=1; m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity, bsPrincipal, bsAuthority); if (m_pProxyCache) m_pCurProxy = m_pProxyCache->GetInitialProxy (); // Create a new privilege set m_pPrivilegeSet = new CSWbemPrivilegeSet; InterlockedIncrement(&g_cObj); } //*************************************************************************** // // CSWbemSecurity::CSWbemSecurity // // CONSTRUCTOR // This form of the constructor is used for securing a new WBEM interface // non-remoted interface using the security attributes attached to another // (already secured) remoted interface; a non-remoted interface is secured // by virtue of securing a new proxy on an underlying remoted interface. // It is used to "secure" an ISWbemObjectEx interface using the security // settings of an IWbemServices interface. // //*************************************************************************** CSWbemSecurity::CSWbemSecurity ( CSWbemSecurity *pSecurity) : m_pPrivilegeSet (NULL), m_pProxyCache (NULL), m_pCurProxy (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); m_cRef=1; // Clone the privilege set if (pSecurity) { CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet (); if (pPrivilegeSet) { m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet); pPrivilegeSet->Release (); } else { // Create a new one m_pPrivilegeSet = new CSWbemPrivilegeSet (); } m_pProxyCache = pSecurity->GetProxyCache (); m_pCurProxy = pSecurity->GetProxy (); } InterlockedIncrement(&g_cObj); } CSWbemSecurity::CSWbemSecurity ( IUnknown *pUnk, ISWbemInternalSecurity *pISWbemInternalSecurity) : m_pPrivilegeSet (NULL), m_pProxyCache (NULL), m_pCurProxy (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); m_cRef=1; if (pISWbemInternalSecurity) { // Clone the privilege set ISWbemSecurity *pISWbemSecurity = NULL; if (SUCCEEDED(pISWbemInternalSecurity->QueryInterface (IID_ISWbemSecurity, (void**) &pISWbemSecurity))) { ISWbemPrivilegeSet *pISWbemPrivilegeSet = NULL; if (SUCCEEDED(pISWbemSecurity->get_Privileges (&pISWbemPrivilegeSet))) { // Build the privilege set m_pPrivilegeSet = new CSWbemPrivilegeSet (pISWbemPrivilegeSet); // Build the proxy cache BSTR bsAuthority = NULL; BSTR bsPrincipal = NULL; BSTR bsUser = NULL; BSTR bsPassword = NULL; BSTR bsDomain = NULL; pISWbemInternalSecurity->GetAuthority (&bsAuthority); pISWbemInternalSecurity->GetPrincipal (&bsPrincipal); pISWbemInternalSecurity->GetUPD (&bsUser, &bsPassword, &bsDomain); COAUTHIDENTITY *pCoAuthIdentity = NULL; // Decide if we need a COAUTHIDENTITY if ((bsUser && (0 < wcslen (bsUser))) || (bsPassword && (0 < wcslen (bsPassword))) || (bsDomain && (0 < wcslen (bsDomain)))) WbemAllocAuthIdentity (bsUser, bsPassword, bsDomain, &pCoAuthIdentity); m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity, bsPrincipal, bsAuthority); if (pCoAuthIdentity) WbemFreeAuthIdentity (pCoAuthIdentity); if (bsAuthority) SysFreeString (bsAuthority); if (bsPrincipal) SysFreeString (bsPrincipal); if (bsUser) SysFreeString (bsUser); if (bsPassword) SysFreeString (bsPassword); if (bsDomain) SysFreeString (bsDomain); if (m_pProxyCache) m_pCurProxy = m_pProxyCache->GetInitialProxy (); } pISWbemPrivilegeSet->Release (); } pISWbemSecurity->Release (); } InterlockedIncrement(&g_cObj); } //*************************************************************************** // // CSWbemSecurity::CSWbemSecurity // // CONSTRUCTOR // This form of the constructor is used for securing a new WBEM remoted // interface interface using the security attributes attached to another // (already secured) remoted interface. // It is used to "secure" an ISWbemObjectSet interface using the security // settings of an IWbemServices interface. // //*************************************************************************** CSWbemSecurity::CSWbemSecurity ( IUnknown *pUnk, CSWbemSecurity *pSecurity) : m_pPrivilegeSet (NULL), m_pProxyCache (NULL), m_pCurProxy (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); m_cRef=1; InterlockedIncrement(&g_cObj); if (pSecurity) { // Clone the privilege set CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet (); if (pPrivilegeSet) { m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet); pPrivilegeSet->Release (); } m_pProxyCache = new CSWbemProxyCache (pUnk, pSecurity); if (m_pProxyCache) m_pCurProxy = m_pProxyCache->GetInitialProxy (); } else { m_pPrivilegeSet = new CSWbemPrivilegeSet (); m_pProxyCache = new CSWbemProxyCache (pUnk, NULL); if (m_pProxyCache) m_pCurProxy = m_pProxyCache->GetInitialProxy (); } } //*************************************************************************** // // CSWbemSecurity::~CSWbemSecurity // // DESTRUCTOR // //*************************************************************************** CSWbemSecurity::~CSWbemSecurity (void) { InterlockedDecrement(&g_cObj); if (m_pCurProxy) m_pCurProxy->Release (); if (m_pProxyCache) m_pProxyCache->Release (); if (m_pPrivilegeSet) m_pPrivilegeSet->Release (); } //*************************************************************************** // HRESULT CSWbemSecurity::QueryInterface // long CSWbemSecurity::AddRef // long CSWbemSecurity::Release // // DESCRIPTION: // // Standard Com IUNKNOWN functions. // //*************************************************************************** STDMETHODIMP CSWbemSecurity::QueryInterface ( IN REFIID riid, OUT LPVOID *ppv ) { *ppv=NULL; if (IID_IUnknown==riid) *ppv = reinterpret_cast(this); else if (IID_ISWbemSecurity==riid) *ppv = (ISWbemSecurity *)this; else if (IID_IDispatch==riid) *ppv = (IDispatch *)this; else if (IID_ISupportErrorInfo==riid) *ppv = (ISupportErrorInfo *)this; else if (IID_ISWbemInternalSecurity==riid) *ppv = (ISWbemInternalSecurity *)this; else if (IID_IProvideClassInfo==riid) *ppv = (IProvideClassInfo *)this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CSWbemSecurity::AddRef(void) { long l = InterlockedIncrement(&m_cRef); return l; } STDMETHODIMP_(ULONG) CSWbemSecurity::Release(void) { long l = InterlockedDecrement(&m_cRef); if (0L!=l) return l; delete this; return 0; } //*************************************************************************** // HRESULT CSWbemSecurity::InterfaceSupportsErrorInfo // // DESCRIPTION: // // Standard Com ISupportErrorInfo functions. // //*************************************************************************** STDMETHODIMP CSWbemSecurity::InterfaceSupportsErrorInfo (IN REFIID riid) { return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE; } //*************************************************************************** // // SCODE CSWbemSecurity::get_AuthenticationLevel // // DESCRIPTION: // // Retrieve the authentication level // // PARAMETERS: // // pAuthenticationLevel holds the value on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemSecurity::get_AuthenticationLevel ( WbemAuthenticationLevelEnum *pAuthenticationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pAuthenticationLevel) hr = WBEM_E_INVALID_PARAMETER; else if (m_pCurProxy) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) { *pAuthenticationLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel; hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemSecurity::put_AuthenticationLevel // // DESCRIPTION: // // Set the authentication level // // PARAMETERS: // // authenticationLevel the new value // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemSecurity::put_AuthenticationLevel ( WbemAuthenticationLevelEnum authenticationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) || (WBEMS_MAX_AUTHN_LEVEL < authenticationLevel)) hr = WBEM_E_INVALID_PARAMETER; else if (m_pCurProxy && m_pProxyCache) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) { // Only refressh from cache if settings have changed if (authenticationLevel != (WbemAuthenticationLevelEnum) dwAuthnLevel) { m_pCurProxy->Release (); m_pCurProxy = NULL; m_pCurProxy = m_pProxyCache->GetProxy (authenticationLevel, (WbemImpersonationLevelEnum) dwImpLevel); } hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemSecurity::get_ImpersonationLevel // // DESCRIPTION: // // Retrieve the impersonation level // // PARAMETERS: // // pImpersonationLevel holds the value on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemSecurity::get_ImpersonationLevel ( WbemImpersonationLevelEnum *pImpersonationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pImpersonationLevel) hr = WBEM_E_INVALID_PARAMETER; else if (m_pCurProxy) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) { *pImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel; hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemSecurity::put_ImpersonationLevel // // DESCRIPTION: // // Set the impersonation level // // PARAMETERS: // // impersonationLevel the new value // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemSecurity::put_ImpersonationLevel ( WbemImpersonationLevelEnum impersonationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel)) hr = WBEM_E_INVALID_PARAMETER; else if (m_pCurProxy && m_pProxyCache) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) { // Only refressh from cache if settings have changed if (impersonationLevel != (WbemImpersonationLevelEnum) dwImpLevel) { m_pCurProxy->Release (); m_pCurProxy = NULL; m_pCurProxy = m_pProxyCache->GetProxy ((WbemAuthenticationLevelEnum) dwAuthnLevel, impersonationLevel); } hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemSecurity::get_Privileges // // DESCRIPTION: // // Return the Privilege override set // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemSecurity::get_Privileges ( ISWbemPrivilegeSet **ppPrivileges ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == ppPrivileges) hr = WBEM_E_INVALID_PARAMETER; { *ppPrivileges = NULL; if (m_pPrivilegeSet) { if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet, (PPVOID) ppPrivileges))) hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // CSWbemSecurity::SecureInterface // // DESCRIPTION: // // Set the security on the specified interface using the security settings // on this interface. // // PARAMETERS: // // pUnk The interface to secure // // RETURN VALUES: // none //*************************************************************************** void CSWbemSecurity::SecureInterface (IUnknown *pUnk) { if(pUnk) { if (m_pCurProxy) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) if (m_pProxyCache) m_pProxyCache->SecureProxy (pUnk, (WbemAuthenticationLevelEnum) dwAuthnLevel, (WbemImpersonationLevelEnum) dwImpLevel); } } } //*************************************************************************** // // CSWbemSecurity::SecureInterfaceRev // // DESCRIPTION: // // Set the security on this interface using the security settings // on the specified interface. // // PARAMETERS: // // pUnk The interface whose security settings we will // use to set this interface // // RETURN VALUES: // none //*************************************************************************** void CSWbemSecurity::SecureInterfaceRev (IUnknown *pUnk) { if (pUnk) { DWORD dwAuthnLevel; DWORD dwImpLevel; if (S_OK == GetAuthImp (pUnk, &dwAuthnLevel, &dwImpLevel)) { if (m_pCurProxy) { m_pCurProxy->Release (); m_pCurProxy = NULL; } if (m_pProxyCache) { m_pCurProxy = m_pProxyCache->GetProxy ((WbemAuthenticationLevelEnum) dwAuthnLevel, (WbemImpersonationLevelEnum) dwImpLevel); } } } } //*************************************************************************** // // CSWbemSecurity::AdjustTokenPrivileges // // DESCRIPTION: // // Adjust the Privileges on the specified token without allowing a future // restore of the current settings.. // // PARAMETERS: // // hHandle Handle of the token on which to adjust privileges // pPrivilegeSet Specified privilege adjustments // // RETURN VALUES: // none //*************************************************************************** void CSWbemSecurity::AdjustTokenPrivileges ( HANDLE hHandle, CSWbemPrivilegeSet *pPrivilegeSet ) { DWORD lastErr = 0; if (pPrivilegeSet) { pPrivilegeSet->AddRef (); long lNumPrivileges = 0; pPrivilegeSet->get_Count (&lNumPrivileges); if (lNumPrivileges) { DWORD dwPrivilegeIndex = 0; /* * Set up the token privileges array. Note that some jiggery-pokery * is required here because the Privileges field is an [ANYSIZE_ARRAY] * type. */ TOKEN_PRIVILEGES *pTokenPrivileges = (TOKEN_PRIVILEGES *) new BYTE [sizeof(TOKEN_PRIVILEGES) + (lNumPrivileges * sizeof (LUID_AND_ATTRIBUTES [1]))]; if (pTokenPrivileges) { // Get the iterator PrivilegeMap::iterator next = pPrivilegeSet->m_PrivilegeMap.begin (); while (next != pPrivilegeSet->m_PrivilegeMap.end ()) { CSWbemPrivilege *pPrivilege = (*next).second; pPrivilege->AddRef (); LUID luid; pPrivilege->GetLUID (&luid); VARIANT_BOOL vBool; pPrivilege->get_IsEnabled (&vBool); pTokenPrivileges->Privileges [dwPrivilegeIndex].Luid = luid; /* * Note that any setting other than SE_PRIVILEGE_ENABLED * is interpreted by AdjustTokenPrivileges as a DISABLE * request for that Privilege. */ pTokenPrivileges->Privileges [dwPrivilegeIndex].Attributes = (VARIANT_TRUE == vBool) ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_ENABLED_BY_DEFAULT; dwPrivilegeIndex++; pPrivilege->Release (); next++; } // Now we should have recorded the number of privileges that were OK if (0 < dwPrivilegeIndex) { pTokenPrivileges->PrivilegeCount = dwPrivilegeIndex; BOOL result = ::AdjustTokenPrivileges (hHandle, FALSE, pTokenPrivileges, 0, NULL, NULL); lastErr = GetLastError (); } delete [] pTokenPrivileges; } } pPrivilegeSet->Release (); } } //*************************************************************************** // // SCODE CSWbemSecurity::SetSecurity // // DESCRIPTION: // // Set Privileges on the Thread Token. // //*************************************************************************** BOOL CSWbemSecurity::SetSecurity ( bool &needToResetSecurity, HANDLE &hThreadToken ) { BOOL result = TRUE; // Default is success DWORD lastErr = 0; hThreadToken = NULL; // Default assume we'll modify process token needToResetSecurity = false; // Default assume we changed no privileges // Win9x has no security support if (IsNT ()) { // Start by checking whether we are being impersonated. On an NT4 // box (which has no cloaking, and therefore cannot allow us to // pass on this impersonation to Winmgmt) we should RevertToSelf // if we have been configured to allow this. If we haven't been // configured to allow this, bail out now. if (4 >= GetNTMajorVersion ()) { if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, true, &hThreadToken)) { // We are being impersonated if (s_bCanRevert) { if (result = RevertToSelf()) needToResetSecurity = true; } else { // Error - cannot do this! Time to bail out CloseHandle (hThreadToken); hThreadToken = NULL; result = FALSE; } } } else { #ifdef WSCRPDEBUG HANDLE hToken = NULL; if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken)) { PrintPrivileges (hToken); CloseHandle (hToken); } #endif } if (result) { // Now we check if we need to set privileges bool bIsUsingExplicitUserName = false; if (m_pProxyCache) bIsUsingExplicitUserName = m_pProxyCache->IsUsingExplicitUserName (); /* * Specifying a user only makes sense for remote operations, and we * don't need to mess with privilege for remote operations since * they are set up by server logon anyway. */ if (!bIsUsingExplicitUserName && m_pPrivilegeSet) { // Nothing to do unless some privilege overrides have been set long lCount = 0; m_pPrivilegeSet->get_Count (&lCount); if (0 < lCount) { if (4 < GetNTMajorVersion ()) { /* * On NT5 we try to open the Thread token. If the client app * is calling into us on an impersonated thread (as IIS may be, * for example), this will succeed. */ HANDLE hToken; SECURITY_IMPERSONATION_LEVEL secImpLevel = SecurityImpersonation; if (!(result = OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_IMPERSONATE, true, &hToken))) { // No thread token - go for the Process token instead HANDLE hProcess = GetCurrentProcess (); result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken); CloseHandle (hProcess); } else { // We are working with a thread token hThreadToken = hToken; // Try and get the impersonation level of this token DWORD dwReturnLength = 0; BOOL thisRes = GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel, sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength); } if (result) { /* * Getting here means we have a valid token, be it process or thread. We * now attempt to duplicate it before Adjusting the Privileges. */ #ifdef WSCRPDEBUG PrintPrivileges (hToken); #endif HANDLE hDupToken; EnterCriticalSection (&g_csSecurity); result = s_pfnDuplicateTokenEx && s_pfnDuplicateTokenEx (hToken, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, NULL, secImpLevel, TokenImpersonation, &hDupToken); LeaveCriticalSection (&g_csSecurity); if (result) { CSWbemSecurity::AdjustTokenPrivileges (hDupToken, m_pPrivilegeSet); // Now use this token on the current thread if (SetThreadToken(NULL, hDupToken)) { needToResetSecurity = true; #ifdef WSCRPDEBUG CSWbemSecurity::PrintPrivileges (hDupToken); #endif // Reset the blanket for the benefit of RPC DWORD dwAuthnLevel, dwImpLevel; if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel)) { // Force the cache to resecure the proxy IUnknown *pNewProxy = m_pProxyCache->GetProxy ((WbemAuthenticationLevelEnum) dwAuthnLevel, (WbemImpersonationLevelEnum) dwImpLevel, true); if (pNewProxy) { if (m_pCurProxy) m_pCurProxy->Release (); m_pCurProxy = pNewProxy; } } } CloseHandle (hDupToken); } else { lastErr = GetLastError (); } /* * If we are not using a thread token, close the token now. Otherwise * the handle will be closed in the balanced call to RestorePrivileges (). */ if (!hThreadToken) CloseHandle (hToken); } } else { // For NT4 we adjust the privileges in the process token HANDLE hProcessToken = NULL; HANDLE hProcess = GetCurrentProcess (); result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken); CloseHandle (hProcess); // Adjust privilege on the process if (result) { #ifdef WSCRPDEBUG CSWbemSecurity::PrintPrivileges (hProcessToken); #endif CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet); #ifdef WSCRPDEBUG CSWbemSecurity::PrintPrivileges (hProcessToken); #endif CloseHandle (hProcessToken); } } } } } } return result; } //*************************************************************************** // // SCODE CSWbemSecurity::ResetSecurity // // DESCRIPTION: // // Restore Privileges on the Thread Token. // //*************************************************************************** void CSWbemSecurity::ResetSecurity ( HANDLE hThreadToken ) { // Win9x has no security palaver if (IsNT ()) { /* * Set the supplied token (which may be NULL) into * the current thread. */ BOOL result = SetThreadToken (NULL, hThreadToken); DWORD error = 0; if (!result) error = GetLastError (); #ifdef WSCRPDEBUG // Print out the current privileges to see what's changed HANDLE hToken = NULL; if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken)) { // No thread token - go for the Process token instead HANDLE hProcess = GetCurrentProcess (); OpenProcessToken(hProcess, TOKEN_QUERY, &hToken); CloseHandle (hProcess); } if (hToken) { PrintPrivileges (hToken); CloseHandle (hToken); } #endif if (hThreadToken) CloseHandle (hThreadToken); } } bool CSWbemSecurity::IsImpersonating (bool useDefaultUser, bool useDefaultAuthority) { bool result = false; if (useDefaultUser && useDefaultAuthority && CSWbemSecurity::IsNT () && (4 < CSWbemSecurity::GetNTMajorVersion ())) { // A suitable candidate - find out if we are running on an impersonated thread HANDLE hThreadToken = NULL; if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, true, &hThreadToken)) { // Check we have an impersonation token SECURITY_IMPERSONATION_LEVEL secImpLevel; DWORD dwReturnLength = 0; if (GetTokenInformation (hThreadToken, TokenImpersonationLevel, &secImpLevel, sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength)) result = ((SecurityImpersonation == secImpLevel) || (SecurityDelegation == secImpLevel)); CloseHandle (hThreadToken); } } return result; } HRESULT CSWbemSecurity::GetAuthority (BSTR *bsAuthority) { HRESULT hr = WBEM_E_FAILED; if (m_pProxyCache) { *bsAuthority = SysAllocString(m_pProxyCache->GetAuthority ()); hr = S_OK; } return hr; } HRESULT CSWbemSecurity::GetUPD (BSTR *bsUser, BSTR *bsPassword, BSTR *bsDomain) { HRESULT hr = WBEM_E_FAILED; if (m_pProxyCache) { COAUTHIDENTITY *pCoAuthIdentity = m_pProxyCache->GetCoAuthIdentity (); if (pCoAuthIdentity) { *bsUser = SysAllocString (pCoAuthIdentity->User); *bsPassword = SysAllocString (pCoAuthIdentity->Password); *bsDomain = SysAllocString (pCoAuthIdentity->Domain); WbemFreeAuthIdentity (pCoAuthIdentity); } hr = S_OK; } return hr; } HRESULT CSWbemSecurity::GetPrincipal (BSTR *bsPrincipal) { HRESULT hr = WBEM_E_FAILED; if (m_pProxyCache) { *bsPrincipal = SysAllocString(m_pProxyCache->GetPrincipal ()); hr = S_OK; } return hr; } // CWbemLocatorSecurity methods //*************************************************************************** // // CSWbemLocatorSecurity::CSWbemLocatorSecurity // // CONSTRUCTOR // //*************************************************************************** CWbemLocatorSecurity::CWbemLocatorSecurity (CSWbemPrivilegeSet *pPrivilegeSet) : m_cRef (1), m_impLevelSet (false), m_authnLevelSet (false), m_pPrivilegeSet (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); InterlockedIncrement(&g_cObj); if (pPrivilegeSet) m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet); else m_pPrivilegeSet = new CSWbemPrivilegeSet; } CWbemLocatorSecurity::CWbemLocatorSecurity (CWbemLocatorSecurity *pCWbemLocatorSecurity) : m_cRef (1), m_impLevelSet (false), m_authnLevelSet (false), m_pPrivilegeSet (NULL) { m_Dispatch.SetObj (this, IID_ISWbemSecurity, CLSID_SWbemSecurity, L"SWbemSecurity"); InterlockedIncrement(&g_cObj); if (pCWbemLocatorSecurity) { m_pPrivilegeSet = new CSWbemPrivilegeSet (pCWbemLocatorSecurity->m_pPrivilegeSet); m_impLevelSet = pCWbemLocatorSecurity->m_impLevelSet; m_authnLevelSet = pCWbemLocatorSecurity->m_authnLevelSet; if (m_impLevelSet) m_impLevel = pCWbemLocatorSecurity->m_impLevel; if (m_authnLevelSet) m_authnLevel = pCWbemLocatorSecurity->m_authnLevel; } else { m_pPrivilegeSet = new CSWbemPrivilegeSet; m_impLevelSet = false; m_authnLevelSet = false; } } //*************************************************************************** // // CWbemLocatorSecurity::CWbemLocatorSecurity // // DESTRUCTOR // //*************************************************************************** CWbemLocatorSecurity::~CWbemLocatorSecurity (void) { InterlockedDecrement(&g_cObj); if (m_pPrivilegeSet) m_pPrivilegeSet->Release (); } //*************************************************************************** // HRESULT CWbemLocatorSecurity::QueryInterface // long CWbemLocatorSecurity::AddRef // long CWbemLocatorSecurity::Release // // DESCRIPTION: // // Standard Com IUNKNOWN functions. // //*************************************************************************** STDMETHODIMP CWbemLocatorSecurity::QueryInterface ( IN REFIID riid, OUT LPVOID *ppv ) { *ppv=NULL; if (IID_IUnknown==riid) *ppv = reinterpret_cast(this); else if (IID_ISWbemSecurity==riid) *ppv = (ISWbemSecurity *)this; else if (IID_IDispatch==riid) *ppv = (IDispatch *)this; else if (IID_ISupportErrorInfo==riid) *ppv = (ISupportErrorInfo *)this; else if (IID_IProvideClassInfo==riid) *ppv = (IProvideClassInfo *)this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CWbemLocatorSecurity::AddRef(void) { long l = InterlockedIncrement(&m_cRef); return l; } STDMETHODIMP_(ULONG) CWbemLocatorSecurity::Release(void) { long l = InterlockedDecrement(&m_cRef); if (0L!=l) return l; delete this; return 0; } //*************************************************************************** // HRESULT CSWbemLocatorSecurity::InterfaceSupportsErrorInfo // // DESCRIPTION: // // Standard Com ISupportErrorInfo functions. // //*************************************************************************** STDMETHODIMP CWbemLocatorSecurity::InterfaceSupportsErrorInfo (IN REFIID riid) { return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::get_AuthenticationLevel // // DESCRIPTION: // // Retrieve the authentication level // // PARAMETERS: // // pAuthenticationLevel holds the value on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CWbemLocatorSecurity::get_AuthenticationLevel ( WbemAuthenticationLevelEnum *pAuthenticationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pAuthenticationLevel) hr = WBEM_E_INVALID_PARAMETER; else if (m_authnLevelSet) { *pAuthenticationLevel = m_authnLevel; hr = WBEM_S_NO_ERROR; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::put_AuthenticationLevel // // DESCRIPTION: // // Set the authentication level // // PARAMETERS: // // authenticationLevel the new value // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CWbemLocatorSecurity::put_AuthenticationLevel ( WbemAuthenticationLevelEnum authenticationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) || (WBEMS_MAX_AUTHN_LEVEL < authenticationLevel)) hr = WBEM_E_INVALID_PARAMETER; else { m_authnLevel = authenticationLevel; m_authnLevelSet = true; hr = WBEM_S_NO_ERROR; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::get_ImpersonationLevel // // DESCRIPTION: // // Retrieve the impersonation level // // PARAMETERS: // // pImpersonationLevel holds the value on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CWbemLocatorSecurity::get_ImpersonationLevel ( WbemImpersonationLevelEnum *pImpersonationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pImpersonationLevel) hr = WBEM_E_INVALID_PARAMETER; else if (m_impLevelSet) { *pImpersonationLevel = m_impLevel; hr = WBEM_S_NO_ERROR; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::put_ImpersonationLevel // // DESCRIPTION: // // Set the impersonation level // // PARAMETERS: // // impersonationLevel the new value // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CWbemLocatorSecurity::put_ImpersonationLevel ( WbemImpersonationLevelEnum impersonationLevel ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel)) hr = WBEM_E_INVALID_PARAMETER; else { m_impLevel = impersonationLevel; m_impLevelSet = true; hr = WBEM_S_NO_ERROR; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::get_Privileges // // DESCRIPTION: // // Return the Privilege override set // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CWbemLocatorSecurity::get_Privileges ( ISWbemPrivilegeSet **ppPrivileges ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == ppPrivileges) hr = WBEM_E_INVALID_PARAMETER; { *ppPrivileges = NULL; if (m_pPrivilegeSet) { if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet, (PPVOID) ppPrivileges))) hr = WBEM_S_NO_ERROR; } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::SetSecurity // // DESCRIPTION: // // Set Privileges on the Process Token. // //*************************************************************************** BOOL CWbemLocatorSecurity::SetSecurity ( BSTR bsUser, bool &needToResetSecurity, HANDLE &hThreadToken ) { BOOL result = TRUE; needToResetSecurity = false; hThreadToken = NULL; /* * NT5 supports the concept of dynamic cloaking, which means * we can set privileges temporarily on a thread (impersonation) * token basis immediately before a call to a remoted proxy. * * Setting prior to locator.connectserver therefore makes no * sense for NT5. * * Oh and Win9x has no security support */ if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ())) { /* * Start by checking whether we are being impersonated. On an NT4 * box (which has no cloaking, and therefore cannot allow us to * pass on this impersonation to Winmgmt) we should RevertToSelf * if we have been configured to allow this. If we haven't been * configured to allow this, bail out now. */ if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, false, &hThreadToken)) { // We are being impersonated if (CSWbemSecurity::CanRevertToSelf ()) { if (result = RevertToSelf()) needToResetSecurity = true; } else { // Error - cannot do this! Time to bail out CloseHandle (hThreadToken); hThreadToken = NULL; result = FALSE; } } if (result && m_pPrivilegeSet) { /* * Specifying a user only makes sense for remote operations, and we * don't need to mess with privilege for remote operations since * they are set up by server logon anyway. */ if (!bsUser || (0 == wcslen(bsUser))) { // Nothing to do unless some privilege overrides have been set long lCount = 0; m_pPrivilegeSet->get_Count (&lCount); if (0 < lCount) { /* * For NT4 privilege settings on impersonation tokens are ignored * by DCOM/RPC. Hence we have to set this on the process token. * * On NT4 we must set the configured privileges on the Process * Token before the first call to RPC (i.e. IWbemLocator::ConnectServer) * if we need to guarantee privilege settings will be communicated to * the server. * * This is because (a) NT4 does not support cloaking to allow the * impersonation (i.e. thread) token privilege setting to propagate * on a per-DCOM call basis, (b) changes to Process-token level * privileges _may_ be ignored after the first remote DCOM call due * to RPC caching behavior. * * Note that this is a non-reversible operation, and is highly discouraged * on apps (such as IE and IIS) which host multiple "tasks" since it adjusts * the Privilege set for all of the other threads in the process. */ HANDLE hProcess = GetCurrentProcess (); HANDLE hProcessToken = NULL; result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken); CloseHandle (hProcess); if (result) { #ifdef WSCRPDEBUG CSWbemSecurity::PrintPrivileges (hProcessToken); #endif CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet); #ifdef WSCRPDEBUG CSWbemSecurity::PrintPrivileges (hProcessToken); #endif CloseHandle (hProcessToken); } } } } } return result; } //*************************************************************************** // // SCODE CWbemLocatorSecurity::ResetSecurity // // DESCRIPTION: // // Restore Privileges on the Thread Token. // //*************************************************************************** void CWbemLocatorSecurity::ResetSecurity ( HANDLE hThreadToken ) { // Win9x has no concept of impersonation // On NT5 we never set privileges through this class anyway if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ()) && hThreadToken) { /* * Set the supplied token back into * the current thread. */ BOOL result = SetThreadToken (NULL, hThreadToken); #ifdef WSCRPDEBUG // Print out the current privileges to see what's changed HANDLE hToken = NULL; if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken)) { // No thread token - go for the Process token instead HANDLE hProcess = GetCurrentProcess (); OpenProcessToken(hProcess, TOKEN_QUERY, &hToken); CloseHandle (hProcess); } if (hToken) { CSWbemSecurity::PrintPrivileges (hToken); CloseHandle (hToken); } #endif CloseHandle (hThreadToken); } } #ifdef WSCRPDEBUG //*************************************************************************** // // SCODE CSWbemSecurity::PrintPrivileges // // DESCRIPTION: // // Debug logging for privileges and other token info // //*************************************************************************** void CSWbemSecurity::PrintPrivileges (HANDLE hToken) { DWORD dwSize = sizeof (TOKEN_PRIVILEGES); TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize]; if (!tp) { return; } DWORD dwRequiredSize = 0; DWORD dwLastError = 0; FILE *fDebug = fopen ("C:/temp/wmidsec.txt", "a+"); fprintf (fDebug, "\n\n***********************************************\n\n"); bool status = false; // Step 0 - get impersonation level SECURITY_IMPERSONATION_LEVEL secImpLevel; if (GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel, sizeof (SECURITY_IMPERSONATION_LEVEL), &dwRequiredSize)) { switch (secImpLevel) { case SecurityAnonymous: fprintf (fDebug, "IMPERSONATION LEVEL: Anonymous\n"); break; case SecurityIdentification: fprintf (fDebug, "IMPERSONATION LEVEL: Identification\n"); break; case SecurityImpersonation: fprintf (fDebug, "IMPERSONATION LEVEL: Impersonation\n"); break; case SecurityDelegation: fprintf (fDebug, "IMPERSONATION LEVEL: Delegation\n"); break; default: fprintf (fDebug, "IMPERSONATION LEVEL: Unknown!\n"); break; } fflush (fDebug); } DWORD dwUSize = sizeof (TOKEN_USER); TOKEN_USER *tu = (TOKEN_USER *) new BYTE [dwUSize]; if (!tu) { delete [] tp; fclose (fDebug); return; } // Step 1 - get user info if (0 == GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize, &dwRequiredSize)) { delete [] tu; dwUSize = dwRequiredSize; dwRequiredSize = 0; tu = (TOKEN_USER *) new BYTE [dwUSize]; if (!tu) { delete [] tp; fclose (fDebug); return; } if (!GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize, &dwRequiredSize)) dwLastError = GetLastError (); else status = true; } if (status) { // Dig out the user info dwRequiredSize = BUFSIZ; char *userName = new char [dwRequiredSize]; char *domainName = new char [dwRequiredSize]; if (!userName || !domainName) { delete [] tp; delete [] tu; delete [] userName; delete [] domainName; return; } SID_NAME_USE eUse; LookupAccountSid (NULL, (tu->User).Sid, userName, &dwRequiredSize, domainName, &dwRequiredSize, &eUse); fprintf (fDebug, "USER: [%s\\%s]\n", domainName, userName); fflush (fDebug); delete [] userName; delete [] domainName; } else { fprintf (fDebug, " FAILED : %d\n", dwLastError); fflush (fDebug); } delete [] tu; status = false; dwRequiredSize = 0; // Step 2 - get privilege info if (0 == GetTokenInformation (hToken, TokenPrivileges, (LPVOID) tp, dwSize, &dwRequiredSize)) { delete [] tp; dwSize = dwRequiredSize; dwRequiredSize = 0; tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize]; if (!tp) { fclose (fDebug); return; } if (!GetTokenInformation (hToken, TokenPrivileges, (LPVOID) tp, dwSize, &dwRequiredSize)) { dwLastError = GetLastError (); } else status = true; } else status = true; if (status) { fprintf (fDebug, "PRIVILEGES: [%d]\n", tp->PrivilegeCount); fflush (fDebug); for (DWORD i = 0; i < tp->PrivilegeCount; i++) { DWORD dwNameSize = 256; LPTSTR name = new TCHAR [dwNameSize + 1]; if (!name) { delete [] tp; fclose (fDebug); return; } DWORD dwRequiredSize = dwNameSize; if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize)) { BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT); BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED); BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS); fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n", name, enabDefault, enabled, usedForAccess); fflush (fDebug); } else { dwLastError = GetLastError (); delete [] name; dwNameSize = dwRequiredSize; name = new TCHAR [dwRequiredSize]; if (!name) { delete [] tp; fclose (fDebug); return; } if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize)) { BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT); BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED); BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS); fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n", name, enabDefault, enabled, usedForAccess); fflush (fDebug); } else dwLastError = GetLastError (); } delete [] name; } } else { fprintf (fDebug, " FAILED : %d\n", dwLastError); fflush (fDebug); } delete [] tp; fclose (fDebug); } #endif