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

com.sun.xml.wss.provider.wsit.SecurityTubeFactory 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.wss.provider.wsit;

import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.ha.HighAvailabilityProvider;
import com.sun.xml.ws.api.model.wsdl.WSDLBoundOperation;
import com.sun.xml.ws.api.model.wsdl.WSDLPort;
import com.sun.xml.ws.api.pipe.ClientPipeAssemblerContext;
import com.sun.xml.ws.api.pipe.Codec;
import com.sun.xml.ws.api.pipe.Codecs;
import com.sun.xml.ws.api.pipe.Pipe;
import com.sun.xml.ws.api.pipe.StreamSOAPCodec;
import com.sun.xml.ws.api.pipe.Tube;
import com.sun.xml.ws.api.pipe.helper.PipeAdapter;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.assembler.dev.ClientTubelineAssemblyContext;
import com.sun.xml.ws.assembler.dev.ServerTubelineAssemblyContext;
import com.sun.xml.ws.assembler.dev.TubeFactory;
import com.sun.xml.ws.assembler.dev.TubelineAssemblyContextUpdater;
import com.sun.xml.ws.assembler.metro.ServerPipelineHook;
import com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook;
import com.sun.xml.ws.assembler.metro.dev.MetroClientTubelineAssemblyContext;
import com.sun.xml.ws.policy.Policy;
import com.sun.xml.ws.policy.PolicyException;
import com.sun.xml.ws.policy.PolicyMap;
import com.sun.xml.ws.policy.PolicyMapKey;
import com.sun.xml.ws.runtime.dev.SessionManager;
import com.sun.xml.ws.security.encoding.LazyStreamCodec;
import com.sun.xml.ws.security.impl.policy.SecurityFeatureConfigurator;
import com.sun.xml.ws.security.opt.impl.util.JAXBUtil;
import com.sun.xml.ws.security.policy.SecurityPolicyVersion;
import com.sun.xml.ws.security.secconv.SecureConversationInitiator;
import com.sun.xml.ws.util.ServiceConfigurationError;
import com.sun.xml.ws.util.ServiceFinder;
import com.sun.xml.wss.NonceManager;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.config.SecurityConfigProvider;
import com.sun.xml.wss.impl.misc.SecurityUtil;
import com.sun.xml.wss.jaxws.impl.SecurityClientTube;
import com.sun.xml.wss.jaxws.impl.SecurityServerTube;
import com.sun.xml.wss.provider.wsit.logging.LogDomainConstants;
import com.sun.xml.wss.util.ServletContextUtil;
import com.sun.xml.wss.util.WSSServletContextFacade;
import com.sun.xml.xwss.XWSSClientTube;
import com.sun.xml.xwss.XWSSServerTube;

import jakarta.security.auth.message.config.AuthConfigFactory;
import javax.xml.namespace.QName;
import jakarta.xml.ws.WebServiceException;
import jakarta.xml.ws.WebServiceFeature;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;

public final class SecurityTubeFactory implements TubeFactory, TubelineAssemblyContextUpdater {

    private static final Logger log =
        Logger.getLogger(
        LogDomainConstants.WSIT_PVD_DOMAIN,
        LogDomainConstants.WSIT_PVD_DOMAIN_BUNDLE);

    //Added for Security Pipe Unification with JSR 196 on GlassFish
    private static final String ENDPOINT = "ENDPOINT";
    private static final String NEXT_PIPE = "NEXT_PIPE";
    private static final String POLICY = "POLICY";
    private static final String SEI_MODEL = "SEI_MODEL";
    // private static final String SERVICE_ENDPOINT = "SERVICE_ENDPOINT";
    private static final String WSDL_MODEL = "WSDL_MODEL";
    private static final String GF_SERVER_SEC_PIPE = "com.sun.enterprise.webservice.CommonServerSecurityPipe";

    private static final boolean disable;
    private static long maxNonceAge;
    static  {
       disable = Boolean.getBoolean("DISABLE_XWSS_SECURITY");
       maxNonceAge = SecurityConfigProvider.INSTANCE.getMaxNonceAge();
       if(maxNonceAge == MessageConstants.MAX_NONCE_AGE){ //if max nonce age is not set in domain.xml
           String maxNAge = System.getProperty("MAX_NONCE_AGE");
           maxNonceAge = (maxNAge != null) ? Long.parseLong(maxNAge) : MessageConstants.MAX_NONCE_AGE ;
       }
    }

