/
security-manager.c
308 lines (254 loc) · 9.25 KB
/
security-manager.c
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
/*
* security-manager.c: Security Manager (Unmanaged side)
*
* Author:
* Sebastien Pouliot <sebastien@ximian.com>
*
* Copyright 2005-2009 Novell, Inc (http://www.novell.com)
*/
#include "security-manager.h"
static MonoSecurityMode mono_security_mode = MONO_SECURITY_MODE_NONE;
static MonoBoolean mono_security_manager_activated = FALSE;
static MonoBoolean mono_security_manager_enabled = TRUE;
static MonoBoolean mono_security_manager_execution = TRUE;
void
mono_security_set_mode (MonoSecurityMode mode)
{
mono_security_mode = mode;
}
MonoSecurityMode
mono_security_get_mode (void)
{
return mono_security_mode;
}
/*
* Note: The security manager is activate once when executing the Mono. This
* is not meant to be a turn on/off runtime switch.
*/
void
mono_activate_security_manager (void)
{
mono_security_manager_activated = TRUE;
}
gboolean
mono_is_security_manager_active (void)
{
return mono_security_manager_activated;
}
#ifndef DISABLE_SECURITY
static MonoSecurityManager secman;
MonoSecurityManager*
mono_security_manager_get_methods (void)
{
/* Already initialized ? */
if (secman.securitymanager)
return &secman;
/* Initialize */
secman.securitymanager = mono_class_from_name (mono_defaults.corlib,
"System.Security", "SecurityManager");
g_assert (secman.securitymanager);
if (!secman.securitymanager->inited)
mono_class_init (secman.securitymanager);
secman.demand = mono_class_get_method_from_name (secman.securitymanager,
"InternalDemand", 2);
g_assert (secman.demand);
secman.demandchoice = mono_class_get_method_from_name (secman.securitymanager,
"InternalDemandChoice", 2);
g_assert (secman.demandchoice);
secman.demandunmanaged = mono_class_get_method_from_name (secman.securitymanager,
"DemandUnmanaged", 0);
g_assert (secman.demandunmanaged);
secman.inheritancedemand = mono_class_get_method_from_name (secman.securitymanager,
"InheritanceDemand", 3);
g_assert (secman.inheritancedemand);
secman.inheritsecurityexception = mono_class_get_method_from_name (secman.securitymanager,
"InheritanceDemandSecurityException", 4);
g_assert (secman.inheritsecurityexception);
secman.linkdemand = mono_class_get_method_from_name (secman.securitymanager,
"LinkDemand", 3);
g_assert (secman.linkdemand);
secman.linkdemandunmanaged = mono_class_get_method_from_name (secman.securitymanager,
"LinkDemandUnmanaged", 1);
g_assert (secman.linkdemandunmanaged);
secman.linkdemandfulltrust = mono_class_get_method_from_name (secman.securitymanager,
"LinkDemandFullTrust", 1);
g_assert (secman.linkdemandfulltrust);
secman.linkdemandsecurityexception = mono_class_get_method_from_name (secman.securitymanager,
"LinkDemandSecurityException", 2);
g_assert (secman.linkdemandsecurityexception);
secman.allowpartiallytrustedcallers = mono_class_from_name (mono_defaults.corlib, "System.Security",
"AllowPartiallyTrustedCallersAttribute");
g_assert (secman.allowpartiallytrustedcallers);
secman.suppressunmanagedcodesecurity = mono_class_from_name (mono_defaults.corlib, "System.Security",
"SuppressUnmanagedCodeSecurityAttribute");
g_assert (secman.suppressunmanagedcodesecurity);
return &secman;
}
static gboolean
mono_secman_inheritance_check (MonoClass *klass, MonoDeclSecurityActions *demands)
{
MonoSecurityManager* secman = mono_security_manager_get_methods ();
MonoDomain *domain = mono_domain_get ();
MonoAssembly *assembly = mono_image_get_assembly (klass->image);
MonoReflectionAssembly *refass = mono_assembly_get_object (domain, assembly);
MonoObject *res;
gpointer args [3];
args [0] = domain->domain;
args [1] = refass;
args [2] = demands;
res = mono_runtime_invoke (secman->inheritancedemand, NULL, args, NULL);
return (*(MonoBoolean *) mono_object_unbox (res));
}
void
mono_secman_inheritancedemand_class (MonoClass *klass, MonoClass *parent)
{
MonoDeclSecurityActions demands;
/* don't hide previous results -and- don't calc everything for nothing */
if (klass->exception_type != 0)
return;
/* short-circuit corlib as it is fully trusted (within itself)
* and because this cause major recursion headaches */
if ((klass->image == mono_defaults.corlib) && (parent->image == mono_defaults.corlib))
return;
/* Check if there are an InheritanceDemand on the parent class */
if (mono_declsec_get_inheritdemands_class (parent, &demands)) {
/* If so check the demands on the klass (inheritor) */
if (!mono_secman_inheritance_check (klass, &demands)) {
/* Keep flags in MonoClass to be able to throw a SecurityException later (if required) */
mono_class_set_failure (klass, MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND, NULL);
}
}
}
void
mono_secman_inheritancedemand_method (MonoMethod *override, MonoMethod *base)
{
MonoDeclSecurityActions demands;
/* don't hide previous results -and- don't calc everything for nothing */
if (override->klass->exception_type != 0)
return;
/* short-circuit corlib as it is fully trusted (within itself)
* and because this cause major recursion headaches */
if ((override->klass->image == mono_defaults.corlib) && (base->klass->image == mono_defaults.corlib))
return;
/* Check if there are an InheritanceDemand on the base (virtual) method */
if (mono_declsec_get_inheritdemands_method (base, &demands)) {
/* If so check the demands on the overriding method */
if (!mono_secman_inheritance_check (override->klass, &demands)) {
/* Keep flags in MonoClass to be able to throw a SecurityException later (if required) */
mono_class_set_failure (override->klass, MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND, base);
}
}
}
#else
MonoSecurityManager*
mono_security_manager_get_methods (void)
{
return NULL;
}
void
mono_secman_inheritancedemand_class (MonoClass *klass, MonoClass *parent)
{
}
void
mono_secman_inheritancedemand_method (MonoMethod *override, MonoMethod *base)
{
}
#endif /* DISABLE_SECURITY */
/*
* @publickey An encoded (with header) public key
* @size The length of the public key
*
* returns TRUE if the public key is the ECMA "key", FALSE otherwise
*
* ECMA key isn't a real public key - it's simply an empty (but valid) header
* so it's length (16) and value (00000000000000000400000000000000) are
* constants.
*/
gboolean
mono_is_ecma_key (const char *publickey, int size)
{
int i;
if ((publickey == NULL) || (size != MONO_ECMA_KEY_LENGTH) || (publickey [8] != 0x04))
return FALSE;
for (i=0; i < size; i++) {
if ((publickey [i] != 0x00) && (i != 8))
return FALSE;
}
return TRUE;
}
/*
* Context propagation is required when:
* (a) the security manager is active (1.x and later)
* (b) other contexts needs to be propagated (2.x and later)
*
* returns NULL if no context propagation is required, else the returns the
* MonoMethod to call to Capture the ExecutionContext.
*/
MonoMethod*
mono_get_context_capture_method (void)
{
static MonoMethod *method = NULL;
if (!mono_security_manager_activated) {
if (mono_image_get_assembly (mono_defaults.corlib)->aname.major < 2)
return NULL;
}
/* older corlib revisions won't have the class (nor the method) */
if (mono_defaults.executioncontext_class && !method) {
mono_class_init (mono_defaults.executioncontext_class);
method = mono_class_get_method_from_name (mono_defaults.executioncontext_class, "Capture", 0);
}
return method;
}
/* System.Security icalls */
MonoBoolean
ves_icall_System_Security_SecurityManager_get_SecurityEnabled (void)
{
if (!mono_security_manager_activated) {
/* SecurityManager is internal for Moonlight and SecurityEnabled is used to know if CoreCLR is active
* (e.g. plugin executing in the browser) or not (e.g. smcs compiling source code with corlib 2.1)
*/
return (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR);
}
return mono_security_manager_enabled;
}
void
ves_icall_System_Security_SecurityManager_set_SecurityEnabled (MonoBoolean value)
{
/* value can be changed only if the security manager is activated */
if (mono_security_manager_activated) {
mono_security_manager_enabled = value;
}
}
MonoBoolean
ves_icall_System_Security_SecurityManager_get_CheckExecutionRights (void)
{
if (!mono_security_manager_activated)
return FALSE;
return mono_security_manager_execution;
}
void
ves_icall_System_Security_SecurityManager_set_CheckExecutionRights (MonoBoolean value)
{
/* value can be changed only id the security manager is activated */
if (mono_security_manager_activated) {
mono_security_manager_execution = value;
}
}
MonoBoolean
ves_icall_System_Security_SecurityManager_GetLinkDemandSecurity (MonoReflectionMethod *m, MonoDeclSecurityActions *kactions, MonoDeclSecurityActions *mactions)
{
MonoMethod *method = m->method;
/* we want the original as the wrapper is "free" of the security informations */
if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
method = mono_marshal_method_from_wrapper (method);
}
mono_class_init (method->klass);
/* if either the method or it's class has security (any type) */
if ((method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) || (method->klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
memset (kactions, 0, sizeof (MonoDeclSecurityActions));
memset (mactions, 0, sizeof (MonoDeclSecurityActions));
/* get any linkdemand (either on the method or it's class) */
return mono_declsec_get_linkdemands (method, kactions, mactions);
}
return FALSE;
}