Ejemplo n.º 1
0
        private void AggregateAffectedPermissions(PermissionTypeBase permission, AggregationType aggregationType, Dictionary <int, PermissionTypeBase> aggregation)
        {
            if (aggregation.ContainsKey(permission.Index))
            {
                return;
            }

            aggregation[permission.Index] = permission;
            PermissionTypeBase[] morePermissions;
            switch (aggregationType)
            {
            case AggregationType.Allow:
                morePermissions = permission.Allows;
                break;

            case AggregationType.Deny:
                morePermissions = permission.Denies.ToArray();
                break;

            default:
                throw new NotSupportedException("Unknown AggregationType: " + aggregationType);
            }

            if (morePermissions?.Length > 0)
            {
                foreach (var perm in morePermissions)
                {
                    if (perm != null)
                    {
                        AggregateAffectedPermissions(perm, aggregationType, aggregation);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /**************************************************************************************************** Related Identities #2 */

        public static IEnumerable <int> GetRelatedIdentities(SecurityContext context, int entityId, PermissionLevel level, IEnumerable <PermissionTypeBase> permissionTypes)
        {
            SecurityEntity.EnterReadLock();
            try
            {
                var identities = new List <int>();
                var mask       = PermissionTypeBase.GetPermissionMask(permissionTypes);
                var root       = SecurityEntity.GetEntitySafe(context, entityId, true);
                foreach (var entity in new EntityTreeWalker(root))
                {
                    // step forward if there is no any setting
                    if (!entity.HasExplicitAcl)
                    {
                        continue;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    if (!entity.IsInherited && entity.Parent != null)
                    {
                        CollectIdentitiesFromAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id), level, mask, identities);
                    }

                    // adding explicite identities
                    CollectIdentitiesFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id), level, mask, identities);
                }
                return(identities);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
Ejemplo n.º 3
0
        internal void ToString(StringBuilder sb)
        {
            // +U1:____++++
            sb.Append(LocalOnly ? '-':'+');
            sb.Append("(" + IdentityId + ")");
            sb.Append(':');
            var chars = new char[PermissionTypeBase.PermissionCount];

            for (var i = 0; i < chars.Length; i++)
            {
                chars[i] = '_';
            }

            foreach (var perm in Permissions)
            {
                var index = PermissionTypeBase.PermissionCount - PermissionTypeBase.GetPermissionTypeByName(perm.Name).Index - 1;
                if (perm.Deny)
                {
                    chars[index] = '-';
                }
                if (perm.Allow)
                {
                    chars[index] = '+';
                }
            }

            sb.Append(chars);
        }
Ejemplo n.º 4
0
        internal PermissionValue GetPermissionSafe(int userId, int entityId, int ownerId, EntryType?entryType, params PermissionTypeBase[] permissions)
        {
            if (userId == Configuration.Identities.SystemUserId)
            {
                return(PermissionValue.Allowed);
            }

            //==>
            var identities = GetIdentities(userId, ownerId, entityId);
            var allow      = 0ul;
            var deny       = 0ul;

            var firstAcl = SecurityEntity.GetFirstAclSafe(_securityContext, entityId, true);

            if (firstAcl == null)
            {
                return(PermissionValue.Undefined);
            }

            if (entryType == null)
            {
                if (entityId == firstAcl.EntityId)
                {
                    firstAcl.AggregateLocalOnlyValues(identities, ref allow, ref deny);
                }
                for (var aclInfo = firstAcl; aclInfo != null; aclInfo = aclInfo.Inherits ? aclInfo.Parent : null)
                {
                    aclInfo.AggregateEffectiveValues(identities, ref allow, ref deny);
                }
            }
            else
            {
                if (entityId == firstAcl.EntityId)
                {
                    firstAcl.AggregateLocalOnlyValues(identities, entryType.Value, ref allow, ref deny);
                }
                for (var aclInfo = firstAcl; aclInfo != null; aclInfo = aclInfo.Inherits ? aclInfo.Parent : null)
                {
                    aclInfo.AggregateEffectiveValues(identities, entryType.Value, ref allow, ref deny);
                }
            }
            //==<

            var mask = PermissionTypeBase.GetPermissionMask(permissions);

            if ((deny & mask) != 0)
            {
                return(PermissionValue.Denied);
            }
            if ((allow & mask) != mask)
            {
                return(PermissionValue.Undefined);
            }
            return(PermissionValue.Allowed);
        }
Ejemplo n.º 5
0
        /****************************************************************************************************** Related Permissions */

        public static Dictionary <PermissionTypeBase, int> GetRelatedPermissions(SecurityContext context, int entityId, PermissionLevel level, bool explicitOnly, int identityId, Func <int, bool> isEnabled)
        {
            if (!explicitOnly)
            {
                throw new NotSupportedException("Not supported in this version. Use explicitOnly = true");
            }

            SecurityEntity.EnterReadLock();
            try
            {
                var counters = new int[PermissionTypeBase.PermissionCount];

                var identities = new[] { identityId };

                var root = SecurityEntity.GetEntitySafe(context, entityId, true);
                foreach (var entity in new EntityTreeWalker(root))
                {
                    // step forward if there is no any setting
                    if (!entity.HasExplicitAcl)
                    {
                        continue;
                    }

                    if (!isEnabled(entity.Id))
                    {
                        continue;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    var localBits = new PermissionBitMask();
                    if (!entity.IsInherited && entity.Parent != null)
                    {
                        CollectPermissionsFromLocalAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), localBits);
                    }

                    // adding explicite identities
                    CollectPermissionsFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), level, counters, localBits);
                }

                var result = new Dictionary <PermissionTypeBase, int>();
                for (var i = 0; i < PermissionTypeBase.PermissionCount; i++)
                {
                    result.Add(PermissionTypeBase.GetPermissionTypeByIndex(i), counters[i]);
                }

                return(result);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
Ejemplo n.º 6
0
        /********************************************************************************************************* Related Entities */

        public static IEnumerable <int> GetRelatedEntities(SecurityContext context, int entityId, PermissionLevel level, bool explicitOnly, int identityId, IEnumerable <PermissionTypeBase> permissionTypes)
        {
            if (!explicitOnly)
            {
                throw new NotSupportedException("Not supported in this version. Use explicitOnly = true");
            }

            SecurityEntity.EnterReadLock();
            try
            {
                var entityIds = new List <int>();

                var mask       = PermissionTypeBase.GetPermissionMask(permissionTypes);
                var identities = new[] { identityId };

                var root = SecurityEntity.GetEntitySafe(context, entityId, true);
                foreach (var entity in new EntityTreeWalker(root))
                {
                    // step forward if there is no any setting
                    if (!entity.HasExplicitAcl)
                    {
                        continue;
                    }

                    var added = false;
                    if (!entity.IsInherited && entity.Parent != null)
                    {
                        if (HasBitsByEffectiveAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), level, mask))
                        {
                            entityIds.Add(entity.Id);
                            added = true;
                        }
                    }

                    // adding explicite identities
                    if (!added)
                    {
                        if (HasBitsByExpliciteAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), level, mask))
                        {
                            entityIds.Add(entity.Id);
                        }
                    }
                }

                return(entityIds);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