    /**
     * Default constructor.
     */
    public SecurityTubeFactory() {}

    @Override
    public void prepareContext(ClientTubelineAssemblyContext context) throws WebServiceException {
        if (isSecurityEnabled(context.getPolicyMap(), context.getWsdlPort())) {
            context.setCodec(createSecurityCodec(context.getBinding()));
        }
    }

    @Override
    public void prepareContext(ServerTubelineAssemblyContext context) throws WebServiceException {
        if (isSecurityEnabled(context.getPolicyMap(), context.getWsdlPort())) {
            context.setCodec(createSecurityCodec(context.getEndpoint().getBinding()));
        }
    }

    @Override
    public Tube createTube(ServerTubelineAssemblyContext context) throws WebServiceException {
        if (HighAvailabilityProvider.INSTANCE.isHaEnvironmentConfigured()) {
            initHaBackingStores( context.getEndpoint());
        }

        //TEMP: uncomment this ServerPipelineHook hook = context.getEndpoint().getContainer().getSPI(ServerPipelineHook.class);
        ServerPipelineHook[] hooks = getServerTubeLineHooks();
        ServerPipelineHook hook = null;
        if (hooks != null && hooks.length > 0 && hooks[0] instanceof com.sun.xml.wss.provider.wsit.ServerPipeCreator) {
            //we let it override GF defaults
            hook = hooks[0];
            //set the Factory to JMACAuthConfigFactory if it is not already set to
            //something else.
            initializeJMAC();
        } else {
            hook = context.getEndpoint().getContainer().getSPI(ServerPipelineHook.class);
        }

        if (hook != null) {
            // TODO ask security to implement the hook.createSecurityTube(context);
            Tube head = context.getTubelineHead();
            Tube securityTube = hook.createSecurityTube(context);
            if (head == securityTube) {
                //it means we have hit the Default BaseClass Impl (shown above)
                // so fall back to createSecurityPipe
                // This can happen if we are running on SALIFIN/9.1.1 or any previous Appserver
                Pipe securityPipe = hook.createSecurityPipe(
                        context.getPolicyMap(),
                        context.getSEIModel(),
                        context.getWsdlPort(),
                        context.getEndpoint(),
                        context.getAdaptedTubelineHead());
                securityTube = PipeAdapter.adapt(securityPipe);
            }
            return securityTube;
        } else if (isSecurityEnabled(context.getPolicyMap(), context.getWsdlPort())) {
            if (hooks != null && hooks.length == 0) {
                return createSecurityTube(context);
            } else if (hooks != null && hooks.length > 0) {
                hook = hooks[0];
                Tube head = context.getTubelineHead();
                Tube securityTube = hook.createSecurityTube(context);
                if (head == securityTube) {
                    //it means we have hit the Default BaseClass Impl (shown above)
                    // so fall back to createSecurityPipe
                    // This can happen if we are running on SALIFIN/9.1.1 or any previous Appserver
                    Pipe securityPipe = hook.createSecurityPipe(
                            context.getPolicyMap(),
                            context.getSEIModel(),
                            context.getWsdlPort(),
                            context.getEndpoint(),
                            context.getAdaptedTubelineHead());
                    securityTube = PipeAdapter.adapt(securityPipe);
                }
                return securityTube;

            } else {
                log.log(Level.FINE, "cannot not use Unified Tube.");
                //return PipeAdapter.adapt(new SecurityServerPipe(context, context.getAdaptedTubelineHead()));
                return new SecurityServerTube(context, context.getTubelineHead());
            }

        } else {
            try {
                //look for XWSS 2.0 Style Security
                if (!context.isPolicyAvailable() && isSecurityConfigPresent(context)) {
                    return initializeXWSSServerTube(context);
                }
            } catch (NoClassDefFoundError err) {
            // do nothing
            }
        }

        return context.getTubelineHead();
    }

