PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/corlib/System.Security/PermissionSet.cs

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