From: danmosemsft Date: Sat, 11 Feb 2017 01:01:50 +0000 (-0800) Subject: Dead files X-Git-Tag: submit/tizen/20210909.063632~11030^2~8108^2~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7912500e77a8c71aa0ea827bd2245d31506f691b;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Dead files Commit migrated from https://github.com/dotnet/coreclr/commit/396f7d43b3c0f3ca7034a6d1d9cd7d6914778a1e --- diff --git a/src/coreclr/src/vm/aptca.cpp b/src/coreclr/src/vm/aptca.cpp deleted file mode 100644 index e4e8f19..0000000 --- a/src/coreclr/src/vm/aptca.cpp +++ /dev/null @@ -1,1363 +0,0 @@ -// 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. -//-------------------------------------------------------------------------- -// aptca.h -// -// Functions for handling allow partially trusted callers assemblies -// - -// -//-------------------------------------------------------------------------- - - -#include "common.h" -#include "aptca.h" - -// -// Conditional APTCA cache implementation -// - -ConditionalAptcaCache::ConditionalAptcaCache(AppDomain *pAppDomain) - : m_pAppDomain(pAppDomain), - m_canonicalListIsNull(false), - m_domainState(kDomainStateUnknown) -{ - WRAPPER_NO_CONTRACT; - - _ASSERTE(pAppDomain != NULL); -} - -ConditionalAptcaCache::~ConditionalAptcaCache() -{ - WRAPPER_NO_CONTRACT; -} - -void ConditionalAptcaCache::SetCachedState(PTR_PEImage pImage, ConditionalAptcaCache::State state) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pImage)); - PRECONDITION(state != kUnknown); - } - CONTRACTL_END; - - if (state == kNotCAptca) - { - pImage->SetIsNotConditionalAptca(); - } -} - -ConditionalAptcaCache::State ConditionalAptcaCache::GetCachedState(PTR_PEImage pImage) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pImage)); - } - CONTRACTL_END; - - if (!pImage->MayBeConditionalAptca()) - { - return kNotCAptca; - } - - return kUnknown; -} - -void ConditionalAptcaCache::SetCanonicalConditionalAptcaList(LPCWSTR wszCanonicalConditionalAptcaList) -{ - WRAPPER_NO_CONTRACT; - m_canonicalListIsNull = (wszCanonicalConditionalAptcaList == NULL); - m_canonicalList.Set(wszCanonicalConditionalAptcaList); -} - -#ifndef CROSSGEN_COMPILE -ConditionalAptcaCache::DomainState ConditionalAptcaCache::GetConditionalAptcaDomainState() -{ - CONTRACTL - { - GC_TRIGGERS; - THROWS; - MODE_ANY; - } - CONTRACTL_END; - - if (m_domainState == kDomainStateUnknown) - { - IApplicationSecurityDescriptor *pASD = m_pAppDomain->GetSecurityDescriptor(); - DomainState domainState = kDomainStateUnknown; - - // In the full trust case we only need to look at the conditional APTCA list in the case that the host - // has configured one on the default domain (for instance WPF). Otherwise, all full trust domains have - // all conditional APTCA assemblies enabled. - bool processFullTrustAptcaList = false; - if (m_pAppDomain->IsCompilationDomain()) - { - processFullTrustAptcaList = false; - } - else if (m_pAppDomain->IsDefaultDomain()) - { - processFullTrustAptcaList = !m_canonicalListIsNull; - } - else - { - processFullTrustAptcaList = ConsiderFullTrustConditionalAptcaLists(); - } - - // Consider the domain to be fully trusted if it really is fully trusted, or if we're currently - // setting the domain up, it looks like it will be fully trusted, and the AppDomainManager has - // promised that won't change. - bool isFullTrustDomain = !m_pAppDomain->GetSecurityDescriptor()->DomainMayContainPartialTrustCode(); - if (pASD->IsInitializationInProgress() && (m_pAppDomain->GetAppDomainManagerInitializeNewDomainFlags() & eInitializeNewDomainFlags_NoSecurityChanges)) - { - BOOL preResolveFullTrust; - BOOL preResolveHomogenous; - pASD->PreResolve(&preResolveFullTrust, &preResolveHomogenous); - - isFullTrustDomain = preResolveFullTrust && preResolveHomogenous; - } - - if (m_pAppDomain->IsCompilationDomain()) - { - // NGEN always enables all conditional APTCA assemblies - domainState = kAllEnabled; - } - else if (!isFullTrustDomain || processFullTrustAptcaList) - { - if (m_canonicalList.GetCount() == 0) - { - // A null or empty conditional APTCA list means that no assemblies are enabled in this domain - domainState = kAllDisabled; - } - else - { - // We're in a domain that supports conditional APTCA and an interesting list is supplied. In - // this domain, some assemblies are enabled. - domainState = kSomeEnabled; - } - } - else - { - domainState = kAllEnabled; - } - - _ASSERTE(domainState != kDomainStateUnknown); - InterlockedCompareExchange(reinterpret_cast(&m_domainState), domainState, kDomainStateUnknown); - } - - return m_domainState; -} - -// static -bool ConditionalAptcaCache::ConsiderFullTrustConditionalAptcaLists() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - if (GetAppDomain()->IsCompilationDomain()) - { - return false; - } - - IApplicationSecurityDescriptor *pASD = SystemDomain::System()->DefaultDomain()->GetSecurityDescriptor(); - ConditionalAptcaCache *pDefaultDomainCaptca = pASD->GetConditionalAptcaCache(); - - // The only way that we use CAPTCA lists is if the host has configured the default domain to not be all - // enabled (that is, the host has setup a CAPTCA list of any sort for the default domain) - return pDefaultDomainCaptca->GetConditionalAptcaDomainState() != kAllEnabled; -} - -// APTCA killbit list helper functions -namespace -{ - static const LPCWSTR wszAptcaRootKey = W("SOFTWARE\\Microsoft\\.NETFramework\\Policy\\APTCA"); - - //-------------------------------------------------------------------------------------------------------- - // - // The AptcaKillBitList class is responsible for holding the machine wide list of assembly name / file - // versions which have been disabled for APTCA on the machine. - // - - class AptcaKillBitList - { - private: - ArrayList m_killBitList; - - public: - ~AptcaKillBitList(); - - bool AreAnyAssembliesKillBitted(); - bool IsAssemblyKillBitted(PEAssembly *pAssembly); - bool IsAssemblyKillBitted(IAssemblyName *pAssemblyName, ULARGE_INTEGER fileVersion); - - static AptcaKillBitList *ReadMachineKillBitList(); - - private: - AptcaKillBitList(); - AptcaKillBitList(const AptcaKillBitList &other); // not implemented - - private: - static const LPCWSTR wszKillBitValue; - - private: - static bool FileVersionsAreEqual(ULARGE_INTEGER targetVersion, IAssemblyName *pKillBitAssemblyName); - }; - const LPCWSTR AptcaKillBitList::wszKillBitValue = W("APTCA_FLAG"); - - AptcaKillBitList::AptcaKillBitList() - { - LIMITED_METHOD_CONTRACT; - } - - AptcaKillBitList::~AptcaKillBitList() - { - WRAPPER_NO_CONTRACT; - - // Release all of the IAssemblyName objects stored in this list - for (DWORD i = 0; i < m_killBitList.GetCount(); ++i) - { - IAssemblyName *pKillBitAssemblyName = reinterpret_cast(m_killBitList.Get(i)); - if (pKillBitAssemblyName != NULL) - { - pKillBitAssemblyName->Release(); - } - } - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine if any assemblies are on the APTCA killbit list - // - - bool AptcaKillBitList::AreAnyAssembliesKillBitted() - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // We don't consider the killbit for NGEN, as ngened code always assumes that APTCA is enabled. - if (GetAppDomain()->IsCompilationDomain()) - { - return false; - } - - return m_killBitList.GetCount() > 0; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Compare the file versions of an assembly with the verison that is being killbitted to see if they - // match. For compatibility with v3.5, we assume any failure means that the versions do not match. - // - - // static - bool AptcaKillBitList::FileVersionsAreEqual(ULARGE_INTEGER targetVersion, IAssemblyName *pKillBitAssemblyName) - { - DWORD dwKillBitMajorVersion = 0; - DWORD dwVersionSize = sizeof(dwKillBitMajorVersion); - if (FAILED(pKillBitAssemblyName->GetProperty(ASM_NAME_FILE_MAJOR_VERSION, &dwKillBitMajorVersion, &dwVersionSize)) || - dwVersionSize == 0) - { - return false; - } - - DWORD dwKillBitMinorVersion = 0; - dwVersionSize = sizeof(dwKillBitMinorVersion); - if (FAILED(pKillBitAssemblyName->GetProperty(ASM_NAME_FILE_MINOR_VERSION, &dwKillBitMinorVersion, &dwVersionSize)) || - dwVersionSize == 0) - { - return false; - } - - DWORD dwKillBitBuildVersion = 0; - dwVersionSize = sizeof(dwKillBitBuildVersion); - if (FAILED(pKillBitAssemblyName->GetProperty(ASM_NAME_FILE_BUILD_NUMBER, &dwKillBitBuildVersion, &dwVersionSize)) || - dwVersionSize == 0) - { - return false; - } - - DWORD dwKillBitRevisionVersion = 0; - dwVersionSize = sizeof(dwKillBitRevisionVersion); - if (FAILED(pKillBitAssemblyName->GetProperty(ASM_NAME_FILE_REVISION_NUMBER, &dwKillBitRevisionVersion, &dwVersionSize)) || - dwVersionSize == 0) - { - return false; - } - - DWORD dwTargetMajorVersion = (targetVersion.HighPart & 0xFFFF0000) >> 16; - DWORD dwTargetMinorVersion = targetVersion.HighPart & 0x0000FFFF; - DWORD dwTargetBuildVersion = (targetVersion.LowPart & 0xFFFF0000) >> 16; - DWORD dwTargetRevisionVersion = targetVersion.LowPart & 0x0000FFFF; - - return dwTargetMajorVersion == dwKillBitMajorVersion && - dwTargetMinorVersion == dwKillBitMinorVersion && - dwTargetBuildVersion == dwKillBitBuildVersion && - dwTargetRevisionVersion == dwKillBitRevisionVersion; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine if a specific assembly is on the killbit list - // - - bool AptcaKillBitList::IsAssemblyKillBitted(PEAssembly *pAssembly) - { - STANDARD_VM_CONTRACT; - - IAssemblyName *pTargetAssemblyName = pAssembly->GetFusionAssemblyName(); - - // For compat with v3.5, we use hte Win32 file version here rather than the Fusion version - LPCWSTR pwszPath = pAssembly->GetPath().GetUnicode(); - if (pwszPath != NULL) - { - ULARGE_INTEGER fileVersion = { 0, 0 }; - HRESULT hr = GetFileVersion(pwszPath, &fileVersion); - if (SUCCEEDED(hr)) - { - return IsAssemblyKillBitted(pTargetAssemblyName, fileVersion); - } - } - - return false; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine if a specific assembly is on the killbit list - // - - bool AptcaKillBitList::IsAssemblyKillBitted(IAssemblyName *pTargetAssemblyName, ULARGE_INTEGER fileVersion) - { - STANDARD_VM_CONTRACT; - - // If nothing is killbitted, then this assembly cannot be killbitted - if (!AreAnyAssembliesKillBitted()) - { - return false; - } - - for (DWORD i = 0; i < m_killBitList.GetCount(); ++i) - { - IAssemblyName *pKillBitAssemblyName = reinterpret_cast(m_killBitList.Get(i)); - - // By default, we compare all fields of the assembly's name, however if the culture was neutral, - // we strip that out. - DWORD dwCmpFlags = ASM_CMPF_IL_ALL; - - DWORD cbCultureSize = 0; - SString strCulture; - HRESULT hrCulture = pKillBitAssemblyName->GetProperty(ASM_NAME_CULTURE, NULL, &cbCultureSize); - if (hrCulture == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - DWORD cchCulture = (cbCultureSize / sizeof(WCHAR)) - 1; - WCHAR *wszCultureBuffer = strCulture.OpenUnicodeBuffer(cchCulture); - hrCulture = pKillBitAssemblyName->GetProperty(ASM_NAME_CULTURE, wszCultureBuffer, &cbCultureSize); - strCulture.CloseBuffer(); - } - - if (SUCCEEDED(hrCulture)) - { - if (cbCultureSize == 0 || strCulture.EqualsCaseInsensitive(W("")) || strCulture.EqualsCaseInsensitive(W("neutral"))) - { - dwCmpFlags &= ~ASM_CMPF_CULTURE; - } - } - - // If the input assembly matches the kill bit assembly's name and file version, then we need to - // kill it. - if (pTargetAssemblyName->IsEqual(pKillBitAssemblyName, dwCmpFlags) == S_OK && - FileVersionsAreEqual(fileVersion, pKillBitAssemblyName)) - { - return true; - } - } - - return false; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Read the machine-wide APTCA kill bit list into a kill bit list object. For compatibility with v3.5, - // errors during this initialization are ignored - leading to APTCA entries that may not be considered - // for kill bitting. - // - - // static - AptcaKillBitList *AptcaKillBitList::ReadMachineKillBitList() - { - CONTRACT(AptcaKillBitList *) - { - STANDARD_VM_CHECK; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - NewHolder pKillBitList(new AptcaKillBitList); - - HKEYHolder hKeyAptca; - - // Open the APTCA subkey in the registry. - if (WszRegOpenKeyEx(HKEY_LOCAL_MACHINE, wszAptcaRootKey, 0, KEY_READ, &hKeyAptca) == ERROR_SUCCESS) - { - - DWORD cchSubKeySize = 0; - if (WszRegQueryInfoKey(hKeyAptca, NULL, NULL, NULL, NULL, &cchSubKeySize, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) - { - cchSubKeySize = MAX_PATH_FNAME; - } - ++cchSubKeySize; - - NewArrayHolder wszSubKey(new WCHAR[cchSubKeySize]); - - DWORD dwKey = 0; - DWORD cchWszSubKey = cchSubKeySize; - // Assembly specific records are represented as subkeys of the key we've just opened with names - // equal to the strong name of the assembly being kill bitted, and a value of APTCA_FLAG = 1. - while (WszRegEnumKeyEx(hKeyAptca, dwKey, wszSubKey, &cchWszSubKey, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) - { - ++dwKey; - cchWszSubKey = cchSubKeySize; - - // Open the subkey: the key name is the full name of the assembly to potentially kill-bit - HKEYHolder hSubKey; - if (WszRegOpenKeyEx(hKeyAptca, wszSubKey, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) - { - continue; - } - - DWORD dwKillbit = 0; - DWORD dwType = REG_DWORD; - DWORD dwSize = sizeof(dwKillbit); - - // look for the APTCA flag - LONG queryValue = WszRegQueryValueEx(hSubKey, - wszKillBitValue, - NULL, - &dwType, - reinterpret_cast(&dwKillbit), - &dwSize); - if (queryValue == ERROR_SUCCESS && dwKillbit == 1) - { - // We have a strong named assembly with an APTCA killbit value set - parse the key into - // an assembly name, and add it to our list - ReleaseHolder pKillBitAssemblyName; - HRESULT hrAssemblyName = CreateAssemblyNameObject(&pKillBitAssemblyName, wszSubKey, CANOF_PARSE_DISPLAY_NAME, NULL); - if (FAILED(hrAssemblyName)) - { - continue; - } - - // - // For compatibility with v3.5, we only accept kill bit entries which have four part - // assembly versions, names, and public key tokens. - // - - // Verify the version first - bool validVersion = true; - for (DWORD dwVersionPartId = ASM_NAME_MAJOR_VERSION; dwVersionPartId <= ASM_NAME_REVISION_NUMBER; ++dwVersionPartId) - { - DWORD dwVersionPart; - DWORD cbVersionPart = sizeof(dwVersionPart); - HRESULT hrVersion = pKillBitAssemblyName->GetProperty(dwVersionPartId, &dwVersionPart, &cbVersionPart); - if (FAILED(hrVersion) || cbVersionPart == 0) - { - validVersion = false; - } - } - if (!validVersion) - { - continue; - } - - // Make sure there is a simple name - DWORD cbNameSize = 0; - HRESULT hrName = pKillBitAssemblyName->GetProperty(ASM_NAME_NAME, NULL, &cbNameSize); - if (hrName != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - continue; - } - - // Verify the killbit assembly has a public key token - DWORD cbPublicKeyTokenSize = 0; - HRESULT hrPublicKey = pKillBitAssemblyName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, NULL, &cbPublicKeyTokenSize); - if (hrPublicKey != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - continue; - } - - // Verify the killbit assembly has either no culture or a valid culture token - DWORD cbCultureSize = 0; - HRESULT hrCulture = pKillBitAssemblyName->GetProperty(ASM_NAME_CULTURE, NULL, &cbCultureSize); - if (FAILED(hrCulture) && hrCulture != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - continue; - } - - // The name checks out, so add the kill bit entry - LOG((LF_SECURITY, - LL_INFO10, - "APTCA killbit added for assembly '%S'.\n", - wszSubKey)); - pKillBitList->m_killBitList.Append(pKillBitAssemblyName.Extract()); - } - } - } - - RETURN(pKillBitList.Extract()); - } - - VolatilePtr g_pAptcaKillBitList(NULL); - - //-------------------------------------------------------------------------------------------------------- - // - // Get the APTCA killbit list - // - - AptcaKillBitList *GetKillBitList() - { - STANDARD_VM_CONTRACT; - - if (g_pAptcaKillBitList.Load() == NULL) - { - NewHolder pAptcaKillBitList(AptcaKillBitList::ReadMachineKillBitList()); - - LPVOID pvOldValue = InterlockedCompareExchangeT(g_pAptcaKillBitList.GetPointer(), - pAptcaKillBitList.GetValue(), - NULL); - if (pvOldValue == NULL) - { - pAptcaKillBitList.SuppressRelease(); - } - } - - _ASSERTE(g_pAptcaKillBitList.Load() != NULL); - return g_pAptcaKillBitList.Load(); - } -} - -// APTCA helper functions -namespace -{ - enum ConditionalAptcaSharingMode - { - kShareUnknown, - kShareIfEnabled, // Share an assembly only if all conditional APTCA assemblies in its closure are enabled - kShareIfDisabled, // Share an assembly only if all conditional APTCA assemblies in its closure are disabled - }; - - //-------------------------------------------------------------------------------------------------------- - // - // Get the name of an assembly as it would appear in the APTCA enabled list of an AppDomain - // - - void GetAssemblyNameForConditionalAptca(Assembly *pAssembly, SString *pAssemblyName) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pAssembly)); - PRECONDITION(CheckPointer(pAssemblyName)); - } - CONTRACTL_END; - - GCX_COOP(); - - // Call assembly.GetName().GetNameWithPublicKey() to get the name the user would have to add to the - // whitelist to enable this assembly - struct - { - OBJECTREF orAssembly; - STRINGREF orAssemblyName; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - gc.orAssembly = pAssembly->GetExposedObject(); - MethodDescCallSite getAssemblyName(METHOD__ASSEMBLY__GET_NAME_FOR_CONDITIONAL_APTCA, &gc.orAssembly); - ARG_SLOT args[1] = - { - ObjToArgSlot(gc.orAssembly) - }; - gc.orAssemblyName = getAssemblyName.Call_RetSTRINGREF(args); - - // Copy to assemblyName - pAssemblyName->Set(gc.orAssemblyName->GetBuffer()); - - GCPROTECT_END(); - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine which types of conditional APTCA assemblies may be shared - // - - ConditionalAptcaSharingMode GetConditionalAptcaSharingMode() - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - static ConditionalAptcaSharingMode sharingMode = kShareUnknown; - - if (sharingMode == kShareUnknown) - { - // If the default domain has any conditional APTCA assemblies enabled in it, then we share in the - // enabled direction. Otherwise, the default domain has all conditional APTCA assemblies disabled - // so we need to share in the disabled direction - ConditionalAptcaCache *pDefaultDomainCache = SystemDomain::System()->DefaultDomain()->GetSecurityDescriptor()->GetConditionalAptcaCache(); - ConditionalAptcaCache::DomainState domainState = pDefaultDomainCache->GetConditionalAptcaDomainState(); - - if (domainState == ConditionalAptcaCache::kAllDisabled) - { - sharingMode = kShareIfDisabled; - } - else - { - sharingMode = kShareIfEnabled; - } - } - - return sharingMode; - } - - /* XXX Fri 7/17/2009 - * I can't call DomainAssembly::IsConditionalAPTCAVisible() here. That requires an Assembly which means - * we have to be at FILE_LOAD_ALLOCATE. There are two problems: - * 1) We don't want to load dependencies here if we can avoid it - * 2) We can't load them anyway (hard bound dependencies can't get past - * FILE_LOAD_VERIFY_NATIVE_IMAGE_DEPENDENCIES. - * - * We're going to do a relaxed check here. Instead of checking the public key, we're - * only going to check the public key token. See - * code:AppDomain::IsAssemblyOnAptcaVisibleListRaw for more information. - * - * pAsmName - The name of the assembly to check. - * pDomainAssembly - The Domain Assembly used for logging. - */ - bool IsAssemblyOnAptcaVisibleList(IAssemblyName * pAsmName, DomainAssembly *pDomainAssembly) - { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pAsmName)); - } - CONTRACTL_END; - - ConditionalAptcaCache *pDomainCache = pDomainAssembly->GetAppDomain()->GetSecurityDescriptor()->GetConditionalAptcaCache(); - if (pDomainCache->GetConditionalAptcaDomainState() == ConditionalAptcaCache::kAllEnabled) - { - return true; - } - - CQuickBytes qbName; - LPWSTR pszName; - DWORD cbName = 0; - HRESULT hr = pAsmName->GetProperty(ASM_NAME_NAME, NULL, &cbName); - if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - pszName = (LPWSTR)qbName.AllocThrows(cbName); - } - else - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting native image / code sharing because there was an ") - W("error checking for conditional APTCA: 0x%x"), hr); - return false; - } - hr = pAsmName->GetProperty(ASM_NAME_NAME, (void *)pszName, &cbName); - if (FAILED(hr)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting native image / code sharing because there was an ") - W("error checking for conditional APTCA: 0x%x"), hr); - return false; - } - BYTE rgPublicKeyToken[8]; - DWORD cbPkt = _countof(rgPublicKeyToken); - hr = pAsmName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, - (void*)rgPublicKeyToken, &cbPkt); - if (FAILED(hr)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting native image / code sharing because there was an ") - W("error obtaining the public key token for %s: 0x%x"), - pszName, hr); - return false; - } - - GCX_COOP(); - - CLR_BOOL isVisible = FALSE; - - struct - { - OBJECTREF orThis; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - GCPROTECT_BEGIN(gc); - gc.orThis = pDomainAssembly->GetAppDomain()->GetExposedObject(); - - MethodDescCallSite assemblyVisible(METHOD__APP_DOMAIN__IS_ASSEMBLY_ON_APTCA_VISIBLE_LIST_RAW, - &gc.orThis); - ARG_SLOT args[] = { - ObjToArgSlot(gc.orThis), - (ARG_SLOT)pszName, - (ARG_SLOT)wcslen(pszName), - (ARG_SLOT)rgPublicKeyToken, - (ARG_SLOT)cbPkt - }; - isVisible = assemblyVisible.Call_RetBool(args); - GCPROTECT_END(); - - return isVisible; - } - - bool IsAssemblyOnAptcaVisibleList(DomainAssembly *pAssembly) - { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pAssembly)); - PRECONDITION(GetAppDomain() == pAssembly->GetAppDomain()); - } - CONTRACTL_END; - - ConditionalAptcaCache *pDomainCache = pAssembly->GetAppDomain()->GetSecurityDescriptor()->GetConditionalAptcaCache(); - if (pDomainCache->GetConditionalAptcaDomainState() == ConditionalAptcaCache::kAllEnabled) - { - return true; - } - - GCX_COOP(); - - bool foundInList = false; - - // Otherwise, we need to transition into the BCL code to find out if the assembly is on the list - struct - { - OBJECTREF orAppDomain; - OBJECTREF orAssembly; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - MethodDescCallSite isAssemblyOnAptcaVisibleList(METHOD__APP_DOMAIN__IS_ASSEMBLY_ON_APTCA_VISIBLE_LIST); - gc.orAppDomain = GetAppDomain()->GetExposedObject(); - gc.orAssembly = pAssembly->GetAssembly()->GetExposedObject(); - - ARG_SLOT args[] = - { - ObjToArgSlot(gc.orAppDomain), - ObjToArgSlot(gc.orAssembly) - }; - - foundInList = isAssemblyOnAptcaVisibleList.Call_RetBool(args); - - GCPROTECT_END(); - - return foundInList; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine if an assembly is APTCA in the current domain or not - // - // Arguments: - // pDomainAssembly - Assembly to check for APTCA-ness - // tokenFlags - raw metadata security bits from the assembly - // - // Return Value: - // true if the assembly is APTCA, false if it is not - // - - bool IsAssemblyAptcaEnabled(DomainAssembly *pDomainAssembly, TokenSecurityDescriptorFlags tokenFlags) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pDomainAssembly)); - } - CONTRACTL_END; - -#ifdef _DEBUG - SString strAptcaAssemblyBreak(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_Security_AptcaAssemblyBreak)); - SString strAssemblySimpleName(SString::Utf8, pDomainAssembly->GetSimpleName()); - if (strAptcaAssemblyBreak.EqualsCaseInsensitive(strAssemblySimpleName)) - { - _ASSERTE(!"Checking APTCA-ness of an APTCA break assembly"); - } -#endif // _DEBUG - - // If the assembly is not marked APTCA, then it cannot possibly be APTCA enabled - if ((tokenFlags & TokenSecurityDescriptorFlags_APTCA) == TokenSecurityDescriptorFlags_None) - { - return false; - } - - GCX_PREEMP(); - - // Additionally, if the assembly is on the APTCA kill list, then no matter what it says in its metadata, - // it should not be considered APTCA - if (GetKillBitList()->IsAssemblyKillBitted(pDomainAssembly->GetFile())) - { - return false; - } - - // If the assembly is conditionally APTCA, then we need to check the current AppDomain's APTCA enabled - // list to figure out if it is APTCA in this domain. - if (tokenFlags & TokenSecurityDescriptorFlags_ConditionalAPTCA) - { - return IsAssemblyOnAptcaVisibleList(pDomainAssembly); - } - - // Otherwise, the assembly is APTCA - return true; - } - - //-------------------------------------------------------------------------------------------------------- - // - // Determine if the assembly matches the conditional APTCA sharing mode. That is, if we are sharing - // enabled conditional APTCA assemblies check that this assembly is enabled. Similarly, if we are - // sharing disabled conditional APTCA assemblies check that this assembly is disabled. - // - // This method assumes that the assembly is conditionally APTCA - // - - bool AssemblyMatchesShareMode(IAssemblyName *pAsmName, DomainAssembly *pDomainAssembly) - { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pAsmName)); - PRECONDITION(GetConditionalAptcaSharingMode() != kShareUnknown); - } - CONTRACTL_END; - - if (IsAssemblyOnAptcaVisibleList(pAsmName, pDomainAssembly)) - { - return GetConditionalAptcaSharingMode() == kShareIfEnabled; - } - else - { - return GetConditionalAptcaSharingMode() == kShareIfDisabled; - } - } - - bool AssemblyMatchesShareMode(ConditionalAptcaCache::State state) - { - STANDARD_VM_CONTRACT; - - _ASSERTE(state == ConditionalAptcaCache::kEnabled || state == ConditionalAptcaCache::kDisabled); - - if (state == ConditionalAptcaCache::kEnabled) - { - return GetConditionalAptcaSharingMode() == kShareIfEnabled; - } - else - { - return GetConditionalAptcaSharingMode() == kShareIfDisabled; - } - } -} - -//------------------------------------------------------------------------------------------------------------ -// -// Determine if the AppDomain can share an assembly or if APTCA restrictions prevent sharing -// - -bool DomainCanShareAptcaAssembly(DomainAssembly *pDomainAssembly) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pDomainAssembly)); - } - CONTRACTL_END; - -#ifdef _DEBUG - DWORD dwAptcaAssemblyDomainBreak = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_Security_AptcaAssemblySharingDomainBreak); - if (dwAptcaAssemblyDomainBreak == 0 || ADID(dwAptcaAssemblyDomainBreak) == pDomainAssembly->GetAppDomain()->GetId()) - { - SString strAptcaAssemblySharingBreak(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_Security_AptcaAssemblySharingBreak)); - SString strAssemblySimpleName(SString::Utf8, pDomainAssembly->GetSimpleName()); - - if (strAptcaAssemblySharingBreak.EqualsCaseInsensitive(strAssemblySimpleName)) - { - _ASSERTE(!"Checking code sharing for APTCA break assembly"); - } - } -#endif // _DEBUG - - // - // We can only share an assembly if all conditional APTCA assemblies in its full closure of dependencies - // are enabled. - // - - // We always allow sharing of mscorlib - if (pDomainAssembly->IsSystem()) - { - return true; - } - - IApplicationSecurityDescriptor *pDomainSecDesc = pDomainAssembly->GetAppDomain()->GetSecurityDescriptor(); - ConditionalAptcaCache *pConditionalAptcaCache = pDomainSecDesc->GetConditionalAptcaCache(); - - // If all assemblies in the domain match the sharing mode, then we can share the assembly - ConditionalAptcaCache::DomainState domainState = pConditionalAptcaCache->GetConditionalAptcaDomainState(); - if (GetConditionalAptcaSharingMode() == kShareIfEnabled) - { - if (domainState == ConditionalAptcaCache::kAllEnabled) - { - return true; - } - } - else - { - if (domainState == ConditionalAptcaCache::kAllDisabled) - { - return true; - } - } - - // If the root assembly is conditionally APTCA, then it needs to be enabled - ReleaseHolder pRootImport(pDomainAssembly->GetFile()->GetMDImportWithRef()); - TokenSecurityDescriptorFlags rootSecurityAttributes = - TokenSecurityDescriptor::ReadSecurityAttributes(pRootImport, TokenFromRid(1, mdtAssembly)); - if (rootSecurityAttributes & TokenSecurityDescriptorFlags_ConditionalAPTCA) - { - if (!AssemblyMatchesShareMode(pDomainAssembly->GetFile()->GetFusionAssemblyName(), pDomainAssembly)) - { - return false; - } - } - - // Now we need to get the full closure of assemblies that this assembly depends upon and ensure that each - // one of those is either not conditional APTCA or is enabled in the domain. We get a new assembly - // closure object here rather than using DomainAssembly::GetAssemblyBindingClosure because we don't want - // to force that closure to walk the full dependency graph (and therefore not be considered equal to - // closures which weren't fully walked). - IUnknown *pFusionAssembly; - if (pDomainAssembly->GetFile()->IsIStream()) - { - pFusionAssembly = pDomainAssembly->GetFile()->GetIHostAssembly(); - } - else - { - pFusionAssembly = pDomainAssembly->GetFile()->GetFusionAssembly(); - } - - // Get the closure and force it to do a full dependency walk, not stopping at framework assemblies - SafeComHolder pClosure; - - - LPCWSTR pNIPath = NULL; - PEAssembly *pPEAsm = pDomainAssembly->GetFile(); - if (pPEAsm->HasNativeImage()) - { - ReleaseHolder pNIImage = pPEAsm->GetNativeImageWithRef(); - pNIPath = pNIImage->GetPath().GetUnicode(); - } - - IfFailThrow(pDomainAssembly->GetAppDomain()->GetFusionContext()->GetAssemblyBindingClosure(pFusionAssembly, pNIPath, &pClosure)); - IfFailThrow(pClosure->EnsureWalked(pFusionAssembly, pDomainAssembly->GetAppDomain()->GetFusionContext(), LEVEL_FXPROBED)); - - // Now iterate the closure looking for conditional APTCA assemblies - SafeComHolder pClosureEnumerator; - IfFailThrow(pClosure->EnumerateAssemblies(&pClosureEnumerator)); - LPCOLESTR szDependentAssemblyPath = NULL; - LPCOLESTR szDependentNIAssemblyPath = NULL; - - for (HRESULT hr = pClosureEnumerator->GetNextAssemblyPath(&szDependentAssemblyPath, &szDependentNIAssemblyPath); - SUCCEEDED(hr); - hr = pClosureEnumerator->GetNextAssemblyPath(&szDependentAssemblyPath, &szDependentNIAssemblyPath)) - { - // Make sure we've succesfully enumerated an item - if (hr != S_OK && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting code sharing because of an error enumerating dependent assemblies: 0x%x"), hr); - return false; - } - else if (szDependentAssemblyPath == NULL) - { - // This means we have an assembly but no way to verify the image at this point -- should we get - // into this state, we'll be conservative and fail the share - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting code sharing because an assembly in the closure does not have a path")); - return false; - } - else - { - // We have succesfully found a new item in the closure of assemblies - now check to ensure that - // it is either not conditionally APTCA or is enabled in tihs domain. - PEImageHolder pDependentImage; - - // Use the native image if it is loaded. - if (szDependentNIAssemblyPath != NULL) - { - SString strNIAssemblyPath(szDependentNIAssemblyPath); - pDependentImage = PEImage::OpenImage(strNIAssemblyPath, MDInternalImport_OnlyLookInCache); - if (pDependentImage != NULL && !pDependentImage->HasLoadedLayout()) - { - pDependentImage = NULL; - } - else - { -#if FEATURE_CORECLR -#error Coreclr needs to check native image version here. -#endif - } - } - - if (pDependentImage == NULL) - { - SString strAssemblyPath(szDependentAssemblyPath); - pDependentImage = PEImage::OpenImage(strAssemblyPath); - } - - // See if we already know if this image is enabled in the current domain or not - ConditionalAptcaCache::State dependentState = pConditionalAptcaCache->GetCachedState(pDependentImage); - - // We don't know this assembly's conditional APTCA state in this domain, so we need to figure it - // out now. - if (dependentState == ConditionalAptcaCache::kUnknown) - { - // First figure out if the assembly is even conditionally APTCA to begin with - IMDInternalImport *pDependentImport = pDependentImage->GetMDImport(); - TokenSecurityDescriptorFlags dependentSecurityAttributes = - TokenSecurityDescriptor::ReadSecurityAttributes(pDependentImport, TokenFromRid(1, mdtAssembly)); - - if (dependentSecurityAttributes & TokenSecurityDescriptorFlags_ConditionalAPTCA) - { - // The the assembly name of the dependent assembly so we can check it to the domain - // enabled list - ReleaseHolder pDependentAssemblyName; - AssemblySpec dependentAssemblySpec(pDomainAssembly->GetAppDomain()); - dependentAssemblySpec.InitializeSpec(TokenFromRid(1, mdtAssembly), pDependentImport); - IfFailThrow(dependentAssemblySpec.CreateFusionName(&pDependentAssemblyName, FALSE)); - - // Check the domain list to see if the assembly is on it - if (IsAssemblyOnAptcaVisibleList(pDependentAssemblyName, pDomainAssembly)) - { - dependentState = ConditionalAptcaCache::kEnabled; - } - else - { - dependentState = ConditionalAptcaCache::kDisabled; - } - } - else - { - // The dependent assembly doesn't have the conditional APTCA bit set on it, so we don't - // need to do any checking to see if it's enabled - dependentState = ConditionalAptcaCache::kNotCAptca; - } - - // Cache the result of evaluating conditional APTCA on this assembly in the domain - pConditionalAptcaCache->SetCachedState(pDependentImage, dependentState); - } - - // If the dependent assembly does not match the sharing mode, then we cannot share the - // dependency. We can always share dependencies which are not conditionally APTCA, so don't - // bother checking the share mode for them. - if (dependentState != ConditionalAptcaCache::kNotCAptca) - { - if (!AssemblyMatchesShareMode(dependentState)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting code sharing because a dependent assembly did not match the conditional APTCA share mode")); - return false; - } - } - } - } - - // The root assembly and all of its dependents were either on the conditional APTCA list or are not - // conditional APTCA, so we can share this assembly - return true; -} - -//------------------------------------------------------------------------------------------------------------ -// -// Get an exception string indicating how to enable a conditional APTCA assembly if it was disabled and -// caused an exception -// - -SString GetConditionalAptcaAccessExceptionContext(Assembly *pTargetAssembly) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pTargetAssembly)); - } - CONTRACTL_END; - - SString exceptionContext; - - ModuleSecurityDescriptor *pMSD = ModuleSecurityDescriptor::GetModuleSecurityDescriptor(pTargetAssembly); - - if (pMSD->GetTokenFlags() & TokenSecurityDescriptorFlags_ConditionalAPTCA) - { - GCX_PREEMP(); - - if (!IsAssemblyOnAptcaVisibleList(pTargetAssembly->GetDomainAssembly())) - { - // We have a conditional APTCA assembly which is not on the visible list for the current - // AppDomain, provide information on how to enable it. - SString assemblyDisplayName; - pTargetAssembly->GetDisplayName(assemblyDisplayName); - - SString assemblyConditionalAptcaName; - GetAssemblyNameForConditionalAptca(pTargetAssembly, &assemblyConditionalAptcaName); - - EEException::GetResourceMessage(IDS_ACCESS_EXCEPTION_CONTEXT_CONDITIONAL_APTCA, - exceptionContext, - assemblyDisplayName, - assemblyConditionalAptcaName); - } - } - - return exceptionContext; -} - -//------------------------------------------------------------------------------------------------------------ -// -// Get an exception string indicating that an assembly was on the kill bit list if it caused an exception -// - -SString GetAptcaKillBitAccessExceptionContext(Assembly *pTargetAssembly) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pTargetAssembly)); - } - CONTRACTL_END; - - GCX_PREEMP(); - - SString exceptionContext; - - if (GetKillBitList()->IsAssemblyKillBitted(pTargetAssembly->GetDomainAssembly()->GetFile())) - { - SString assemblyDisplayName; - pTargetAssembly->GetDisplayName(assemblyDisplayName); - - EEException::GetResourceMessage(IDS_ACCESS_EXCEPTION_CONTEXT_APTCA_KILLBIT, - exceptionContext, - assemblyDisplayName); - } - - return exceptionContext; -} - -//------------------------------------------------------------------------------------------------------------ -// -// Determine if a native image is valid to use from the perspective of APTCA. This means that the image -// itself and all of its dependencies must: -// 1. Not be killbitted -// 2. Be enabled if they are conditionally APTCA -// -// Arguments: -// pNativeImage - native image to accept or reject -// pDomainAssembly - assembly that is being loaded -// -// Return Value: -// true if the native image can be accepted due to APTCA-ness, false if we need to reject it -// - -bool NativeImageHasValidAptcaDependencies(PEImage *pNativeImage, DomainAssembly *pDomainAssembly) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pNativeImage)); - PRECONDITION(CheckPointer(pDomainAssembly)); - } - CONTRACTL_END; - - AptcaKillBitList *pKillBitList = GetKillBitList(); - - ConditionalAptcaCache *pDomainCache = pDomainAssembly->GetAppDomain()->GetSecurityDescriptor()->GetConditionalAptcaCache(); - // If we have any killbitted assemblies, then we need to make sure that the current assembly and its dependencies - BOOL aptcaChecks = pKillBitList->AreAnyAssembliesKillBitted(); - BOOL conditionalAptcaChecks = pDomainCache->GetConditionalAptcaDomainState() != ConditionalAptcaCache::kAllEnabled; - if (!aptcaChecks && !conditionalAptcaChecks) - return true; - - // - // Check to see if the NGEN image itself is APTCA and killbitted - // - - ReleaseHolder pAssemblyMD(pDomainAssembly->GetFile()->GetMDImportWithRef()); - TokenSecurityDescriptorFlags assemblySecurityAttributes = - TokenSecurityDescriptor::ReadSecurityAttributes(pAssemblyMD, TokenFromRid(1, mdtAssembly)); - - if (aptcaChecks) - { - if ((assemblySecurityAttributes & TokenSecurityDescriptorFlags_APTCA) && - pKillBitList->IsAssemblyKillBitted(pDomainAssembly->GetFile())) - { - return false; - } - } - if (conditionalAptcaChecks - && (assemblySecurityAttributes & TokenSecurityDescriptorFlags_ConditionalAPTCA)) - { - // - // First check to see if we're disabled. - // - - AssemblySpec spec; - spec.InitializeSpec(pDomainAssembly->GetFile()); - ReleaseHolder pAsmName; - IfFailThrow(spec.CreateFusionName(&pAsmName, FALSE)); - - if (!IsAssemblyOnAptcaVisibleList(pAsmName, pDomainAssembly)) - { - //IsAssemblyOnAptcaVisibleList has already logged an error. - return false; - } - } - - if (aptcaChecks || conditionalAptcaChecks) - { - // - // Also check its dependencies - // - - COUNT_T dependencyCount; - PEImageLayout *pNativeLayout = pNativeImage->GetLoadedLayout(); - CORCOMPILE_DEPENDENCY *pDependencies = pNativeLayout->GetNativeDependencies(&dependencyCount); - - for (COUNT_T i = 0; i < dependencyCount; ++i) - { - CORCOMPILE_DEPENDENCY* pDependency = &(pDependencies[i]); - // Look for any dependency which is APTCA - if (pDependencies[i].dwAssemblyDef != mdAssemblyRefNil) - { - AssemblySpec name; - name.InitializeSpec(pDependency->dwAssemblyRef, - pNativeImage->GetNativeMDImport(), - NULL, - pDomainAssembly->GetFile()->IsIntrospectionOnly()); - - ReleaseHolder pDependencyAssemblyName; - HRESULT hr = name.CreateFusionName(&pDependencyAssemblyName, FALSE); - - // If we couldn't build the assemlby name up conservatively discard the image - if (FAILED(hr)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting native image because could not get ") - W("name for assemblyref 0x%x for native image dependency: ") - W("hr=0x%x"), pDependency->dwAssemblyRef, hr); - return false; - } - - if (pDependencies[i].dependencyInfo & (CORCOMPILE_DEPENDENCY_IS_APTCA)) - { - ULARGE_INTEGER fileVersion; - - //This is a workaround for Dev10# 743602 - fileVersion.QuadPart = GET_UNALIGNED_VAL64(&(pDependencies[i].uliFileVersion)); - // If the dependency really is killbitted, then discard the image - if (pKillBitList->IsAssemblyKillBitted(pDependencyAssemblyName, fileVersion)) - { - pDomainAssembly->ExternalLog(LL_ERROR, W("Rejecting native image because dependency ") - W("assemblyref 0x%x is killbitted."), - pDependency->dwAssemblyRef); - return false; - } - } - if (pDependencies[i].dependencyInfo & (CORCOMPILE_DEPENDENCY_IS_CAPTCA)) - { - if (!IsAssemblyOnAptcaVisibleList(pDependencyAssemblyName, pDomainAssembly)) - { - //IsAssemblyOnAptcaVisibleList has already logged an error. - return false; - } - } - } - } - } - return true; -} -#else // CROSSGEN_COMPILE -namespace -{ - bool IsAssemblyAptcaEnabled(DomainAssembly *pDomainAssembly, TokenSecurityDescriptorFlags tokenFlags) - { - // No killbits or conditional APTCA for crossgen. Just check whether the assembly is marked APTCA. - return ((tokenFlags & TokenSecurityDescriptorFlags_APTCA) != TokenSecurityDescriptorFlags_None); - } -} -#endif // CROSSGEN_COMPILE - -//------------------------------------------------------------------------------------------------------------ -// -// Process an assembly's real APTCA flags to determine if the assembly should be considered -// APTCA or not -// -// Arguments: -// pDomainAssembly - Assembly to check for APTCA-ness -// tokenFlags - raw metadata security bits from the assembly -// -// Return Value: -// updated token security descriptor flags which indicate the assembly's true APTCA state -// - -TokenSecurityDescriptorFlags ProcessAssemblyAptcaFlags(DomainAssembly *pDomainAssembly, - TokenSecurityDescriptorFlags tokenFlags) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pDomainAssembly)); - } - CONTRACTL_END; - - const TokenSecurityDescriptorFlags aptcaFlags = TokenSecurityDescriptorFlags_APTCA | - TokenSecurityDescriptorFlags_ConditionalAPTCA; - - if (IsAssemblyAptcaEnabled(pDomainAssembly, tokenFlags)) - { - // The assembly is APTCA - temporarially remove all of its APTCA bits, and then add back the - // unconditionally APTCA bit - tokenFlags = tokenFlags & ~aptcaFlags; - return tokenFlags | TokenSecurityDescriptorFlags_APTCA; - } - else - { - // The assembly is not APTCA, so remove all of its APTCA bits from the token security descriptor - return tokenFlags & ~aptcaFlags; - } -} diff --git a/src/coreclr/src/vm/aptca.h b/src/coreclr/src/vm/aptca.h deleted file mode 100644 index 5825eb7..0000000 --- a/src/coreclr/src/vm/aptca.h +++ /dev/null @@ -1,108 +0,0 @@ -// 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. -//-------------------------------------------------------------------------- -// aptca.h -// -// Functions for handling allow partially trusted callers assemblies -// -// This should be the only interface for talking about the APTCA-ness of an assembly, and even then should -// be used only from very select areas of the CLR that absolutely need to know the information. For -// instance: -// -// * the class loader (for code sharing and formatting exception messages) -// * NGEN (for determining if a native image is valid) -// * security attribute processing code (for obvious reasons) -// -// may use this interface. Nearly every other section of the code should simply be relying on the -// ModuleSecurityDescriptor for the assembly in question. And no other sections of the code should be -// directly asking questions like "is this assembly conditional APTCA" ... we explicitly want to hide that -// information away behind the final assembly security attribute computation as much as possible. -// -// In particular, no code should be making security enforcement decisions based upon conditional APTCA, and -// instead should rely on the existing transparency / legacy APTCA enforcement. This means that once the -// security system, JIT, and class loader have finished setting up an assembly's APTCA attributes, there -// should be no further questions asked about the particular APTCA attribute applied to the assembly. -// -// Put another way, once an assembly is loaded, the APTCA kill bit and conditional APTCA enabled / disabled -// decision for an assembly should evaporate away, and all assemblies should look as if they either have a -// full APTCA attribute (in the not-killbitted / conditional APTCA enabled case) or no APTCA attribute at -// all (killbitted or conditional APTCA disabled). -// - -// -//-------------------------------------------------------------------------- - - -#ifndef __APTCA_H__ -#define __APTCA_H__ - -#error FEATURE_APTCA is required for this file - -#include "securitymeta.h" - -class ConditionalAptcaCache -{ -public: - typedef enum - { - kUnknown, // No cached state - kEnabled, // The assembly is enabled in this domain - kDisabled, // The assembly is disabled in this domain - kNotCAptca, // The assembly is not conditionally APTCA - } - State; - - typedef enum - { - kDomainStateUnknown, // The domain state is not yet initialized - kAllEnabled, // All assemblies in the domain are enabled - kSomeEnabled, // Some assemblies in the domain are enabled - kAllDisabled, // All assemblies in the domain are disabled - } - DomainState; - - ConditionalAptcaCache(AppDomain *pAppDomain); - ~ConditionalAptcaCache(); - - State GetCachedState(PTR_PEImage pImage); - void SetCachedState(PTR_PEImage pImage, State state); - - DomainState GetConditionalAptcaDomainState(); - void SetCanonicalConditionalAptcaList(LPCWSTR wszCanonicalConditionalAptcaList); - - static bool ConsiderFullTrustConditionalAptcaLists(); - -private: - ConditionalAptcaCache(ConditionalAptcaCache &other); // not implemented - used to prevent compiler generating a copy constructor - ConditionalAptcaCache& operator=(const ConditionalAptcaCache &other); // not implemented - used to prevent compiler generating an assignment operator - -private: - AppDomain *m_pAppDomain; - - bool m_canonicalListIsNull; - SString m_canonicalList; - DomainState m_domainState; -}; - -// Determine if the AppDomain can share an assembly or if APTCA restrictions prevent sharing -bool DomainCanShareAptcaAssembly(DomainAssembly *pDomainAssembly); - -// Get an exception string indicating how to enable a conditional APTCA assembly if it was disabled and -// caused an exception -SString GetConditionalAptcaAccessExceptionContext(Assembly *pTargetAssembly); - -// Get an exception string indicating that -SString GetConditionalAptcaSharingExceptionContext(Assembly *pTargetAssembly); - -// Get an exception string indicating that an assembly was on the kill bit list if it caused an exception -SString GetAptcaKillBitAccessExceptionContext(Assembly *pTargetAssembly); - -// Determine if a native image is OK to use from an APTCA perspective (it and its dependencies all have the -// same APTCA-ness now as at NGEN time) -bool NativeImageHasValidAptcaDependencies(PEImage *pNativeImage, DomainAssembly *pDomainAssembly); - -// Process an assembly's real APTCA flags to determine if the assembly should be considered APTCA or not -TokenSecurityDescriptorFlags ProcessAssemblyAptcaFlags(DomainAssembly *pDomainAssembly, TokenSecurityDescriptorFlags tokenFlags); - -#endif // __APTCA_H__