All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.xwss.XWSSServerTube Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2022 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package com.sun.xml.xwss;

import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.message.Message;
import com.sun.xml.ws.api.message.Messages;
import com.sun.xml.ws.api.message.Packet;
import com.sun.xml.ws.api.model.wsdl.WSDLPort;
import com.sun.xml.ws.api.pipe.NextAction;
import com.sun.xml.ws.api.pipe.Tube;
import com.sun.xml.ws.api.pipe.TubeCloner;
import com.sun.xml.ws.api.pipe.helper.AbstractFilterTubeImpl;
import com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.PolicyTypeUtil;
import com.sun.xml.wss.impl.PolicyViolationException;
import com.sun.xml.wss.impl.ProcessingContextImpl;
import com.sun.xml.wss.impl.SecurableSoapMessage;
import com.sun.xml.wss.impl.SecurityAnnotator;
import com.sun.xml.wss.impl.SecurityRecipient;
import com.sun.xml.wss.impl.WssSoapFaultException;
import com.sun.xml.wss.impl.config.ApplicationSecurityConfiguration;
import com.sun.xml.wss.impl.config.DeclarativeSecurityConfiguration;
import com.sun.xml.wss.impl.configuration.StaticApplicationContext;
import com.sun.xml.wss.impl.misc.SecurityUtil;
import com.sun.xml.wss.impl.policy.SecurityPolicy;
import com.sun.xml.wss.util.ServletContextUtil;
import com.sun.xml.wss.util.WSSServletContextFacade;

import java.io.InputStream;
import java.net.URL;
import java.util.jar.Attributes.Name;
import jakarta.servlet.ServletContext;
import javax.xml.namespace.QName;
import jakarta.xml.soap.MessageFactory;
import org.w3c.dom.Node;
import jakarta.xml.soap.SOAPBody;
import jakarta.xml.soap.SOAPConstants;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPFactory;
import jakarta.xml.soap.SOAPFault;
import jakarta.xml.soap.SOAPMessage;
import jakarta.xml.ws.WebServiceException;
import jakarta.xml.ws.soap.SOAPFaultException;
import org.w3c.dom.NodeList;


public class XWSSServerTube extends AbstractFilterTubeImpl {

    protected static final String FAILURE = "com.sun.xml.ws.shd.failure";
    protected static final String TRUE = "true";
    protected static final String FALSE = "false";
    protected static final String CONTEXT_WSDL_OPERATION = "com.sun.xml.ws.wsdl.operation";

    private final WSEndpoint endPoint;
    private final WSDLPort port;

    private SecurityConfiguration config;

    protected SOAPFactory soapFactory;
    protected MessageFactory messageFactory;
    protected SOAPVersion soapVersion;
    protected boolean isSOAP12;


    /** Creates a new instance of XWSSServerPipe */
    public XWSSServerTube(WSEndpoint epoint, WSDLPort prt, Tube nextTube) {
        super(nextTube);
        endPoint = epoint;
        port = prt;
        try {
        config = new SecurityConfiguration(getServerConfig());
        } catch (XWSSecurityException ex) {
            throw new WebServiceException(ex);
        }
        soapVersion = endPoint.getBinding().getSOAPVersion();
        isSOAP12 = soapVersion == SOAPVersion.SOAP_12;
        soapFactory = soapVersion.getSOAPFactory();
        messageFactory = soapVersion.getMessageFactory();
    }

    public XWSSServerTube(XWSSServerTube that, TubeCloner cloner) {

        super(that,cloner);
        this.endPoint = that.endPoint;
        this.port = that.port;

        this.soapFactory = that.soapFactory;
        this.messageFactory = that.messageFactory;
        this.soapVersion = that.soapVersion;
        this.isSOAP12 = that.isSOAP12;
        this.config = that.config;
    }


    @Override
    public void preDestroy() {
    }


