예제 #1
0
        // Copy the nodes of the first list. Note that the
        // list gets new nodes, but the Permissions aren't deep
        // copied. As long as we never directly expose a list,
        // and if the Permissions are treated as read only,
        // then this is OK.
        public PermissionList(PermissionList permList)

            : this()
        {
            if (permList == null || permList.m_head == null)
            {
                return;
            }

            // Assign head to a copy of the first node
            m_head = new PListNode(permList.m_head);

            // Use m_last to traverse list starting from head
            m_last = m_head;

            // While m_last isn't really the last, continue to
            // make copies of the original nodes that m_last.next points to.\
            // When we're done, m_last points to last of the copies.
            while (m_last.next != null)
            {
                m_last.next = new PListNode(m_last.next);
                m_last      = m_last.next;
            }

            // Copy how many elements there are.
            m_cElt = permList.m_cElt;
        }
        private PermissionList GetListForToken(PermissionToken permToken, bool create)
        {
            TokenBasedSet permSet;

            BCLDebug.Assert(permToken != null, "permToken != null");

            if (permToken.m_isUnrestricted)
            {
                permSet = m_unrestrictedPermSet;
            }
            else
            {
                permSet = m_normalPermSet;
            }

            PermissionList plist = (PermissionList)permSet.GetItem(permToken.m_index);

            if (plist == null && create)
            {
                plist = new PermissionList();
                permSet.SetItem(permToken.m_index, plist);
            }

            return(plist);
        }
예제 #3
0
        // Appends a PermissionList to the current list.
        // NOTE: Since AppendList does not make a copy of the parameter before
        // appending it, operations on the newly formed list also side-effect
        // the parameter. If this is not desired, make a copy of the parameter
        // before calling AppendList.
        public virtual void AppendList(PermissionList permList)
        {
            // Check for null
            if (permList == null)
            {
                return;
            }

            // If current list is empty, then DO NOT
            // append list, possibly adding Permissions!
            if (m_head == null)
            {
                return;
            }
            // Append list only if the last element of the current list does
            // not guarantee a failed check, thus stopping a walk.
            else if (!(m_last.type == MatchChecked && m_last.perm == null))
            {
                // Make sure there is something in the target
                // list to append.
                if (permList.m_head != null)
                {
                    // Stick the head of the target list to the end of
                    // the current list...
                    m_last.next = permList.m_head;

                    // The new last is the last of the target list...
                    m_last = permList.m_last;

                    // Add up the elements.
                    m_cElt += permList.m_cElt;
                }
            }
        }
