|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.acl; |
|
|
|
import java.io.*; |
|
import java.util.*; |
|
import java.security.Principal; |
|
import java.security.acl.*; |
|
|
|
|
|
|
|
|
|
*/ |
|
public class AclImpl extends OwnerImpl implements Acl { |
|
// |
|
// Maintain four tables. one each for positive and negative |
|
// ACLs. One each depending on whether the entity is a group |
|
// or principal. |
|
|
|
private Hashtable<Principal, AclEntry> allowedUsersTable = |
|
new Hashtable<>(23); |
|
private Hashtable<Principal, AclEntry> allowedGroupsTable = |
|
new Hashtable<>(23); |
|
private Hashtable<Principal, AclEntry> deniedUsersTable = |
|
new Hashtable<>(23); |
|
private Hashtable<Principal, AclEntry> deniedGroupsTable = |
|
new Hashtable<>(23); |
|
private String aclName = null; |
|
private Vector<Permission> zeroSet = new Vector<>(1,1); |
|
|
|
|
|
|
|
|
|
*/ |
|
public AclImpl(Principal owner, String name) { |
|
super(owner); |
|
try { |
|
setName(owner, name); |
|
} catch (Exception e) {} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setName(Principal caller, String name) |
|
throws NotOwnerException |
|
{ |
|
if (!isOwner(caller)) |
|
throw new NotOwnerException(); |
|
|
|
aclName = name; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String getName() { |
|
return aclName; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized boolean addEntry(Principal caller, AclEntry entry) |
|
throws NotOwnerException |
|
{ |
|
if (!isOwner(caller)) |
|
throw new NotOwnerException(); |
|
|
|
Hashtable<Principal, AclEntry> aclTable = findTable(entry); |
|
Principal key = entry.getPrincipal(); |
|
|
|
if (aclTable.get(key) != null) |
|
return false; |
|
|
|
aclTable.put(key, entry); |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized boolean removeEntry(Principal caller, AclEntry entry) |
|
throws NotOwnerException |
|
{ |
|
if (!isOwner(caller)) |
|
throw new NotOwnerException(); |
|
|
|
Hashtable<Principal, AclEntry> aclTable = findTable(entry); |
|
Principal key = entry.getPrincipal(); |
|
|
|
AclEntry o = aclTable.remove(key); |
|
return (o != null); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized Enumeration<Permission> getPermissions(Principal user) { |
|
|
|
Enumeration<Permission> individualPositive; |
|
Enumeration<Permission> individualNegative; |
|
Enumeration<Permission> groupPositive; |
|
Enumeration<Permission> groupNegative; |
|
|
|
// |
|
// canonicalize the sets. That is remove common permissions from |
|
// positive and negative sets. |
|
|
|
groupPositive = |
|
subtract(getGroupPositive(user), getGroupNegative(user)); |
|
groupNegative = |
|
subtract(getGroupNegative(user), getGroupPositive(user)); |
|
individualPositive = |
|
subtract(getIndividualPositive(user), getIndividualNegative(user)); |
|
individualNegative = |
|
subtract(getIndividualNegative(user), getIndividualPositive(user)); |
|
|
|
// |
|
// net positive permissions is individual positive permissions |
|
// plus (group positive - individual negative). |
|
|
|
Enumeration<Permission> temp1 = |
|
subtract(groupPositive, individualNegative); |
|
Enumeration<Permission> netPositive = |
|
union(individualPositive, temp1); |
|
|
|
// recalculate the enumeration since we lost it in performing the |
|
// subtraction |
|
|
|
individualPositive = |
|
subtract(getIndividualPositive(user), getIndividualNegative(user)); |
|
individualNegative = |
|
subtract(getIndividualNegative(user), getIndividualPositive(user)); |
|
|
|
// |
|
// net negative permissions is individual negative permissions |
|
// plus (group negative - individual positive). |
|
|
|
temp1 = subtract(groupNegative, individualPositive); |
|
Enumeration<Permission> netNegative = union(individualNegative, temp1); |
|
|
|
return subtract(netPositive, netNegative); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean checkPermission(Principal principal, Permission permission) |
|
{ |
|
Enumeration<Permission> permSet = getPermissions(principal); |
|
while (permSet.hasMoreElements()) { |
|
Permission p = permSet.nextElement(); |
|
if (p.equals(permission)) |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public synchronized Enumeration<AclEntry> entries() { |
|
return new AclEnumerator(this, |
|
allowedUsersTable, allowedGroupsTable, |
|
deniedUsersTable, deniedGroupsTable); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String toString() { |
|
StringBuffer sb = new StringBuffer(); |
|
Enumeration<AclEntry> entries = entries(); |
|
while (entries.hasMoreElements()) { |
|
AclEntry entry = entries.nextElement(); |
|
sb.append(entry.toString().trim()); |
|
sb.append("\n"); |
|
} |
|
|
|
return sb.toString(); |
|
} |
|
|
|
// |
|
// Find the table that this entry belongs to. There are 4 |
|
// tables that are maintained. One each for postive and |
|
// negative ACLs and one each for groups and users. |
|
// This method figures out which |
|
// table is the one that this AclEntry belongs to. |
|
|
|
private Hashtable<Principal, AclEntry> findTable(AclEntry entry) { |
|
Hashtable<Principal, AclEntry> aclTable = null; |
|
|
|
Principal p = entry.getPrincipal(); |
|
if (p instanceof Group) { |
|
if (entry.isNegative()) |
|
aclTable = deniedGroupsTable; |
|
else |
|
aclTable = allowedGroupsTable; |
|
} else { |
|
if (entry.isNegative()) |
|
aclTable = deniedUsersTable; |
|
else |
|
aclTable = allowedUsersTable; |
|
} |
|
return aclTable; |
|
} |
|
|
|
// |
|
// returns the set e1 U e2. |
|
|
|
private static Enumeration<Permission> union(Enumeration<Permission> e1, |
|
Enumeration<Permission> e2) { |
|
Vector<Permission> v = new Vector<>(20, 20); |
|
|
|
while (e1.hasMoreElements()) |
|
v.addElement(e1.nextElement()); |
|
|
|
while (e2.hasMoreElements()) { |
|
Permission o = e2.nextElement(); |
|
if (!v.contains(o)) |
|
v.addElement(o); |
|
} |
|
|
|
return v.elements(); |
|
} |
|
|
|
// |
|
// returns the set e1 - e2. |
|
|
|
private Enumeration<Permission> subtract(Enumeration<Permission> e1, |
|
Enumeration<Permission> e2) { |
|
Vector<Permission> v = new Vector<>(20, 20); |
|
|
|
while (e1.hasMoreElements()) |
|
v.addElement(e1.nextElement()); |
|
|
|
while (e2.hasMoreElements()) { |
|
Permission o = e2.nextElement(); |
|
if (v.contains(o)) |
|
v.removeElement(o); |
|
} |
|
|
|
return v.elements(); |
|
} |
|
|
|
private Enumeration<Permission> getGroupPositive(Principal user) { |
|
Enumeration<Permission> groupPositive = zeroSet.elements(); |
|
Enumeration<Principal> e = allowedGroupsTable.keys(); |
|
while (e.hasMoreElements()) { |
|
Group g = (Group)e.nextElement(); |
|
if (g.isMember(user)) { |
|
AclEntry ae = allowedGroupsTable.get(g); |
|
groupPositive = union(ae.permissions(), groupPositive); |
|
} |
|
} |
|
return groupPositive; |
|
} |
|
|
|
private Enumeration<Permission> getGroupNegative(Principal user) { |
|
Enumeration<Permission> groupNegative = zeroSet.elements(); |
|
Enumeration<Principal> e = deniedGroupsTable.keys(); |
|
while (e.hasMoreElements()) { |
|
Group g = (Group)e.nextElement(); |
|
if (g.isMember(user)) { |
|
AclEntry ae = deniedGroupsTable.get(g); |
|
groupNegative = union(ae.permissions(), groupNegative); |
|
} |
|
} |
|
return groupNegative; |
|
} |
|
|
|
private Enumeration<Permission> getIndividualPositive(Principal user) { |
|
Enumeration<Permission> individualPositive = zeroSet.elements(); |
|
AclEntry ae = allowedUsersTable.get(user); |
|
if (ae != null) |
|
individualPositive = ae.permissions(); |
|
return individualPositive; |
|
} |
|
|
|
private Enumeration<Permission> getIndividualNegative(Principal user) { |
|
Enumeration<Permission> individualNegative = zeroSet.elements(); |
|
AclEntry ae = deniedUsersTable.get(user); |
|
if (ae != null) |
|
individualNegative = ae.permissions(); |
|
return individualNegative; |
|
} |
|
} |
|
|
|
final class AclEnumerator implements Enumeration<AclEntry> { |
|
Acl acl; |
|
Enumeration<AclEntry> u1, u2, g1, g2; |
|
|
|
AclEnumerator(Acl acl, Hashtable<?,AclEntry> u1, Hashtable<?,AclEntry> g1, |
|
Hashtable<?,AclEntry> u2, Hashtable<?,AclEntry> g2) { |
|
this.acl = acl; |
|
this.u1 = u1.elements(); |
|
this.u2 = u2.elements(); |
|
this.g1 = g1.elements(); |
|
this.g2 = g2.elements(); |
|
} |
|
|
|
public boolean hasMoreElements() { |
|
return (u1.hasMoreElements() || |
|
u2.hasMoreElements() || |
|
g1.hasMoreElements() || |
|
g2.hasMoreElements()); |
|
} |
|
|
|
public AclEntry nextElement() |
|
{ |
|
AclEntry o; |
|
synchronized (acl) { |
|
if (u1.hasMoreElements()) |
|
return u1.nextElement(); |
|
if (u2.hasMoreElements()) |
|
return u2.nextElement(); |
|
if (g1.hasMoreElements()) |
|
return g1.nextElement(); |
|
if (g2.hasMoreElements()) |
|
return g2.nextElement(); |
|
} |
|
throw new NoSuchElementException("Acl Enumerator"); |
|
} |
|
} |