Ejemplo n.º 7
0
        private static void IncrementCounters(ulong bits, int[] counters)
        {
            var mask = 1uL;
            var b    = bits;

            foreach (var pt in PermissionTypeBase.GetPermissionTypes())
            {
                if ((b & mask) > 0)
                {
                    counters[pt.Index]++;
                }
                mask = mask << 1;
            }
        }
Ejemplo n.º 8
0
        private AccessControlEntry CreateEmptyAce(AceInfo aceInfo)
        {
            var perms = new Permission[PermissionTypeBase.PermissionCount];

            for (var i = 0; i < perms.Length; i++)
            {
                perms[i] = new Permission {
                    Name = PermissionTypeBase.GetPermissionTypeByIndex(i).Name
                }
            }
            ;

            return(new AccessControlEntry
            {
                IdentityId = aceInfo.IdentityId,
                LocalOnly = aceInfo.LocalOnly,
                Permissions = perms
            });
        }
Ejemplo n.º 9
0
        public static Dictionary <PermissionTypeBase, int> GetExplicitPermissionsInSubtree(SecurityContext context, int entityId, int[] identities, bool includeRoot)
        {
            SecurityEntity.EnterReadLock();
            try
            {
                var counters = new int[PermissionTypeBase.PermissionCount];

                var root = SecurityEntity.GetEntitySafe(context, entityId, true);
                foreach (var entity in new EntityTreeWalker(root))
                {
                    // step forward if there is no any setting
                    if (!entity.HasExplicitAcl || (entity.Id == entityId && !includeRoot))
                    {
                        continue;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    var localBits = new PermissionBitMask();
                    if (!entity.IsInherited && entity.Parent != null && (includeRoot || entity.Parent.Id != entityId))
                    {
                        CollectPermissionsFromLocalAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), localBits);
                    }

                    // adding explicite identities
                    CollectPermissionsFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), PermissionLevel.AllowedOrDenied, counters, localBits);
                }

                var result = new Dictionary <PermissionTypeBase, int>();
                for (var i = 0; i < PermissionTypeBase.PermissionCount; i++)
                {
                    result.Add(PermissionTypeBase.GetPermissionTypeByIndex(i), counters[i]);
                }

                return(result);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