예제 #4
0
        // Makes a copy of the list and a deep copy of all the permissions.
        public virtual PermissionList DeepPermissionCopy()
        {
            PermissionList nlist = new PermissionList();

            if (m_head == null)
            {
                return(nlist);
            }

            nlist.m_head = new PListNode(m_head.perm == null ? null : (CodeAccessPermission)m_head.perm.Copy(), m_head.type, m_head.next, m_head.prev);
            nlist.m_last = nlist.m_head;
            while (nlist.m_last.next != null)
            {
                nlist.m_last.next = new PListNode(nlist.m_last.next.perm == null ?
                                                  null :
                                                  (CodeAccessPermission)nlist.m_last.next.perm.Copy(),
                                                  nlist.m_last.next.type,
                                                  nlist.m_last.next.next,
                                                  nlist.m_last);
                nlist.m_last = nlist.m_last.next;
            }

            nlist.m_cElt = m_cElt;
            return(nlist);
        }
        internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList)
        {
            PermissionList zone = this.FindPermissionList(typeof(ZoneIdentityPermission));
            PermissionList url  = this.FindPermissionList(typeof(UrlIdentityPermission));

            IEnumerator enumerator;

            enumerator = new PermissionListEnumerator(zone);

            while (enumerator.MoveNext())
            {
                PListNode node = (PListNode)enumerator.Current;

                if (node.type == PermissionList.MatchChecked && node.perm != null)
                {
                    zoneList.Add(((ZoneIdentityPermission)node.perm).SecurityZone);
                }
            }

            enumerator = new PermissionListEnumerator(url);

            while (enumerator.MoveNext())
            {
                PListNode node = (PListNode)enumerator.Current;

                if (node.type == PermissionList.MatchChecked && node.perm != null)
                {
                    originList.Add(((UrlIdentityPermission)node.perm).Url);
                }
            }
        }
        /*
         * Helpers designed for stack compression
         */

        private void NullTerminateRest(int startIndex, int action)
        {
            for (int i = startIndex; i <= m_unrestrictedPermSet.GetMaxUsedIndex(); i++)
            {
                PermissionList plist = (PermissionList)m_unrestrictedPermSet.GetItem(i);
                if (plist != null)
                {
                    plist.AppendPermissionAndCompress(null, action);
                }
            }
        }
        public void AddPermission(CodeAccessPermission perm, int type)
        {
            //BCLDebug.Assert(type == MatchAssert || type == MatchDeny, "type == MatchAssert || type == MatchDeny");

            // can't get token if perm is null
            if (perm == null)
            {
                return;
            }

            PermissionToken permToken = PermissionToken.GetToken(perm);
            PermissionList  plist     = GetListForToken(permToken, true);

            plist.AppendPermission(perm, type);
        }
        public PermissionListSet(PermissionListSet permListSet)
        {
            if (permListSet == null)
            {
                Reset();
                return;
            }

            m_unrestrictedPermSet = new TokenBasedSet(permListSet.m_unrestrictedPermSet);

            // Now deep copy all permission lists in set.
            // Note that this DOES deep copy permissions in the list.
            for (int i = 0; i <= m_unrestrictedPermSet.GetMaxUsedIndex(); i++)
            {
                PermissionList plist = (PermissionList)m_unrestrictedPermSet.GetItem(i);
                if (plist != null)
                {
                    m_unrestrictedPermSet.SetItem(i, plist.Copy());
                }
            }

            m_normalPermSet = new TokenBasedSet(permListSet.m_normalPermSet);

            // Now deep copy all permission lists in set.
            // Note that this DOES deep copy permissions in the list.
            for (int i = 0; i <= m_normalPermSet.GetMaxUsedIndex(); i++)
            {
                PermissionList plist = (PermissionList)m_normalPermSet.GetItem(i);
                if (plist != null)
                {
                    m_normalPermSet.SetItem(i, plist.Copy());
                }
            }

            m_unrestricted = permListSet.m_unrestricted;
            m_state        = permListSet.m_state;
        }
예제 #9
0
     // Copy the nodes of the first list. Note that the
     // list gets new nodes, but the Permissions aren't deep
     // copied. As long as we never directly expose a list,
     // and if the Permissions are treated as read only,
     // then this is OK.
     public PermissionList(PermissionList permList)
     
         : this() {
         if (permList == null || permList.m_head == null)
             return;
 
         // Assign head to a copy of the first node
         m_head = new PListNode(permList.m_head);
 
         // Use m_last to traverse list starting from head
         m_last = m_head;
 
         // While m_last isn't really the last, continue to
         // make copies of the original nodes that m_last.next points to.\
         // When we're done, m_last points to last of the copies.
         while (m_last.next != null)
         {
             m_last.next = new PListNode(m_last.next);
             m_last = m_last.next;
         }
         
         // Copy how many elements there are.
         m_cElt = permList.m_cElt;
     }
        private void AppendStackHelper(TokenBasedSet thisSet, TokenBasedSet permSet, bool unrestrictedThisSet, bool unrestrictedPermSet, bool unrestricted)
        {
            int maxThis = thisSet.GetMaxUsedIndex();
            int maxPerm = permSet.GetMaxUsedIndex();

            int maxIndex = maxThis > maxPerm ? maxThis : maxPerm;

            for (int i = 0; i <= maxIndex; i++)
            {
                PermissionList plist      = (PermissionList)thisSet.GetItem(i);
                PermissionList appendList = (PermissionList)permSet.GetItem(i);
                if (plist != null)
                {
                    if (appendList != null)
                    {
                        // This call will not add the permission if the list is
                        // empty, or if the last element is a normal check with
                        // a null Permission. Let the method take care of it...
                        plist.AppendStack(appendList.Copy());
                    }
                    else
                    {
                        // Nothing on the compressed stack for this index,
                        // so terminate current list.
                        if (!unrestrictedPermSet)
                        {
                            plist.AppendPermissionAndCompress(null, PermissionList.MatchChecked);
                        }
                    }
                }
                else if (unrestrictedThisSet && appendList != null)
                {
                    thisSet.SetItem(i, appendList.Copy());
                }
            }
        }