    private void initHaBackingStores(final WSEndpoint endpoint) {
        boolean wasNonceBsInitialized = false;
        boolean wasScBsInitialized = false;

        for (WebServiceFeature _feature : endpoint.getBinding().getFeatures()) {
            if (_feature instanceof SecurityFeatureConfigurator.SecurityStickyFeature) {
                SecurityFeatureConfigurator.SecurityStickyFeature feature = (SecurityFeatureConfigurator.SecurityStickyFeature) _feature;
                if (!wasNonceBsInitialized && feature.isNonceManagerUsed()) {
                    NonceManager.getInstance(maxNonceAge, endpoint);  //init the Nonce Manager HA BS
                    wasNonceBsInitialized = true;
                }
                if (!wasScBsInitialized && feature.isScUsed()) {
                    SessionManager.getSessionManager(endpoint, true,null); // this call initializes SCT backing store (if not initializes already
                    wasScBsInitialized = true;
                }
            }
        }
    }

    @Override
    public Tube createTube(ClientTubelineAssemblyContext context) throws WebServiceException {
        ClientPipelineHook hook = null;
        ClientPipelineHook[] hooks = getClientTublineHooks(context);
       if (context.getSEIModel() != null) {
            JAXBUtil.setSEIJAXBContext(context.getSEIModel().getJAXBContext());
        }
        if (hooks != null && hooks.length > 0) {
            for (ClientPipelineHook h : hooks) {
                if (h instanceof com.sun.xml.wss.provider.wsit.ClientPipeCreator) {
                    //give it preference
                    hook = h;
                    //set the Factory to JMACAuthConfigFactory if it is not already set to
                    //something else.
                    initializeJMAC();
                    break;
                } else {
                    hook = h;
                    break;
                }
            }
        }
        if (hook == null) {
            //Look for pipe-creation hook exposed in contaner.
            hook = context.getContainer().getSPI(ClientPipelineHook.class);
        }

        //If either mechanism for finding a ClientPipelineHook has found one, use it.
        if (hook != null) {
            Tube head = context.getTubelineHead();
            Tube securityTube = hook.createSecurityTube(context);
            if (head == securityTube) {
                //we have hit default baseclass impl
                //can happen with SailFin and GlassFish 9.x
                ClientPipeAssemblerContext pipeContext = new ClientPipeAssemblerContext(
                        context.getAddress(),
                        context.getWsdlPort(),
                        context.getService(),
                        context.getBinding(),
                        context.getContainer());
                Pipe securityPipe = hook.createSecurityPipe(context.getPolicyMap(), pipeContext, context.getAdaptedTubelineHead());
                if (isSecurityEnabled(context.getPolicyMap(), context.getWsdlPort())) {
                    ((MetroClientTubelineAssemblyContext) context).setScInitiator((SecureConversationInitiator) securityPipe);
                }
                securityTube = PipeAdapter.adapt(securityPipe);
            }
            return securityTube;
        } else if (isSecurityEnabled(context.getPolicyMap(), context.getWsdlPort())) {
            //Use the default WSIT Client Security Pipe
            //Pipe securityPipe = new SecurityClientPipe(context, context.getAdaptedTubelineHead());
            Tube securityTube = new SecurityClientTube(context, context.getTubelineHead());
            //context.setScInitiator((SecureConversationInitiator) securityPipe);
            ((MetroClientTubelineAssemblyContext) context).setScInitiator((SecureConversationInitiator) securityTube);
            //return PipeAdapter.adapt(securityPipe);
            return securityTube;
        } else if (!context.isPolicyAvailable() && isSecurityConfigPresent(context)) {
            //look for XWSS 2.0 Style Security
            // policyMap may be null in case of client dispatch without a client config file
            return initializeXWSSClientTube(context);
        } else {
            return context.getTubelineHead();
        }
    }

    private ClientPipelineHook[] getClientTublineHooks(ClientTubelineAssemblyContext context) {
        try {
            ClientPipelineHook[] hooks = loadSPs(ClientPipelineHook.class);
            if (hooks != null && hooks.length > 0) {
                return hooks;
            }
        } catch (ServiceConfigurationError ex) {
            if (ex.getCause() instanceof InstantiationException) {
                return new ClientPipelineHook[0];
            }
            return null;
        }
        return null;
    }