Ejemplo n.º 10
0
        internal string _traceEffectivePermissionValues(int entityId, int userId, int ownerId)
        {
            var values = new char[PermissionTypeBase.PermissionCount];

            foreach (var permType in PermissionTypeBase.GetPermissionTypes())
            {
                var  val = GetPermission(userId, entityId, ownerId, permType);
                char c;
                switch (val)
                {
                case PermissionValue.Undefined: c = '_'; break;

                case PermissionValue.Allowed: c = '+'; break;

                case PermissionValue.Denied: c = '-'; break;

                default: throw new NotSupportedException("Unknown PermissionValue: " + val);
                }
                values[values.Length - permType.Index - 1] = c;
            }
            return(new string(values));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Starts the security subsystem using the passed configuration.
        /// Call this method only once in your application's startup sequence.
        /// The method prepares and memorizes the main components for
        /// creating SecurityContext instances in a fastest possible way.
        /// The main components are global objects:
        /// ISecurityDataProvider instance, IMessageProvider instance and SecurityCache instance.
        /// </summary>
        protected static void StartTheSystem(SecurityConfiguration configuration)
        {
            _generalContext = null;

            // The messageprovider provider must receive ongoing activities at this time.
            StartedAt = DateTime.UtcNow;

            int lastActivityIdFromDb;
            var uncompleted = DataHandler.LoadCompletionState(configuration.SecurityDataProvider, out lastActivityIdFromDb);

            _messageProvider = configuration.MessageProvider;
            _messageProvider.MessageReceived += MessageProvider_MessageReceived;

            Configuration.Identities.SystemUserId    = configuration.SystemUserId ?? -1;
            Configuration.Identities.VisitorUserId   = configuration.VisitorUserId ?? 6;
            Configuration.Identities.EveryoneGroupId = configuration.EveryoneGroupId ?? 8;
            Configuration.Identities.OwnerGroupId    = configuration.OwnerGroupId ?? 9;

            Configuration.Messaging.CommunicationMonitorRunningPeriodInSeconds = configuration.CommunicationMonitorRunningPeriodInSeconds ?? 30;
            Configuration.Messaging.SecuritActivityLifetimeInMinutes           = configuration.SecuritActivityLifetimeInMinutes ?? 42;
            Configuration.Messaging.SecuritActivityTimeoutInSeconds            = configuration.SecuritActivityTimeoutInSeconds ?? 120;

            _securityDataProviderPrototype = configuration.SecurityDataProvider;
            PermissionTypeBase.InferForcedRelations();

            using (var op = SnTrace.Security.StartOperation("Security initial loading."))
            {
                _cacheHolder  = SecurityCache.Initialize(configuration.SecurityDataProvider);
                op.Successful = true;
            }

            CommunicationMonitor.Initialize();

            _generalContext = new SecurityContext(SystemUser);
            SecurityActivityQueue.Startup(uncompleted, lastActivityIdFromDb);

            _killed = false;
        }
Ejemplo n.º 12
0
        public void Start()
        {
            GeneralSecurityContext = null;

            // The message provider must receive ongoing activities at this time.
            StartedAt = DateTime.UtcNow;

            var uncompleted = DataHandler.LoadCompletionState(out var lastActivityIdFromDb);

            PermissionTypeBase.InferForcedRelations();

            using (var op = SnTrace.Security.StartOperation("Security initial loading."))
            {
                var cache = new SecurityCache(DataHandler);
                cache.Initialize();
                Cache         = cache;
                op.Successful = true;
            }

            EntityManager             = new SecurityEntityManager(Cache, DataHandler, MissingEntityHandler);
            Cache.EntityManager       = EntityManager; // Property injection
            DataHandler.EntityManager = EntityManager; // Property injection

            PermissionQuery        = new PermissionQuery(EntityManager, Cache);
            CommunicationMonitor   = new CommunicationMonitor(DataHandler, Options.Create(MessagingOptions));
            GeneralSecurityContext = new SecurityContext(SystemUser, this);

            SecurityActivityQueue = new SecurityActivityQueue(this, CommunicationMonitor, DataHandler, ActivityHistory);
            SecurityActivityQueue.Startup(uncompleted, lastActivityIdFromDb);
            ActivityHistory.SecurityActivityQueue = SecurityActivityQueue; // Property injection

            MessageProvider.MessageReceived += MessageProvider_MessageReceived;
            MessageProvider.Initialize();
            MessageProvider.Start(StartedAt);

            _killed = false;
        }
Ejemplo n.º 13
0
        /********************************************************************************************* Related Entities one level#2 */

        public static IEnumerable <int> GetRelatedEntitiesOneLevel(SecurityContext context, int entityId, PermissionLevel level, int identityId, IEnumerable <PermissionTypeBase> permissionTypes)
        {
            SecurityEntity.EnterReadLock();
            try
            {
                var result     = new List <int>();
                var identities = new[] { identityId };
                var mask       = PermissionTypeBase.GetPermissionMask(permissionTypes);
                var root       = SecurityEntity.GetEntitySafe(context, entityId, true);
                foreach (var childEntity in root.Children)
                {
                    var aces = context.Evaluator.GetEffectiveEntriesSafe(childEntity.Id, identities);
                    if (aces.Any(a => HasBits(a.AllowBits, a.DenyBits, level, mask)))
                    {
                        result.Add(childEntity.Id);
                    }
                }
                return(result);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
Ejemplo n.º 14
0
        public override string ToString()
        {
            var chars = new char[PermissionTypeBase.PermissionCount];

            for (var i = 0; i < chars.Length; i++)
            {
                chars[i] = '_';
            }

            foreach (var perm in Permissions)
            {
                var index = PermissionTypeBase.PermissionCount - PermissionTypeBase.GetPermissionTypeByName(perm.Name).Index - 1;
                if (perm.Deny)
                {
                    chars[index] = '-';
                }
                if (perm.Allow)
                {
                    chars[index] = '+';
                }
            }

            return($"{EntryType}|{(LocalOnly ? '-' : '+')}({IdentityId}):{new string(chars)}");
        }
Ejemplo n.º 15
0
        private static SenseNet.Security.PermissionValue GetValue(ulong allowBits, ulong denyBits, SenseNet.Security.PermissionTypeBase perm)
        {
            var mask = 1uL << (perm.Index);

            if ((denyBits & mask) != 0)
            {
                return(SenseNet.Security.PermissionValue.Denied);
            }
            if ((allowBits & mask) == mask)
            {
                return(SenseNet.Security.PermissionValue.Allowed);
            }
            return(SenseNet.Security.PermissionValue.Undefined);
        }
Ejemplo n.º 16
0
        /*=========================================================================================== Tools */

        internal static void SetBits(ref ulong allowBits, ref ulong denyBits, SenseNet.Security.PermissionTypeBase permissionType, SenseNet.Security.PermissionValue permissionValue)
        {
            var permCount     = PermissionType.PermissionCount;
            var y             = permissionType.Index;
            var thisbit       = 1uL << y;
            var allowedBefore = (allowBits & thisbit) != 0uL;
            var deniedBefore  = (denyBits & thisbit) != 0uL;

            var dependencyTable = Providers.Instance.SecurityHandler.PermissionDependencyTable;

            switch (permissionValue)
            {
            case SenseNet.Security.PermissionValue.Allowed:
                for (var x = 0; x < permCount; x++)
                {
                    if (dependencyTable[y][x] == 1)
                    {
                        allowBits |= 1uL << x;
                        denyBits  &= ~(1uL << x);
                    }
                }
                break;

            case SenseNet.Security.PermissionValue.Denied:
                for (var x = 0; x < permCount; x++)
                {
                    if (dependencyTable[x][y] == 1)
                    {
                        allowBits &= ~(1uL << x);
                        denyBits  |= 1uL << x;
                    }
                }
                break;

            case SenseNet.Security.PermissionValue.Undefined:
                if (allowedBefore)
                {
                    for (var x = 0; x < permCount; x++)
                    {
                        if (dependencyTable[x][y] == 1)
                        {
                            allowBits &= ~(1uL << x);
                        }
                    }
                }
                else if (deniedBefore)
                {
                    for (var x = 0; x < permCount; x++)
                    {
                        if (dependencyTable[y][x] == 1)
                        {
                            denyBits &= ~(1uL << x);
                        }
                    }
                }
                break;

            default:
                throw new NotSupportedException("Unknown PermissionValue: " + permissionValue);
            }
        }
Ejemplo n.º 17
0
        /*=========================================================================================== method for backward compatibility */

        /// <summary>
        /// Allowes, denies or clears a permission on the requested entity for the requested identity.
        /// This is a backward compatible legacy method.
        /// </summary>
        /// <param name="entityId">The requested entity.</param>
        /// <param name="identityId">The requested identity.</param>
        /// <param name="localOnly">Determines whether the edited entry is inheritable or not.</param>
        /// <param name="permission">Permission that will be modified.</param>
        /// <param name="value">Value that will be set. It can be Undefined, Allowed or Denied.</param>
        /// <returns>A reference to this instance for calling more operations.</returns>
        public SnAclEditor SetPermission(int entityId, int identityId, bool localOnly, SenseNet.Security.PermissionTypeBase permission, SenseNet.Security.PermissionValue value)
        {
            switch (value)
            {
            case SenseNet.Security.PermissionValue.Allowed: Allow(entityId, identityId, localOnly, permission); break;

            case SenseNet.Security.PermissionValue.Denied: Deny(entityId, identityId, localOnly, permission); break;

            case SenseNet.Security.PermissionValue.Undefined: ClearPermission(entityId, identityId, localOnly, permission); break;

            default: throw new SnNotSupportedException("Unknown PermissionValue: " + value);
            }
            return(this);
        }
Ejemplo n.º 18
0
        internal PermissionValue GetSubtreePermission(int userId, int entityId, int ownerId, params PermissionTypeBase[] permissions)
        {
            if (userId == Configuration.Identities.SystemUserId)
            {
                return(PermissionValue.Allowed);
            }

            var identities = GetIdentities(userId, ownerId, entityId);

            SecurityEntity.EnterReadLock();
            try
            {
                var entity   = SecurityEntity.GetEntitySafe(_securityContext, entityId, true);
                var firstAcl = SecurityEntity.GetFirstAclSafe(_securityContext, entityId, true);

                //======== #1: startbits: getpermbits
                //==>

                var allow = 0ul;
                var deny  = 0ul;

                if (entityId == firstAcl.EntityId)
                {
                    firstAcl.AggregateLocalOnlyValues(identities, ref allow, ref deny);
                }
                for (var permInfo = firstAcl; permInfo != null; permInfo = permInfo.Inherits ? permInfo.Parent : null)
                {
                    permInfo.AggregateEffectiveValues(identities, ref allow, ref deny);
                }
                //==<

                var mask = PermissionTypeBase.GetPermissionMask(permissions);
                if ((deny & mask) != 0)
                {
                    return(PermissionValue.Denied);
                }
                if ((allow & mask) != mask)
                {
                    return(PermissionValue.Undefined);
                }

                // doesn't depend from the value of the entity's Inherits (need to evaluate through the breaks)
                // doesn't depend from the value of the LocalOnly (need to evaluate any entry)
                foreach (var descendantEntity in new EntityTreeWalker(entity))
                {
                    // if nearest holder is different, this entity is irrelevant (there is no entry to evaluate)
                    if (!descendantEntity.HasExplicitAcl)
                    {
                        continue;
                    }

                    // only this level is sufficient to evaluate because any difference from "allow" causes exit instantly

                    // filtered by relevant identities
                    AceInfo[] relevantAces;
                    try
                    {
                        relevantAces = GetExplicitEntriesSafe(descendantEntity.Id, identities).ToArray();
                    }
                    catch (EntityNotFoundException) // catch only: well known exception
                    {
                        // do nothing because entity was deleted
                        continue;
                    }

                    // different evaluation that depends on the inheritance continuity
                    if (descendantEntity.IsInherited)
                    {
                        // if inherited, only denied bits play
                        foreach (var ace in relevantAces)
                        {
                            deny |= ace.DenyBits;
                        }
                        if ((deny & mask) != 0uL)
                        {
                            return(PermissionValue.Denied);
                        }
                    }
                    else
                    {
                        // if breaked, need to recalculate allow and deny bits too.
                        allow = 0ul;
                        deny  = 0ul;
                        var hasLocalOnly = false;
                        // on this level need to explicit "allow"
                        foreach (var ace in relevantAces)
                        {
                            allow        |= ace.AllowBits;
                            deny         |= ace.DenyBits;
                            hasLocalOnly |= ace.LocalOnly;
                        }
                        // return if inadequate
                        if ((deny & mask) != 0)
                        {
                            return(PermissionValue.Denied);
                        }
                        if ((allow & mask) != mask)
                        {
                            return(PermissionValue.Undefined);
                        }

                        // if there is any local only entry, the children decide to exit or move forward.
                        if (hasLocalOnly)
                        {
                            // move forward if the entity is a leaf (children is null)
                            if (descendantEntity.Children != null)
                            {
                                foreach (var childEntity in descendantEntity.Children)
                                {
                                    var value = GetPermissionSafe(userId, childEntity.Id, childEntity.OwnerId, permissions);
                                    // return if not allowed
                                    if (value != PermissionValue.Allowed)
                                    {
                                        return(value);
                                    }
                                    // move forward
                                }
                            }
                        }
                    }
                    // walk forward on the tree
                }
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
            return(PermissionValue.Allowed);
        }