blob: 5eea7df5b000e76146a133a37bf1b6c18cb65add [file] [log] [blame]
/**
* 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.
*/
package org.swssf.policy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyBuilder;
import org.apache.ws.secpolicy.WSSPolicyException;
import org.swssf.wss.ext.WSSConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.wsdl.*;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.wsdl.extensions.soap12.SOAP12Operation;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.net.URL;
import java.util.*;
/**
* PolicyEnforcerFactory builds a map of all the possible effective Policies
* and caches them for reuse
*
* @author $Author$
* @version $Revision$ $Date$
*/
public class PolicyEnforcerFactory {
protected static final transient Log log = LogFactory.getLog(PolicyEnforcerFactory.class);
private Definition wsdlDefinition;
private List<OperationPolicy> operationPolicies;
private final Map<Element, Policy> elementPolicyCache;
private PolicyEnforcerFactory() {
elementPolicyCache = new HashMap<Element, Policy>();
}
public static PolicyEnforcerFactory newInstance(URL wsdlUrl) throws WSSPolicyException {
PolicyEnforcerFactory policyEnforcerFactory = new PolicyEnforcerFactory();
policyEnforcerFactory.parseWsdl(wsdlUrl);
return policyEnforcerFactory;
}
public static PolicyEnforcerFactory newInstance(Document document) throws WSSPolicyException {
PolicyEnforcerFactory policyEnforcerFactory = new PolicyEnforcerFactory();
policyEnforcerFactory.parseWsdl(document);
return policyEnforcerFactory;
}
//todo enforce uniqueness of operation names to prevent SOAPAction spoofing.
private void parseWsdl(URL wsdlUrl) throws WSSPolicyException {
try {
WSDLFactory wsdlFactory = WSDLFactory.newInstance();
WSDLReader reader = wsdlFactory.newWSDLReader();
reader.setFeature("javax.wsdl.verbose", false);
wsdlDefinition = reader.readWSDL(wsdlUrl.toString());
operationPolicies = findPoliciesByOperation(wsdlDefinition);
} catch (WSDLException e) {
throw new WSSPolicyException(e.getMessage(), e);
}
}
//todo enforce uniqueness of operation names to prevent SOAPAction spoofing.
private void parseWsdl(Document document) throws WSSPolicyException {
try {
WSDLFactory wsdlFactory = WSDLFactory.newInstance();
WSDLReader reader = wsdlFactory.newWSDLReader();
reader.setFeature("javax.wsdl.verbose", false);
wsdlDefinition = reader.readWSDL(document.getDocumentURI(), document);
operationPolicies = findPoliciesByOperation(wsdlDefinition);
} catch (WSDLException e) {
throw new WSSPolicyException(e.getMessage(), e);
}
}
private List<OperationPolicy> findPoliciesByOperation(Definition wsdlDefinition) throws WSSPolicyException {
List<OperationPolicy> operationPolicyList = new ArrayList<OperationPolicy>();
@SuppressWarnings("unchecked")
Iterator<Map.Entry> services = wsdlDefinition.getAllServices().entrySet().iterator();
while (services.hasNext()) {
@SuppressWarnings("unchecked")
Map.Entry<QName, Service> serviceEntry = services.next();
Service service = serviceEntry.getValue();
@SuppressWarnings("unchecked")
Iterator<Map.Entry> ports = service.getPorts().entrySet().iterator();
while (ports.hasNext()) {
@SuppressWarnings("unchecked")
Map.Entry<QName, Port> portEntry = ports.next();
Port port = portEntry.getValue();
Binding binding = port.getBinding();
@SuppressWarnings("unchecked")
List<BindingOperation> bindingOperations = binding.getBindingOperations();
for (int i = 0; i < bindingOperations.size(); i++) {
BindingOperation bindingOperation = bindingOperations.get(i);
Operation operation = bindingOperation.getOperation();
OperationPolicy operationPolicy = new OperationPolicy(operation.getName());
operationPolicyList.add(operationPolicy);
@SuppressWarnings("unchecked")
List<ExtensibilityElement> extensibilityElements = bindingOperation.getExtensibilityElements();
for (int j = 0; j < extensibilityElements.size(); j++) {
ExtensibilityElement extensibilityElement = extensibilityElements.get(j);
if (extensibilityElement instanceof SOAPOperation) {
SOAPOperation soapOperation = (SOAPOperation) extensibilityElement;
String soapActionUri = soapOperation.getSoapActionURI();
operationPolicy.setOperationAction(soapActionUri);
operationPolicy.setSoapMessageVersionNamespace(WSSConstants.NS_SOAP11);
} else if (extensibilityElement instanceof SOAP12Operation) {
SOAP12Operation soap12Operation = (SOAP12Operation) extensibilityElement;
String soapActionUri = soap12Operation.getSoapActionURI();
operationPolicy.setOperationAction(soapActionUri);
operationPolicy.setSoapMessageVersionNamespace(WSSConstants.NS_SOAP12);
}
}
Policy policy = getPolicy(service, port, binding, bindingOperation, operation);
operationPolicy.setPolicy(policy.normalize(true));
}
}
}
return operationPolicyList;
}
private Policy getPolicy(Service service, Port port, Binding binding, BindingOperation bindingOperation, Operation operation) throws WSSPolicyException {
List<Policy> policies = new ArrayList<Policy>();
Policy servicePolicy = findPolicies(service);
if (servicePolicy != null) {
policies.add(servicePolicy);
}
Policy portPolicy = findPolicies(port);
if (portPolicy != null) {
policies.add(portPolicy);
}
Policy bindingPolicy = findPolicies(binding);
if (bindingPolicy != null) {
policies.add(bindingPolicy);
}
Policy bindingOperationPolicy = findPolicies(bindingOperation);
if (bindingOperationPolicy != null) {
policies.add(bindingOperationPolicy);
}
Policy bindingOperationInputPolicy = findPolicies(bindingOperation.getBindingInput());
if (bindingOperationInputPolicy != null) {
policies.add(bindingOperationInputPolicy);
}
Policy portTypePolicy = findPortTypePolicy(binding, operation);
if (portTypePolicy != null) {
policies.add(portTypePolicy);
}
if (policies.size() == 0) {
return new Policy();
}
Policy mergedPolicy = policies.get(0);
for (int i = 1; i < policies.size(); i++) {
Policy policy = policies.get(i);
mergedPolicy = mergedPolicy.merge(policy);
}
return mergedPolicy;
}
private Policy findPortTypePolicy(Binding binding, Operation operation) throws WSSPolicyException {
List<Policy> policies = new ArrayList<Policy>();
PortType portType = binding.getPortType();
Policy portTypePolicy = findPolicies(portType);
if (portTypePolicy != null) {
policies.add(portTypePolicy);
}
@SuppressWarnings("unchecked")
List<Operation> operations = portType.getOperations();
for (int i = 0; i < operations.size(); i++) {
Operation portTypeOperation = operations.get(i);
if (portTypeOperation.getName().equals(operation.getName())) {
Policy operationPolicy = findPolicies(portTypeOperation);
if (operationPolicy != null) {
policies.add(operationPolicy);
}
Policy inputPolicy = findPolicies(portTypeOperation.getInput());
if (inputPolicy != null) {
policies.add(inputPolicy);
}
Policy messagePolicy = findPolicies(portTypeOperation.getInput().getMessage());
if (messagePolicy != null) {
policies.add(messagePolicy);
}
}
}
if (policies.size() == 0) {
return new Policy();
}
Policy mergedPolicy = policies.get(0);
for (int i = 1; i < policies.size(); i++) {
Policy policy = policies.get(i);
mergedPolicy = mergedPolicy.merge(policy);
}
return mergedPolicy;
}
private Policy findPolicies(WSDLElement wsdlElement) throws WSSPolicyException {
if (wsdlElement == null) {
return new Policy();
}
List<Policy> policies = new ArrayList<Policy>();
@SuppressWarnings("unchecked")
List<ExtensibilityElement> extensibilityElements = wsdlElement.getExtensibilityElements();
for (int i = 0; i < extensibilityElements.size(); i++) {
ExtensibilityElement extensibilityElement = extensibilityElements.get(i);
if (extensibilityElement instanceof UnknownExtensibilityElement) {
UnknownExtensibilityElement unknownExtensibilityElement = (UnknownExtensibilityElement) extensibilityElement;
if (unknownExtensibilityElement.getElementType().getLocalPart().equals("PolicyReference")) {
String uri = unknownExtensibilityElement.getElement().getAttribute("URI").substring(1);
NodeList policyNodeList = unknownExtensibilityElement.getElement().getOwnerDocument().getElementsByTagNameNS("*", "Policy");
boolean found = false;
for (int j = 0; j < policyNodeList.getLength(); j++) {
Element element = (Element) policyNodeList.item(j);
String refUri = element.getAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id");
if (refUri != null && refUri.equals(uri)) {
found = true;
Policy policy = parsePolicy(element);
policies.add(policy);
break;
}
}
if (!found) {
throw new WSSPolicyException("Referenced Policy not found " + uri);
}
} else if (unknownExtensibilityElement.getElementType().getLocalPart().equals("Policy")) {
Element element = unknownExtensibilityElement.getElement();
Policy policy = parsePolicy(element);
policies.add(policy);
}
}
}
if (policies.size() == 0) {
return new Policy();
}
Policy mergedPolicy = policies.get(0);
for (int i = 1; i < policies.size(); i++) {
Policy policy = policies.get(i);
mergedPolicy = mergedPolicy.merge(policy);
}
return mergedPolicy;
}
private Policy parsePolicy(Element element) throws WSSPolicyException {
if (elementPolicyCache.containsKey(element)) {
return elementPolicyCache.get(element);
}
PolicyBuilder policyBuilder = new PolicyBuilder();
Policy policy = policyBuilder.getPolicy(element);
elementPolicyCache.put(element, policy);
return policy;
}
public PolicyEnforcer newPolicyEnforcer(String soapAction) throws WSSPolicyException {
return new PolicyEnforcer(this.operationPolicies, soapAction);
}
}