/*
* This file or a portion of this file is licensed under the terms of the
* Globus Toolkit Public License, found at
* http://www.globus.org/toolkit/download/license.html.
* If you redistribute this file, with or without modifications,
* you must include this notice in the file.
*/
package org.globus.wsrf.impl.security.authorization;
import org.globus.wsrf.security.SecurityManager;
import org.globus.wsrf.impl.security.authorization.exceptions.AuthorizationException;
import org.globus.wsrf.impl.security.util.AuthUtil;
import org.globus.util.I18n;
import com.sun.xacml.ParsingException;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.PDP;
import com.sun.xacml.PDPConfig;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.ResponseCtx;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Subject;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.impl.CurrentEnvModule;
import com.sun.xacml.finder.impl.SelectorModule;
import org.apache.axis.AxisFault;
import org.apache.axis.utils.XMLUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.rpc.handler.MessageContext;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.List;
import java.util.Set;
import java.util.Iterator;
import java.security.Principal;
import org.globus.wsrf.security.authorization.PDPConstants;
import org.globus.wsrf.impl.security.authorization.exceptions.CloseException;
import org.globus.wsrf.impl.security.authorization.exceptions.InitializeException;
import org.globus.wsrf.impl.security.authorization.exceptions.InvalidPolicyException;
/**
* This class evaluates and stores XACML based policies on a service or
* resource instance level. The id specified when initilizing the chain is
* used to key the policy in the database. XACML Attributes that have been
* collected by PIPs or PDPs preceeding this PDP in the chain may be used as
* environment attributes in XACML policy rule conditions. For more
* information about the API see the {@link ServicePDP} documentation.
* @see ServicePDP
* @see ServiceInterceptor
* @see ServiceAuthorizationChain
* @see XMLDB
*/
public class XACMLPDP implements org.globus.wsrf.security.authorization.PDP {
private static I18n i18n = I18n.getI18n(PDPConstants.RESOURCE,
XACMLPDP.class.getClassLoader());
private static Log logger = LogFactory.getLog(XACMLPDP.class.getName());
private PDP pdp = null;
private ServicePolicyFinderModule servicePolicyModule = null;
private XMLDB db = null;
private String serviceId = null;
private String serviceOwner;
private ArrayList allowedOperations;
private boolean initialized;
private org.globus.wsrf.security.authorization.PDPConfig config;
private String name;
public static final String POLICY_FILE_NAME = "policyFile";
public static final String[] POLICY_NAMES =
new String[] { "urn:oasis:names:tc:xacml:1.0:policy" };
public XACMLPDP() {
this.servicePolicyModule = new ServicePolicyFinderModule();
PolicyFinder policyFinder = new PolicyFinder();
Set policyModules = new HashSet();
policyModules.add(servicePolicyModule);
policyFinder.setModules(policyModules);
CurrentEnvModule envAttributeModule = new CurrentEnvModule();
SelectorModule selectorAttributeModule = new SelectorModule();
AttributeFinder attributeFinder = new AttributeFinder();
List attributeModules = new ArrayList();
attributeModules.add(envAttributeModule);
attributeModules.add(selectorAttributeModule);
attributeFinder.setModules(attributeModules);
this.pdp = new PDP(new PDPConfig(attributeFinder, policyFinder, null));
}
public String[] getPolicyNames() {
return POLICY_NAMES;
}
private void initOwner() throws InitializeException {
SecurityManager manager = SecurityManager.getManager();
String creator = manager.getCaller();
if (creator != null) {
this.serviceOwner = creator;
} else {
// No caller credentials found. Use container credentials instead.
javax.security.auth.Subject systemSubject = null;
try {
systemSubject = manager.getSystemSubject();
} catch (Exception e) {
throw new InitializeException(i18n.getMessage("systemSubject"),
e);
}
try {
Principal principal = (Principal) systemSubject.getPrincipals()
.iterator().next();
creator = principal.getName();
} catch (Exception e) {
throw new InitializeException(i18n.getMessage("containerCred"),
e);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Setting service admin to:\n " + creator);
}
this.serviceOwner = creator;
}
/**
* Initializes a default policy for the service, where the service creator
* has full access to all service operations. Others are unauthorized.
*/
private void initPolicy() throws InitializeException {
String policy = null;
// try to get file name from config
String policyFile = (String)this.config.getProperty(this.name,
POLICY_FILE_NAME);
if (policyFile != null) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(policyFile));
String str = null;
while ((str = reader.readLine()) != null) {
if (policy == null) {
policy = str;
} else {
policy = policy + str;
}
}
} catch (IOException exp) {
logger.error(exp);
throw new InitializeException(i18n.getMessage("policyFile",
new Object[]
{ policyFile }),
exp);
} finally {
try {
reader.close();
} catch (IOException e) {
}
}
} else {
// Set default policy
initOwner();
String policyOwner = this.serviceOwner.replaceAll(" ","__s__");
policy =
XACMLPDPConstants.DEFAULT_POLICY
.replaceAll(XACMLPDPConstants.SERVICE_OWNER, policyOwner);
}
InputStream policyStream = new ByteArrayInputStream(policy.getBytes());
Document doc = null;
Element defaultPolicy = null;
try {
// Create new factory -> not thread safe according to API
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(policyStream);
defaultPolicy = doc.getDocumentElement();
} catch (Exception e) {
throw new InitializeException(i18n.getMessage("defaultParse"), e);
}
if (logger.isDebugEnabled()) {
logger.debug("Default policy:\n" + policy);
}
this.servicePolicyModule.setPolicy(defaultPolicy);
try {
this.db.store(defaultPolicy);
} catch (Exception e) {
throw new InitializeException("Default policy could not be stored",
e);