001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.acls.domain;
017:
018: import org.acegisecurity.AccessDeniedException;
019: import org.acegisecurity.Authentication;
020: import org.acegisecurity.GrantedAuthority;
021:
022: import org.acegisecurity.acls.Acl;
023: import org.acegisecurity.acls.Permission;
024: import org.acegisecurity.acls.sid.PrincipalSid;
025: import org.acegisecurity.acls.sid.Sid;
026: import org.acegisecurity.acls.sid.SidRetrievalStrategy;
027: import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl;
028:
029: import org.acegisecurity.context.SecurityContextHolder;
030:
031: import org.springframework.util.Assert;
032:
033: /**
034: * Default implementation of {@link AclAuthorizationStrategy}.<p>Permission will be granted provided the current
035: * principal is either the owner (as defined by the ACL), has {@link BasePermission#ADMINISTRATION} (as defined by the
036: * ACL and via a {@link Sid} retrieved for the current principal via {@link #sidRetrievalStrategy}), or if the current
037: * principal holds the relevant system-wide {@link GrantedAuthority} and injected into the constructor.</p>
038: *
039: * @author Ben Alex
040: * @version $Id: AclAuthorizationStrategyImpl.java 1784 2007-02-24 21:00:24Z luke_t $
041: */
042: public class AclAuthorizationStrategyImpl implements
043: AclAuthorizationStrategy {
044: //~ Instance fields ================================================================================================
045:
046: private GrantedAuthority gaGeneralChanges;
047: private GrantedAuthority gaModifyAuditing;
048: private GrantedAuthority gaTakeOwnership;
049: private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
050:
051: //~ Constructors ===================================================================================================
052:
053: /**
054: * Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that
055: * can be held to always permit ACL changes.
056: *
057: * @param auths an array of <code>GrantedAuthority</code>s that have
058: * special permissions (index 0 is the authority needed to change
059: * ownership, index 1 is the authority needed to modify auditing details,
060: * index 2 is the authority needed to change other ACL and ACE details) (required)
061: */
062: public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) {
063: Assert.notEmpty(auths,
064: "GrantedAuthority[] with three elements required");
065: Assert.isTrue(auths.length == 3,
066: "GrantedAuthority[] with three elements required");
067: this .gaTakeOwnership = auths[0];
068: this .gaModifyAuditing = auths[1];
069: this .gaGeneralChanges = auths[2];
070: }
071:
072: //~ Methods ========================================================================================================
073:
074: public void securityCheck(Acl acl, int changeType) {
075: if ((SecurityContextHolder.getContext() == null)
076: || (SecurityContextHolder.getContext()
077: .getAuthentication() == null)
078: || !SecurityContextHolder.getContext()
079: .getAuthentication().isAuthenticated()) {
080: throw new AccessDeniedException(
081: "Authenticated principal required to operate with ACLs");
082: }
083:
084: Authentication authentication = SecurityContextHolder
085: .getContext().getAuthentication();
086:
087: // Check if authorized by virtue of ACL ownership
088: Sid currentUser = new PrincipalSid(authentication);
089:
090: if (currentUser.equals(acl.getOwner())
091: && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
092: return;
093: }
094:
095: // Not authorized by ACL ownership; try via adminstrative permissions
096: GrantedAuthority requiredAuthority = null;
097:
098: if (changeType == CHANGE_AUDITING) {
099: requiredAuthority = this .gaModifyAuditing;
100: } else if (changeType == CHANGE_GENERAL) {
101: requiredAuthority = this .gaGeneralChanges;
102: } else if (changeType == CHANGE_OWNERSHIP) {
103: requiredAuthority = this .gaTakeOwnership;
104: } else {
105: throw new IllegalArgumentException("Unknown change type");
106: }
107:
108: // Iterate this principal's authorities to determine right
109: GrantedAuthority[] auths = authentication.getAuthorities();
110:
111: for (int i = 0; i < auths.length; i++) {
112: if (requiredAuthority.equals(auths[i])) {
113: return;
114: }
115: }
116:
117: // Try to get permission via ACEs within the ACL
118: Sid[] sids = sidRetrievalStrategy.getSids(authentication);
119:
120: if (acl.isGranted(
121: new Permission[] { BasePermission.ADMINISTRATION },
122: sids, false)) {
123: return;
124: }
125:
126: throw new AccessDeniedException(
127: "Principal does not have required ACL permissions to perform requested operation");
128: }
129:
130: public void setSidRetrievalStrategy(
131: SidRetrievalStrategy sidRetrievalStrategy) {
132: Assert.notNull(sidRetrievalStrategy,
133: "SidRetrievalStrategy required");
134: this.sidRetrievalStrategy = sidRetrievalStrategy;
135: }
136: }
|