| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| /* |
| * AT&T - PROPRIETARY |
| * THIS FILE CONTAINS PROPRIETARY INFORMATION OF |
| * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN |
| * ACCORDANCE WITH APPLICABLE AGREEMENTS. |
| * |
| * Copyright (c) 2013 AT&T Knowledge Ventures |
| * Unpublished and Not for Publication |
| * All Rights Reserved |
| */ |
| package org.apache.openaz.xacml.pdp.policy.dom; |
| |
| import java.io.File; |
| import java.util.Iterator; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.openaz.xacml.api.Identifier; |
| import org.apache.openaz.xacml.api.XACML3; |
| import org.apache.openaz.xacml.pdp.policy.CombiningAlgorithm; |
| import org.apache.openaz.xacml.pdp.policy.CombiningAlgorithmFactory; |
| import org.apache.openaz.xacml.pdp.policy.Policy; |
| import org.apache.openaz.xacml.pdp.policy.PolicyDefaults; |
| import org.apache.openaz.xacml.pdp.policy.PolicySet; |
| import org.apache.openaz.xacml.pdp.policy.Rule; |
| import org.apache.openaz.xacml.std.StdStatusCode; |
| import org.apache.openaz.xacml.std.dom.DOMProperties; |
| import org.apache.openaz.xacml.std.dom.DOMStructureException; |
| import org.apache.openaz.xacml.std.dom.DOMUtil; |
| import org.apache.openaz.xacml.util.FactoryException; |
| import org.apache.openaz.xacml.util.StringUtils; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * DOMPolicy extends {@link org.apache.openaz.xacml.pdp.policy.Policy} with methods for creation from a DOM |
| * {@link org.w3c.dom.Node}. |
| */ |
| public class DOMPolicy { |
| private static final Log logger = LogFactory.getLog(DOMPolicy.class); |
| |
| /** |
| * Creates a new <code>DOMPolicy</code> to be configured from a DOM <code>Node</code>. |
| */ |
| protected DOMPolicy() { |
| } |
| |
| /** |
| * Creates a new <code>DOMPolicy</code> by parsing the given <code>Node</code> representing a XACML Policy |
| * element. |
| * |
| * @param nodePolicy the <code>Node</code> representing the Policy element |
| * @param policyDefaultsParent the <code>PolicyDefaults</code> of the parent element of the Policy element |
| * or null if this is the root |
| * @return a new <code>DOMPolicy</code> parsed from the given <code>Node</code> |
| * @throws DOMStructureException if there is an error parsing the <code>Node</code> |
| */ |
| public static Policy newInstance(Node nodePolicy, PolicySet policySetParent, |
| PolicyDefaults policyDefaultsParent) throws DOMStructureException { |
| Element elementPolicy = DOMUtil.getElement(nodePolicy); |
| boolean bLenient = DOMProperties.isLenient(); |
| |
| Policy domPolicy = new Policy(policySetParent); |
| |
| Identifier identifier; |
| Integer integer; |
| Iterator<?> iterator; |
| |
| try { |
| NodeList children = elementPolicy.getChildNodes(); |
| int numChildren; |
| if (children != null && (numChildren = children.getLength()) > 0) { |
| /* |
| * Run through once, quickly, to set the PolicyDefaults for the new DOMPolicySet |
| */ |
| for (int i = 0; i < numChildren; i++) { |
| Node child = children.item(i); |
| if (DOMUtil.isNamespaceElement(child, XACML3.XMLNS) |
| && XACML3.ELEMENT_POLICYDEFAULTS.equals(child.getLocalName())) { |
| if (domPolicy.getPolicyDefaults() != null && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy.setPolicyDefaults(DOMPolicyDefaults |
| .newInstance(child, policyDefaultsParent)); |
| } |
| } |
| if (domPolicy.getPolicyDefaults() == null) { |
| domPolicy.setPolicyDefaults(policyDefaultsParent); |
| } |
| |
| for (int i = 0; i < numChildren; i++) { |
| Node child = children.item(i); |
| if (DOMUtil.isElement(child) && DOMUtil.isInNamespace(child, XACML3.XMLNS)) { |
| String childName = child.getLocalName(); |
| if (XACML3.ELEMENT_DESCRIPTION.equals(childName)) { |
| if (domPolicy.getDescription() != null && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy.setDescription(child.getTextContent()); |
| } else if (XACML3.ELEMENT_POLICYISSUER.equals(childName)) { |
| if (domPolicy.getPolicyIssuer() != null && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy.setPolicyIssuer(DOMPolicyIssuer.newInstance(child)); |
| } else if (XACML3.ELEMENT_POLICYDEFAULTS.equals(childName)) { //NOPMD |
| // TODO |
| } else if (XACML3.ELEMENT_TARGET.equals(childName)) { |
| if (domPolicy.getTarget() != null && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy.setTarget(DOMTarget.newInstance(child)); |
| } else if (XACML3.ELEMENT_COMBINERPARAMETERS.equals(childName)) { |
| domPolicy.addCombinerParameters(DOMCombinerParameter.newList(child)); |
| } else if (XACML3.ELEMENT_RULECOMBINERPARAMETERS.equals(childName)) { |
| domPolicy.addRuleCombinerParameter(DOMRuleCombinerParameters |
| .newInstance(child)); |
| } else if (XACML3.ELEMENT_VARIABLEDEFINITION.equals(childName)) { |
| domPolicy.addVariableDefinition(DOMVariableDefinition.newInstance(child, |
| domPolicy)); |
| } else if (XACML3.ELEMENT_RULE.equals(childName)) { |
| domPolicy.addRule(DOMRule.newInstance(child, domPolicy)); |
| } else if (XACML3.ELEMENT_OBLIGATIONEXPRESSIONS.equals(childName)) { |
| if ((iterator = domPolicy.getObligationExpressions()) != null |
| && iterator.hasNext() && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy |
| .setObligationExpressions(DOMObligationExpression.newList(child, |
| domPolicy)); |
| } else if (XACML3.ELEMENT_ADVICEEXPRESSIONS.equals(childName)) { |
| if ((iterator = domPolicy.getAdviceExpressions()) != null |
| && iterator.hasNext() && !bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| domPolicy.setAdviceExpressions(DOMAdviceExpression.newList(child, domPolicy)); |
| } else if (!bLenient) { |
| throw DOMUtil.newUnexpectedElementException(child, nodePolicy); |
| } |
| } |
| } |
| } |
| domPolicy.setIdentifier(DOMUtil.getIdentifierAttribute(elementPolicy, XACML3.ATTRIBUTE_POLICYID, |
| !bLenient)); |
| domPolicy.setVersion(DOMUtil.getVersionAttribute(elementPolicy, XACML3.ATTRIBUTE_VERSION, |
| !bLenient)); |
| |
| identifier = DOMUtil.getIdentifierAttribute(elementPolicy, XACML3.ATTRIBUTE_RULECOMBININGALGID, |
| !bLenient); |
| CombiningAlgorithm<Rule> combiningAlgorithmRule = null; |
| try { |
| combiningAlgorithmRule = CombiningAlgorithmFactory.newInstance() |
| .getRuleCombiningAlgorithm(identifier); |
| } catch (FactoryException ex) { |
| if (!bLenient) { |
| throw new DOMStructureException("Failed to get CombiningAlgorithm", ex); |
| } |
| } |
| if (combiningAlgorithmRule == null && !bLenient) { |
| throw new DOMStructureException(elementPolicy, "Unknown rule combining algorithm \"" |
| + identifier.toString() + "\" in \"" |
| + DOMUtil.getNodeLabel(nodePolicy)); |
| } else { |
| domPolicy.setRuleCombiningAlgorithm(combiningAlgorithmRule); |
| } |
| |
| if ((integer = DOMUtil.getIntegerAttribute(elementPolicy, XACML3.ATTRIBUTE_MAXDELEGATIONDEPTH)) != null) { |
| domPolicy.setMaxDelegationDepth(integer); |
| } |
| } catch (DOMStructureException ex) { |
| domPolicy.setStatus(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage()); |
| if (DOMProperties.throwsExceptions()) { |
| throw ex; |
| } |
| } |
| |
| return domPolicy; |
| } |
| |
| public static boolean repair(Node nodePolicy) throws DOMStructureException { |
| Element elementPolicy = DOMUtil.getElement(nodePolicy); |
| boolean result = false; |
| |
| NodeList children = elementPolicy.getChildNodes(); |
| int numChildren; |
| boolean sawDescription = false; |
| boolean sawIssuer = false; |
| boolean sawTarget = false; |
| boolean sawPolicyDefaults = false; |
| boolean sawObligationExprs = false; |
| boolean sawAdviceExprs = false; |
| |
| if (children != null && (numChildren = children.getLength()) > 0) { |
| for (int i = 0; i < numChildren; i++) { |
| Node child = children.item(i); |
| if (DOMUtil.isElement(child) && DOMUtil.isInNamespace(child, XACML3.XMLNS)) { |
| String childName = child.getLocalName(); |
| if (XACML3.ELEMENT_DESCRIPTION.equals(childName)) { |
| if (sawDescription) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawDescription = true; |
| } |
| } else if (XACML3.ELEMENT_POLICYISSUER.equals(childName)) { |
| if (sawIssuer) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawDescription = true; |
| result = DOMPolicyIssuer.repair(child) || result; |
| } |
| } else if (XACML3.ELEMENT_POLICYDEFAULTS.equals(childName)) { |
| if (sawPolicyDefaults) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawPolicyDefaults = true; |
| result = DOMPolicyDefaults.repair(child) || result; |
| } |
| } else if (XACML3.ELEMENT_TARGET.equals(childName)) { |
| if (sawTarget) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawTarget = true; |
| result = DOMTarget.repair(child) || result; |
| } |
| } else if (XACML3.ELEMENT_COMBINERPARAMETERS.equals(childName)) { |
| result = DOMCombinerParameter.repair(child) || result; |
| } else if (XACML3.ELEMENT_RULECOMBINERPARAMETERS.equals(childName)) { |
| result = DOMRuleCombinerParameters.repair(child) || result; |
| } else if (XACML3.ELEMENT_VARIABLEDEFINITION.equals(childName)) { |
| result = DOMVariableDefinition.repair(child) || result; |
| } else if (XACML3.ELEMENT_RULE.equals(childName)) { |
| result = DOMRule.repair(child) || result; |
| } else if (XACML3.ELEMENT_OBLIGATIONEXPRESSIONS.equals(childName)) { |
| if (sawObligationExprs) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawObligationExprs = true; |
| result = DOMObligationExpression.repairList(child) || result; |
| } |
| } else if (XACML3.ELEMENT_ADVICEEXPRESSIONS.equals(childName)) { |
| if (sawAdviceExprs) { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } else { |
| sawAdviceExprs = true; |
| result = DOMAdviceExpression.repairList(child) || result; |
| } |
| } else { |
| logger.warn("Unexpected element " + child.getNodeName()); |
| elementPolicy.removeChild(child); |
| result = true; |
| } |
| } |
| } |
| } |
| result = DOMUtil.repairIdentifierAttribute(elementPolicy, XACML3.ATTRIBUTE_POLICYID, logger) |
| || result; |
| result = DOMUtil.repairVersionAttribute(elementPolicy, XACML3.ATTRIBUTE_VERSION, logger) || result; |
| result = DOMUtil.repairIdentifierAttribute(elementPolicy, XACML3.ATTRIBUTE_RULECOMBININGALGID, |
| XACML3.ID_RULE_DENY_OVERRIDES, logger) || result; |
| |
| Identifier identifier = DOMUtil.getIdentifierAttribute(elementPolicy, |
| XACML3.ATTRIBUTE_RULECOMBININGALGID); |
| CombiningAlgorithm<Rule> combiningAlgorithmRule = null; |
| try { |
| combiningAlgorithmRule = CombiningAlgorithmFactory.newInstance() |
| .getRuleCombiningAlgorithm(identifier); |
| } catch (FactoryException ex) { |
| combiningAlgorithmRule = null; |
| } |
| if (combiningAlgorithmRule == null) { |
| logger.warn("Setting invalid " + XACML3.ATTRIBUTE_RULECOMBININGALGID + " attribute " |
| + identifier.stringValue() + " to " + XACML3.ID_RULE_DENY_OVERRIDES.stringValue()); |
| elementPolicy.setAttribute(XACML3.ATTRIBUTE_RULECOMBININGALGID, |
| XACML3.ID_RULE_DENY_OVERRIDES.stringValue()); |
| result = true; |
| } |
| return result; |
| } |
| |
| public static void main(String args[]) { |
| try { |
| for (String fileName : args) { |
| File filePolicy = new File(fileName); |
| if (filePolicy.exists() && filePolicy.canRead()) { |
| try { |
| Document documentPolicy = DOMUtil.loadDocument(filePolicy); |
| if (documentPolicy.getFirstChild() == null) { |
| System.err.println(fileName + ": Error: No Policy found"); |
| } else if (!XACML3.ELEMENT_POLICY.equals(documentPolicy.getFirstChild() |
| .getLocalName())) { |
| System.err.println(fileName + ": Error: Not a Policy documnt"); |
| } else { |
| Policy policy = DOMPolicy.newInstance(documentPolicy.getFirstChild(), null, null); |
| System.out.println(fileName + ": validate()=" + policy.validate()); |
| System.out.println(StringUtils.prettyPrint(policy.toString())); |
| } |
| } catch (Exception ex) { |
| System.err.println("Exception processing policy file \"" + fileName + "\""); |
| ex.printStackTrace(System.err); |
| } |
| } else { |
| System.err.println("Cannot read policy file \"" + fileName + "\""); |
| } |
| } |
| } catch (Exception ex) { |
| ex.printStackTrace(System.err); |
| System.exit(1); |
| } |
| System.exit(0); |
| } |
| } |