    private InputStream getServerConfigStream() {
        QName serviceQName = endPoint.getServiceName();
        String serviceName = serviceQName.getLocalPart();

        String serverConfig = "/WEB-INF/" + serviceName + "_" + "security_config.xml";
        ServletContext context = endPoint.getContainer().getSPI(ServletContext.class);
        if(context == null) {
            return null;
        }
        InputStream in = context.getResourceAsStream(serverConfig);

        if (in == null) {
            serverConfig = "/WEB-INF/" + "server" + "_" + "security_config.xml";
            in = context.getResourceAsStream(serverConfig);
        }

        return in;
    }

    private URL getServerConfig() {
        QName serviceQName = endPoint.getServiceName();
        String serviceName = serviceQName.getLocalPart();
        WSSServletContextFacade ctxt = ServletContextUtil.getServletContextFacade(endPoint);
        String serverName = "server";
        URL url = null;
        if (ctxt != null) {
            String serverConfig = "/WEB-INF/" + serverName + "_security_config.xml";
            url = ctxt.getResource(serverConfig);
            if (url == null) {
                serverConfig = "/WEB-INF/" + serviceName + "_security_config.xml";
                url = ctxt.getResource(serverConfig);
            }
            return url;
        } else {
            //this could be an EJB or JDK6 endpoint
            //so let us try to locate the config from META-INF classpath
            String serverConfig = "META-INF/" + serverName + "_security_config.xml";
            url = SecurityUtil.loadFromClasspath(serverConfig);
            if (url == null) {
                serverConfig = "META-INF/" + serviceName + "_security_config.xml";
                url = SecurityUtil.loadFromClasspath(serverConfig);
            }
            return url;
        }
    }


     private static final String ENCRYPTED_BODY_QNAME =
            "{" + MessageConstants.XENC_NS + "}" + MessageConstants.ENCRYPTED_DATA_LNAME;

    // server side incoming request handling hook
    public Packet validateRequest(Packet packet)
    throws Exception {

        if (config == null) {
            return  packet;
        }

        ProcessingContext context = null;
        SOAPMessage message =  packet.getMessage().readAsSOAPMessage();
        try {

            StaticApplicationContext sContext =
                    new StaticApplicationContext(getPolicyContext(packet));

            context = new ProcessingContextImpl(packet.invocationProperties);

            context.setSOAPMessage(message);

            String operation = getOperationName(message);

            ApplicationSecurityConfiguration _sConfig =
                    config.getSecurityConfiguration();

            if (operation.equals(ENCRYPTED_BODY_QNAME) &&
                    _sConfig.hasOperationPolicies()) {
                // get enclosing port level configuration
                if (MessageConstants.debug) {
                    System.out.println("context in plugin= " +
                            sContext);
                }
                ApplicationSecurityConfiguration appconfig =
                        (ApplicationSecurityConfiguration)
                        _sConfig.getSecurityPolicies(sContext).next();

                if (appconfig != null) {
                    context.setPolicyContext(sContext);
                    context.setSecurityPolicy(appconfig);
                } else {
                    ApplicationSecurityConfiguration config0 =
                            (ApplicationSecurityConfiguration) _sConfig.
                            getAllTopLevelApplicationSecurityConfigurations().
                            iterator().next();

                    //sContext.setPortIdentifier ("");
                    context.setPolicyContext(sContext);
                    context.setSecurityPolicy(config0);
                }
            } else {
                sContext.setOperationIdentifier(operation);
                packet.invocationProperties.put(CONTEXT_WSDL_OPERATION, operation);
                SecurityPolicy policy =
                        _sConfig.getSecurityConfiguration(sContext);

                context.setPolicyContext(sContext);

                if (PolicyTypeUtil.declarativeSecurityConfiguration(policy)) {
                    context.setSecurityPolicy(
                            ((DeclarativeSecurityConfiguration)policy).
                            receiverSettings());
                } else {
                    context.setSecurityPolicy(policy);
                }
            }

            context.setSecurityEnvironment(config.getSecurityEnvironment());
            context.isInboundMessage(true);

            if (_sConfig.retainSecurityHeader()) {
                context.retainSecurityHeader(true);
            }

            if (_sConfig.resetMustUnderstand()) {
                context.resetMustUnderstand(true);
            }

            SecurityRecipient.validateMessage(context);
            String operationName = getOperationName(message);

            packet.invocationProperties.put(CONTEXT_WSDL_OPERATION, operationName);
            packet.setMessage(Messages.create(context.getSOAPMessage()));
            /* TODO, how to change this
            if (packet.invocationProperties.get("javax.security.auth.Subject") != null) {
                packet.invocationProperties.("javax.security.auth.Subject",MessageContext.Scope.APPLICATION);
            }*/
            return packet;

        } catch (com.sun.xml.wss.impl.WssSoapFaultException soapFaultException) {

            packet.invocationProperties.put(FAILURE, TRUE);
            addFault(soapFaultException,message,isSOAP12);
            packet.setMessage(Messages.create(message));
            return packet;

        } catch (com.sun.xml.wss.XWSSecurityException xwse) {
            QName qname = null;

            if (xwse.getCause() instanceof PolicyViolationException) {
                qname = MessageConstants.WSSE_RECEIVER_POLICY_VIOLATION;
            } else {
                qname = MessageConstants.WSSE_FAILED_AUTHENTICATION;
            }

            com.sun.xml.wss.impl.WssSoapFaultException wsfe =
                    SecurableSoapMessage.newSOAPFaultException(
                    qname, xwse.getMessage(), xwse);

            //TODO: MISSING-LOG
            packet.invocationProperties.put(FAILURE, TRUE);
            addFault(wsfe,message,isSOAP12);
            packet.setMessage(Messages.create(message));

            return packet;
        }

    }

