1 // 2 // System.Security.PermissionSet.cs 3 // 4 // Authors: 5 // Nick Drochak(ndrochak@gol.com) 6 // Sebastien Pouliot <sebastien@ximian.com> 7 // 8 // (C) Nick Drochak 9 // Portions (C) 2003, 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 using System.Collections; 33 using System.Diagnostics; 34 using System.IO; 35 using System.Reflection; 36 using System.Runtime.InteropServices; 37 using System.Runtime.Serialization; 38 using System.Runtime.Serialization.Formatters.Binary; 39 using System.Security.Permissions; 40 using System.Security.Policy; 41 using System.Text; 42 using System.Threading; 43 44 namespace System.Security { 45 46 [Serializable] 47 // Microsoft public key - i.e. only MS signed assembly can inherit from PermissionSet (1.x) or (2.0) FullTrust assemblies 48 [StrongNameIdentityPermission (SecurityAction.InheritanceDemand, PublicKey="002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")] 49 [ComVisible (true)] 50 [MonoTODO ("CAS support is experimental (and unsupported).")] 51 public class PermissionSet: ISecurityEncodable, ICollection, IEnumerable, IStackWalk, IDeserializationCallback { 52 53 private const string tagName = "PermissionSet"; 54 private const int version = 1; 55 private static object[] psUnrestricted = new object [1] { PermissionState.Unrestricted }; 56 57 private PermissionState state; 58 private ArrayList list; 59 private PolicyLevel _policyLevel; 60 private bool _declsec; 61 private bool _readOnly; 62 private bool[] _ignored; // for asserts and non-CAS permissions 63 64 // constructors 65 66 // for PolicyLevel (to avoid validation duplication) PermissionSet()67 internal PermissionSet () 68 { 69 list = new ArrayList (); 70 } 71 PermissionSet(PermissionState state)72 public PermissionSet (PermissionState state) : this () 73 { 74 this.state = CodeAccessPermission.CheckPermissionState (state, true); 75 } 76 PermissionSet(PermissionSet permSet)77 public PermissionSet (PermissionSet permSet) : this () 78 { 79 // LAMESPEC: This would be handled by the compiler. No way permSet is not a PermissionSet. 80 //if (!(permSet is PermissionSet)) 81 // throw new System.ArgumentException(); // permSet is not an instance of System.Security.PermissionSet. 82 if (permSet != null) { 83 state = permSet.state; 84 foreach (IPermission p in permSet.list) 85 list.Add (p); 86 } 87 } 88 PermissionSet(string xml)89 internal PermissionSet (string xml) 90 : this () 91 { 92 state = PermissionState.None; 93 if (xml != null) { 94 SecurityElement se = SecurityElement.FromString (xml); 95 FromXml (se); 96 } 97 } 98 99 // Light version for creating a (non unrestricted) PermissionSet with 100 // a single permission. This allows to relax most validations. PermissionSet(IPermission perm)101 internal PermissionSet (IPermission perm) 102 : this () 103 { 104 if (perm != null) { 105 // note: we do not copy IPermission like AddPermission 106 list.Add (perm); 107 } 108 } 109 110 // methods 111 AddPermission(IPermission perm)112 public IPermission AddPermission (IPermission perm) 113 { 114 if ((perm == null) || _readOnly) 115 return perm; 116 117 // we don't add to an unrestricted permission set unless... 118 if (state == PermissionState.Unrestricted) { 119 // identity permissions can be unrestricted under 2.x 120 { 121 // we return the union of the permission with unrestricted 122 // which results in a permission of the same type initialized 123 // with PermissionState.Unrestricted 124 return (IPermission) Activator.CreateInstance (perm.GetType (), psUnrestricted); 125 } 126 } 127 128 // we can't add two permissions of the same type in a set 129 // so we remove an existing one, union with it and add it back 130 IPermission existing = RemovePermission (perm.GetType ()); 131 if (existing != null) { 132 perm = perm.Union (existing); 133 } 134 135 // note: Add doesn't copy 136 list.Add (perm); 137 return perm; 138 } 139 140 [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")] 141 [SecurityPermission (SecurityAction.Demand, Assertion = true)] Assert()142 public void Assert () 143 { 144 int count = this.Count; 145 146 // we (current frame) must have the permission to assert it to others 147 // otherwise we don't assert (but we don't throw an exception) 148 foreach (IPermission p in list) { 149 // note: we ignore non-CAS permissions 150 if (p is IStackWalk) { 151 if (!SecurityManager.IsGranted (p)) { 152 return; 153 } 154 } else 155 count--; 156 } 157 158 // note: we must ignore the stack modifiers for the non-CAS permissions 159 if (SecurityManager.SecurityEnabled && (count > 0)) 160 throw new NotSupportedException ("Currently only declarative Assert are supported."); 161 } 162 Clear()163 internal void Clear () 164 { 165 list.Clear (); 166 } 167 Copy()168 public virtual PermissionSet Copy () 169 { 170 return new PermissionSet (this); 171 } 172 CopyTo(Array array, int index)173 public virtual void CopyTo (Array array, int index) 174 { 175 if (null == array) 176 throw new ArgumentNullException ("array"); 177 178 if (list.Count > 0) { 179 if (array.Rank > 1) { 180 throw new ArgumentException (Locale.GetText ( 181 "Array has more than one dimension")); 182 } 183 if (index < 0 || index >= array.Length) { 184 throw new IndexOutOfRangeException ("index"); 185 } 186 187 list.CopyTo (array, index); 188 } 189 } 190 Demand()191 public void Demand () 192 { 193 // Note: SecurityEnabled only applies to CAS permissions 194 // so we're not checking for it (yet) 195 if (IsEmpty ()) 196 return; 197 198 int n = list.Count; 199 if ((_ignored == null) || (_ignored.Length != n)) { 200 _ignored = new bool [n]; 201 } 202 203 bool call_cas_only = this.IsUnrestricted (); 204 // non CAS permissions (e.g. PrincipalPermission) do not requires a stack walk 205 for (int i = 0; i < n; i++) { 206 IPermission p = (IPermission) list [i]; 207 Type t = p.GetType (); 208 if (t.IsSubclassOf (typeof (CodeAccessPermission))) { 209 _ignored [i] = false; 210 call_cas_only = true; 211 } else { 212 _ignored [i] = true; 213 p.Demand (); 214 } 215 } 216 217 // don't start the stack walk if 218 // - the permission set only contains non CAS permissions; or 219 // - security isn't enabled (applis only to CAS!) 220 if (call_cas_only && SecurityManager.SecurityEnabled) 221 CasOnlyDemand (_declsec ? 5 : 3); 222 } 223 224 // The number of frames to skip depends on who's calling 225 // - CodeAccessPermission.Demand (imperative) 226 // - PermissionSet.Demand (imperative) 227 // - SecurityManager.InternalDemand (declarative) CasOnlyDemand(int skip)228 internal void CasOnlyDemand (int skip) 229 { 230 #if !MONO 231 Assembly current = null; 232 AppDomain domain = null; 233 #endif 234 235 if (_ignored == null) { 236 // special case when directly called from CodeAccessPermission.Demand 237 _ignored = new bool [list.Count]; 238 } 239 } 240 241 [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")] Deny()242 public void Deny () 243 { 244 if (!SecurityManager.SecurityEnabled) 245 return; 246 247 foreach (IPermission p in list) { 248 // note: we ignore non-CAS permissions 249 if (p is IStackWalk) { 250 throw new NotSupportedException ("Currently only declarative Deny are supported."); 251 } 252 } 253 } 254 FromXml(SecurityElement et)255 public virtual void FromXml (SecurityElement et) 256 { 257 if (et == null) 258 throw new ArgumentNullException ("et"); 259 if (et.Tag != tagName) { 260 string msg = String.Format ("Invalid tag {0} expected {1}", et.Tag, tagName); 261 throw new ArgumentException (msg, "et"); 262 } 263 264 list.Clear (); 265 266 if (CodeAccessPermission.IsUnrestricted (et)) { 267 state = PermissionState.Unrestricted; 268 // no need to continue for an unrestricted permission 269 // because identity permissions now "supports" unrestricted 270 return; 271 } else { 272 state = PermissionState.None; 273 } 274 275 if (et.Children != null) { 276 foreach (SecurityElement se in et.Children) { 277 string className = se.Attribute ("class"); 278 if (className == null) { 279 throw new ArgumentException (Locale.GetText ( 280 "No permission class is specified.")); 281 } 282 if (Resolver != null) { 283 // policy class names do not have to be fully qualified 284 className = Resolver.ResolveClassName (className); 285 } 286 287 list.Add (PermissionBuilder.Create (className, se)); 288 } 289 } 290 } 291 GetEnumerator()292 public IEnumerator GetEnumerator () 293 { 294 return list.GetEnumerator (); 295 } 296 IsSubsetOf(PermissionSet target)297 public bool IsSubsetOf (PermissionSet target) 298 { 299 // if target is empty we must be empty too 300 if ((target == null) || (target.IsEmpty ())) 301 return this.IsEmpty (); 302 303 // all permissions support unrestricted in 2.0 304 if (target.IsUnrestricted ()) 305 return true; 306 if (this.IsUnrestricted ()) 307 return false; 308 309 if (this.IsUnrestricted () && ((target == null) || !target.IsUnrestricted ())) 310 return false; 311 312 // if each of our permission is (a) present and (b) a subset of target 313 foreach (IPermission p in list) { 314 // non CAS permissions must be evaluated for unrestricted 315 Type t = p.GetType (); 316 IPermission i = null; 317 if (target.IsUnrestricted () && (p is CodeAccessPermission) && (p is IUnrestrictedPermission)) { 318 i = (IPermission) Activator.CreateInstance (t, psUnrestricted); 319 } else { 320 i = target.GetPermission (t); 321 } 322 323 if (!p.IsSubsetOf (i)) 324 return false; // not a subset (condition b) 325 } 326 return true; 327 } 328 329 [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")] PermitOnly()330 public void PermitOnly () 331 { 332 if (!SecurityManager.SecurityEnabled) 333 return; 334 335 foreach (IPermission p in list) { 336 // note: we ignore non-CAS permissions 337 if (p is IStackWalk) { 338 throw new NotSupportedException ("Currently only declarative Deny are supported."); 339 } 340 } 341 } 342 ContainsNonCodeAccessPermissions()343 public bool ContainsNonCodeAccessPermissions () 344 { 345 if (list.Count > 0) { 346 foreach (IPermission p in list) { 347 if (! p.GetType ().IsSubclassOf (typeof (CodeAccessPermission))) 348 return true; 349 } 350 } 351 return false; 352 } 353 354 // FIXME little documentation in Fx 2.0 beta 1 ConvertPermissionSet(string inFormat, byte[] inData, string outFormat)355 public static byte[] ConvertPermissionSet (string inFormat, byte[] inData, string outFormat) 356 { 357 if (inFormat == null) 358 throw new ArgumentNullException ("inFormat"); 359 if (outFormat == null) 360 throw new ArgumentNullException ("outFormat"); 361 if (inData == null) 362 return null; 363 364 if (inFormat == outFormat) 365 return inData; 366 367 PermissionSet ps = null; 368 369 if (inFormat == "BINARY") { 370 if (outFormat.StartsWith ("XML")) { 371 using (MemoryStream ms = new MemoryStream (inData)) { 372 BinaryFormatter formatter = new BinaryFormatter (); 373 ps = (PermissionSet) formatter.Deserialize (ms); 374 ms.Close (); 375 } 376 string xml = ps.ToString (); 377 switch (outFormat) { 378 case "XML": 379 case "XMLASCII": 380 return Encoding.ASCII.GetBytes (xml); 381 case "XMLUNICODE": 382 return Encoding.Unicode.GetBytes (xml); 383 } 384 } 385 } 386 else if (inFormat.StartsWith ("XML")) { 387 if (outFormat == "BINARY") { 388 string xml = null; 389 switch (inFormat) { 390 case "XML": 391 case "XMLASCII": 392 xml = Encoding.ASCII.GetString (inData); 393 break; 394 case "XMLUNICODE": 395 xml = Encoding.Unicode.GetString (inData); 396 break; 397 } 398 if (xml != null) { 399 ps = new PermissionSet (PermissionState.None); 400 ps.FromXml (SecurityElement.FromString (xml)); 401 402 MemoryStream ms = new MemoryStream (); 403 BinaryFormatter formatter = new BinaryFormatter (); 404 formatter.Serialize (ms, ps); 405 ms.Close (); 406 return ms.ToArray (); 407 } 408 } 409 else if (outFormat.StartsWith ("XML")) { 410 string msg = String.Format (Locale.GetText ("Can't convert from {0} to {1}"), inFormat, outFormat); 411 throw new XmlSyntaxException (msg); 412 } 413 } 414 else { 415 // unknown inFormat, returns null 416 return null; 417 } 418 // unknown outFormat, throw 419 throw new SerializationException (String.Format (Locale.GetText ("Unknown output format {0}."), outFormat)); 420 } 421 GetPermission(Type permClass)422 public IPermission GetPermission (Type permClass) 423 { 424 if ((permClass == null) || (list.Count == 0)) 425 return null; 426 427 foreach (object o in list) { 428 if ((o != null) && o.GetType ().Equals (permClass)) 429 return (IPermission) o; 430 } 431 // it's normal to return null for unrestricted sets 432 return null; 433 } 434 Intersect(PermissionSet other)435 public PermissionSet Intersect (PermissionSet other) 436 { 437 // no intersection possible 438 if ((other == null) || (other.IsEmpty ()) || (this.IsEmpty ())) 439 return null; 440 441 PermissionState state = PermissionState.None; 442 if (this.IsUnrestricted () && other.IsUnrestricted ()) 443 state = PermissionState.Unrestricted; 444 445 PermissionSet interSet = null; 446 // much simpler with 2.0 447 if (state == PermissionState.Unrestricted) { 448 interSet = new PermissionSet (state); 449 } else if (this.IsUnrestricted ()) { 450 interSet = other.Copy (); 451 } else if (other.IsUnrestricted ()) { 452 interSet = this.Copy (); 453 } else { 454 interSet = new PermissionSet (state); 455 InternalIntersect (interSet, this, other, false); 456 } 457 return interSet; 458 } 459 InternalIntersect(PermissionSet intersect, PermissionSet a, PermissionSet b, bool unrestricted)460 internal void InternalIntersect (PermissionSet intersect, PermissionSet a, PermissionSet b, bool unrestricted) 461 { 462 foreach (IPermission p in b.list) { 463 // for every type in both list 464 IPermission i = a.GetPermission (p.GetType ()); 465 if (i != null) { 466 // add intersection for this type 467 intersect.AddPermission (p.Intersect (i)); 468 } 469 // unrestricted is possible for indentity permissions 470 else if (unrestricted) { 471 intersect.AddPermission (p); 472 } 473 // or reject! 474 } 475 } 476 IsEmpty()477 public bool IsEmpty () 478 { 479 // note: Unrestricted isn't empty 480 if (state == PermissionState.Unrestricted) 481 return false; 482 if ((list == null) || (list.Count == 0)) 483 return true; 484 // the set may include some empty permissions 485 foreach (IPermission p in list) { 486 // empty == fully restricted == IsSubsetOf(null) == true 487 if (!p.IsSubsetOf (null)) 488 return false; 489 } 490 return true; 491 } 492 IsUnrestricted()493 public bool IsUnrestricted () 494 { 495 return (state == PermissionState.Unrestricted); 496 } 497 RemovePermission(Type permClass)498 public IPermission RemovePermission (Type permClass) 499 { 500 if ((permClass == null) || _readOnly) 501 return null; 502 503 foreach (object o in list) { 504 if (o.GetType ().Equals (permClass)) { 505 list.Remove (o); 506 return (IPermission) o; 507 } 508 } 509 return null; 510 } 511 SetPermission(IPermission perm)512 public IPermission SetPermission (IPermission perm) 513 { 514 if ((perm == null) || _readOnly) 515 return perm; 516 IUnrestrictedPermission u = (perm as IUnrestrictedPermission); 517 if (u == null) { 518 state = PermissionState.None; 519 } else { 520 state = u.IsUnrestricted () ? state : PermissionState.None; 521 } 522 RemovePermission (perm.GetType ()); 523 list.Add (perm); 524 return perm; 525 } 526 ToString()527 public override string ToString () 528 { 529 return ToXml ().ToString (); 530 } 531 ToXml()532 public virtual SecurityElement ToXml () 533 { 534 SecurityElement se = new SecurityElement (tagName); 535 se.AddAttribute ("class", GetType ().FullName); 536 se.AddAttribute ("version", version.ToString ()); 537 if (state == PermissionState.Unrestricted) 538 se.AddAttribute ("Unrestricted", "true"); 539 540 // required for permissions that do not implement IUnrestrictedPermission 541 foreach (IPermission p in list) { 542 se.AddChild (p.ToXml ()); 543 } 544 return se; 545 } 546 Union(PermissionSet other)547 public PermissionSet Union (PermissionSet other) 548 { 549 if (other == null) 550 return this.Copy (); 551 552 PermissionSet copy = null; 553 if (this.IsUnrestricted () || other.IsUnrestricted ()) { 554 // there are no child elements in unrestricted permission sets 555 return new PermissionSet (PermissionState.Unrestricted); 556 } else { 557 copy = this.Copy (); 558 // PermissionState.None -> copy all permissions 559 foreach (IPermission p in other.list) { 560 copy.AddPermission (p); 561 } 562 } 563 return copy; 564 } 565 566 public virtual int Count { 567 get { return list.Count; } 568 } 569 570 public virtual bool IsSynchronized { 571 get { return list.IsSynchronized; } 572 } 573 574 public virtual bool IsReadOnly { 575 // always false (as documented) but the PermissionSet can be read-only 576 // e.g. in a PolicyStatement 577 get { return false; } 578 } 579 580 public virtual object SyncRoot { 581 get { return this; } 582 } 583 584 internal bool DeclarativeSecurity { 585 get { return _declsec; } 586 set { _declsec = value; } 587 } 588 589 [MonoTODO ("may not be required")] IDeserializationCallback.OnDeserialization(object sender)590 void IDeserializationCallback.OnDeserialization (object sender) 591 { 592 } 593 594 [ComVisible (false)] Equals(object obj)595 public override bool Equals (object obj) 596 { 597 if (obj == null) 598 return false; 599 PermissionSet ps = (obj as PermissionSet); 600 if (ps == null) 601 return false; 602 if (state != ps.state) 603 return false; 604 if (list.Count != ps.Count) 605 return false; 606 607 for (int i=0; i < list.Count; i++) { 608 bool found = false; 609 for (int j=0; i < ps.list.Count; j++) { 610 if (list [i].Equals (ps.list [j])) { 611 found = true; 612 break; 613 } 614 } 615 if (!found) 616 return false; 617 } 618 return true; 619 } 620 621 [ComVisible (false)] GetHashCode()622 public override int GetHashCode () 623 { 624 return (list.Count == 0) ? (int) state : base.GetHashCode (); 625 } 626 627 // FIXME what's it doing here? There's probably a reason this was added here. RevertAssert()628 static public void RevertAssert () 629 { 630 CodeAccessPermission.RevertAssert (); 631 } 632 633 // internal 634 635 internal PolicyLevel Resolver { 636 get { return _policyLevel; } 637 set { _policyLevel = value; } 638 } 639 SetReadOnly(bool value)640 internal void SetReadOnly (bool value) 641 { 642 _readOnly = value; 643 } 644 AllIgnored()645 private bool AllIgnored () 646 { 647 if (_ignored == null) 648 throw new NotSupportedException ("bad bad bad"); 649 650 for (int i=0; i < _ignored.Length; i++) { 651 if (!_ignored [i]) 652 return false; 653 } 654 // everything is ignored (i.e. non-CAS permission or asserted permission). 655 return true; 656 } 657 658 // 2.0 metadata format 659 CreateFromBinaryFormat(byte[] data)660 internal static PermissionSet CreateFromBinaryFormat (byte[] data) 661 { 662 if ((data == null) || (data [0] != 0x2E) || (data.Length < 2)) { 663 string msg = Locale.GetText ("Invalid data in 2.0 metadata format."); 664 throw new SecurityException (msg); 665 } 666 667 int pos = 1; 668 int numattr = ReadEncodedInt (data, ref pos); 669 PermissionSet ps = new PermissionSet (PermissionState.None); 670 for (int i = 0; i < numattr; i++) { 671 IPermission p = ProcessAttribute (data, ref pos); 672 if (p == null) { 673 string msg = Locale.GetText ("Unsupported data found in 2.0 metadata format."); 674 throw new SecurityException (msg); 675 } 676 ps.AddPermission (p); 677 } 678 return ps; 679 } 680 ReadEncodedInt(byte[] data, ref int position)681 internal static int ReadEncodedInt (byte[] data, ref int position) 682 { 683 int len = 0; 684 if ((data [position] & 0x80) == 0) { 685 len = data [position]; 686 position ++; 687 } else if ((data [position] & 0x40) == 0) { 688 len = ((data [position] & 0x3f) << 8 | data [position + 1]); 689 position += 2; 690 } else { 691 len = (((data [position] & 0x1f) << 24) | (data [position + 1] << 16) | 692 (data [position + 2] << 8) | (data [position + 3])); 693 position += 4; 694 } 695 return len; 696 } 697 698 static object[] action = new object [1] { (SecurityAction) 0 }; 699 700 // TODO: add support for arrays and enums (2.0) ProcessAttribute(byte[] data, ref int position)701 internal static IPermission ProcessAttribute (byte[] data, ref int position) 702 { 703 int clen = ReadEncodedInt (data, ref position); 704 string cnam = Encoding.UTF8.GetString (data, position, clen); 705 position += clen; 706 707 Type secattr = Type.GetType (cnam); 708 SecurityAttribute sa = (Activator.CreateInstance (secattr, action) as SecurityAttribute); 709 if (sa == null) 710 return null; 711 712 /*int optionalParametersLength =*/ ReadEncodedInt (data, ref position); 713 int numberOfParameters = ReadEncodedInt (data, ref position); 714 for (int j=0; j < numberOfParameters; j++) { 715 bool property = false; 716 switch (data [position++]) { 717 case 0x53: // field (technically possible and working) 718 property = false; 719 break; 720 case 0x54: // property (common case) 721 property = true; 722 break; 723 default: 724 return null; 725 } 726 727 bool array = false; 728 byte type = data [position++]; 729 if (type == 0x1D) { 730 array = true; 731 type = data [position++]; 732 } 733 734 int plen = ReadEncodedInt (data, ref position); 735 string pnam = Encoding.UTF8.GetString (data, position, plen); 736 position += plen; 737 738 int arrayLength = 1; 739 if (array) { 740 arrayLength = BitConverter.ToInt32 (data, position); 741 position += 4; 742 } 743 744 object obj = null; 745 object[] arrayIndex = null; 746 for (int i = 0; i < arrayLength; i++) { 747 if (array) { 748 // TODO - setup index (2.0) 749 } 750 751 // sadly type values doesn't match ther TypeCode enum :( 752 switch (type) { 753 case 0x02: // MONO_TYPE_BOOLEAN 754 obj = (object) Convert.ToBoolean (data [position++]); 755 break; 756 case 0x03: // MONO_TYPE_CHAR 757 obj = (object) Convert.ToChar (data [position]); 758 position += 2; 759 break; 760 case 0x04: // MONO_TYPE_I1 761 obj = (object) Convert.ToSByte (data [position++]); 762 break; 763 case 0x05: // MONO_TYPE_U1 764 obj = (object) Convert.ToByte (data [position++]); 765 break; 766 case 0x06: // MONO_TYPE_I2 767 obj = (object) Convert.ToInt16 (data [position]); 768 position += 2; 769 break; 770 case 0x07: // MONO_TYPE_U2 771 obj = (object) Convert.ToUInt16 (data [position]); 772 position += 2; 773 break; 774 case 0x08: // MONO_TYPE_I4 775 obj = (object) Convert.ToInt32 (data [position]); 776 position += 4; 777 break; 778 case 0x09: // MONO_TYPE_U4 779 obj = (object) Convert.ToUInt32 (data [position]); 780 position += 4; 781 break; 782 case 0x0A: // MONO_TYPE_I8 783 obj = (object) Convert.ToInt64 (data [position]); 784 position += 8; 785 break; 786 case 0x0B: // MONO_TYPE_U8 787 obj = (object) Convert.ToUInt64 (data [position]); 788 position += 8; 789 break; 790 case 0x0C: // MONO_TYPE_R4 791 obj = (object) Convert.ToSingle (data [position]); 792 position += 4; 793 break; 794 case 0x0D: // MONO_TYPE_R8 795 obj = (object) Convert.ToDouble (data [position]); 796 position += 8; 797 break; 798 case 0x0E: // MONO_TYPE_STRING 799 string s = null; 800 if (data [position] != 0xFF) { 801 int slen = ReadEncodedInt (data, ref position); 802 s = Encoding.UTF8.GetString (data, position, slen); 803 position += slen; 804 } else { 805 position++; 806 } 807 obj = (object) s; 808 break; 809 case 0x50: // special for TYPE 810 int tlen = ReadEncodedInt (data, ref position); 811 obj = (object) Type.GetType (Encoding.UTF8.GetString (data, position, tlen)); 812 position += tlen; 813 break; 814 default: 815 return null; // unsupported 816 } 817 818 if (property) { 819 PropertyInfo pi = secattr.GetProperty (pnam); 820 pi.SetValue (sa, obj, arrayIndex); 821 } else { 822 FieldInfo fi = secattr.GetField (pnam); 823 fi.SetValue (sa, obj); 824 } 825 } 826 } 827 return sa.CreatePermission (); 828 } 829 } 830 } 831