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__
|