    // server side response writing hook
    public Packet secureResponse(Packet packet)
    throws Exception {

        if (config == null) {
            return packet;
        }
        try {
            ProcessingContext context = new ProcessingContextImpl(packet.invocationProperties);

            String operation =
                    (String)packet.invocationProperties.get(CONTEXT_WSDL_OPERATION);
            StaticApplicationContext sContext =
                    new StaticApplicationContext(getPolicyContext(packet));
            sContext.setOperationIdentifier(operation);

            ApplicationSecurityConfiguration _sConfig =
                    config.getSecurityConfiguration();

            SecurityPolicy policy = _sConfig.getSecurityConfiguration(sContext);
            context.setPolicyContext(sContext);

            if (PolicyTypeUtil.declarativeSecurityConfiguration(policy)) {
                context.setSecurityPolicy(((DeclarativeSecurityConfiguration)policy).senderSettings());
            } else {
                context.setSecurityPolicy(policy);
            }

            context.setSecurityEnvironment(config.getSecurityEnvironment());
            context.isInboundMessage(false);
            context.setSOAPMessage(packet.getMessage().readAsSOAPMessage());
            SecurityAnnotator.secureMessage(context);
            packet.setMessage(Messages.create(context.getSOAPMessage()));
            return packet;
        } catch (com.sun.xml.wss.impl.WssSoapFaultException soapFaultException) {
            Message msg = Messages.create(getSOAPFault(soapFaultException));
            packet.setMessage(msg);
            return packet;
        } catch (com.sun.xml.wss.XWSSecurityException xwse) {
            //TODO: MISSING-LOG
            com.sun.xml.wss.impl.WssSoapFaultException wsfe =
                    SecurableSoapMessage.newSOAPFaultException(
                    MessageConstants.WSSE_INTERNAL_SERVER_ERROR,
                    xwse.getMessage(), xwse);
            Message msg = Messages.create(getSOAPFault(wsfe));
            packet.setMessage(msg);
            return packet;
        }
    }

    private StaticApplicationContext getPolicyContext(Packet packet) {
        // assumed to contain single nested container
        ApplicationSecurityConfiguration appconfig =
                config.getSecurityConfiguration();

        StaticApplicationContext iContext =
                (StaticApplicationContext)appconfig.getAllContexts().next();
        StaticApplicationContext sContext =
                new StaticApplicationContext(iContext);

        QName portQname = null;
        if (port != null) {
            portQname = port.getName();
        }
        String prt = null;

        if (portQname == null) {
            prt = "";
        } else {
            prt = portQname.toString();
        }

        sContext.setPortIdentifier(prt);
        return sContext;
    }

