#if NET_2_0
[ComVisible (true)]
#endif
+ [MonoTODO ("CAS support is experimental (and unsupported).")]
public class PermissionSet: ISecurityEncodable, ICollection, IEnumerable, IStackWalk, IDeserializationCallback {
private const string tagName = "PermissionSet";
private PermissionState state;
private ArrayList list;
- private int _hashcode;
private PolicyLevel _policyLevel;
private bool _declsec;
private bool _readOnly;
+ private bool[] _ignored; // for asserts and non-CAS permissions
// constructors
// methods
+#if NET_2_0
+ public IPermission AddPermission (IPermission perm)
+#else
public virtual IPermission AddPermission (IPermission perm)
+#endif
{
if ((perm == null) || _readOnly)
return perm;
return perm;
}
- [MonoTODO ("Imperative mode isn't supported")]
+ [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
[SecurityPermission (SecurityAction.Demand, Assertion = true)]
+#if NET_2_0
+ public void Assert ()
+#else
public virtual void Assert ()
+#endif
{
int count = this.Count;
}
}
+#if NET_2_0
+ public void Demand ()
+#else
public virtual void Demand ()
+#endif
{
// Note: SecurityEnabled only applies to CAS permissions
// so we're not checking for it (yet)
if (IsEmpty ())
return;
- PermissionSet cas = this;
- // avoid copy (if possible)
- if (ContainsNonCodeAccessPermissions ()) {
- // non CAS permissions (e.g. PrincipalPermission) do not requires a stack walk
- cas = this.Copy ();
- foreach (IPermission p in list) {
- Type t = p.GetType ();
- if (!t.IsSubclassOf (typeof (CodeAccessPermission))) {
- p.Demand ();
- // we wont have to process this one in the stack walk
- cas.RemovePermission (t);
- }
+ int n = list.Count;
+ if ((_ignored == null) || (_ignored.Length != n)) {
+ _ignored = new bool [n];
+ }
+
+ bool call_cas_only = this.IsUnrestricted ();
+ // non CAS permissions (e.g. PrincipalPermission) do not requires a stack walk
+ for (int i = 0; i < n; i++) {
+ IPermission p = (IPermission) list [i];
+ Type t = p.GetType ();
+ if (t.IsSubclassOf (typeof (CodeAccessPermission))) {
+ _ignored [i] = false;
+ call_cas_only = true;
+ } else {
+ _ignored [i] = true;
+ p.Demand ();
}
}
// don't start the stack walk if
// - the permission set only contains non CAS permissions; or
// - security isn't enabled (applis only to CAS!)
- if (!cas.IsEmpty () && SecurityManager.SecurityEnabled)
+ if (call_cas_only && SecurityManager.SecurityEnabled)
CasOnlyDemand (_declsec ? 5 : 3);
}
Assembly current = null;
AppDomain domain = null;
+ if (_ignored == null) {
+ // special case when directly called from CodeAccessPermission.Demand
+ _ignored = new bool [list.Count];
+ }
+
ArrayList frames = SecurityFrame.GetStack (skip);
if ((frames != null) && (frames.Count > 0)) {
SecurityFrame first = ((SecurityFrame) frames [0]);
domain = first.Domain;
// skip ourself, Demand and other security runtime methods
foreach (SecurityFrame sf in frames) {
- if (ProcessFrame (sf, ref current, ref domain))
- return; // reached Assert
+ if (ProcessFrame (sf, ref current, ref domain)) {
+ if (AllIgnored ())
+ return; // reached Assert
+ }
}
SecurityFrame last = ((SecurityFrame) frames [frames.Count - 1]);
CheckAssembly (current, last);
CompressedStack stack = Thread.CurrentThread.GetCompressedStack ();
if ((stack != null) && !stack.IsEmpty ()) {
foreach (SecurityFrame frame in stack.List) {
- if (ProcessFrame (frame, ref current, ref domain))
- return; // reached Assert
+ if (ProcessFrame (frame, ref current, ref domain)) {
+ if (AllIgnored ())
+ return; // reached Assert
+ }
}
}
}
- [MonoTODO ("Imperative mode isn't supported")]
+ [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
+#if NET_2_0
+ public void Deny ()
+#else
public virtual void Deny ()
+#endif
{
if (!SecurityManager.SecurityEnabled)
return;
}
}
+#if NET_2_0
+ public IEnumerator GetEnumerator ()
+#else
public virtual IEnumerator GetEnumerator ()
+#endif
{
return list.GetEnumerator ();
}
- public virtual bool IsSubsetOf (PermissionSet target)
- {
#if NET_2_0
+ public bool IsSubsetOf (PermissionSet target)
+ {
// if target is empty we must be empty too
if ((target == null) || (target.IsEmpty ()))
return this.IsEmpty ();
return true;
if (this.IsUnrestricted ())
return false;
+#else
+ public virtual bool IsSubsetOf (PermissionSet target)
+ {
#endif
if (this.IsUnrestricted () && ((target == null) || !target.IsUnrestricted ()))
return false;
return true;
}
- [MonoTODO ("Imperative mode isn't supported")]
+ [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
+#if NET_2_0
+ public void PermitOnly ()
+#else
public virtual void PermitOnly ()
+#endif
{
if (!SecurityManager.SecurityEnabled)
return;
return false;
}
- [MonoTODO ("little documentation in Fx 2.0 beta 1")]
+ // FIXME little documentation in Fx 2.0 beta 1
public static byte[] ConvertPermissionSet (string inFormat, byte[] inData, string outFormat)
{
if (inFormat == null)
throw new SerializationException (String.Format (Locale.GetText ("Unknown output format {0}."), outFormat));
}
- public virtual IPermission GetPermission (Type permClass)
+#if NET_2_0
+ public IPermission GetPermission (Type permClass)
+#else
+ public virtual IPermission GetPermission (Type permClass)
+#endif
{
if ((permClass == null) || (list.Count == 0))
return null;
return null;
}
- public virtual PermissionSet Intersect (PermissionSet other)
+#if NET_2_0
+ public PermissionSet Intersect (PermissionSet other)
+#else
+ public virtual PermissionSet Intersect (PermissionSet other)
+#endif
{
// no intersection possible
if ((other == null) || (other.IsEmpty ()) || (this.IsEmpty ()))
}
}
- public virtual bool IsEmpty ()
+#if NET_2_0
+ public bool IsEmpty ()
+#else
+ public virtual bool IsEmpty ()
+#endif
{
// note: Unrestricted isn't empty
if (state == PermissionState.Unrestricted)
return true;
}
- public virtual bool IsUnrestricted ()
+#if NET_2_0
+ public bool IsUnrestricted ()
+#else
+ public virtual bool IsUnrestricted ()
+#endif
{
return (state == PermissionState.Unrestricted);
}
- public virtual IPermission RemovePermission (Type permClass)
+#if NET_2_0
+ public IPermission RemovePermission (Type permClass)
+#else
+ public virtual IPermission RemovePermission (Type permClass)
+#endif
{
if ((permClass == null) || _readOnly)
return null;
return null;
}
- public virtual IPermission SetPermission (IPermission perm)
+#if NET_2_0
+ public IPermission SetPermission (IPermission perm)
+#else
+ public virtual IPermission SetPermission (IPermission perm)
+#endif
{
if ((perm == null) || _readOnly)
return perm;
return se;
}
+#if NET_2_0
+ public PermissionSet Union (PermissionSet other)
+#else
public virtual PermissionSet Union (PermissionSet other)
+#endif
{
if (other == null)
return this.Copy ();
set { _declsec = value; }
}
- [MonoTODO()]
+ [MonoTODO ("may not be required")]
void IDeserializationCallback.OnDeserialization (object sender)
{
}
return (list.Count == 0) ? (int) state : base.GetHashCode ();
}
- [MonoTODO ("what's it doing here?")]
+ // FIXME what's it doing here? There's probably a reason this was added here.
static public void RevertAssert ()
{
- // FIXME: There's probably a reason this was added here ?
CodeAccessPermission.RevertAssert ();
}
#endif
_readOnly = value;
}
+ private bool AllIgnored ()
+ {
+ if (_ignored == null)
+ throw new NotSupportedException ("bad bad bad");
+
+ for (int i=0; i < _ignored.Length; i++) {
+ if (!_ignored [i])
+ return false;
+ }
+ // everything is ignored (i.e. non-CAS permission or asserted permission).
+ return true;
+ }
+
internal bool ProcessFrame (SecurityFrame frame, ref Assembly current, ref AppDomain domain)
{
if (IsUnrestricted ()) {
if (frame.Deny != null) {
// but have restrictions (some denied permissions)
CodeAccessPermission.ThrowSecurityException (this, "Deny", frame, SecurityAction.Demand, null);
- } else if (frame.PermitOnly != null) {
+ } else if ((frame.PermitOnly != null) && !frame.PermitOnly.IsUnrestricted ()) {
// but have restrictions (only some permitted permissions)
CodeAccessPermission.ThrowSecurityException (this, "PermitOnly", frame, SecurityAction.Demand, null);
}
// skip next steps if no Assert, Deny or PermitOnly are present
if (frame.HasStackModifiers) {
- foreach (CodeAccessPermission cap in list) {
- if (cap.ProcessFrame (frame))
- return true; // Assert reached - abort stack walk!
+ for (int i = 0; i < list.Count; i++) {
+ CodeAccessPermission cap = (CodeAccessPermission) list [i];
+ if (cap.ProcessFrame (frame)) {
+ _ignored [i] = true; // asserted
+ if (AllIgnored ())
+ return true; // no more, abort stack walk!
+ }
}
}
static object[] action = new object [1] { (SecurityAction) 0 };
- // TODO: add support for arrays and enums
+ // TODO: add support for arrays and enums (2.0)
internal static IPermission ProcessAttribute (byte[] data, ref int position)
{
int clen = ReadEncodedInt (data, ref position);
object[] arrayIndex = null;
for (int i = 0; i < arrayLength; i++) {
if (array) {
- // TODO - setup index
+ // TODO - setup index (2.0)
}
// sadly type values doesn't match ther TypeCode enum :(