Package org.jasig.portal.security.provider

Source Code of org.jasig.portal.security.provider.AnyUnblockedGrantPermissionPolicy

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a
* copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.jasig.portal.security.provider;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.portal.AuthorizationException;
import org.jasig.portal.groups.GroupsException;
import org.jasig.portal.groups.IGroupMember;
import org.jasig.portal.security.IAuthorizationPrincipal;
import org.jasig.portal.security.IAuthorizationService;
import org.jasig.portal.security.IPermission;
import org.jasig.portal.security.IPermissionPolicy;

/**
* If there exists a GRANT explicitly for the Principal for the Activity under consideration,
* this permission policy will GRANT permission.
*
*  If there exists a GRANT for a group containing the Principal for the Activity
*  under consideration, and there is a path up the groups tree from the Principal
*  to that GRANTed group that is not interrupted by a Deny for an intervening
*  group in the tree, then this permission policy will GRANT permission.
*
*  Otherwise, this permission policy will DENY permission.
*
*  Examples:
*  Principal (GRANT) -- Small group -- Bigger group -- Huge group
*  Results in GRANT because the Principal has an explicit permission.
*
*  Principal -- Small group -- Bigger group (GRANT) -- Huge group
*  Results in GRANT because there is an unblocked path to a containing group
*  with GRANT.
*
*  Principal -- Small group (DENY) -- Bigger group (GRANT) -- Huge group
*  Results in DENY because there is no unblocked path to a grant --
*  the "Bigger group"'s GRANT does not apply because of the intervening DENY.
*
*  Principal -- Small group (DENY) -- Bigger group -- Huge group
*  Principal -- Some other group -- Bigger other group (GRANT) -- Huge group
*  Results in GRANT because there is an unblocked path to a GRANT.
*/
public class AnyUnblockedGrantPermissionPolicy
    implements IPermissionPolicy {

    protected final Log log = LogFactory.getLog(getClass());
   

    public boolean doesPrincipalHavePermission(IAuthorizationService service, IAuthorizationPrincipal principal, String owner, String activity, String target) throws AuthorizationException {
        // the API states that the service, owner, and activity arguments must
        // not be null. If for some reason they are null, log and fail closed
        // The principal must also not be null.
        if (service == null || principal == null || owner == null || activity == null) {

            log.error("Null argument to AnyUnblockedGrantPermissionPolicy doesPrincipalHavePermission() method " +
                    "should not be possible.  This is indicative of a potentially serious bug in the " +
                    "permissions and authorization infrastructure. " +
                    "service= [" + service + "] principal = [" + principal + "] owner = [" + owner + "] activity = [" + activity + "] target = [" + target + "]");

            // fail closed
            return false;
        }

       
       
        // first check for explicit permissions for this Principal
        IPermission[] perms = service.getPermissionsForPrincipal(principal, owner, activity, target);

        Set<IPermission> activePermissions = activePermissions(perms);

        if (containsType(activePermissions, IPermission.PERMISSION_TYPE_DENY)) {
            if (log.isTraceEnabled()) {
              log.trace("Principal [" + principal + "] is explicitly denied permission to perform activity [" + activity + "] on target [" + target + "] under permission owning system [" + owner + "].");
            }
            return false;
        }

        if (containsType(activePermissions, IPermission.PERMISSION_TYPE_GRANT)) {
            // explicit GRANT
            if (log.isTraceEnabled()) {
              log.trace("Principal [" + principal + "] is granted permission to perform activity [" + activity + "] on target [" + target + "] under permission owning system [" + owner + "] because this principal has an excplicit GRANT and does not have an exlicit DENY.");
            }
            return true;
        }

        // no explicit permission.  Search for an unblocked GRANT.
        boolean hasUnblockedPathToGrant;
        try {
            // track groups we've already explored to avoid infinite loop
            Set<IGroupMember> seenGroups = new HashSet<IGroupMember>(100);
            hasUnblockedPathToGrant = hasUnblockedPathToGrant(service, principal, owner, activity, target, seenGroups);
        } catch (Exception e) {
            log.error("Error searching for unblocked path to grant for principal [" + principal + "]", e);
            // fail closed
            return false;
        }
       
        if (log.isTraceEnabled()) {
          if (hasUnblockedPathToGrant) {
            log.trace("Principal [" + principal + "] is granted permission to perform activity [" + activity + "] on target [" + target + "] under permission owning system [" + owner + "] because this principal has an unblocked path to a GRANT.");
          } else {
            log.trace("Principal [" + principal + "] is denied permission to perform activity [" + activity + "] on target [" + target + "] under permission owning system [" + owner + "] because this principal does not have an unblocked path to a GRANT.");
          }
        }
       
        return hasUnblockedPathToGrant;

    }

    private boolean hasUnblockedPathToGrant(IAuthorizationService service, IAuthorizationPrincipal principal, String owner, String activity, String target, Set<IGroupMember> seenGroups) throws GroupsException {

      if (log.isTraceEnabled()) {
        log.trace("Searching for unblocked path to GRANT for principal [" + principal + "] to [" + activity + "] on target [" + target + "] having already checked ["+ seenGroups + "]");
      }
     
        IGroupMember principalAsGroupMember = service.getGroupMember(principal);

        if (seenGroups.contains(principalAsGroupMember)) {
         
          if (log.isTraceEnabled()) {
            log.trace("Declining to re-examine principal [" + principal + "] for permission to [" + activity + "] on [" + target + "] because this group is among already checked groups [" + seenGroups + "]");
          }
         
            return false;
        }

        seenGroups.add(principalAsGroupMember);



        Iterator<IGroupMember> immediatelyContainingGroups = principalAsGroupMember.getContainingGroups();

        while (immediatelyContainingGroups.hasNext()) {
            IGroupMember parentGroup = immediatelyContainingGroups.next();
            try {
                if (parentGroup != null) {
                    IAuthorizationPrincipal parentPrincipal = service.newPrincipal( parentGroup );
                    IPermission[] parentPermissions = service.getPermissionsForPrincipal(parentPrincipal, owner, activity, target);

                    Set<IPermission> activeParentPermissions = activePermissions(parentPermissions);

                    boolean parentPermissionsContainsDeny = containsType(activeParentPermissions, IPermission.PERMISSION_TYPE_DENY);
                    boolean parentPermissionsContainsGrant = containsType(activeParentPermissions, IPermission.PERMISSION_TYPE_GRANT);

                    if (parentPermissionsContainsGrant && ! parentPermissionsContainsDeny) {
                        // there's a GRANT on this group to which we had an unblocked path, and
                        // there's no DENY on this group.
                     
                      if (log.isTraceEnabled()) {
                        log.trace("Found unblocked path to this permission set including a GRANT: [" + activeParentPermissions + "]");
                      }
                     
                        return true;
                    }

                    if (! parentPermissionsContainsDeny) {
                        // there's no blocking deny, so recursively check to see if the parent has an unblocked path to a grant


                        boolean parentHasUnblockedPathToGrant = hasUnblockedPathToGrant(service, parentPrincipal, owner, activity, target, seenGroups);
                        if (parentHasUnblockedPathToGrant) {
                            return true;
                        }


                        // parent didn't have a path to grant.  Fall through and try another parent if any
                    }


                }
            } catch (Exception e) {
                // problem evaluating this path, but let's not let it stop
                // us from exploring other paths.  Though a portion of the
                // group structure is broken, permission may be granted by
                // an unbroken portion
                log.error("Error evaluating permissions of parent group [" + parentGroup + "]", e);
            }

        }
        return false;
    }

    /**
     * Returns a Set containing those IPermission instances where the present
     * date is neither after the permission expiration if present nor before
     * the permission start date if present.
     * @param perms
     * @return potentially empty non-null Set of active permissions.
     */
    private Set<IPermission> activePermissions(final IPermission[] perms) {
        Date now = new Date();

        Set<IPermission> activePermissions = new HashSet<IPermission>(1);

        for (int i = 0; i < perms.length; i++) {
            IPermission p = perms[i];

            if (
                (p.getEffective() == null || ! p.getEffective().after(now))
                &&
                (p.getExpires() == null || p.getExpires().after(now))
               ) {

                activePermissions.add(p);


            }

        }

        return activePermissions;


    }

    /**
     * Returns true if a set of IPermission instances contains a permission of
     * the specified type.
     * False otherwise.
     * @param permissions
     * @return true if the set contains a permission of the sought type, false otherwise
     * @throws IllegalArgumentException if input set or type is null.
     */
    private boolean containsType(final Set<IPermission> permissions, final String soughtType) {

        if (permissions == null) {
            throw new IllegalArgumentException("Cannot check null set for contents.");
        }

        if (soughtType == null) {
            throw new IllegalArgumentException("Cannot search for type null.");
        }

        for (Iterator<IPermission> permissionIter = permissions.iterator(); permissionIter.hasNext(); ) {
            IPermission permission = permissionIter.next();

            if (permission != null && soughtType.equals(permission.getType())) {
                return true;
            }
        }

        return false;

    }

}
TOP

Related Classes of org.jasig.portal.security.provider.AnyUnblockedGrantPermissionPolicy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.