Replace SIZEOF_REGISTER with sizeof(mgreg_t) for consistency with sizeof(gpointer)
[mono.git] / mcs / class / corlib / System.Security / SecurityManager.cs
1 //
2 // System.Security.SecurityManager.cs
3 //
4 // Authors:
5 //      Nick Drochak(ndrochak@gol.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) Nick Drochak
9 // Portions (C) 2004 Motus Technologies Inc. (http://www.motus.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if !MOONLIGHT
33
34 using System.Collections;
35 using System.Diagnostics;
36 using System.Globalization;
37 using System.IO;
38 using System.Reflection;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Security.Permissions;
42 using System.Security.Policy;
43 using System.Text;
44
45 using Mono.Xml;
46
47 namespace System.Security {
48
49         // Must match MonoDeclSecurityActions in /mono/metadata/reflection.h
50         internal struct RuntimeDeclSecurityActions {
51                 public RuntimeDeclSecurityEntry cas;
52                 public RuntimeDeclSecurityEntry noncas;
53                 public RuntimeDeclSecurityEntry choice;
54         }
55
56         [ComVisible (true)]
57         public static class SecurityManager {
58                 private static object _lockObject;
59                 private static ArrayList _hierarchy;
60                 private static IPermission _unmanagedCode;
61                 private static Hashtable _declsecCache;
62                 private static PolicyLevel _level;
63
64                 static SecurityManager () 
65                 {
66                         // lock(this) is bad
67                         // http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp?frame=true
68                         _lockObject = new object ();
69                 }
70
71                 // properties
72
73                 extern public static bool CheckExecutionRights {
74                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
75                         get;
76
77                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
78                         [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
79                         set;
80                 }
81
82                 [Obsolete ("The security manager cannot be turned off on MS runtime")]
83                 extern public static bool SecurityEnabled {
84                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
85                         get;
86
87                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
88                         [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
89                         set;
90                 }
91
92                 internal static bool CheckElevatedPermissions ()
93                 {
94                         return true; // always true outside Moonlight
95                 }
96
97                 [Conditional ("MOONLIGHT")]
98                 internal static void EnsureElevatedPermissions ()
99                 {
100                         // do nothing outside of Moonlight
101                 }
102
103                 // methods
104
105                 // NOTE: This method doesn't show in the class library status page because
106                 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
107                 // But it's there!
108                 // FIXME works for fulltrust (empty), documentation doesn't really make sense, type wise
109                 [MonoTODO ("CAS support is experimental (and unsupported). This method only works in FullTrust.")]
110                 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey = "0x00000000000000000400000000000000")]
111                 public static void GetZoneAndOrigin (out ArrayList zone, out ArrayList origin) 
112                 {
113                         zone = new ArrayList ();
114                         origin = new ArrayList ();
115                 }
116
117                 public static bool IsGranted (IPermission perm)
118                 {
119                         if (perm == null)
120                                 return true;
121                         if (!SecurityEnabled)
122                                 return true;
123
124                         // - Policy driven
125                         // - Only check the caller (no stack walk required)
126                         // - Not affected by overrides (like Assert, Deny and PermitOnly)
127                         // - calls IsSubsetOf even for non CAS permissions
128                         //   (i.e. it does call Demand so any code there won't be executed)
129                         // with 2.0 identity permission are unrestrictable
130                         return IsGranted (Assembly.GetCallingAssembly (), perm);
131                 }
132
133                 // note: in 2.0 *all* permissions (including identity permissions) support unrestricted
134                 internal static bool IsGranted (Assembly a, IPermission perm)
135                 {
136                         PermissionSet granted = a.GrantedPermissionSet;
137                         if ((granted != null) && !granted.IsUnrestricted ()) {
138                                 CodeAccessPermission grant = (CodeAccessPermission) granted.GetPermission (perm.GetType ());
139                                 if (!perm.IsSubsetOf (grant)) {
140                                         return false;
141                                 }
142                         }
143
144                         PermissionSet denied = a.DeniedPermissionSet;
145                         if ((denied != null) && !denied.IsEmpty ()) {
146                                 if (denied.IsUnrestricted ())
147                                         return false;
148                                 CodeAccessPermission refuse = (CodeAccessPermission) a.DeniedPermissionSet.GetPermission (perm.GetType ());
149                                 if ((refuse != null) && perm.IsSubsetOf (refuse))
150                                         return false;
151                         }
152                         return true;
153                 }
154
155                 internal static IPermission CheckPermissionSet (Assembly a, PermissionSet ps, bool noncas)
156                 {
157                         if (ps.IsEmpty ())
158                                 return null;
159
160                         foreach (IPermission p in ps) {
161                                 // note: this may contains non CAS permissions
162                                 if ((!noncas) && (p is CodeAccessPermission)) {
163                                         if (!IsGranted (a, p))
164                                                 return p;
165                                 } else {
166                                         // but non-CAS will throw on failure...
167                                         try {
168                                                 p.Demand ();
169                                         }
170                                         catch (SecurityException) {
171                                                 // ... so we catch
172                                                 return p;
173                                         }
174                                 }
175                         }
176                         return null;
177                 }
178
179                 internal static IPermission CheckPermissionSet (AppDomain ad, PermissionSet ps)
180                 {
181                         if ((ps == null) || ps.IsEmpty ())
182                                 return null;
183
184                         PermissionSet granted = ad.GrantedPermissionSet;
185                         if (granted == null)
186                                 return null;
187                         if (granted.IsUnrestricted ())
188                                 return null;
189                         if (ps.IsUnrestricted ())
190                                 return new SecurityPermission (SecurityPermissionFlag.NoFlags);
191
192                         foreach (IPermission p in ps) {
193                                 if (p is CodeAccessPermission) {
194                                         CodeAccessPermission grant = (CodeAccessPermission) granted.GetPermission (p.GetType ());
195                                         if (grant == null) {
196                                                 if (!granted.IsUnrestricted () || !(p is IUnrestrictedPermission)) {
197                                                         if (!p.IsSubsetOf (null))
198                                                                 return p;
199                                                 }
200                                         } else if (!p.IsSubsetOf (grant)) {
201                                                 return p;
202                                         }
203                                 } else {
204                                         // but non-CAS will throw on failure...
205                                         try {
206                                                 p.Demand ();
207                                         }
208                                         catch (SecurityException) {
209                                                 // ... so we catch
210                                                 return p;
211                                         }
212                                 }
213                         }
214                         return null;
215                 }
216
217                 [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
218                 public static PolicyLevel LoadPolicyLevelFromFile (string path, PolicyLevelType type)
219                 {
220                         if (path == null)
221                                 throw new ArgumentNullException ("path");
222
223                         PolicyLevel pl = null;
224                         try {
225                                 pl = new PolicyLevel (type.ToString (), type);
226                                 pl.LoadFromFile (path);
227                         }
228                         catch (Exception e) {
229                                 throw new ArgumentException (Locale.GetText ("Invalid policy XML"), e);
230                         }
231                         return pl;
232                 }
233
234                 [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
235                 public static PolicyLevel LoadPolicyLevelFromString (string str, PolicyLevelType type)
236                 {
237                         if (null == str)
238                                 throw new ArgumentNullException ("str");
239
240                         PolicyLevel pl = null;
241                         try {
242                                 pl = new PolicyLevel (type.ToString (), type);
243                                 pl.LoadFromString (str);
244                         }
245                         catch (Exception e) {
246                                 throw new ArgumentException (Locale.GetText ("Invalid policy XML"), e);
247                         }
248                         return pl;
249                 }
250
251                 [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
252                 public static IEnumerator PolicyHierarchy ()
253                 {
254                         return Hierarchy;
255                 }
256
257                 public static PermissionSet ResolvePolicy (Evidence evidence)
258                 {
259                         // no evidence, no permission
260                         if (evidence == null)
261                                 return new PermissionSet (PermissionState.None);
262
263                         PermissionSet ps = null;
264                         // Note: can't call PolicyHierarchy since ControlPolicy isn't required to resolve policies
265                         IEnumerator ple = Hierarchy;
266                         while (ple.MoveNext ()) {
267                                 PolicyLevel pl = (PolicyLevel) ple.Current;
268                                 if (ResolvePolicyLevel (ref ps, pl, evidence)) {
269                                         break;  // i.e. PolicyStatementAttribute.LevelFinal
270                                 }
271                         }
272
273                         ResolveIdentityPermissions (ps, evidence);
274
275                         return ps;
276                 }
277
278                 [MonoTODO ("(2.0) more tests are needed")]
279                 public static PermissionSet ResolvePolicy (Evidence[] evidences)
280                 {
281                         if ((evidences == null) || (evidences.Length == 0) ||
282                                 ((evidences.Length == 1) && (evidences [0].Count == 0))) {
283                                 return new PermissionSet (PermissionState.None);
284                         }
285
286                         // probably not optimal
287                         PermissionSet ps = ResolvePolicy (evidences [0]);
288                         for (int i=1; i < evidences.Length; i++) {
289                                 ps = ps.Intersect (ResolvePolicy (evidences [i]));
290                         }
291                         return ps;
292                 }
293
294                 public static PermissionSet ResolveSystemPolicy (Evidence evidence)
295                 {
296                         // no evidence, no permission
297                         if (evidence == null)
298                                 return new PermissionSet (PermissionState.None);
299
300                         // Note: can't call PolicyHierarchy since ControlPolicy isn't required to resolve policies
301                         PermissionSet ps = null;
302                         IEnumerator ple = Hierarchy;
303                         while (ple.MoveNext ()) {
304                                 PolicyLevel pl = (PolicyLevel) ple.Current;
305                                 if (pl.Type == PolicyLevelType.AppDomain)
306                                         break;
307                                 if (ResolvePolicyLevel (ref ps, pl, evidence))
308                                         break;  // i.e. PolicyStatementAttribute.LevelFinal
309                         }
310
311                         ResolveIdentityPermissions (ps, evidence);
312                         return ps;
313                 }
314
315                 static private SecurityPermission _execution = new SecurityPermission (SecurityPermissionFlag.Execution);
316
317                 public static PermissionSet ResolvePolicy (Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, out PermissionSet denied)
318                 {
319                         PermissionSet resolved = ResolvePolicy (evidence);
320                         // do we have the minimal permission requested by the assembly ?
321                         if ((reqdPset != null) && !reqdPset.IsSubsetOf (resolved)) {
322                                 throw new PolicyException (Locale.GetText (
323                                         "Policy doesn't grant the minimal permissions required to execute the assembly."));
324                         }
325
326                         // do we check for execution rights ?
327                         if (CheckExecutionRights) {
328                                 bool execute = false;
329                                 // an empty permissionset doesn't include Execution
330                                 if (resolved != null) {
331                                         // unless we have "Full Trust"...
332                                         if (resolved.IsUnrestricted ()) {
333                                                 execute = true;
334                                         } else {
335                                                 // ... we need to find a SecurityPermission
336                                                 IPermission security = resolved.GetPermission (typeof (SecurityPermission));
337                                                 execute = _execution.IsSubsetOf (security);
338                                         }
339                                 }
340
341                                 if (!execute) {
342                                         throw new PolicyException (Locale.GetText (
343                                                 "Policy doesn't grant the right to execute the assembly."));
344                                 }
345                         }
346
347                         denied = denyPset;
348                         return resolved;
349                 }
350
351                 public static IEnumerator ResolvePolicyGroups (Evidence evidence)
352                 {
353                         if (evidence == null)
354                                 throw new ArgumentNullException ("evidence");
355
356                         ArrayList al = new ArrayList ();
357                         // Note: can't call PolicyHierarchy since ControlPolicy isn't required to resolve policies
358                         IEnumerator ple = Hierarchy;
359                         while (ple.MoveNext ()) {
360                                 PolicyLevel pl = (PolicyLevel) ple.Current;
361                                 CodeGroup cg = pl.ResolveMatchingCodeGroups (evidence);
362                                 al.Add (cg);
363                         }
364                         return al.GetEnumerator ();
365                 }
366
367                 [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
368                 public static void SavePolicy () 
369                 {
370                         IEnumerator e = Hierarchy;
371                         while (e.MoveNext ()) {
372                                 PolicyLevel level = (e.Current as PolicyLevel);
373                                 level.Save ();
374                         }
375                 }
376
377                 [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
378                 public static void SavePolicyLevel (PolicyLevel level) 
379                 {
380                         // Yes this will throw a NullReferenceException, just like MS (see FDBK13121)
381                         level.Save ();
382                 }
383
384                 // private/internal stuff
385
386                 private static IEnumerator Hierarchy {
387                         get {
388                                 lock (_lockObject) {
389                                         if (_hierarchy == null)
390                                                 InitializePolicyHierarchy ();
391                                 }
392                                 return _hierarchy.GetEnumerator ();
393                         }
394                 }
395
396                 private static void InitializePolicyHierarchy ()
397                 {
398                         string machinePolicyPath = Path.GetDirectoryName (Environment.GetMachineConfigPath ());
399                         // note: use InternalGetFolderPath to avoid recursive policy initialization
400                         string userPolicyPath = Path.Combine (Environment.InternalGetFolderPath (Environment.SpecialFolder.ApplicationData), "mono");
401
402                         PolicyLevel enterprise = new PolicyLevel ("Enterprise", PolicyLevelType.Enterprise);
403                         _level = enterprise;
404                         enterprise.LoadFromFile (Path.Combine (machinePolicyPath, "enterprisesec.config"));
405
406                         PolicyLevel machine = new PolicyLevel ("Machine", PolicyLevelType.Machine);
407                         _level = machine;
408                         machine.LoadFromFile (Path.Combine (machinePolicyPath, "security.config"));
409
410                         PolicyLevel user = new PolicyLevel ("User", PolicyLevelType.User);
411                         _level = user;
412                         user.LoadFromFile (Path.Combine (userPolicyPath, "security.config"));
413
414                         ArrayList al = new ArrayList ();
415                         al.Add (enterprise);
416                         al.Add (machine);
417                         al.Add (user);
418
419                         _hierarchy = ArrayList.Synchronized (al);
420                         _level = null;
421                 }
422
423                 internal static bool ResolvePolicyLevel (ref PermissionSet ps, PolicyLevel pl, Evidence evidence)
424                 {
425                         PolicyStatement pst = pl.Resolve (evidence);
426                         if (pst != null) {
427                                 if (ps == null) {
428                                         // only for initial (first) policy level processed
429                                         ps = pst.PermissionSet;
430                                 } else {
431                                         ps = ps.Intersect (pst.PermissionSet);
432                                         if (ps == null) {
433                                                 // null is equals to None - exist that null can throw NullReferenceException ;-)
434                                                 ps = new PermissionSet (PermissionState.None);
435                                         }
436                                 }
437
438                                 if ((pst.Attributes & PolicyStatementAttribute.LevelFinal) == PolicyStatementAttribute.LevelFinal)
439                                         return true;
440                         }
441                         return false;
442                 }
443
444                 internal static void ResolveIdentityPermissions (PermissionSet ps, Evidence evidence)
445                 {
446                         // in 2.0 identity permissions can now be unrestricted
447                         if (ps.IsUnrestricted ())
448                                 return;
449
450                         // Only host evidence are used for policy resolution
451                         IEnumerator ee = evidence.GetHostEnumerator ();
452                         while (ee.MoveNext ()) {
453                                 IIdentityPermissionFactory ipf = (ee.Current as IIdentityPermissionFactory);
454                                 if (ipf != null) {
455                                         IPermission p = ipf.CreateIdentityPermission (evidence);
456                                         ps.AddPermission (p);
457                                 }
458                         }
459                 }
460
461                 internal static PolicyLevel ResolvingPolicyLevel {
462                         get { return _level; }
463                         set { _level = value; }
464                 }
465
466                 internal static PermissionSet Decode (IntPtr permissions, int length)
467                 {
468                         // Permission sets from the runtime (declarative security) can be cached
469                         // for performance as they can never change (i.e. they are read-only).
470                         PermissionSet ps = null;
471
472                         lock (_lockObject) {
473                                 if (_declsecCache == null) {
474                                         _declsecCache = new Hashtable ();
475                                 }
476
477                                 object key = (object) (int) permissions;
478                                 ps = (PermissionSet) _declsecCache [key];
479                                 if (ps == null) {
480                                         // create permissionset and add it to the cache
481                                         byte[] data = new byte [length];
482                                         Marshal.Copy (permissions, data, 0, length);
483                                         ps = Decode (data);
484                                         ps.DeclarativeSecurity = true;
485                                         _declsecCache.Add (key, ps);
486                                 }
487                         }
488                         return ps;
489                 }
490
491                 internal static PermissionSet Decode (byte[] encodedPermissions)
492                 {
493                         if ((encodedPermissions == null) || (encodedPermissions.Length < 1))
494                                 throw new SecurityException ("Invalid metadata format.");
495
496                         switch (encodedPermissions [0]) {
497                         case 60:
498                                 // Fx 1.0/1.1 declarative security permissions metadata is in Unicode-encoded XML
499                                 string xml = Encoding.Unicode.GetString (encodedPermissions);
500                                 return new PermissionSet (xml);
501                         case 0x2E:
502                                 // Fx 2.0 are encoded "somewhat, but not enough, like" custom attributes
503                                 // note: we still support the older format!
504                                 return PermissionSet.CreateFromBinaryFormat (encodedPermissions);
505                         default:
506                                 throw new SecurityException (Locale.GetText ("Unknown metadata format."));
507                         }
508                 }
509
510                 private static IPermission UnmanagedCode {
511                         get {
512                                 lock (_lockObject) {
513                                         if (_unmanagedCode == null)
514                                                 _unmanagedCode = new SecurityPermission (SecurityPermissionFlag.UnmanagedCode);
515                                 }
516                                 return _unmanagedCode;
517                         }
518                 }
519
520                 //  security check when using reflection
521
522                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
523                 private static unsafe extern bool GetLinkDemandSecurity (MethodBase method, RuntimeDeclSecurityActions *cdecl, RuntimeDeclSecurityActions *mdecl);
524
525                 // When using reflection LinkDemand are promoted to full Demand (i.e. stack walk)
526                 internal unsafe static void ReflectedLinkDemandInvoke (MethodBase mb)
527                 {
528                         RuntimeDeclSecurityActions klass;
529                         RuntimeDeclSecurityActions method;
530
531                         if (!GetLinkDemandSecurity (mb, &klass, &method))
532                                 return;
533
534                         PermissionSet ps = null;
535
536                         if (klass.cas.size > 0) {
537                                 ps = Decode (klass.cas.blob, klass.cas.size);
538                         }
539                         if (klass.noncas.size > 0) {
540                                 PermissionSet p = Decode (klass.noncas.blob, klass.noncas.size);
541                                 ps = (ps == null) ? p : ps.Union (p);
542                         }
543
544                         if (method.cas.size > 0) {
545                                 PermissionSet p = Decode (method.cas.blob, method.cas.size);
546                                 ps = (ps == null) ? p : ps.Union (p);
547                         }
548                         if (method.noncas.size > 0) {
549                                 PermissionSet p = Decode (method.noncas.blob, method.noncas.size);
550                                 ps = (ps == null) ? p : ps.Union (p);
551                         }
552
553                         // in this case we union-ed the permission sets because we want to do 
554                         // a single stack walk (not up to 4).
555                         if (ps != null)
556                                 ps.Demand ();
557                 }
558
559                 internal unsafe static bool ReflectedLinkDemandQuery (MethodBase mb)
560                 {
561                         RuntimeDeclSecurityActions klass;
562                         RuntimeDeclSecurityActions method;
563
564                         if (!GetLinkDemandSecurity (mb, &klass, &method))
565                                 return true;
566
567                         return LinkDemand (mb.ReflectedType.Assembly, &klass, &method);
568                 }
569
570                 private unsafe static bool LinkDemand (Assembly a, RuntimeDeclSecurityActions *klass, RuntimeDeclSecurityActions *method)
571                 {
572                         try {
573                                 PermissionSet ps = null;
574                                 bool result = true;
575                                 if (klass->cas.size > 0) {
576                                         ps = Decode (klass->cas.blob, klass->cas.size);
577                                         result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
578                                 }
579                                 if (result && (klass->noncas.size > 0)) {
580                                         ps = Decode (klass->noncas.blob, klass->noncas.size);
581                                         result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
582                                 }
583
584                                 if (result && (method->cas.size > 0)) {
585                                         ps = Decode (method->cas.blob, method->cas.size);
586                                         result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
587                                 }
588                                 if (result && (method->noncas.size > 0)) {
589                                         ps = Decode (method->noncas.blob, method->noncas.size);
590                                         result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
591                                 }
592                                 return result;
593                         }
594                         catch (SecurityException) {
595                                 return false;
596                         }
597                 }
598
599 #pragma warning disable 169
600                 private static bool LinkDemandFullTrust (Assembly a)
601                 {
602                         // FullTrust is immutable (and means Unrestricted) 
603                         // so we can skip the subset operations and jump to IsUnrestricted.
604                         PermissionSet granted = a.GrantedPermissionSet;
605                         if ((granted != null) && !granted.IsUnrestricted ())
606                                 return false;
607
608                         PermissionSet denied = a.DeniedPermissionSet;
609                         if ((denied != null) && !denied.IsEmpty ())
610                                 return false;
611
612                         return true;
613                 }
614
615                 private static bool LinkDemandUnmanaged (Assembly a)
616                 {
617                         // note: we know that UnmanagedCode (SecurityPermission) implements IUnrestrictedPermission
618                         return IsGranted (a, UnmanagedCode);
619                 }
620
621                 // we try to provide as much details as possible to help debugging
622                 private static void LinkDemandSecurityException (int securityViolation, IntPtr methodHandle)
623                 {
624                         RuntimeMethodHandle runtimeHandle = new RuntimeMethodHandle (methodHandle);
625                         MethodInfo method = (MethodInfo)(MethodBase.GetMethodFromHandle (runtimeHandle));
626                         Assembly a = method.DeclaringType.Assembly;
627
628                         string message = null;
629                         AssemblyName an = null;
630                         PermissionSet granted = null;
631                         PermissionSet refused = null;
632                         object demanded = null;
633                         IPermission failed = null;
634
635                         if (a != null) {
636                                 an = a.UnprotectedGetName ();
637                                 granted = a.GrantedPermissionSet;
638                                 refused = a.DeniedPermissionSet;
639                         }
640
641                         switch (securityViolation) {
642                         case 1: // MONO_JIT_LINKDEMAND_PERMISSION
643                                 message = Locale.GetText ("Permissions refused to call this method.");
644                                 break;
645                         case 2: // MONO_JIT_LINKDEMAND_APTC
646                                 message = Locale.GetText ("Partially trusted callers aren't allowed to call into this assembly.");
647                                 demanded = (object) DefaultPolicies.FullTrust; // immutable
648                                 break;
649                         case 4: // MONO_JIT_LINKDEMAND_ECMA
650                                 message = Locale.GetText ("Calling internal calls is restricted to ECMA signed assemblies.");
651                                 break;
652                         case 8: // MONO_JIT_LINKDEMAND_PINVOKE
653                                 message = Locale.GetText ("Calling unmanaged code isn't allowed from this assembly.");
654                                 demanded = (object) _unmanagedCode;
655                                 failed = _unmanagedCode;
656                                 break;
657                         default:
658                                 message = Locale.GetText ("JIT time LinkDemand failed.");
659                                 break;
660                         }
661
662                         throw new SecurityException (message, an, granted, refused, method, SecurityAction.LinkDemand, demanded, failed, null);
663                 }
664
665                 private static void InheritanceDemandSecurityException (int securityViolation, Assembly a, Type t, MethodInfo method)
666                 {
667                         string message = null;
668                         AssemblyName an = null;
669                         PermissionSet granted = null;
670                         PermissionSet refused = null;
671
672                         if (a != null) {
673                                 an = a.UnprotectedGetName ();
674                                 granted = a.GrantedPermissionSet;
675                                 refused = a.DeniedPermissionSet;
676                         }
677
678                         switch (securityViolation) {
679                         case 1: // MONO_METADATA_INHERITANCEDEMAND_CLASS
680                                 message = String.Format (Locale.GetText ("Class inheritance refused for {0}."), t);
681                                 break;
682                         case 2: // MONO_METADATA_INHERITANCEDEMAND_CLASS
683                                 message = Locale.GetText ("Method override refused.");
684                                 break;
685                         default:
686                                 message = Locale.GetText ("Load time InheritDemand failed.");
687                                 break;
688                         }
689
690                         throw new SecurityException (message, an, granted, refused, method, SecurityAction.InheritanceDemand, null, null, null);
691                 }
692
693                 // called by the runtime when CoreCLR is enabled
694
695                 private static void ThrowException (Exception ex)
696                 {
697                         throw ex;
698                 }
699
700                 // internal - get called by the class loader
701
702                 // Called when
703                 // - class inheritance
704                 // - method overrides
705                 private unsafe static bool InheritanceDemand (AppDomain ad, Assembly a, RuntimeDeclSecurityActions *actions)
706                 {
707                         try {
708                                 PermissionSet ps = null;
709                                 bool result = true;
710                                 if (actions->cas.size > 0) {
711                                         ps = Decode (actions->cas.blob, actions->cas.size);
712                                         result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
713                                         if (result) {
714                                                 // also check appdomain
715                                                 result = (SecurityManager.CheckPermissionSet (ad, ps) == null);
716                                         }
717                                 }
718                                 if (actions->noncas.size > 0) {
719                                         ps = Decode (actions->noncas.blob, actions->noncas.size);
720                                         result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
721                                         if (result) {
722                                                 // also check appdomain
723                                                 result = (SecurityManager.CheckPermissionSet (ad, ps) == null);
724                                         }
725                                 }
726                                 return result;
727                         }
728                         catch (SecurityException) {
729                                 return false;
730                         }
731                 }
732
733                 // internal - get called at JIT time
734
735                 private static void DemandUnmanaged ()
736                 {
737                         UnmanagedCode.Demand ();
738                 }
739
740                 // internal - get called by JIT generated code
741
742                 private static void InternalDemand (IntPtr permissions, int length)
743                 {
744                         PermissionSet ps = Decode (permissions, length);
745                         ps.Demand ();
746                 }
747
748                 private static void InternalDemandChoice (IntPtr permissions, int length)
749                 {
750                         throw new SecurityException ("SecurityAction.DemandChoice was removed from 2.0");
751                 }
752 #pragma warning restore 169             
753         }
754 }
755
756 #endif
757