예제 #11
0
 // Makes a copy of the list and a deep copy of all the permissions.
 public virtual PermissionList DeepPermissionCopy()
 {
     PermissionList nlist = new PermissionList();
     if (m_head == null)
         return nlist;
     
     nlist.m_head = new PListNode(m_head.perm == null ? null : (CodeAccessPermission)m_head.perm.Copy(), m_head.type, m_head.next);
     nlist.m_last = nlist.m_head;
     while (nlist.m_last.next != null)
     {
         nlist.m_last.next = new PListNode(nlist.m_last.next.perm == null ?
                                           null :
                                           (CodeAccessPermission)nlist.m_last.next.perm.Copy(),
                                           nlist.m_last.next.type,
                                           nlist.m_last.next.next);
         nlist.m_last = nlist.m_last.next;
     }
     
     nlist.m_cElt = m_cElt;
     return nlist;
 }
예제 #12
0
        public virtual void AppendStack(PermissionList permList)
        {
            // Check for null
            if (permList == null)
            {
                return;
            }

            // If current list is empty, then DO NOT
            // append list, possibly adding Permissions!
            if (m_head == null)
            {
                return;
            }
            else
            {
                // Make sure there is something in the target
                // list to append.
                if (permList.m_head != null)
                {
                    // If the last element of the current list and the first element of the
                    // appended list are both of type MatchChecked, then we can merge the
                    // entries together using intersect to conserve the number of entries
                    // in the final list.
                    if (m_last.type == MatchChecked && permList.m_head.type == MatchChecked)
                    {
                        // If the entries are non-null, then call Intersect.
                        if (m_last.perm != null && permList.m_head.perm != null)
                        {
                            m_last.perm = (CodeAccessPermission)m_last.perm.Intersect(permList.m_head.perm);
                        }
                        else
                        {
                            m_last.perm = null;
                        }

                        // If the last element is now null, then don't bother appending
                        // anything more. Also,
                        // if the combined element was the only element in the appended list,
                        // then there is nothing further to append. So, only do work to append
                        // if the m_head.next is non-null.
                        if (m_last.perm != null && permList.m_head.next != null)
                        {
                            // Stick the element after the head of the target list
                            // to the end of the current list...
                            m_last.next = permList.m_head.next;

                            // The new last is the last element of the target list...
                            m_last = permList.m_last;

                            // The new count is is the sum minus 1 to account for the
                            // merge performed above.
                            m_cElt += (permList.m_cElt - 1);
                        }
                    }
                    // Otherwise, append the list only if the last element is not a
                    // guaranteed failure during a stack walk: the type is Normal and
                    // it is null.
                    else if (!(m_last.type == MatchChecked && m_last.perm == null))
                    {
                        // Stick the head of the target list to the end of
                        // the current list...
                        m_last.next = permList.m_head;

                        // The new last is the last of the target list...
                        m_last = permList.m_last;

                        // Add up the elements.
                        m_cElt += permList.m_cElt;
                    }
                }
            }
        }
예제 #13
0
 internal PermissionListEnumerator(PermissionList list)
 {
     m_list = list;
     Reset();
 }
예제 #14
0
 public virtual void AppendStack(PermissionList permList)
 {
     // Check for null
     if (permList == null)
         return;
     
     // If current list is empty, then DO NOT
     // append list, possibly adding Permissions!
     if (m_head == null)
     {
         return;
     }
     else
     {
         // Make sure there is something in the target
         // list to append.
         if (permList.m_head != null)
         {
             // If the last element of the current list and the first element of the
             // appended list are both of type MatchChecked, then we can merge the
             // entries together using intersect to conserve the number of entries
             // in the final list.
             if (m_last.type == MatchChecked && permList.m_head.type == MatchChecked)
             {
                 // If the entries are non-null, then call Intersect.
                 if (m_last.perm != null && permList.m_head.perm != null)
                 {
                     m_last.perm = (CodeAccessPermission) m_last.perm.Intersect(permList.m_head.perm);
                 }
                 else
                 {
                     m_last.perm = null;
                 }
                 
                 // If the last element is now null, then don't bother appending
                 // anything more. Also,
                 // if the combined element was the only element in the appended list,
                 // then there is nothing further to append. So, only do work to append
                 // if the m_head.next is non-null.
                 if (m_last.perm != null && permList.m_head.next != null)
                 {
                     // Stick the element after the head of the target list
                     // to the end of the current list...
                     m_last.next = permList.m_head.next;
                     
                     // The new last is the last element of the target list...
                     m_last = permList.m_last;
                     
                     // The new count is is the sum minus 1 to account for the
                     // merge performed above.
                     m_cElt += (permList.m_cElt - 1);
                 }
             }
             // Otherwise, append the list only if the last element is not a
             // guaranteed failure during a stack walk: the type is Normal and
             // it is null.
             else if (! (m_last.type == MatchChecked && m_last.perm == null))
             {
                 // Stick the head of the target list to the end of
                 // the current list...
                 m_last.next = permList.m_head;
                 
                 // The new last is the last of the target list...
                 m_last = permList.m_last;
                 
                 // Add up the elements.
                 m_cElt += permList.m_cElt;
             }
         }
     }
 }
        internal bool CheckDemandInternal(CodeAccessPermission demand, PermissionToken permToken, bool createException, out Exception exception)
        {
            BCLDebug.Assert(demand != null, "demand != null");
            BCLDebug.Assert(permToken != null, "permToken != null");

            // First, find if there is a permission list of this type.

            PermissionList permList = FindPermissionList(permToken);

            if (permList != null)
            {
                // If so, check against it to determine our action.

                bool cont = permList.CheckDemandInternal(demand, createException, out exception);

                // We don't record modifiers for the unrestricted permission set in the
                // individual lists.  Therefore, permList.CheckDemandInternal may say
                // that we have to continue the stackwalk, but we know better.

                if (cont && permToken.m_isUnrestricted)
                {
                    if ((m_state & PermissionListSetState.UnrestrictedDeny) != 0)
                    {
                        if (createException)
                        {
                            exception = new SecurityException(String.Format(Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName));
                        }
                        else
                        {
                            exception = GetStaticException();
                        }
                        return(false);
                    }
                    else
                    {
                        cont = cont && ((m_state & PermissionListSetState.UnrestrictedAssert) == 0);
                    }
                }

                return(cont);
            }
#if _DEBUG
            // Let's check to make sure we always pass demands for empty permissions.

            else if (demand.IsSubsetOf(null))
            {
                BCLDebug.Assert(false, "We should pick of empty demands before this point");
                exception = null;
                return(true);
            }
#endif
            // If the permission is not unrestricted, the lack of a permission list
            // denotes that no frame on the stack granted this permission, and therefore
            // we pass back the failure condition.

            else if (!permToken.m_isUnrestricted)
            {
                if (createException)
                {
                    exception = new SecurityException(String.Format(Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName));
                }
                else
                {
                    exception = GetStaticException();
                }
                return(false);
            }

            // If this permission list set is not unrestricted and there is no unrestricted assert
            // then the lack of a permission list denotes that no frame on the stack granted
            // this permission, and therefore we pass back the failure condition.  If there is
            // an unrestricted assert, then we pass back success and terminate the stack walk.

            else if (!this.IsUnrestricted())
            {
                if (createException)
                {
                    exception = new SecurityException(String.Format(Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName));
                }
                else
                {
                    exception = GetStaticException();
                }
                return(false);
            }

            // If we made it all the way through, that means that we are in the unrestricted
            // state and that this permission is encompassed in that.  If we have an unrestricted
            // assert, we are done with the state walk (return false), otherwise keep going.

            exception = null;
            return((m_state & PermissionListSetState.UnrestrictedAssert) == 0);
        }
예제 #16
0
 private PermissionList GetListForToken(PermissionToken permToken, bool create)
 {
     TokenBasedSet permSet;
     
     BCLDebug.Assert(permToken != null, "permToken != null");
     
     if (permToken.m_isUnrestricted)
         permSet = m_unrestrictedPermSet;
     else
         permSet = m_normalPermSet;
     
     PermissionList plist = (PermissionList)permSet.GetItem(permToken.m_index);
     if (plist == null && create)
     {
         plist = new PermissionList();
         permSet.SetItem(permToken.m_index, plist);
     }
     
     return plist;
 }
        private void AppendTokenBasedSets(TokenBasedSet thisSet, TokenBasedSet permSet, int type, bool unrestricted)
        {
            int thisMaxIndex = thisSet.GetMaxUsedIndex();
            int permMaxIndex = permSet == null ? 0 : permSet.GetMaxUsedIndex();
            int maxIndex     = thisMaxIndex > permMaxIndex ? thisMaxIndex : permMaxIndex;

            // Loop over the relevant indexes...
            for (int i = 0; i <= maxIndex; i++)
            {
                PermissionList       plist = (PermissionList)thisSet.GetItem(i);
                CodeAccessPermission cap   = permSet == null ? null : (CodeAccessPermission)permSet.GetItem(i);

                if (plist == null)
                {
                    if (this.m_unrestricted)
                    {
                        switch (type)
                        {
                        case PermissionList.MatchChecked:
                        case PermissionList.MatchPermitOnly:
                            plist = new PermissionList();
                            plist.AppendPermission(cap, type);
                            thisSet.SetItem(i, plist);
                            break;

                        case PermissionList.MatchDeny:
                        case PermissionList.MatchAssert:
                            if (cap != null)
                            {
                                plist = new PermissionList();
                                plist.AppendPermission(cap, type);
                                thisSet.SetItem(i, plist);
                            }
                            break;

                        default:
                            throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionListType"));
                        }
                    }
                }
                else
                {
                    // A list already exists. All lists should have at least
                    // one element in them.

                    // Normally, only append if the permission is not null.
                    // However, if the type is Checked, then make sure the
                    // list is terminated with a permission, null or not.
                    switch (type)
                    {
                    case PermissionList.MatchChecked:
                    case PermissionList.MatchPermitOnly:
                        plist.AppendPermissionAndCompress(cap, type);
                        break;

                    case PermissionList.MatchDeny:
                    case PermissionList.MatchAssert:
                        if (cap != null)
                        {
                            plist.AppendPermissionAndCompress(cap, type);
                        }
                        break;

                    default:
                        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionListType"));
                    }
                }
            }
        }
        private static bool CheckTokenBasedSets(TokenBasedSet thisSet, TokenBasedSet permSet, bool unrestricted, PermissionListSetState state, bool createException, out Exception exception, bool bNeedAlteredSet, out TokenBasedSet alteredSet)
        {
            alteredSet = null;

            // If the set is empty, there is no reason to walk the
            // stack.

            if (permSet == null || permSet.FastIsEmpty())
            {
                if (bNeedAlteredSet)
                {
                    alteredSet = new TokenBasedSet(1, 4);
                }
                exception = null;
                return(false);
            }

            int permMaxIndex = permSet.GetMaxUsedIndex();

            // Make a quick check to see if permSet definitely contains permissions that this set doesn't

            if (permMaxIndex > thisSet.GetMaxUsedIndex())
            {
                // The only way we don't want to throw an exception is
                // if we are unrestricted.  Then, if we don't want to throw
                // an exception we may want to terminate the stack walk
                // based on an unrestricted assert.

                if (unrestricted)
                {
                    if (((state & PermissionListSetState.UnrestrictedAssert) != 0))
                    {
                        if (bNeedAlteredSet)
                        {
                            alteredSet = new TokenBasedSet(1, 4);
                        }
                        exception = null;
                        return(false);
                    }
                    else
                    {
                        exception = null;
                        return(true);
                    }
                }
                else
                {
                    if (createException)
                    {
                        exception = new SecurityException(Environment.GetResourceString("Security_GenericNoType"));
                    }
                    else
                    {
                        exception = GetStaticException();
                    }
                    return(false);
                }
            }


            bool continueStackWalk = false;

            // We know that checking to <permMaxIndex> is sufficient because of above check
            for (int i = 0; i <= permMaxIndex; i++)
            {
                Object obj = permSet.GetItem(i);

                if (obj != null)
                {
                    CodeAccessPermission cap = (CodeAccessPermission)obj;

                    PermissionList permList = (PermissionList)thisSet.GetItem(i);

                    if (permList != null)
                    {
                        bool tempContinue = permList.CheckDemandInternal(cap, createException, out exception);

                        if (exception != null)
                        {
                            return(false);
                        }

                        if (tempContinue)
                        {
                            // If we are supposed to continue the stack walk but there is an unrestricted
                            // deny, then we should fail.

                            if (((state & PermissionListSetState.UnrestrictedDeny) != 0) && (cap is IUnrestrictedPermission))
                            {
                                if (createException)
                                {
                                    exception = new SecurityException(String.Format(Environment.GetResourceString("Security_Generic"), cap.GetType().AssemblyQualifiedName));
                                }
                                else
                                {
                                    exception = GetStaticException();
                                }
                                return(false);
                            }

                            continueStackWalk = true;
                        }
                        else if (((state & PermissionListSetState.UnrestrictedAssert) == 0) && (cap is IUnrestrictedPermission))
                        {
                            // We only want to build the altered set if we don't have an
                            // unrestricted assert because we know if we have an unrestricted
                            // assert and we don't throw an exception that the stackwalk should
                            // include no unrestricted permissions.

                            if (bNeedAlteredSet)
                            {
                                if (alteredSet == null)
                                {
                                    alteredSet = CopyTokenBasedSet(permSet);
                                }

                                alteredSet.SetItem(i, null);
                            }
                        }
                    }
                    else
                    {
                        if (!unrestricted)
                        {
                            if (createException)
                            {
                                exception = new SecurityException(String.Format(Environment.GetResourceString("Security_Generic"), cap.GetType().AssemblyQualifiedName));
                            }
                            else
                            {
                                exception = GetStaticException();
                            }
                            return(false);
                        }
                    }
                }
            }

            exception = null;
            return(continueStackWalk);
        }
예제 #19
0
     private void AppendTokenBasedSets( TokenBasedSet thisSet, TokenBasedSet permSet, int type, bool unrestricted )
     {
         int thisMaxIndex = thisSet.GetMaxUsedIndex();
         int permMaxIndex = permSet == null ? 0 : permSet.GetMaxUsedIndex();
         int maxIndex = thisMaxIndex > permMaxIndex ? thisMaxIndex : permMaxIndex;
         
         // Loop over the relevant indexes...
         for (int i = 0; i <= maxIndex; i++)
         {
             PermissionList plist = (PermissionList)thisSet.GetItem(i);
             CodeAccessPermission cap = permSet == null ? null : (CodeAccessPermission)permSet.GetItem(i);
             
             if (plist == null)
             {
                 if (this.m_unrestricted)
                 {
                     switch (type)
                     {
                     case PermissionList.MatchChecked:
                     case PermissionList.MatchPermitOnly:
                         plist = new PermissionList();
                         plist.AppendPermission(cap, type);
                         thisSet.SetItem( i, plist );
                         break;
                     
                     case PermissionList.MatchDeny:
                     case PermissionList.MatchAssert:
                         if (cap != null)
                         {
                             plist = new PermissionList();
                             plist.AppendPermission(cap, type);
                             thisSet.SetItem( i, plist );
                         }
                         break;
                     
                     default:
                         throw new ArgumentException(Environment.GetResourceString( "Argument_InvalidPermissionListType" ));
                     }
                 }
             }
             else
             {                    
                 // A list already exists. All lists should have at least
                 // one element in them.
 
                 // Normally, only append if the permission is not null.
                 // However, if the type is Checked, then make sure the
                 // list is terminated with a permission, null or not.
                 switch (type)
                 {
                 case PermissionList.MatchChecked:
                 case PermissionList.MatchPermitOnly:
                     plist.AppendPermissionAndCompress(cap, type);
                     break;
                         
                 case PermissionList.MatchDeny:
                 case PermissionList.MatchAssert:
                     if (cap != null)
                         plist.AppendPermissionAndCompress(cap, type);
                     break;
                         
                 default:
                     throw new ArgumentException(Environment.GetResourceString( "Argument_InvalidPermissionListType" ));
                 }
             }
         }
     }
예제 #20
0
     // Appends a PermissionList to the current list.
     // NOTE: Since AppendList does not make a copy of the parameter before
     // appending it, operations on the newly formed list also side-effect
     // the parameter. If this is not desired, make a copy of the parameter
     // before calling AppendList.
     public virtual void AppendList(PermissionList permList)
     {
         // Check for null
         if (permList == null)
             return;
 
         // If current list is empty, then DO NOT
         // append list, possibly adding Permissions!
         if (m_head == null)
         {
             return;
         }
         // Append list only if the last element of the current list does
         // not guarantee a failed check, thus stopping a walk.
         else if (! (m_last.type == MatchChecked && m_last.perm == null))
         {
             // Make sure there is something in the target
             // list to append.
             if (permList.m_head != null)
             {
                 // Stick the head of the target list to the end of
                 // the current list...
                 m_last.next = permList.m_head;
                 
                 // The new last is the last of the target list...
                 m_last = permList.m_last;
                 
                 // Add up the elements.
                 m_cElt += permList.m_cElt;
             }
         }
     }