    /**
     * Checks to see whether WS-Security is enabled or not.
     *
     * @param policyMap policy map for {@link SecurityTubeFactory} assembler
     * @param wsdlPort wsdl:port
     * @return true if Security is enabled, false otherwise
     */
    private boolean isSecurityEnabled(PolicyMap policyMap, WSDLPort wsdlPort) {
        if (policyMap == null || wsdlPort == null) {
            return false;
        }

        try {
            PolicyMapKey endpointKey = PolicyMap.createWsdlEndpointScopeKey(wsdlPort.getOwner().getName(),
                    wsdlPort.getName());
            Policy policy = policyMap.getEndpointEffectivePolicy(endpointKey);

            if ((policy != null) &&
                    (policy.contains(SecurityPolicyVersion.SECURITYPOLICY200507.namespaceUri) ||
                    policy.contains(SecurityPolicyVersion.SECURITYPOLICY12NS.namespaceUri) ||
                    policy.contains(SecurityPolicyVersion.SECURITYPOLICY200512.namespaceUri))) {
                return true;
            }

            for (WSDLBoundOperation wbo : wsdlPort.getBinding().getBindingOperations()) {
                PolicyMapKey operationKey = PolicyMap.createWsdlOperationScopeKey(wsdlPort.getOwner().getName(),
                        wsdlPort.getName(),
                        wbo.getName());
                policy = policyMap.getOperationEffectivePolicy(operationKey);
                if ((policy != null) &&
                        (policy.contains(SecurityPolicyVersion.SECURITYPOLICY200507.namespaceUri) ||
                        policy.contains(SecurityPolicyVersion.SECURITYPOLICY12NS.namespaceUri))) {
                    return true;
                }

                policy = policyMap.getInputMessageEffectivePolicy(operationKey);
                if ((policy != null) &&
                        (policy.contains(SecurityPolicyVersion.SECURITYPOLICY200507.namespaceUri) ||
                        policy.contains(SecurityPolicyVersion.SECURITYPOLICY12NS.namespaceUri))) {
                    return true;
                }

                policy = policyMap.getOutputMessageEffectivePolicy(operationKey);
                if ((policy != null) &&
                        (policy.contains(SecurityPolicyVersion.SECURITYPOLICY200507.namespaceUri) ||
                        policy.contains(SecurityPolicyVersion.SECURITYPOLICY12NS.namespaceUri))) {
                    return true;
                }

                policy = policyMap.getFaultMessageEffectivePolicy(operationKey);
                if ((policy != null) &&
                        (policy.contains(SecurityPolicyVersion.SECURITYPOLICY200507.namespaceUri) ||
                        policy.contains(SecurityPolicyVersion.SECURITYPOLICY12NS.namespaceUri))) {
                    return true;
                }
            }
        } catch (PolicyException e) {
            throw new WebServiceException(e);
        }

        return false;
    }

    private Codec createSecurityCodec(WSBinding binding) {
        StreamSOAPCodec primaryCodec = Codecs.createSOAPEnvelopeXmlCodec(binding.getSOAPVersion());
        LazyStreamCodec lsc = new LazyStreamCodec(primaryCodec);
        return Codecs.createSOAPBindingCodec(binding, lsc);
    }

    private static 

P[] loadSPs(final Class

svcClass) { return ServiceFinder.find(svcClass, ServiceLoader.load(svcClass)).toArray(); } private ServerPipelineHook[] getServerTubeLineHooks() { // The ServerPipeline Hook in GF fails to create the Pipe because GF ServerPipeCreator does not have a // Default CTOR. //TODO: change this method impl later. try { ServerPipelineHook[] hooks = loadSPs(ServerPipelineHook.class); if (hooks != null && hooks.length > 0) { return hooks; } } catch (ServiceConfigurationError ex) { //workaround since GF ServerPipeCreator has no Default CTOR. if (ex.getCause() instanceof InstantiationException) { return new ServerPipelineHook[0]; } return null; } return null; } private boolean isSecurityConfigPresent(ClientTubelineAssemblyContext context) { //look for XWSS 2.0 style config file in META-INF classpath try { String configUrl = "META-INF/client_security_config.xml"; URL url = SecurityUtil.loadFromClasspath(configUrl); if (url != null) { return true; } } catch (Exception e) { //boolean bool = Boolean.getBoolean("USE_XWSS_SECURITY"); } //returning true by default for now, because the Client Side Security Config is //only accessible as a Runtime Property on BindingProvider.RequestContext //With Metro 2.0 provide a way of disabling the default rule above and one would need to //set System Property DISABLE_XWSS_SECURITY to disable the client pipeline. return !disable; } private boolean isSecurityConfigPresent(ServerTubelineAssemblyContext context) { QName serviceQName = context.getEndpoint().getServiceName(); //TODO: not sure which of the two above will give the service name as specified in DD String serviceLocalName = serviceQName.getLocalPart(); WSSServletContextFacade ctxt = ServletContextUtil.getServletContextFacade(context.getEndpoint()); String serverName = "server"; if (ctxt != null) { String serverConfig = "/WEB-INF/" + serverName + "_security_config.xml"; URL url = ctxt.getResource(serverConfig); if (url == null) { serverConfig = "/WEB-INF/" + serviceLocalName + "_security_config.xml"; url = ctxt.getResource(serverConfig); } return url != null; } 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 url = SecurityUtil.loadFromClasspath(serverConfig); if (url == null) { serverConfig = "META-INF/" + serviceLocalName + "_security_config.xml"; url = SecurityUtil.loadFromClasspath(serverConfig); } return url != null; } } private Tube initializeXWSSClientTube(ClientTubelineAssemblyContext context) { return new XWSSClientTube(context.getWsdlPort(), context.getService(), context.getBinding(), context.getTubelineHead()); } private Tube initializeXWSSServerTube(ServerTubelineAssemblyContext context) { return new XWSSServerTube(context.getEndpoint(), context.getWsdlPort(), context.getTubelineHead()); } @SuppressWarnings("unchecked") private Tube createSecurityTube(ServerTubelineAssemblyContext context) { HashMap props = new HashMap(); props.put(POLICY, context.getPolicyMap()); props.put(SEI_MODEL, context.getSEIModel()); props.put(WSDL_MODEL, context.getWsdlPort()); props.put(ENDPOINT, context.getEndpoint()); props.put(NEXT_PIPE, context.getAdaptedTubelineHead()); //TODO: set it based on owner.getBinding() but it is not clear // how SOAP/TCP is disthinguished. try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class gfServerPipeClass = null; if (loader != null) { gfServerPipeClass = loader.loadClass(GF_SERVER_SEC_PIPE); } else { gfServerPipeClass = Class.forName(GF_SERVER_SEC_PIPE); } if (gfServerPipeClass != null) { //now instantiate the class Constructor[] ctors = gfServerPipeClass.getDeclaredConstructors(); Constructor ctor = null; for (int i = 0; i < ctors.length; i++) { ctor = ctors[i]; Class[] paramTypes = ctor.getParameterTypes(); if (paramTypes[0].equals(Map.class)) { break; } } //Constructor ctor = gfServerPipeClass.getConstructor(Map.class, Pipe.class, Boolean.class); if (ctor != null) { return PipeAdapter.adapt((Pipe) ctor.newInstance(props, context.getAdaptedTubelineHead(), false)); } } return context.getTubelineHead(); } catch (InstantiationException | ClassNotFoundException | SecurityException | InvocationTargetException | IllegalArgumentException | IllegalAccessException ex) { throw new WebServiceException(ex); } } @SuppressWarnings("unchecked") private void initializeJMAC() { // define default factory if it is not already defined // factory will be constructed on first getFactory call. final ClassLoader loader = Thread.currentThread().getContextClassLoader(); AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { /*String defaultFactory = Security.getProperty(AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY); if (defaultFactory == null || !(JMACAuthConfigFactory.class.getName().equals(defaultFactory))) { Security.setProperty(AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY, JMACAuthConfigFactory.class.getName()); }*/ AuthConfigFactory factory = AuthConfigFactory.getFactory(); if (!(factory instanceof JMACAuthConfigFactory)) { AuthConfigFactory.setFactory(new JMACAuthConfigFactory(loader)); } return null; // nothing to return } }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy