예제 #1
0
 /// <summary>
 /// Determines whether this instance equals another (by value).
 /// </summary>
 /// <param name="other">The other instance.</param>
 /// <returns><c>true</c> if this instance equals <b>other</b>, <c>false</c> otherwise.</returns>
 public bool Equals(AclEntry other)
 {
     if (other is null)
     {
         return(false);
     }
     else
     {
         return(Resource == other.Resource && Action == other.Action && Subject == other.Subject);
     }
 }
예제 #2
0
 /// <summary>
 /// Determines whether two instances of <see cref="T:AclEntry" /> are equal (by value).
 /// </summary>
 /// <param name="x">The first instance.</param>
 /// <param name="y">The second instance.</param>
 /// <returns><c>true</c> if <b>x</b> equals <b>y</b>, <c>false</c> otherwise.</returns>
 public static bool Equals(AclEntry x, AclEntry y)
 {
     if (x is null && !(x is null))
     {
         return(false);
     }
     if (!(x is null) && x is null)
     {
         return(false);
     }
     if (x is null && x is null)
     {
         return(true);
     }
     return(x.Equals(y));
 }
예제 #3
0
        /// <summary>
        /// Deletes an ACL entry.
        /// </summary>
        /// <param name="resource">The controlled resource.</param>
        /// <param name="action">The action on the controlled resource.</param>
        /// <param name="subject">The subject whose access to the resource/action is controlled.</param>
        /// <returns><c>true</c> if the entry is deleted, <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="resource"/>, <paramref name="action"/> or <paramref name="subject"/> are <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="resource"/>, <paramref name="action"/> or <paramref name="subject"/> are empty.</exception>
        public bool DeleteEntry(string resource, string action, string subject)
        {
            if (resource == null)
            {
                throw new ArgumentNullException("resource");
            }
            if (resource.Length == 0)
            {
                throw new ArgumentException("Resource cannot be empty.", "resource");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            if (action.Length == 0)
            {
                throw new ArgumentException("Action cannot be empty.", "action");
            }
            if (subject == null)
            {
                throw new ArgumentNullException("subject");
            }
            if (subject.Length == 0)
            {
                throw new ArgumentException("Subject cannot be empty.", "subject");
            }

            AclEntry result = new AclEntry(resource, action, subject, Value.Deny);

            lock (this)
            {
                int index = _entries.FindIndex(delegate(AclEntry x) { return(AclEntry.Equals(x, result)); });
                if (index >= 0)
                {
                    AclEntry entry = _entries[index];
                    _entries.RemoveAt(index);
                    OnAclChanged(new AclEntry[] { entry }, Change.EntryDeleted);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Decides whether a user, member of some groups, is authorized to perform an action on a resource.
        /// </summary>
        /// <param name="resource">The resource.</param>
        /// <param name="action">The action on the resource.</param>
        /// <param name="user">The user, in the form 'U.Name'.</param>
        /// <param name="groups">The groups the user is member of, in the form 'G.Name'.</param>
        /// <param name="entries">The available ACL entries for the resource.</param>
        /// <returns>The positive, negative, or indeterminate result.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="resource"/>, <paramref name="action"/>, <paramref name="user"/>, <paramref name="groups"/> or <paramref name="entries"/> are <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="resource"/>, <paramref name="action"/>, <paramref name="user"/> are empty, or if <paramref name="action"/> equals <see cref="AclEntry.FullControlAction"/>.</exception>
        public static Authorization AuthorizeAction(string resource, string action, string user, string[] groups, AclEntry[] entries)
        {
            if (resource == null)
            {
                throw new ArgumentNullException("resource");
            }
            if (resource.Length == 0)
            {
                throw new ArgumentException("Resource cannot be empty.", "resource");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            if (action.Length == 0)
            {
                throw new ArgumentException("Action cannot be empty.", "action");
            }
            if (action == AclEntry.FullControlAction)
            {
                throw new ArgumentException("Action cannot be the FullControl flag.", "action");
            }
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }
            if (user.Length == 0)
            {
                throw new ArgumentException("User cannot be empty.", "user");
            }
            if (groups == null)
            {
                throw new ArgumentNullException("groups");
            }
            if (entries == null)
            {
                throw new ArgumentNullException("entries");
            }

            // Simple ACL model
            // Sort entries so that FullControl ones are at the bottom
            // First look for an entry specific for the user
            // If not found, look for a group that denies the permission

            AclEntry[] sortedEntries = new AclEntry[entries.Length];
            Array.Copy(entries, sortedEntries, entries.Length);

            Array.Sort(sortedEntries, delegate(AclEntry x, AclEntry y)
            {
                return(x.Action.CompareTo(y.Action));
            });
            Array.Reverse(sortedEntries);

            foreach (AclEntry entry in sortedEntries)
            {
                if (entry.Resource == resource && (entry.Action == action || entry.Action == AclEntry.FullControlAction) && entry.Subject == user)
                {
                    if (entry.Value == Value.Grant)
                    {
                        return(Authorization.Granted);
                    }
                    else if (entry.Value == Value.Deny)
                    {
                        return(Authorization.Denied);
                    }
                    else
                    {
                        throw new NotSupportedException("Entry value not supported.");
                    }
                }
            }

            // For each group, a decision is made
            Dictionary <string, bool> groupFullControlGrant = new Dictionary <string, bool>();
            Dictionary <string, bool> groupExplicitGrant    = new Dictionary <string, bool>();
            Dictionary <string, bool> groupFullControlDeny  = new Dictionary <string, bool>();

            foreach (string group in groups)
            {
                foreach (AclEntry entry in entries)
                {
                    if (entry.Resource == resource && entry.Subject == group)
                    {
                        if (!groupFullControlGrant.ContainsKey(group))
                        {
                            groupFullControlGrant.Add(group, false);
                            groupExplicitGrant.Add(group, false);
                            groupFullControlDeny.Add(group, false);
                        }

                        if (entry.Action == action)
                        {
                            // Explicit action
                            if (entry.Value == Value.Grant)
                            {
                                // An explicit grant only wins if there are no other explicit deny
                                groupExplicitGrant[group] = true;
                            }
                            else if (entry.Value == Value.Deny)
                            {
                                // An explicit deny wins over all other entries
                                return(Authorization.Denied);
                            }
                        }
                        else if (entry.Action == AclEntry.FullControlAction)
                        {
                            // Full control, lower priority
                            if (entry.Value == Value.Deny)
                            {
                                groupFullControlDeny[group] = true;
                            }
                            else if (entry.Value == Value.Grant)
                            {
                                groupFullControlGrant[group] = true;
                            }
                        }
                    }
                }
            }

            // Any explicit grant found at this step wins, because all explicit deny have been processed previously
            bool tentativeGrant = false;
            bool tentativeDeny  = false;

            foreach (string group in groupFullControlGrant.Keys)
            {
                if (groupExplicitGrant[group])
                {
                    return(Authorization.Granted);
                }

                if (groupFullControlGrant[group] && !groupFullControlDeny[group])
                {
                    tentativeGrant = true;
                }
                if (!groupFullControlGrant[group] && groupFullControlDeny[group])
                {
                    tentativeDeny = true;
                }
            }
            if (tentativeGrant && !tentativeDeny)
            {
                return(Authorization.Granted);
            }
            else if (tentativeDeny)
            {
                return(Authorization.Denied);
            }
            else
            {
                return(Authorization.Unknown);
            }
        }