summaryrefslogtreecommitdiff
path: root/src/vm/securitytransparentassembly.h
blob: 9f0d38f7caf14fdfa9b034c6eed833050638aebc (plain)
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__