summaryrefslogtreecommitdiff
path: root/src/vm/securitypolicy.h
blob: ba77bcbda8850b117d88377a2ddf683fe0f8603c (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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
// 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.
// 

//


#ifndef __SECURITYPOLICY_H__
#define __SECURITYPOLICY_H__

#include "crst.h"
#include "objecthandle.h"
#include "securityattributes.h"
#include "securitydeclarativecache.h"
#include "declsec.h"
#include "fcall.h"
#include "qcall.h"
#include "cgensys.h"
#include "rwlock.h"

#define SPFLAGSASSERTION        0x01
#define SPFLAGSUNMANAGEDCODE    0x02
#define SPFLAGSSKIPVERIFICATION 0x04

#define CORSEC_STACKWALK_HALTED       0x00000001   // Stack walk was halted
#define CORSEC_FT_ASSERT              0x00000004   // Hit a FT-assert during the stackwalk

// Forward declarations to avoid pulling in too many headers.
class Frame;
class FramedMethodFrame;
class ClassLoader;
class Thread;
class CrawlFrame;
class SystemNative;
class NDirect;
class SystemDomain;
class AssemblySecurityDescriptor;
#ifndef FEATURE_CORECLR
class PEFileSecurityDescriptor;
#endif
class SharedSecurityDescriptor;
class SecurityStackWalkData;
class DemandStackWalk;
class SecurityDescriptor;
class COMPrincipal;

#define CLR_CASOFF_MUTEX W("Global\\CLR_CASOFF_MUTEX")

// This enumeration must be kept in sync with the managed System.Security.Policy.EvidenceTypeGenerated enum
typedef enum
{
    kAssemblySupplied,              // Evidence supplied by the assembly itself
    kGac,                           // System.Security.Policy.GacInstalled
    kHash,                          // System.Security.Policy.Hash
    kPermissionRequest,             // System.Security.Policy.PermissionRequestEvidence
    kPublisher,                     // System.Security.Policy.Publisher
    kSite,                          // System.Security.Policy.Site
    kStrongName,                    // System.Security.Policy.StrongName
    kUrl,                           // System.Security.Policy.Url
    kZone                           // System.Security.Policy.Zone
}
EvidenceType;

namespace SecurityPolicy
{
    // -----------------------------------------------------------
    // FCalls
    // -----------------------------------------------------------

    BOOL QCALLTYPE IsSameType(LPCWSTR pLeft, LPCWSTR pRight);

    FCDECL1(FC_BOOL_RET, SetThreadSecurity, CLR_BOOL fThreadSecurity);

    void QCALLTYPE GetGrantedPermissions(QCall::ObjectHandleOnStack retGranted, QCall::ObjectHandleOnStack retDenied, QCall::StackCrawlMarkHandle stackmark);


#ifdef FEATURE_IMPERSONATION
    FCDECL0(DWORD, GetImpersonationFlowMode);
#endif // #ifdef FEATURE_IMPERSONATION

    FCDECL0(FC_BOOL_RET, IsDefaultThreadSecurityInfo);
#ifdef FEATURE_CAS_POLICY
    SecZone QCALLTYPE CreateFromUrl(LPCWSTR wszUrl);
#endif // FEATURE_CAS_POLICY
    void QCALLTYPE _GetLongPathName(LPCWSTR wszPath, QCall::StringHandleOnStack retLongPath);
    
    BOOL QCALLTYPE IsLocalDrive(LPCWSTR wszPath);

    void QCALLTYPE GetDeviceName(LPCWSTR wszDriveLetter, QCall::StringHandleOnStack retDeviceName);

    FCDECL0(VOID, IncrementOverridesCount);

    FCDECL0(VOID, DecrementOverridesCount);

    FCDECL0(VOID, IncrementAssertCount);

    FCDECL0(VOID, DecrementAssertCount);

#ifdef FEATURE_CAS_POLICY
    //
    // Evidence QCalls
    // 

//public:
    void QCALLTYPE FireEvidenceGeneratedEvent(PEFile *pPEFile, EvidenceType type);

    void QCALLTYPE GetEvidence(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retEvidence);

    void QCALLTYPE GetAssemblyPermissionRequests(QCall::AssemblyHandle pAssembly,
                                                 QCall::ObjectHandleOnStack retMinimumPermissions,
                                                 QCall::ObjectHandleOnStack retOptionalPermissions,
                                                 QCall::ObjectHandleOnStack retRefusedPermissions);

    void QCALLTYPE GetAssemblySuppliedEvidence(PEFile *pPEFile, QCall::ObjectHandleOnStack retSerializedEvidence);

    void QCALLTYPE GetLocationEvidence(PEFile *pPEFile, SecZone *pZone, QCall::StringHandleOnStack retUrl);

    void QCALLTYPE GetPublisherCertificate(PEFile *pPEFile, QCall::ObjectHandleOnStack retCertificate);

    void QCALLTYPE GetStrongNameInformation(QCall::AssemblyHandle pAssembly,
                                            QCall::ObjectHandleOnStack retPublicKeyBlob,
                                            QCall::StringHandleOnStack retSimpleName,
                                            USHORT *piMajorVersion,
                                            USHORT *piMinorVersion,
                                            USHORT *piBuild,
                                            USHORT *piRevision);
#endif // FEATURE_CAS_POLICY

//private:
    // -----------------------------------------------------------
    // Init methods
    // -----------------------------------------------------------

    // Calls all the security-related init methods
    //   Callers:
    //     EEStartupHelper
    void Start();

    // Calls all the security-related shutdown methods
    //   Callers:
    //     <currently unused> @TODO: shouldn't EEShutDownHelper call this?
    void Stop();

#ifdef FEATURE_CAS_POLICY
    // Saves security cache data
    //   Callers:
    //     EEShutDownHelper
    void SaveCache();
#endif


    // -----------------------------------------------------------
    // Policy
    // -----------------------------------------------------------

    // Returns TRUE if the assembly has permission to call unmanaged code
    //   Callers:
    //     CEEInfo::getNewHelper
    //     MakeStubWorker
    //     MethodDesc::DoPrestub
    BOOL CanCallUnmanagedCode(Module *pModule);

    // Throws a security exception
    //   Callers:
    //     JIT_SecurityUnmanagedCodeException
    void CreateSecurityException(__in_z const char *szDemandClass, DWORD dwFlags, OBJECTREF* pThrowable);
    DECLSPEC_NORETURN void ThrowSecurityException(__in_z const char *szDemandClass, DWORD dwFlags);

    BOOL CanSkipVerification(DomainAssembly * pAssembly);

#ifdef FEATURE_CAS_POLICY
    void TraceEvidenceGeneration(EvidenceType type, PEFile *pPEFile);

    // Map a URL to a zone, applying any user supplied policy
    SecZone MapUrlToZone(__in_z LPCWSTR wszUrl);

    // Apply user supplied policy to a zone
    HRESULT ApplyCustomZoneOverride(SecZone *pdwZone);

    // Determine what the grant set of an assembly is
    OBJECTREF ResolveGrantSet(OBJECTREF evidence, OUT DWORD *pdwSpecialFlags, BOOL fcheckExecutionPermission);

    // Resolve legacy CAS policy on the assembly
    //   Callers:
    //     SecurityDescriptor::ResolveWorker
    OBJECTREF ResolveCasPolicy(OBJECTREF evidence,
                                      OBJECTREF reqdPset,
                                      OBJECTREF optPset,
                                      OBJECTREF denyPset,
                                      OBJECTREF* grantdenied,
                                      DWORD* pdwSpecialFlags,
                                      BOOL checkExecutionPermission);

    // Load the policy config/cache files at EE startup
    void InitPolicyConfig();

    BOOL WasStrongNameEvidenceUsed(OBJECTREF evidence);
#endif
    // Like WszGetLongPathName, but it works with nonexistant files too
    size_t GetLongPathNameHelper( const WCHAR* wszShortPath, SString& wszBuffer);

#ifdef FEATURE_CAS_POLICY
    extern CrstStatic s_crstPolicyInit;
    extern bool s_fPolicyInitialized;
#endif // FEATURE_CAS_POLICY
}

struct SharedPermissionObjects
{
    OBJECTHANDLE        hPermissionObject;  // Commonly used Permission Object
    BinderClassID       idClass;            // ID of class
    BinderMethodID      idConstructor;      // ID of constructor to call      
    DWORD               dwPermissionFlag;   // Flag needed by the constructors (Only a single argument is assumed)
};

/******** Shared Permission Objects related constants *******/
#define NUM_PERM_OBJECTS    (sizeof(g_rPermObjectsTemplate) / sizeof(SharedPermissionObjects))

// Constants to use with SecurityPermission
#define SECURITY_PERMISSION_ASSERTION               1      // SecurityPermission.cs
#define SECURITY_PERMISSION_UNMANAGEDCODE           2      // SecurityPermission.cs
#define SECURITY_PERMISSION_SKIPVERIFICATION        4      // SecurityPermission.cs
#define SECURITY_PERMISSION_CONTROLEVIDENCE         0x20   // SecurityPermission.cs
#define SECURITY_PERMISSION_SERIALIZATIONFORMATTER  0X80   // SecurityPermission.cs
#define SECURITY_PERMISSION_CONTROLPRINCIPAL        0x200  // SecurityPermission.cs
#define SECURITY_PERMISSION_BINDINGREDIRECTS        0X2000 // SecurityPermission.cs

// Constants to use with ReflectionPermission
#define REFLECTION_PERMISSION_TYPEINFO              1      // ReflectionPermission.cs
#define REFLECTION_PERMISSION_MEMBERACCESS          2      // ReflectionPermission.cs
#define REFLECTION_PERMISSION_RESTRICTEDMEMBERACCESS    8      // ReflectionPermission.cs

// PermissionState.Unrestricted
#define PERMISSION_STATE_UNRESTRICTED               1      // PermissionState.cs

SELECTANY const SharedPermissionObjects g_rPermObjectsTemplate[] =
{
    {NULL, CLASS__SECURITY_PERMISSION, METHOD__SECURITY_PERMISSION__CTOR, SECURITY_PERMISSION_UNMANAGEDCODE },
    {NULL, CLASS__SECURITY_PERMISSION, METHOD__SECURITY_PERMISSION__CTOR, SECURITY_PERMISSION_SKIPVERIFICATION },
    {NULL, CLASS__REFLECTION_PERMISSION, METHOD__REFLECTION_PERMISSION__CTOR, REFLECTION_PERMISSION_TYPEINFO },
    {NULL, CLASS__SECURITY_PERMISSION, METHOD__SECURITY_PERMISSION__CTOR, SECURITY_PERMISSION_ASSERTION },
    {NULL, CLASS__REFLECTION_PERMISSION, METHOD__REFLECTION_PERMISSION__CTOR, REFLECTION_PERMISSION_MEMBERACCESS },
    {NULL, CLASS__SECURITY_PERMISSION, METHOD__SECURITY_PERMISSION__CTOR, SECURITY_PERMISSION_SERIALIZATIONFORMATTER},
    {NULL, CLASS__REFLECTION_PERMISSION, METHOD__REFLECTION_PERMISSION__CTOR, REFLECTION_PERMISSION_RESTRICTEDMEMBERACCESS},
    {NULL, CLASS__PERMISSION_SET, METHOD__PERMISSION_SET__CTOR, PERMISSION_STATE_UNRESTRICTED},
    {NULL, CLASS__SECURITY_PERMISSION, METHOD__SECURITY_PERMISSION__CTOR, SECURITY_PERMISSION_BINDINGREDIRECTS },
    {NULL, CLASS__UI_PERMISSION, METHOD__UI_PERMISSION__CTOR, PERMISSION_STATE_UNRESTRICTED },
};

// Array index in SharedPermissionObjects array
// Note: these should all be permissions that implement IUnrestrictedPermission.
// Any changes to these must be reflected in bcl\system\security\codeaccesssecurityengine.cs and the above table

// special flags
#define SECURITY_UNMANAGED_CODE                 0
#define SECURITY_SKIP_VER                       1
#define REFLECTION_TYPE_INFO                    2
#define SECURITY_ASSERT                         3
#define REFLECTION_MEMBER_ACCESS                4
#define SECURITY_SERIALIZATION                  5
#define REFLECTION_RESTRICTED_MEMBER_ACCESS     6
#define SECURITY_FULL_TRUST                     7
#define SECURITY_BINDING_REDIRECTS              8

// special permissions
#define UI_PERMISSION                           9
#define ENVIRONMENT_PERMISSION                  10
#define FILEDIALOG_PERMISSION                   11
#define FILEIO_PERMISSION                       12
#define REFLECTION_PERMISSION                   13
#define SECURITY_PERMISSION                     14

// additional special flags
#define SECURITY_CONTROL_EVIDENCE               16
#define SECURITY_CONTROL_PRINCIPAL              17

// Objects corresponding to the above index could be Permission or PermissionSet objects. 
// Helper macro to identify which kind it is. If you're adding to the index above, please update this also.
#define IS_SPECIAL_FLAG_PERMISSION_SET(x)       ((x) == SECURITY_FULL_TRUST)

// Class holding a grab bag of security stuff we need on a per-appdomain basis.
struct SecurityContext
{
    SharedPermissionObjects     m_rPermObjects[NUM_PERM_OBJECTS];

    // Cached declarative permissions per method
    EEPtrHashTable m_pCachedMethodPermissionsHash;
    SimpleRWLock * m_prCachedMethodPermissionsLock;
    SecurityDeclarativeCache m_pSecurityDeclarativeCache;
    size_t                      m_nCachedPsetsSize;

    SecurityContext(LoaderHeap* pHeap) :
        m_prCachedMethodPermissionsLock(NULL),
        m_nCachedPsetsSize(0)
    {
        CONTRACTL {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;
        memcpy(m_rPermObjects, g_rPermObjectsTemplate, sizeof(m_rPermObjects));
        
        // initialize cache of method-level declarative security permissions
        // Note that the method-level permissions are stored elsewhere
        m_prCachedMethodPermissionsLock = new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT);
        if (!m_pCachedMethodPermissionsHash.Init(100, &g_lockTrustMeIAmThreadSafe))
            ThrowOutOfMemory();

        m_pSecurityDeclarativeCache.Init (pHeap);
    }

    ~SecurityContext()
    {
        CONTRACTL {
            NOTHROW;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;
        
        // no need to explicitly delete the cache contents, since they will be deallocated with the AppDomain's heap
        if (m_prCachedMethodPermissionsLock) delete m_prCachedMethodPermissionsLock;        
    }
};

#ifdef _DEBUG

#define DBG_TRACE_METHOD(cf)                                                \
    do {                                                                    \
        MethodDesc * __pFunc = cf -> GetFunction();                         \
        if (__pFunc) {                                                      \
            LOG((LF_SECURITY, LL_INFO1000,                                  \
                 "    Method: %s.%s\n",                                     \
                 (__pFunc->m_pszDebugClassName == NULL) ?                   \
                "<null>" : __pFunc->m_pszDebugClassName,                    \
                 __pFunc->GetName()));                                      \
        }                                                                   \
    } while (false)

#define DBG_TRACE_STACKWALK(msg, verbose) LOG((LF_SECURITY, (verbose) ? LL_INFO10000 : LL_INFO1000, msg))
#else //_DEBUG

#define DBG_TRACE_METHOD(cf)
#define DBG_TRACE_STACKWALK(msg, verbose)

#endif //_DEBUG


#endif // __SECURITYPOLICY_H__