package org.dcache.acl.mapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import java.util.List;
import org.dcache.acl.ACE;
import org.dcache.acl.ACL;
import org.dcache.acl.ACLException;
import org.dcache.acl.Owner;
import org.dcache.acl.Permission;
import org.dcache.acl.enums.AceFlags;
import org.dcache.acl.enums.RsType;
import org.dcache.auth.Origin;
import org.dcache.auth.Subjects;
/**
* The AclMapper has the task to evaluate an ACL taking information on the subject, object and
* request origin as input and to map it onto two bit masks:
*
* @author David Melkumyan, DESY Zeuthen
*/
public class AclMapper {
private static final Logger logger = LoggerFactory.getLogger("logger.org.dcache.authorization." + AclMapper.class.getName());
private AclMapper() {
}
public static Permission getPermission(Subject subject, Origin origin, Owner owner, ACL acl) {
// if ( logger.isDebugEnabled() ) {
// logger.debug("Subject: " + subject);
// logger.debug("Origin: " + origin);
// logger.debug("Owner: " + owner);
// logger.debug("ACL: " + acl);
// }
Permission permACL = new Permission();
RsType rsType = null;
try {
if ( Subjects.isRoot(subject) ) {
permACL.setAll();
if ( logger.isDebugEnabled() ) {
logger.debug("ROOT has an access to everything.");
}
return permACL;
}
if ( acl == null ) {
return permACL;
}
rsType = acl.getRsType();
int def_msk = 0, allow_msk = 0;
List<ACE> aces = acl.getList();
for (ACE ace : aces) {
int mask;
Permission permACE = getPermission(subject, origin, owner, ace, rsType);
if ( permACE != null && (mask = (permACE.getDefMsk() & (~def_msk))) != 0 ) {
// mask not empty and contains only "new" bits
def_msk |= mask;
if ( permACE.getAllowMsk() == 0 ) {
allow_msk |= mask;
}
}
// if ( logger.isDebugEnabled() )
// logger.debug("Step " + ace.getOrder() + ") " + (new Permission(def_msk,
// allow_msk).asString(rsType)));
}
permACL.setDefMsk(def_msk);
permACL.setAllowMsk(allow_msk);
} catch (ACLException e) {
logger.error(e.getMessage());
} finally {
if ( logger.isDebugEnabled() ) {
logger.debug("Getted Permission: " + (rsType == null ? permACL
.toString() : permACL.asString(rsType)));
}
}
return permACL;
}
public static Permission[] getPermissions(Subject subject, Origin origin, Owner[] owners, ACL[] acls) {
int len = acls.length;
Permission[] perms = new Permission[len];
for (int index = 0; index < len; index++) {
perms[index] = getPermission(subject, origin, owners[index], acls[index]);
}
return perms;
}
private static Permission getPermission(Subject subject, Origin origin, Owner owner, ACE ace, RsType rsType) throws ACLException {
// if ( logger.isDebugEnabled() ) {
// logger.debug("Subject: " + subject);
// logger.debug("Origin: " + origin);
// logger.debug("Owner: " + owner);
// logger.debug("ACE: " + ace.toNFSv4String(rsType));
// logger.debug("rsType: " + rsType);
// }
Permission perm = null;
// match this ace only if either recourse is not a directory or an INHERIT_ONLY_ACE bit is not set in ace.flags
if ( rsType == RsType.DIR && AceFlags.INHERIT_ONLY_ACE.matches(ace.getFlags()) ) {
return null;
}
// // match this ace only if either recourse is not a directory or an INHERIT_ONLY_ACE bit is not set in ace.flags
// if ( (rsType == RsType.DIR && AceFlags.INHERIT_ONLY_ACE.matches(ace.getFlags())) || InetAddrMatcherImpl.matches(ace.getAddressMsk(), origin.getAddress()) == false )
// return null;
switch (ace.getWho()) {
case OWNER:
if ( Subjects.hasUid(subject, owner.getUid()) ) {
perm = new Permission(ace.getAccessMsk(), ace.getType()
.getValue());
}
break;
case OWNER_GROUP:
if ( Subjects.hasGid(subject, owner.getGid()) ) {
perm = new Permission(ace.getAccessMsk(), ace.getType()
.getValue());
}
break;
case EVERYONE:
perm = new Permission(ace.getAccessMsk(), ace.getType().getValue());
break;
case ANONYMOUS:
if (Subjects.isNobody(subject)) {
perm = new Permission(ace.getAccessMsk(), ace.getType().getValue());
}
break;
case AUTHENTICATED:
if (!Subjects.isNobody(subject)) {
perm = new Permission(ace.getAccessMsk(), ace.getType().getValue());
}
break;
case USER:
if ( Subjects.hasUid(subject, ace.getWhoID()) ) {
perm = new Permission(ace.getAccessMsk(), ace.getType()
.getValue());
}
break;
case GROUP:
if ( Subjects.hasGid(subject, ace.getWhoID()) ) {
perm = new Permission(ace.getAccessMsk(), ace.getType()
.getValue());
}
break;
default:
throw new ACLException("Get Permission", "Invalid who: " + ace.getWho());
}
return perm;
}
}