diff options
Diffstat (limited to 'src/vm/securityprincipal.cpp')
-rw-r--r-- | src/vm/securityprincipal.cpp | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/vm/securityprincipal.cpp b/src/vm/securityprincipal.cpp new file mode 100644 index 0000000000..5f31d3a24d --- /dev/null +++ b/src/vm/securityprincipal.cpp @@ -0,0 +1,227 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" + +#include "securityprincipal.h" +#include "corhost.h" +#include "security.h" + +#ifndef FEATURE_CORECLR +INT32 QCALLTYPE COMPrincipal::ImpersonateLoggedOnUser(HANDLE hToken) +{ + QCALL_CONTRACT; + + HRESULT hr = S_OK; + + BEGIN_QCALL; + +#ifdef FEATURE_INCLUDE_ALL_INTERFACES + IHostSecurityManager *pSM = CorHost2::GetHostSecurityManager(); + if (pSM) { + BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); + hr = pSM->ImpersonateLoggedOnUser(hToken); + END_SO_TOLERANT_CODE_CALLING_HOST; + } + else +#endif // FEATURE_INCLUDE_ALL_INTERFACES + { + if (!::ImpersonateLoggedOnUser(hToken)) + hr = HRESULT_FROM_GetLastError(); + } + + STRESS_LOG2(LF_SECURITY, LL_INFO100, "COMPrincipal::ImpersonateLoggedOnUser called with hTokenSAFE = %d. Returning 0x%x\n",hToken,hr); + + END_QCALL; + + return hr; +} + +FCIMPL3(INT32, COMPrincipal::OpenThreadToken, DWORD dwDesiredAccess, DWORD dwOpenAs, SafeHandle** phThreadTokenUNSAFE) +{ + CONTRACTL { + FCALL_CHECK; + PRECONDITION(CheckPointer(phThreadTokenUNSAFE)); + } CONTRACTL_END; + + HRESULT hr = S_OK; + HELPER_METHOD_FRAME_BEGIN_RET_0(); + + SafeHandle** phThreadTokenSAFE = phThreadTokenUNSAFE; + GCPROTECT_BEGININTERIOR(phThreadTokenSAFE); + + *phThreadTokenUNSAFE = NULL; + HandleHolder hThreadToken; + { + GCX_PREEMP(); + BOOL bOpenAsSelf = TRUE; +#ifdef FEATURE_INCLUDE_ALL_INTERFACES + IHostSecurityManager *pSM = CorHost2::GetHostSecurityManager(); + if (pSM) { + if (dwOpenAs == WINSECURITYCONTEXT_THREAD) + bOpenAsSelf = FALSE; + + BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); + hr = pSM->OpenThreadToken(dwDesiredAccess, bOpenAsSelf, &hThreadToken); + END_SO_TOLERANT_CODE_CALLING_HOST; + if (FAILED(hr) && dwOpenAs == WINSECURITYCONTEXT_BOTH) { + bOpenAsSelf = FALSE; + BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); + hr = pSM->OpenThreadToken(dwDesiredAccess, bOpenAsSelf, &hThreadToken); + END_SO_TOLERANT_CODE_CALLING_HOST; + } + } + else +#endif // FEATURE_INCLUDE_ALL_INTERFACES + { + if (dwOpenAs == WINSECURITYCONTEXT_THREAD) + bOpenAsSelf = FALSE; + + if (!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hThreadToken)) { + if (dwOpenAs == WINSECURITYCONTEXT_BOTH) { + bOpenAsSelf = FALSE; + hr = S_OK; + if (!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hThreadToken)) + hr = HRESULT_FROM_GetLastError(); + } + else + hr = HRESULT_FROM_GetLastError(); + } + } + } + + if (SUCCEEDED(hr)) { + struct _gc { + SAFEHANDLE pSafeTokenHandle; + } gc; + gc.pSafeTokenHandle = NULL; + + GCPROTECT_BEGIN(gc); + // Allocate a SafeHandle here + MethodTable *pMT = MscorlibBinder::GetClass(CLASS__SAFE_TOKENHANDLE); + gc.pSafeTokenHandle = (SAFEHANDLE) AllocateObject(pMT); + CallDefaultConstructor(gc.pSafeTokenHandle); + gc.pSafeTokenHandle->SetHandle((void*) hThreadToken); + hThreadToken.SuppressRelease(); + + SetObjectReference((OBJECTREF*) phThreadTokenSAFE, (OBJECTREF) gc.pSafeTokenHandle, gc.pSafeTokenHandle->GetAppDomain()); + GCPROTECT_END(); + } + + GCPROTECT_END(); + + HELPER_METHOD_FRAME_END(); + return hr; +} +FCIMPLEND + +INT32 QCALLTYPE COMPrincipal::RevertToSelf() +{ + QCALL_CONTRACT; + + HRESULT hr = S_OK; + + BEGIN_QCALL; + +#ifdef FEATURE_INCLUDE_ALL_INTERFACES + IHostSecurityManager *pSM = CorHost2::GetHostSecurityManager(); + if (pSM) { + BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); + hr = pSM->RevertToSelf(); + END_SO_TOLERANT_CODE_CALLING_HOST; + } + else +#endif // FEATURE_INCLUDE_ALL_INTERFACES + { + if (!::RevertToSelf()) + hr = HRESULT_FROM_GetLastError(); + } + + STRESS_LOG1(LF_SECURITY, LL_INFO100, "COMPrincipal::RevertToSelf returning 0x%x\n",hr); + + END_QCALL; + + return hr; +} + +INT32 QCALLTYPE COMPrincipal::SetThreadToken(HANDLE hToken) +{ + QCALL_CONTRACT; + + HRESULT hr = S_OK; + + BEGIN_QCALL; + +#ifdef FEATURE_INCLUDE_ALL_INTERFACES + IHostSecurityManager *pSM = CorHost2::GetHostSecurityManager(); + if (pSM) + { + BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); + hr = pSM->SetThreadToken(hToken); + END_SO_TOLERANT_CODE_CALLING_HOST; + } + else +#endif // FEATURE_INCLUDE_ALL_INTERFACES + { + if (!::SetThreadToken(NULL, hToken)) + hr = HRESULT_FROM_GetLastError(); + } + + END_QCALL; + + return hr; +} +#endif // !FEATURE_CORECLR + +void COMPrincipal::CLR_ImpersonateLoggedOnUser(HANDLE hToken) +{ + CONTRACTL { + NOTHROW; + GC_TRIGGERS; + MODE_ANY; + } CONTRACTL_END; + + HRESULT hr = S_OK; + + { + GCX_PREEMP(); +#ifdef FEATURE_INCLUDE_ALL_INTERFACES + IHostSecurityManager *pSM = CorHost2::GetHostSecurityManager(); + if (pSM) { + hr = pSM->RevertToSelf(); + if (hr != S_OK) + { + // FailFast + STRESS_LOG2(LF_EH, LL_INFO100, "CLR_ImpersonateLoggedOnUser failed for hImpersonateToken = %d with error:0x%x\n",hToken, hr); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_SECURITY); + } + if (hToken != NULL) + hr = pSM->ImpersonateLoggedOnUser(hToken); + } + else +#endif // FEATURE_INCLUDE_ALL_INTERFACES + { + if (!::RevertToSelf()) + hr = HRESULT_FROM_GetLastError(); + if (hr != S_OK) + { + // FailFast + STRESS_LOG2(LF_EH, LL_INFO100, "CLR_ImpersonateLoggedOnUser failed for hImpersonateToken = %d with error:0x%x\n",hToken, hr); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_SECURITY); + } + if (hToken != NULL && !::ImpersonateLoggedOnUser(hToken)) + hr = HRESULT_FROM_GetLastError(); + } + + if (hr != S_OK) + { + // FailFast + STRESS_LOG2(LF_EH, LL_INFO100, "CLR_ImpersonateLoggedOnUser failed for hImpersonateToken = %d with error:0x%x\n",hToken, hr); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_SECURITY); + } + } + + return; +} + |