Quantcast
Channel: Common Language Runtime Internals and Architecture forum
Viewing all articles
Browse latest Browse all 1710

Custom code access permission throws SecurityException with message “Failure decoding embedded permission set object.”

$
0
0

Hello,

We have a pretty elaborate authorization system which requires the use of a custom permission somewhat similar to PrincipalPermission. I followed all suggestions on MSDN and looked at the code of PrincipalPermission and yet I have a pretty stubborn problem: if I declare the permission on the class level with one parameter and then I declare it on one of the methods with different (more specific) parameter the code access security builds a union of the two and calls Demand on it. My implementation of Demand returns with no exception and yet the system throws SecurityException with the cryptic message "Failure decoding embedded permission set object." What does it mean? I see all sorts of calls to my permission, includin ToXml and FromXml and I think that they all behave properly (or at least do not fail). Can someone out there think of what might be missing or done wrong here. Below is the code of the permission class (thanks in advance to anyone who will give it a thought):

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.ServiceModel;
using System.Threading;
using Authorization.DataContracts;
namespace Authorization
{
    [Serializable]
    public sealed class AuthorizationPermission : IPermission, IUnrestrictedPermission, ISerializable, IEquatable<AuthorizationPermission>
    {
        List<string> _activityIdentifiers = new List<string>();
        public AuthorizationPermission()
        {
        }
        public AuthorizationPermission(PermissionState state)
        {
            if (state == PermissionState.Unrestricted)
                _activityIdentifiers.Add(string.Empty);
        }
        public AuthorizationPermission(string activityIdentifier, bool unrestricted = false)
        {
            if (!unrestricted && string.IsNullOrWhiteSpace(activityIdentifier))
                throw new ArgumentNullException("activityIdentifier");
            if (unrestricted)
                _activityIdentifiers.Add(string.Empty);
            else
                _activityIdentifiers.Add(activityIdentifier);
        }
        protected AuthorizationPermission(SerializationInfo info, StreamingContext context)
        {
            var count = info.GetInt32("activityIdentifiersCount");
            for (var i=0; i<count; i++)
                _activityIdentifiers.Add(info.GetString("activityIdentifier_"+i));
        }
        public static bool HasPermission(string protectedIdentifier)
        {
            try
            {
                var auth = AuthorizationCache.GetAuthorization(Thread.CurrentPrincipal.Identity.Name, protectedIdentifier);
                return auth.Granted;
            }
            catch (CommunicationException)
            {
                return false;
            }
        }
        public bool Equals(AuthorizationPermission other)
        {
            if (ReferenceEquals(other, null))
                return false;
            if (ReferenceEquals(this, other))
                return true;
            return _activityIdentifiers.SequenceEqual(other._activityIdentifiers, StringComparer.OrdinalIgnoreCase);
        }
        public override bool Equals(object obj)
        {
            return Equals(obj as AuthorizationPermission);
        }
        public override int GetHashCode()
        {
            var hashCode = 53;
            foreach (var id in _activityIdentifiers)
                hashCode = 17 * hashCode + id.ToUpperInvariant().GetHashCode();
            return hashCode;
        }
        public static bool operator==(AuthorizationPermission left, AuthorizationPermission right)
        {
            return ReferenceEquals(left, null) 
                        ? ReferenceEquals(right, null) 
                        : left.Equals(right);
        }
        public static bool operator!=(AuthorizationPermission left, AuthorizationPermission right)
        {
            return !(left==right);
        }
        public override string ToString()
        {
            return ToXml().ToString();
        }
        public bool IsUnrestricted()
        {
            return _activityIdentifiers.All(id => string.IsNullOrWhiteSpace(id));
        }
        public IPermission Copy()
        {
            return new AuthorizationPermission
            {
                _activityIdentifiers = this._activityIdentifiers.ToList(),
            };
        }
        public void Demand()
        {
            if (IsUnrestricted())
                return;
            if (!Thread.CurrentPrincipal.Identity.IsAuthenticated)
                throw new SecurityException("The principal's identity is not authenticated.", GetType());
            if (!_activityIdentifiers.Any())
                throw new SecurityException("Access is denied.", GetType());
            AuthorizationDto auth = null;
            try
            {
                foreach (var id in _activityIdentifiers)
                {
                    if (string.IsNullOrWhiteSpace(id))
                        continue;
                    auth = AuthorizationCache.GetAuthorization(Thread.CurrentPrincipal.Identity.Name, id);
                    if (auth==null)
                        ThrowSecurityException("Access is denied.");
                    if (!auth.Granted)
                        ThrowSecurityException("Access is denied. " + auth.Message);
                }
            }
            catch (CommunicationException x)
            {
                throw new SecurityException("Access is denied.", x);
            }
        }
        void ThrowSecurityException(string message)
        {
            AssemblyName assemblyName = null;
            Evidence evidence = null;
            try
            {
                var callingAssembly = Assembly.GetCallingAssembly();
                assemblyName = callingAssembly.GetName();
                if (callingAssembly != Assembly.GetExecutingAssembly())
                    evidence = callingAssembly.Evidence;
            }
            catch (SecurityException)
            {
            }
            throw new SecurityException(
                        message,
                        assemblyName,
                        null,
                        null,
                        null,
                        SecurityAction.Demand,
                        this,
                        this,
                        evidence);
        }
        public IPermission Intersect(IPermission target)
        {
            var targetPermission = target as AuthorizationPermission;
            if (targetPermission == null)
                return null;
            if (IsUnrestricted())
                return targetPermission.Copy();
            if (targetPermission.IsUnrestricted())
                return Copy();
            var intersection = _activityIdentifiers.Intersect(targetPermission._activityIdentifiers, StringComparer.OrdinalIgnoreCase).ToList();
            if (!intersection.Any())
                return null;
            var result = new AuthorizationPermission
            {
                _activityIdentifiers = intersection,
            };
            return result;
        }
        public IPermission Union(IPermission target)
        {
            var targetPermission = target as AuthorizationPermission;
            if (targetPermission == null || IsUnrestricted())
                return Copy();
            if (targetPermission.IsUnrestricted())
                return targetPermission.Copy();
            var result = new AuthorizationPermission
            {
                _activityIdentifiers = _activityIdentifiers.Union(targetPermission._activityIdentifiers, StringComparer.OrdinalIgnoreCase).ToList(),
            };
            return result;
        }
        public bool IsSubsetOf(IPermission target)
        {
            var targetPermission = target as AuthorizationPermission;
            if (targetPermission == null)
                return false;
            if (targetPermission.IsUnrestricted())
                return true;
            if (IsUnrestricted())
                return false;
            var intersection = _activityIdentifiers.Intersect(targetPermission._activityIdentifiers, StringComparer.OrdinalIgnoreCase);
            return _activityIdentifiers.Count() == intersection.Count();
        }
        public void FromXml(SecurityElement e)
        {
            if (e == null)
                throw new ArgumentNullException("e");
            _activityIdentifiers = new List<string>();
            foreach (var ids in e.Children)
            {
                var identifiers = ids as SecurityElement;
                if (identifiers != null &&
                    identifiers.Tag == "activityIdentifiers")
                {
                    foreach (var id in identifiers.Children)
                    {
                        var identifier = id as SecurityElement;
                        if (identifier != null &&
                            identifier.Tag == "add")
                            _activityIdentifiers.Add(identifier.Text);
                    }
                    break;
                }
            }
        }
        public SecurityElement ToXml()
        {
            var element = new SecurityElement("IPermission");
            var nameComponents = GetType().AssemblyQualifiedName.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var className = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", nameComponents[0], nameComponents[1]);
            element.AddAttribute("class", className);
            element.AddAttribute("version", "1");
            var activityIdentifiersElement = new SecurityElement("activityIdentifiers");
            foreach (var id in _activityIdentifiers)
                activityIdentifiersElement.AddChild(
                    new SecurityElement("add", SecurityElement.Escape(id)));
            element.AddChild(activityIdentifiersElement);
            return element;
        }
        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");
            info.AddValue("activityIdentifiersCount", _activityIdentifiers.Count());
            for (var i=0; i<_activityIdentifiers.Count(); i++)
                info.AddValue("activityIdentifier_"+i, _activityIdentifiers.ElementAt(i));
        }
    }
}


Thanks Val


Viewing all articles
Browse latest Browse all 1710

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>