/* * (c) 2008- RANDI2 Core Development Team * * This file is part of RANDI2. * * RANDI2 is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * RANDI2 is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * RANDI2. If not, see <http://www.gnu.org/licenses/>. */ package de.randi2.model.security; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Transient; import lombok.Data; import org.springframework.security.acls.model.AccessControlEntry; import org.springframework.security.acls.model.Acl; import org.springframework.security.acls.model.NotFoundException; import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Sid; import org.springframework.security.acls.model.UnloadedSidException; import org.springframework.util.Assert; import edu.umd.cs.findbugs.annotations.SuppressWarnings; @Entity @NamedQuery(name = "acl.findAclByObjectIdentityAndSid", query = "select acl from AclHibernate acl where acl.owner.sidname = ? and acl.objectIdentity.identifier = ? and acl.objectIdentity.type = ?") @Data @SuppressWarnings public class AclHibernate implements Acl, Serializable { private static final long serialVersionUID = 253176536526673664L; @Id @GeneratedValue(strategy = GenerationType.TABLE) private long id; @ManyToOne(targetEntity = AclHibernate.class) private Acl parentAcl; @ManyToOne(cascade = CascadeType.ALL) private ObjectIdentityHibernate objectIdentity; @OneToMany(mappedBy = "acl", fetch = FetchType.EAGER, cascade = CascadeType.ALL) private List<AccessControlEntryHibernate> aces = new ArrayList<AccessControlEntryHibernate>(); @ManyToOne private SidHibernate owner; private boolean entriesInheriting = true; //private String roleName; @Transient private Sid[] loadedSids = null; @Override public List<AccessControlEntry> getEntries() { return new ArrayList<AccessControlEntry>(aces); } @Override public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(sids, "SIDs required"); if (!this.isSidLoaded(sids)) { throw new UnloadedSidException("ACL was not loaded for one or more SID"); } AccessControlEntry firstRejection = null; for (int i = 0; i < permission.size(); i++) { for (int x = 0; x < sids.size(); x++) { // Attempt to find exact match for this permission mask and SID Iterator<AccessControlEntryHibernate> acesIterator = aces.iterator(); boolean scanNextSid = true; while (acesIterator.hasNext()) { AccessControlEntry ace = acesIterator.next(); if ((ace.getPermission().getMask() == permission.get(i).getMask()) && ace.getSid().equals(sids.get(x))) { // Found a matching ACE, so its authorization decision will prevail if (ace.isGranting()) { // Success //if (!administrativeMode) { // auditLogger.logIfNeeded(true, ace); //} return true; } else { // Failure for this permission, so stop search // We will see if they have a different permission // (this permission is 100% rejected for this SID) if (firstRejection == null) { // Store first rejection for auditing reasons firstRejection = ace; } scanNextSid = false; // helps break the loop break; // exit "aceIterator" while loop } } } if (!scanNextSid) { break; // exit SID for loop (now try next permission) } } } if (firstRejection != null) { // We found an ACE to reject the request at this point, as no // other ACEs were found that granted a different permission //if (!administrativeMode) { // auditLogger.logIfNeeded(false, firstRejection); //} return false; } // No matches have been found so far if (isEntriesInheriting() && (parentAcl != null)) { // We have a parent, so let them try to find a matching ACE return parentAcl.isGranted(permission, sids, false); } else { // We either have no parent, or we're the uppermost parent throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs"); } } @Override public boolean isSidLoaded(List<Sid> sids) { // If loadedSides is null, this indicates all SIDs were loaded // Also return true if the caller didn't specify a SID to find if ((this.loadedSids == null) || (sids == null) || (sids.size() == 0)) { return true; } // This ACL applies to a SID subset only. Iterate to check it applies. for (Sid sid : sids) { boolean found = false; for (int y = 0; y < this.loadedSids.length; y++) { if (sid.equals(this.loadedSids[y])) { // this SID is OK found = true; break; // out of loadedSids for loop } } if (!found) { return false; } } return true; } public void insertAce(PermissionHibernate permission, String roleName) { AccessControlEntryHibernate ace = new AccessControlEntryHibernate(); ace.setAcl(this); ace.setPermission(permission); ace.setSid(owner); ace.setRoleName(roleName); aces.add(ace); } }