    public void addFault(
            com.sun.xml.wss.impl.WssSoapFaultException sfe,SOAPMessage soapMessage,boolean isSOAP12)
               throws SOAPException{
        SOAPBody body = soapMessage.getSOAPBody();
        body.removeContents();
        soapMessage.removeAllAttachments();
        QName faultCode = sfe.getFaultCode();
        Name faultCodeName = null;

        if(faultCode == null){
            faultCode = new QName(SOAPConstants.URI_NS_SOAP_ENVELOPE,"Client");
        }
        if(isSOAP12){
            SOAPFault fault = body.addFault(SOAPConstants.SOAP_SENDER_FAULT,sfe.getMessage());
            fault.appendFaultSubcode(faultCode);
        }else{
            body.addFault(faultCode, sfe.getMessage());
        }
        NodeList list = soapMessage.getSOAPPart().getEnvelope().getElementsByTagNameNS(MessageConstants.WSSE_NS,MessageConstants.WSSE_SECURITY_LNAME);
        if(list.getLength() > 0){
            Node node = list.item(0);
            node.getParentNode().removeChild(node);
        }
    }

    protected SOAPFault getSOAPFault(WssSoapFaultException sfe) {

        SOAPFault fault = null;
        try {
            if (isSOAP12) {
                fault = soapFactory.createFault(sfe.getFaultString(),SOAPConstants.SOAP_SENDER_FAULT);
                fault.appendFaultSubcode(sfe.getFaultCode());
            } else {
                fault = soapFactory.createFault(sfe.getFaultString(), sfe.getFaultCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("Security Pipe: Internal Error while trying to create a SOAPFault");
        }
        return fault;
    }

    public SOAPFaultException getSOAPFaultException(
            WssSoapFaultException sfe, boolean isSOAP12) {

        SOAPFault fault = null;
        try {
            if (isSOAP12) {
                fault = soapFactory.createFault(sfe.getFaultString(),SOAPConstants.SOAP_SENDER_FAULT);

                fault.appendFaultSubcode(sfe.getFaultCode());
            } else {
                fault = soapFactory.createFault(sfe.getFaultString(), sfe.getFaultCode());
            }
        } catch (Exception e) {
            throw new RuntimeException(this + ": Internal Error while trying to create a SOAPFault");
        }
        return new SOAPFaultException(fault);
    }

    private String getOperationName(SOAPMessage message)
    throws Exception {
        Node node = null;
        String key = null;
        SOAPBody body = null;

        if (message != null) {
            body = message.getSOAPBody();
        } else {
            throw new XWSSecurityException(
                    "SOAPMessage in message context is null");
        }

        if (body != null) {
            node = body.getFirstChild();
        } else {
            throw new XWSSecurityException(
                    "No body element identifying an operation is found");
        }

        StringBuilder tmp = new StringBuilder();
        String operation = "";

        for (; node != null; node = node.getNextSibling()) {
            tmp.append("{").append(node.getNamespaceURI()).append("}").append(node.getLocalName()).append(":");
        }
        operation = tmp.toString();
        if(operation.length()> 0){
            return operation.substring(0, operation.length()-1);
        }else{
            return operation;
        }
    }

    @Override
    public AbstractTubeImpl copy(TubeCloner cloner) {
        return new XWSSServerTube(this, cloner);
    }

    @Override
    public NextAction processRequest(Packet packet){
        try {
            Packet ret = validateRequest(packet);
            if (TRUE.equals(ret.invocationProperties.get(FAILURE))) {
                return  doReturnWith(ret);
            }
            return doInvoke(super.next, ret);
        } catch (Throwable t) {
            if (!(t instanceof WebServiceException)) {
                t = new WebServiceException(t);
            }
            return doThrow(t);
        }
    }

    @Override
    public NextAction processResponse(Packet ret) {
        try{
            //could be oneway
            if(ret.getMessage() == null){
                return doReturnWith(ret);
            }
            Packet response = secureResponse(ret);
            return doReturnWith(response);
        }catch(Throwable t){
            if (!(t instanceof WebServiceException)) {
                t = new WebServiceException(t);
            }
            return doThrow(t);
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy