1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
// 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.
//--------------------------------------------------------------------------
// securityTransparentAssembly.h
//
// Implementation for transparent code feature
//
//--------------------------------------------------------------------------
#ifndef __SECURITYTRANSPARENT_H__
#define __SECURITYTRANSPARENT_H__
#include "securitymeta.h"
// Reason that a transparency error was flagged
enum SecurityTransparencyError
{
SecurityTransparencyError_None,
SecurityTransparencyError_CallCriticalMethod, // A transparent method tried to call a critical method
SecurityTransparencyError_CallLinkDemand // A transparent method tried to call a method with a LinkDemand
};
namespace SecurityTransparent
{
//private:
BOOL IsMethodTransparent(MethodDesc *pMD);
BOOL IsMethodCritical(MethodDesc *pMD);
BOOL IsMethodSafeCritical(MethodDesc *pMD);
BOOL IsTypeCritical(MethodTable *pMT);
BOOL IsTypeSafeCritical(MethodTable *pMT);
BOOL IsTypeTransparent(MethodTable *pMT);
BOOL IsTypeAllTransparent(MethodTable *pMT);
BOOL IsTypeAllCritical(MethodTable *pMT);
BOOL IsFieldTransparent(FieldDesc *pFD);
BOOL IsFieldCritical(FieldDesc *pFD);
BOOL IsFieldSafeCritical(FieldDesc *pFD);
BOOL IsTokenTransparent(Module *pModule, mdToken tkToken);
//public:
bool SecurityCalloutQuickCheck(MethodDesc *pCallerMD);
CorInfoIsAccessAllowedResult RequiresTransparentCodeChecks(MethodDesc* pCaller,
MethodDesc* pCallee,
SecurityTransparencyError *pError);
CorInfoIsAccessAllowedResult RequiresTransparentAssemblyChecks(MethodDesc* pCaller,
MethodDesc* pCallee,
SecurityTransparencyError *pError);
void EnforceTransparentAssemblyChecks(MethodDesc* pCaller, MethodDesc* pCallee);
void EnforceTransparentDelegateChecks(MethodTable* pDelegateMT, MethodDesc* pCallee);
CorInfoCanSkipVerificationResult JITCanSkipVerification(DomainAssembly * pAssembly);
CorInfoCanSkipVerificationResult JITCanSkipVerification(MethodDesc * pMD);
VOID PerformTransparencyChecksForLoadByteArray(MethodDesc* pCallersMD, AssemblySecurityDescriptor* pLoadedSecDesc);
BOOL CheckCriticalAccess(AccessCheckContext* pContext,
MethodDesc* pOptionalTargetMethod,
FieldDesc* pOptionalTargetField,
MethodTable * pOptionalTargetType);
BOOL IsAllowedToAssert(MethodDesc *pMD);
bool TypeRequiresTransparencyCheck(TypeHandle type, bool checkForLinkDemands);
void DECLSPEC_NORETURN ThrowMethodAccessException(MethodDesc* pMD, DWORD dwMessageId = IDS_CRITICAL_METHOD_ACCESS_DENIED);
void DECLSPEC_NORETURN ThrowTypeLoadException(MethodDesc* pMD, DWORD dwMessageId = IDS_METHOD_INHERITANCE_RULES_VIOLATED);
void DECLSPEC_NORETURN ThrowTypeLoadException(MethodTable* pMT);
void DoSecurityClassAccessChecks(MethodDesc *pCallerMD,
const TypeHandle &calleeTH,
CorInfoSecurityRuntimeChecks checks);
#ifdef _DEBUG
void LogTransparencyError(Assembly *pAssembly, const LPCSTR szError);
void LogTransparencyError(MethodTable *pMT, const LPCSTR szError);
void LogTransparencyError(MethodDesc *pMD, const LPCSTR szError, MethodDesc *pTargetMD = NULL);
#endif // _DEBUG
};
//
// Transparency is implemented slightly differently between v2 desktop, v4 desktop, and CoreCLR. In order to
// support running v2 desktop assemblies on the v4 CLR without modifying their expected transparency behavior,
// we indirect all questions about what transparency means through a SecurityTransparencyBehavior object.
//
// The SecurityTransparencyBehavior object uses implementations of ISecurityTransparencyImpl to query about
// specific behavior differences.
//
enum SecurityTransparencyBehaviorFlags
{
SecurityTransparencyBehaviorFlags_None = 0x0000,
// Custom attributes require transparency checks in order to be used by transparent code
SecurityTransparencyBehaviorFlags_AttributesRequireTransparencyCheck = 0x0001,
// Public critical members of an assembly can behave as if they were safe critical with a LinkDemand
// for FullTrust
SecurityTransparencyBehaviorFlags_CriticalMembersConvertToLinkDemand = 0x0002,
// Types and methods must obey the transparency inheritance rules
SecurityTransparencyBehaviorFlags_InheritanceRulesEnforced = 0x0004,
// Members contained within a scope that introduces members as critical may add their own treat as safe
SecurityTransparencyBehaviorFlags_IntroducedCriticalsMayAddTreatAsSafe = 0x0008,
// Opportunistically critical assemblies consist of entirely transparent types with entirely safe
// critical methods.
SecurityTransparencyBehaviorFlags_OpportunisticIsSafeCriticalMethods = 0x0010,
// Assemblies loaded in partial trust are implicitly all transparent
SecurityTransparencyBehaviorFlags_PartialTrustImpliesAllTransparent = 0x0020,
// All public critical types and methods get an implicit treat as safe marking
SecurityTransparencyBehaviorFlags_PublicImpliesTreatAsSafe = 0x0040,
// Security critical or safe critical at a larger than method scope applies only to methods introduced
// within that scope, rather than all methods contained in the scope
SecurityTransparencyBehaviorFlags_ScopeAppliesOnlyToIntroducedMethods = 0x0080,
// Security transparent code can call methods protected with a LinkDemand
SecurityTransparencyBehaviorFlags_TransparentCodeCanCallLinkDemand = 0x0100,
// Security transparent code can call native code via P/Invoke or COM Interop
SecurityTransaprencyBehaviorFlags_TransparentCodeCanCallUnmanagedCode = 0x0200,
// Security transparent code can skip verification with a runtime check
SecurityTransparencyBehaviorFlags_TransparentCodeCanSkipVerification = 0x0400,
// Unsigned assemblies implicitly are APTCA
SecurityTransparencyBehaviorFlags_UnsignedImpliesAPTCA = 0x0800,
};
inline SecurityTransparencyBehaviorFlags operator|(SecurityTransparencyBehaviorFlags lhs,
SecurityTransparencyBehaviorFlags rhs);
inline SecurityTransparencyBehaviorFlags operator|=(SecurityTransparencyBehaviorFlags& lhs,
SecurityTransparencyBehaviorFlags rhs);
inline SecurityTransparencyBehaviorFlags operator&(SecurityTransparencyBehaviorFlags lhs,
SecurityTransparencyBehaviorFlags rhs);
inline SecurityTransparencyBehaviorFlags operator&=(SecurityTransparencyBehaviorFlags &lhs,
SecurityTransparencyBehaviorFlags rhs);
// Base interface for transparency behavior implementations
class ISecurityTransparencyImpl
{
public:
virtual ~ISecurityTransparencyImpl()
{
LIMITED_METHOD_CONTRACT;
}
// Get flags that indicate specific on/off behaviors of transparency
virtual SecurityTransparencyBehaviorFlags GetBehaviorFlags() const = 0;
// Map security attributes that a field contains to the set of behaviors it supports
virtual FieldSecurityDescriptorFlags MapFieldAttributes(TokenSecurityDescriptorFlags tokenFlags) const = 0;
// Map security attributes that a method contains to the set of behaviors it supports
virtual MethodSecurityDescriptorFlags MapMethodAttributes(TokenSecurityDescriptorFlags tokenFlags) const = 0;
// Map security attributes that a module contains to the set of behaviors it supports
virtual ModuleSecurityDescriptorFlags MapModuleAttributes(TokenSecurityDescriptorFlags tokenFlags) const = 0;
// Map security attributes that a type contains to the set of behaviors it supports
virtual TypeSecurityDescriptorFlags MapTypeAttributes(TokenSecurityDescriptorFlags tokenFlags) const = 0;
};
class SecurityTransparencyBehavior
{
public:
// Get a transparency behavior for a module with the given attributes applied to it
static
const SecurityTransparencyBehavior *GetTransparencyBehavior(SecurityRuleSet ruleSet);
public:
// Are types and methods required to obey the transparency inheritance rules
inline bool AreInheritanceRulesEnforced() const;
// Can public critical members of an assembly behave as if they were safe critical with a LinkDemand
// for FullTrust
inline bool CanCriticalMembersBeConvertedToLinkDemand() const;
// Can members contained within a scope that introduces members as critical add their own TreatAsSafe
// attribute
inline bool CanIntroducedCriticalMembersAddTreatAsSafe() const;
// Can transparent methods call methods protected with a LinkDemand
inline bool CanTransparentCodeCallLinkDemandMethods() const;
// Can transparent methods call native code
inline bool CanTransparentCodeCallUnmanagedCode() const;
// Can transparent members skip verification if the callstack passes a runtime check
inline bool CanTransparentCodeSkipVerification() const;
// Custom attributes require transparency checks in order to be used by transparent code
inline bool DoAttributesRequireTransparencyChecks() const;
// Opportunistically critical assemblies consist of entirely transparent types with entirely safe
// critical methods.
inline bool DoesOpportunisticRequireOnlySafeCriticalMethods() const;
// Does being loaded in partial trust imply that the assembly is implicitly all transparent
inline bool DoesPartialTrustImplyAllTransparent() const;
// Do all public members of the assembly get an implicit treat as safe marking
inline bool DoesPublicImplyTreatAsSafe() const;
// Do security critical or safe critical at a larger than method scope apply only to methods introduced
// within that scope, or to all methods conateind within the scope.
inline bool DoesScopeApplyOnlyToIntroducedMethods() const;
// Do unsigned assemblies implicitly become APTCA
inline bool DoesUnsignedImplyAPTCA() const;
// Get flags that indicate specific on/off behaviors of transparency
inline FieldSecurityDescriptorFlags MapFieldAttributes(TokenSecurityDescriptorFlags tokenFlags) const;
// Map security attributes that a method contains to the set of behaviors it supports
inline MethodSecurityDescriptorFlags MapMethodAttributes(TokenSecurityDescriptorFlags tokenFlags) const;
// Map security attributes that a module contains to the set of behaviors it supports
inline ModuleSecurityDescriptorFlags MapModuleAttributes(TokenSecurityDescriptorFlags tokenFlags) const;
// Map security attributes that a type contains to the set of behaviors it supports
inline TypeSecurityDescriptorFlags MapTypeAttributes(TokenSecurityDescriptorFlags tokenFlags) const;
private:
explicit inline SecurityTransparencyBehavior(ISecurityTransparencyImpl *pTransparencyImpl);
SecurityTransparencyBehavior(const SecurityTransparencyBehavior &); // not implemented
SecurityTransparencyBehavior &operator=(const SecurityTransparencyBehavior &); // not implemented
private:
template <class T>
friend const SecurityTransparencyBehavior *GetOrCreateTransparencyBehavior(SecurityTransparencyBehavior **ppBehavior);
private:
static SecurityTransparencyBehavior *s_pStandardTransparencyBehavior;
static SecurityTransparencyBehavior *s_pLegacyTransparencyBehavior;
ISecurityTransparencyImpl *m_pTransparencyImpl;
SecurityTransparencyBehaviorFlags m_flags;
};
#include "securitytransparentassembly.inl"
#endif // __SECURITYTRANSPARENT_H__
|