Package org.apache.rampart.util

Source Code of org.apache.rampart.util.RampartUtil

/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed 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.apache.rampart.util;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.axiom.soap.*;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.dataretrieval.DRConstants;
import org.apache.axis2.dataretrieval.client.MexClient;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.mex.MexConstants;
import org.apache.axis2.mex.MexException;
import org.apache.axis2.mex.om.Metadata;
import org.apache.axis2.mex.om.MetadataReference;
import org.apache.axis2.mex.om.MetadataSection;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.rahas.RahasConstants;
import org.apache.rahas.Token;
import org.apache.rahas.TrustException;
import org.apache.rahas.TrustUtil;
import org.apache.rahas.client.STSClient;
import org.apache.rampart.PolicyBasedResultsValidator;
import org.apache.rampart.PolicyValidatorCallbackHandler;
import org.apache.rampart.RampartConfigCallbackHandler;
import org.apache.rampart.RampartConstants;
import org.apache.rampart.RampartException;
import org.apache.rampart.RampartMessageData;
import org.apache.rampart.policy.RampartPolicyData;
import org.apache.rampart.policy.SupportingPolicyData;
import org.apache.rampart.policy.model.CryptoConfig;
import org.apache.rampart.policy.model.RampartConfig;
import org.apache.ws.secpolicy.SPConstants;
import org.apache.ws.secpolicy.model.*;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.conversation.ConversationConstants;
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.message.WSSecBase;
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.util.Loader;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.utils.Constants;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import javax.crypto.KeyGenerator;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
import javax.servlet.http.HttpServletRequest;

import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class RampartUtil {

    private static final String CRYPTO_PROVIDER = "org.apache.ws.security.crypto.provider";
    private static Log log = LogFactory.getLog(RampartUtil.class);

    private static Map<String, CachedCrypto> cryptoStore = new ConcurrentHashMap<String, CachedCrypto>();

    private static class CachedCrypto {
        private Crypto crypto;
        private long creationTime;

        public CachedCrypto(Crypto crypto, long creationTime) {
            this.crypto = crypto;
            this.creationTime = creationTime;
        }
    }

    public static CallbackHandler getPasswordCB(RampartMessageData rmd) throws RampartException {

        MessageContext msgContext = rmd.getMsgContext();
        RampartPolicyData rpd = rmd.getPolicyData();
       
        return getPasswordCB(msgContext, rpd);
    }

    /**
     * @param msgContext
     * @param rpd
     * @return The <code>CallbackHandler</code> instance
     * @throws RampartException
     */
    public static CallbackHandler getPasswordCB(MessageContext msgContext, RampartPolicyData rpd) throws RampartException {
       
        CallbackHandler cbHandler;

        if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getPwCbClass() != null) {
           
            String cbHandlerClass = rpd.getRampartConfig().getPwCbClass();
            ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

            if (log.isDebugEnabled()) {
                log.debug("loading class : " + cbHandlerClass);
            }

            Class cbClass;
            try {
                cbClass = Loader.loadClass(classLoader, cbHandlerClass);
            } catch (ClassNotFoundException e) {
                throw new RampartException("cannotLoadPWCBClass",
                        new String[]{cbHandlerClass}, e);
            }
            try {
                cbHandler = (CallbackHandler) cbClass.newInstance();
            } catch (java.lang.Exception e) {
                throw new RampartException("cannotCreatePWCBInstance",
                        new String[]{cbHandlerClass}, e);
            }
        } else {
            cbHandler = (CallbackHandler) msgContext.getProperty(
                    WSHandlerConstants.PW_CALLBACK_REF);
            if(cbHandler == null) {
                Parameter param = msgContext.getParameter(
                        WSHandlerConstants.PW_CALLBACK_REF);
                if(param != null) {
                    cbHandler = (CallbackHandler)param.getValue();
                }
            }
        }
       
        return cbHandler;
    }
   
   /**
    * Returns an instance of PolicyValidatorCallbackHandler to be used to validate ws-security results.
    *
    * @param msgContext {@link MessageContext}
    * @param rpd {@link RampartPolicyData}
    * @return {@link PolicyValidatorCallbackHandler}
    * @throws RampartException RampartException
    */
   public static PolicyValidatorCallbackHandler getPolicyValidatorCB(MessageContext msgContext, RampartPolicyData rpd) throws RampartException {
       
       PolicyValidatorCallbackHandler cbHandler;

        if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getPolicyValidatorCbClass() != null) {
           
            String cbHandlerClass = rpd.getRampartConfig().getPolicyValidatorCbClass();
            ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

            if (log.isDebugEnabled()) {
                log.debug("loading class : " + cbHandlerClass);
            }

            Class cbClass;
            try {
                cbClass = Loader.loadClass(classLoader, cbHandlerClass);
            } catch (ClassNotFoundException e) {
                throw new RampartException("cannotLoadPolicyValidatorCbClass",
                        new String[]{cbHandlerClass}, e);
            }
            try {
                cbHandler = (PolicyValidatorCallbackHandler) cbClass.newInstance();
            } catch (java.lang.Exception e) {
                throw new RampartException("cannotCreatePolicyValidatorCallbackInstance",
                        new String[]{cbHandlerClass}, e);
            }
           
        } else { // Initialise default PolicyValidatorCallbackHandler...
            cbHandler = new PolicyBasedResultsValidator();
        }
       
        return cbHandler;
    }
  
   public static RampartConfigCallbackHandler getRampartConfigCallbackHandler(MessageContext msgContext,
           RampartPolicyData rpd) throws RampartException {
      
       RampartConfigCallbackHandler rampartConfigCB;
  
       if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getRampartConfigCbClass() != null) {
          
           String cbHandlerClass = rpd.getRampartConfig().getRampartConfigCbClass();
           ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

           if (log.isDebugEnabled()) {
               log.debug("loading class : " + cbHandlerClass);
           }

           Class cbClass;
           try {
               cbClass = Loader.loadClass(classLoader, cbHandlerClass);
           } catch (ClassNotFoundException e) {
               throw new RampartException("cannotLoadRampartConfigCallbackClass",
                       new String[]{cbHandlerClass}, e);
           }
           try {
               rampartConfigCB = (RampartConfigCallbackHandler) cbClass.newInstance();
           } catch (java.lang.Exception e) {
               throw new RampartException("cannotCreateRampartConfigCallbackInstance",
                       new String[]{cbHandlerClass}, e);
           }
          
           return rampartConfigCB;
          
       }
      
       return null;
   }

    /**
     * Perform a callback to get a password.
     * <p/>
     * The called back function gets an indication why to provide a password:
     * to produce a UsernameToken, Signature, or a password (key) for a given
     * name.
     */
    public static WSPasswordCallback performCallback(CallbackHandler cbHandler,
                                               String username,
                                               int doAction)
            throws RampartException {

        WSPasswordCallback pwCb;
        int reason = 0;

        switch (doAction) {
        case WSConstants.UT:
        case WSConstants.UT_SIGN:
                reason = WSPasswordCallback.USERNAME_TOKEN;
                break;
            case WSConstants.SIGN:
                reason = WSPasswordCallback.SIGNATURE;
                break;
            case WSConstants.ENCR:
                reason = WSPasswordCallback.KEY_NAME;
                break;
        }
        pwCb = new WSPasswordCallback(username, reason);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = pwCb;
        /*
        * Call back the application to get the password
        */
        try {
            cbHandler.handle(callbacks);
        } catch (Exception e) {
            throw new RampartException("pwcbFailed", e);
        }
        return pwCb;
    }
   
    /**
     * Create the <code>Crypto</code> instance for encryption using information
     * from the rampart configuration assertion
     *
     * @param config
     * @return The <code>Crypto</code> instance to be used for encryption
     * @throws RampartException
     */
    public static Crypto getEncryptionCrypto(RampartConfig config, ClassLoader loader)
            throws RampartException {

        log.debug("Loading encryption crypto");

        Crypto crypto = null;

        if (config != null && config.getEncrCryptoConfig() != null) {
            CryptoConfig cryptoConfig = config.getEncrCryptoConfig();
            String provider = cryptoConfig.getProvider();
            if (log.isDebugEnabled()) {
                log.debug("Using provider: " + provider);
            }
            Properties prop = cryptoConfig.getProp();
            prop.put(CRYPTO_PROVIDER, provider);

            String cryptoKey = null;
            String interval = null;
            if (cryptoConfig.isCacheEnabled()) {
                if (cryptoConfig.getCryptoKey() != null) {
                    cryptoKey = prop.getProperty(cryptoConfig.getCryptoKey());
                    interval = cryptoConfig.getCacheRefreshInterval();
                }
                else if(provider.equals(RampartConstants.MERLIN_CRYPTO_IMPL)){
                    cryptoKey = cryptoConfig.getProp().getProperty(RampartConstants.MERLIN_CRYPTO_IMPL_CACHE_KEY);
                }
            }


            if (cryptoKey != null) {
                // Crypto caching is enabled
                crypto = retrieveCryptoFromCache(cryptoKey.trim() + "#" + provider.trim(), interval);
            }

            if (crypto == null) {
                // cache miss
                crypto = createCrypto(prop, loader);

                if (cryptoKey != null) {
                    // Crypto caching is enabled - cache the Crypto object
                    cacheCrypto(cryptoKey.trim() + "#" + provider.trim(), crypto);
                }
            }
        } else {
            log.debug("Trying the signature crypto info");
            crypto = getSignatureCrypto(config, loader);
        }
        return crypto;
    }

    private static Crypto createCrypto(Properties properties, ClassLoader classLoader) throws RampartException {

        try {
            return CryptoFactory.getInstance(properties, classLoader);
        } catch (WSSecurityException e) {
            log.error("Error loading crypto properties.", e);
            throw new RampartException("cannotCrateCryptoInstance", e);
        }
    }
   
    /**
     * Create the <code>Crypto</code> instance for signature using information
     * from the rampart configuration assertion
     *
     * @param config
     * @return The <code>Crypto</code> instance to be used for signature
     * @throws RampartException
     */
    public static Crypto getSignatureCrypto(RampartConfig config, ClassLoader loader)
            throws RampartException {

        log.debug("Loading Signature crypto");

        Crypto crypto = null;

        if (config != null && config.getSigCryptoConfig() != null) {
            CryptoConfig cryptoConfig = config.getSigCryptoConfig();
            String provider = cryptoConfig.getProvider();
            if (log.isDebugEnabled()) {
                log.debug("Using provider: " + provider);
            }
            Properties prop = cryptoConfig.getProp();
            prop.put(CRYPTO_PROVIDER, provider);
            String cryptoKey = null;
            String interval = null;

            if (cryptoConfig.isCacheEnabled()) {
                if (cryptoConfig.getCryptoKey() != null) {
                    cryptoKey = prop.getProperty(cryptoConfig.getCryptoKey());
                    interval = cryptoConfig.getCacheRefreshInterval();
                }
                else if(provider.equals(RampartConstants.MERLIN_CRYPTO_IMPL)){
                    cryptoKey = cryptoConfig.getProp().getProperty(RampartConstants.MERLIN_CRYPTO_IMPL_CACHE_KEY);
                }
            }

            if (cryptoKey != null) {
                // cache enabled
                crypto = retrieveCryptoFromCache(cryptoKey.trim() + "#" + provider.trim(), interval);
            }

            if (crypto == null) {
                // cache miss
                crypto = createCrypto(prop, loader);
                if (cryptoKey != null) {
                    // cache enabled - let's cache
                    cacheCrypto(cryptoKey.trim() + "#" + provider.trim(), crypto);
                }
            }
        }
        return crypto;
    }
   
   
    /**
     * figureout the key identifier of a give X509Token
     * @param token
     * @return The key identifier of a give X509Token
     * @throws RampartException
     */
    public static int getKeyIdentifier(X509Token token) throws RampartException {
        if (token.isRequireIssuerSerialReference()) {
            return WSConstants.ISSUER_SERIAL;
        } else if (token.isRequireThumbprintReference()) {
            return WSConstants.THUMBPRINT_IDENTIFIER;
        } else if (token.isRequireEmbeddedTokenReference()) {
            return WSConstants.BST_DIRECT_REFERENCE;
        } else {
            throw new RampartException(
                    "unknownKeyRefSpeficier");

        }
    }
   
    /**
     * Process a give issuer address element and return the address.
     * @param issuerAddress
     * @return The address of an issuer address element
     * @throws RampartException If the issuer address element is malformed.
     */
    public static String processIssuerAddress(OMElement issuerAddress)
        throws RampartException {

      if(issuerAddress == null){
        throw new RampartException("invalidIssuerAddress",
                                   new String[] { "Issuer address null" });
      }
     
      if(issuerAddress.getText() == null || "".equals(issuerAddress.getText())) {
        throw new RampartException("invalidIssuerAddress",
                                   new String[] { issuerAddress.toString() });
        }

      return issuerAddress.getText().trim();
    }
   
    /**
     * Retrieve policy using metadata reference
     * <wsa:Metadata xmlns:wsa="http://www.w3.org/2005/08/addressing">
     <mex:Metadata
     *       xmlns:mex="http://schemas.xmlsoap.org/ws/2004/09/mex"
     *       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     *           <mex:MetadataSection>
     *                  <mex:MetadataReference>
     *                      <wsa:Address>http://address/of/mex/service</wsa:Address>
     *                  </mex:MetadataReference>
     *           </mex:MetadataSection>
     </mex:Metadata>
     * </wsa:Metadata>
     * @param mex Metadata element
     * @return Policy from the mex service
     */
    public static Policy getPolicyFromMetadataRef(OMElement mex) throws RampartException {
       
        try {
            Metadata metadata = new Metadata();
            metadata.fromOM(mex.getFirstElement());
           
            MetadataSection[] metadataSections = metadata.getMetadatSections();
            MetadataReference reference = metadataSections[0].getMetadataReference();
           
            MexClient serviceClient = new MexClient();

            Options options = serviceClient.getOptions();
            options.setTo(reference.getEPR());
            options.setAction(DRConstants.SPEC.Actions.GET_METADATA_REQUEST);
           
            OMElement request = serviceClient.setupGetMetadataRequest(
                                                        MexConstants.SPEC.DIALECT_TYPE_POLICY,null);
            OMElement result = serviceClient.sendReceive(request);
           
            metadata.fromOM(result);
            MetadataSection[] mexSecs =  metadata.getMetadataSection(MexConstants.SPEC.DIALECT_TYPE_POLICY, null);
            OMElement policyElement = (OMElement) mexSecs[0].getInlineData();
           
            return PolicyEngine.getPolicy(policyElement);
           
           
        } catch (MexException e) {
            throw new RampartException("Error Retrieving the policy from mex", e);
        } catch (AxisFault e) {
            throw new RampartException("Error Retrieving the policy from mex", e);
        }
       
    }
   
    public static Policy addRampartConfig (RampartMessageData rmd, Policy policy) {
       
        RampartConfig servicRampConf = rmd.getPolicyData().getRampartConfig();       
        RampartConfig stsRampConf = new RampartConfig();
       
        //TODO copy all the properties of service ramp conf to sts ramp conf
        stsRampConf.setUser(servicRampConf.getUser());
        stsRampConf.setSigCryptoConfig(servicRampConf.getSigCryptoConfig());
        stsRampConf.setPwCbClass(servicRampConf.getPwCbClass());
       
        stsRampConf.setEncryptionUser(servicRampConf.getStsAlias());
        stsRampConf.setEncrCryptoConfig(servicRampConf.getStsCryptoConfig());
       
        policy.addAssertion(stsRampConf);
       
        return policy;
       
    }
   
   
    public static OMElement createRSTTempalteForSCT(int conversationVersion,
            int wstVersion) throws RampartException {
        try {
            log.debug("Creating RSTTemplate for an SCT request");
            OMFactory fac = OMAbstractFactory.getOMFactory();
           
            OMNamespace wspNs = fac.createOMNamespace(SPConstants.P_NS, "wsp");
            OMElement rstTempl = fac.createOMElement(
                    SPConstants.REQUEST_SECURITY_TOKEN_TEMPLATE,
                    wspNs);
           
            //Create TokenType element and set the value
            OMElement tokenTypeElem = TrustUtil.createTokenTypeElement(
                    wstVersion, rstTempl);
            String tokenType = ConversationConstants
                    .getWSCNs(conversationVersion)
                    + ConversationConstants.TOKEN_TYPE_SECURITY_CONTEXT_TOKEN;
            tokenTypeElem.setText(tokenType);
           
            return rstTempl;
        } catch (TrustException e) {
            throw new RampartException("errorCreatingRSTTemplateForSCT", e);
        } catch (ConversationException e) {
            throw new RampartException("errorCreatingRSTTemplateForSCT", e);
        }
    }
   

    public static int getTimeToLive(RampartMessageData messageData) {

        RampartConfig rampartConfig = messageData.getPolicyData().getRampartConfig();
        if (rampartConfig != null) {
            String ttl = rampartConfig.getTimestampTTL();
            int ttl_i = 0;
            if (ttl != null) {
                try {
                    ttl_i = Integer.parseInt(ttl);
                } catch (NumberFormatException e) {
                    ttl_i = messageData.getTimeToLive();
                }
            }
            if (ttl_i <= 0) {
                ttl_i = messageData.getTimeToLive();
            }
            return ttl_i;
        } else {
            return RampartConfig.DEFAULT_TIMESTAMP_TTL;
        }
    }

    public static int getTimestampMaxSkew(RampartMessageData messageData) {

        RampartConfig rampartConfig = messageData.getPolicyData().getRampartConfig();
        if (rampartConfig != null) {
            String maxSkew = rampartConfig.getTimestampMaxSkew();
            int maxSkew_i = 0;
            if (maxSkew != null) {
                try {
                    maxSkew_i = Integer.parseInt(maxSkew);
                } catch (NumberFormatException e) {
                    maxSkew_i = messageData.getTimestampMaxSkew();
                }
            }
            if (maxSkew_i < 0) {
                maxSkew_i = 0;
            }
            return maxSkew_i;
        } else {
            return RampartConfig.DEFAULT_TIMESTAMP_MAX_SKEW;
        }
    }

    /**
     * Obtain a security context token.
     * @param rmd
     * @param secConvTok
     * @return Return the SecurityContextidentifier of the token
     * @throws TrustException
     * @throws RampartException
     */
    public static String getSecConvToken(RampartMessageData rmd,
            SecureConversationToken secConvTok) throws TrustException,
            RampartException {
        String action = TrustUtil.getActionValue(
                rmd.getWstVersion(),
                RahasConstants.RST_ACTION_SCT);
       
        // Get sts epr
        OMElement issuerEpr = secConvTok.getIssuerEpr();
        String issuerEprAddress = rmd.getMsgContext().getTo().getAddress();
        if(issuerEpr != null) {
            issuerEprAddress = RampartUtil.processIssuerAddress(issuerEpr);
        }
       
        //Find SC version
        int conversationVersion = rmd.getSecConvVersion();
       
        OMElement rstTemplate = RampartUtil.createRSTTempalteForSCT(
                conversationVersion,
                rmd.getWstVersion());
       
        Policy stsPolicy = null;

        //Try boot strap policy
        Policy bsPol = secConvTok.getBootstrapPolicy();
       
        if(bsPol != null) {
            log.debug("BootstrapPolicy found");
            bsPol.addAssertion(rmd.getPolicyData().getRampartConfig());
            //copy the <wsoma:OptimizedMimeSerialization/> to BootstrapPolicy
            if (rmd.getPolicyData().getMTOMAssertion() != null) {
              bsPol.addAssertion(rmd.getPolicyData().getMTOMAssertion())
            }
            stsPolicy = bsPol;
        } else {
            //No bootstrap policy use issuer policy
            log.debug("No bootstrap policy, using issuer policy");
            stsPolicy = rmd.getPolicyData().getIssuerPolicy();
        }
       
        String id = getToken(rmd, rstTemplate,
                issuerEprAddress, action, stsPolicy);

        if (log.isDebugEnabled()) {
            log.debug("SecureConversationToken obtained: id=" + id);
        }
        return id;
    }
   

    /**
     * Obtain an issued token.
     * @param rmd
     * @param issuedToken
     * @return The identifier of the issued token
     * @throws RampartException
     */
    public static String getIssuedToken(RampartMessageData rmd,
            IssuedToken issuedToken) throws RampartException {

        try {
           
            //TODO : Provide the overriding mechanism to provide a custom way of
            //obtaining a token
           
            String action = TrustUtil.getActionValue(rmd.getWstVersion(),
                    RahasConstants.RST_ACTION_ISSUE);

            // Get sts epr
            String issuerEprAddress = RampartUtil.processIssuerAddress(issuedToken
                    .getIssuerEpr());

            OMElement rstTemplate = issuedToken.getRstTemplate();

            // Get STS policy
            Policy stsPolicy = (Policy)rmd.getMsgContext().getProperty(RampartMessageData.RAMPART_STS_POLICY);
           
            if( stsPolicy == null && issuedToken.getIssuerMex() != null) {
                stsPolicy = RampartUtil.getPolicyFromMetadataRef(issuedToken.getIssuerMex());
                RampartUtil.addRampartConfig(rmd, stsPolicy);
            }

            String id = getToken(rmd, rstTemplate, issuerEprAddress, action,
                    stsPolicy);

            if (log.isDebugEnabled()) {
                log.debug("Issued token obtained: id=" + id);
            }
            return id;
        } catch (TrustException e) {
            throw new RampartException("errorInObtainingToken", e);
        }
    }
   
    /**
     * Request a token.
     * @param rmd
     * @param rstTemplate
     * @param issuerEpr
     * @param action
     * @param issuerPolicy
     * @return Return the identifier of the obtained token
     * @throws RampartException
     */
    public static String getToken(RampartMessageData rmd, OMElement rstTemplate,
            String issuerEpr, String action, Policy issuerPolicy) throws RampartException {

        try {
            //First check whether the user has provided the token
            MessageContext msgContext = rmd.getMsgContext();
            String customTokeId = (String) msgContext
                    .getProperty(RampartMessageData.KEY_CUSTOM_ISSUED_TOKEN);
            if(customTokeId != null) {
                return customTokeId;
            } else {
   
                Axis2Util.useDOOM(false);
               
                STSClient client = new STSClient(rmd.getMsgContext()
                        .getConfigurationContext());
                // Set request action
                client.setAction(action);
               
                client.setVersion(rmd.getWstVersion());
               
                client.setRstTemplate(rstTemplate);
       
                // Set crypto information
                Crypto crypto = RampartUtil.getSignatureCrypto(rmd.getPolicyData().getRampartConfig(),
                        rmd.getMsgContext().getAxisService().getClassLoader());
                CallbackHandler cbh = RampartUtil.getPasswordCB(rmd);
                client.setCryptoInfo(crypto, cbh);
       
                // Get service policy
                Policy servicePolicy = rmd.getServicePolicy();
       
                // Get service epr
                String servceEprAddress = rmd.getMsgContext()
                        .getOptions().getTo().getAddress();
       
                //If addressing version can be found set it
                Object addrVersionNs = msgContext.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
                if(addrVersionNs != null) {
                    client.setAddressingNs((String)addrVersionNs);
                }
               
                Options options = new Options();
               
                options.setUserName(rmd.getMsgContext().getOptions().getUserName());
                options.setPassword(rmd.getMsgContext().getOptions().getPassword());
               
                if (msgContext.getProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER) != null) {
                    Protocol protocolHandler =
                        (Protocol)msgContext.getProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER);;
                    options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, protocolHandler);                
                }
               
                if (msgContext.getParameter(WSHandlerConstants.PW_CALLBACK_REF) != null ) {
                    Parameter pwCallback = msgContext.getParameter(WSHandlerConstants.PW_CALLBACK_REF);
                    client.addParameter(pwCallback);
                }
               
                client.setOptions(options);
               
                //Set soap version
                if (msgContext.isSOAP11()) {
                    client.setSoapVersion(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
                } else {
                    client.setSoapVersion(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
                }
               
               
                //Make the request
                org.apache.rahas.Token rst =
                    client.requestSecurityToken(servicePolicy,
                                                issuerEpr,
                                                issuerPolicy,
                                                servceEprAddress);
               
                //Add the token to token storage
                rst.setState(Token.ISSUED);
                rmd.getTokenStorage().add(rst);
                Axis2Util.useDOOM(true);
                return rst.getId();
            }
        } catch (Exception e) {
            throw new RampartException("errorInObtainingToken", e);
        }
    }

    public static String getSoapBodyId(SOAPEnvelope env) {
        return addWsuIdToElement(env.getBody());
    }
   
    public static String addWsuIdToElement(OMElement elem) {
        String id;
       
        //first try to get the Id attr
        OMAttribute idAttr = elem.getAttribute(new QName("Id"));
        if(idAttr == null) {
            //then try the wsu:Id value
            idAttr = elem.getAttribute(new QName(WSConstants.WSU_NS, "Id"));
        }
       
        if(idAttr != null) {
            id = idAttr.getAttributeValue();
        } else {
            //Add an id
            OMNamespace ns = elem.getOMFactory().createOMNamespace(
                    WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
            id = "Id-" + elem.hashCode();
            idAttr = elem.getOMFactory().createOMAttribute("Id", ns, id);
            elem.addAttribute(idAttr);
        }
       
        return id;
    }
   
    public static Element appendChildToSecHeader(RampartMessageData rmd,
            OMElement elem) {
        return appendChildToSecHeader(rmd, (Element)elem);
    }
   
    public static Element appendChildToSecHeader(RampartMessageData rmd,
            Element elem) {
        Element secHeaderElem = rmd.getSecHeader().getSecurityHeader();
        Node node = secHeaderElem.getOwnerDocument().importNode(
                        elem, true);
        return (Element)secHeaderElem.appendChild(node);
    }

    public static Element insertSiblingAfter(RampartMessageData rmd,
            Element child, Element sibling) {
        if (child == null) {
            return appendChildToSecHeader(rmd, sibling);
        } else {
            if (child.getOwnerDocument().equals(sibling.getOwnerDocument())) {

                if (child.getParentNode() == null
                        && !child.getLocalName().equals("UsernameToken")) {
                    rmd.getSecHeader().getSecurityHeader().appendChild(child);
                }
                ((OMElement) child).insertSiblingAfter((OMElement) sibling);
                return sibling;
            } else {
                Element newSib = (Element) child.getOwnerDocument().importNode(
                        sibling, true);
                ((OMElement) child).insertSiblingAfter((OMElement) newSib);
                return newSib;
            }
        }
    }
   
    public static Element insertSiblingBefore(RampartMessageData rmd, Element child, Element sibling) {
        if(child == null) {
            return appendChildToSecHeader(rmd, sibling);
        } else {
            if(child.getOwnerDocument().equals(sibling.getOwnerDocument())) {
                ((OMElement)child).insertSiblingBefore((OMElement)sibling);
                return sibling;
            } else {
                Element newSib = (Element)child.getOwnerDocument().importNode(sibling, true);
                ((OMElement)child).insertSiblingBefore((OMElement)newSib);
                return newSib;
            }
        }
       
    }
   
    public static List<WSEncryptionPart> getEncryptedParts(RampartMessageData rmd) {
    RampartPolicyData rpd = rmd.getPolicyData();
    SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
    List<WSEncryptionPart> encryptedPartsElements = getPartsAndElements(false, envelope,
        rpd.isEncryptBody() && !rpd.isEncryptBodyOptional(), rpd
            .getEncryptedParts(), rpd.getEncryptedElements(), rpd
            .getDeclaredNamespaces());
    return getContentEncryptedElements(encryptedPartsElements, envelope,
        rpd.getContentEncryptedElements(), rpd.getDeclaredNamespaces());
  }

  public static List<WSEncryptionPart> getSignedParts(RampartMessageData rmd) {
    RampartPolicyData rpd = rmd.getPolicyData();
    SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();

        //"signAllHeaders" indicates that all the headers should be signed.
        if (rpd.isSignAllHeaders()) {
            Iterator childHeaders = envelope.getHeader().getChildElements();
            while (childHeaders.hasNext()) {
               OMElement hb = (OMElement) childHeaders.next();
                if (!(hb.getLocalName().equals(WSConstants.WSSE_LN)
                        && hb.getNamespace().getNamespaceURI().equals(WSConstants.WSSE_NS))) {
                    rpd.addSignedPart(hb.getNamespace().getNamespaceURI(),hb.getLocalName());
                }
           }
        }

    return getPartsAndElements(true, envelope, rpd.isSignBody()
        && !rpd.isSignBodyOptional(), rpd.getSignedParts(), rpd
        .getSignedElements(), rpd.getDeclaredNamespaces());
  }

  public static List<WSEncryptionPart> getSupportingEncryptedParts(RampartMessageData rmd,
      SupportingPolicyData rpd) {
    SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
    return getPartsAndElements(false, envelope, rpd.isEncryptBody()
        && !rpd.isEncryptBodyOptional(), rpd.getEncryptedParts(), rpd
        .getEncryptedElements(), rpd.getDeclaredNamespaces());
  }

  public static List<WSEncryptionPart> getSupportingSignedParts(RampartMessageData rmd,
      SupportingPolicyData rpd) {
    SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
    return getPartsAndElements(true, envelope, rpd.isSignBody()
        && !rpd.isSignBodyOptional(), rpd.getSignedParts(), rpd
        .getSignedElements(), rpd.getDeclaredNamespaces());
  }
   
    public static Set findAllPrefixNamespaces(OMElement currentElement, HashMap decNamespacess)
    {
      Set<OMNamespace> results = new HashSet<OMNamespace>();
     
      //Find declared namespaces
      findPrefixNamespaces(currentElement,results);
     
      //Get all default namespaces
      List defaultNamespaces = getDefaultPrefixNamespaces(currentElement.getOMFactory());
        for (Object defaultNamespace : defaultNamespaces) {
            OMNamespace ns = (OMNamespace) defaultNamespace;
            results.add(ns);
        }

        for (Object o : decNamespacess.keySet()) {
            String prefix = (String) o;
            String ns = (String) decNamespacess.get(prefix);
            OMFactory omFactory = currentElement.getOMFactory();
            OMNamespace namespace = omFactory.createOMNamespace(ns, prefix);
            results.add(namespace);

        }
     
      return results;
    }

    private static void findPrefixNamespaces(OMElement e, Set<OMNamespace> results) {

        Iterator iterator = e.getAllDeclaredNamespaces();

        if (iterator != null) {
            while (iterator.hasNext())
                results.add((OMNamespace)iterator.next());
        }

        Iterator children = e.getChildElements();

        while (children.hasNext()) {
            findPrefixNamespaces((OMElement) children.next(), results);
        }
    }
   
    private static List getDefaultPrefixNamespaces(OMFactory factory)
    {
      List<OMNamespace> namespaces = new ArrayList<OMNamespace>();

      // put default namespaces here (sp, soapenv, wsu, etc...)
      namespaces.add(factory.createOMNamespace(WSConstants.ENC_NS, WSConstants.ENC_PREFIX));
      namespaces.add(factory.createOMNamespace(WSConstants.SIG_NS, WSConstants.SIG_PREFIX));
      namespaces.add(factory.createOMNamespace(WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX));
      namespaces.add(factory.createOMNamespace(WSConstants.WSU_NS, WSConstants.WSU_PREFIX));
     
      return namespaces;
     
    }
   
    public static List<WSEncryptionPart> getContentEncryptedElements (List<WSEncryptionPart> encryptedPartsElements,
                                                 SOAPEnvelope envelope,List<String> elements, HashMap decNamespaces ) {
       
        Set namespaces = findAllPrefixNamespaces(envelope, decNamespaces);

        for (String expression : elements) {
            try {
                XPath xp = new AXIOMXPath(expression);

                for (Object objectNamespace : namespaces) {
                    OMNamespace tmpNs = (OMNamespace) objectNamespace;
                    xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
                }

                List selectedNodes = xp.selectNodes(envelope);

                for (Object selectedNode : selectedNodes) {
                    OMElement e = (OMElement) selectedNode;

                    String localName = e.getLocalName();
                    String namespace = e.getNamespace() != null ? e.getNamespace().getNamespaceURI() : null;

                    OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                    String wsuId = null;
                    if (wsuIdAttribute != null) {
                        wsuId = wsuIdAttribute.getAttributeValue();
                    }

                    encryptedPartsElements.add(createEncryptionPart(localName,
                            wsuId, namespace, "Content", expression));

                }

            } catch (JaxenException e) {
                // This has to be changed to propagate an instance of a RampartException up
                throw new RuntimeException(e);
            }
        }
       
    
        return encryptedPartsElements;
       
    }


    /**
     * Creates an Encryption or Signature paert with given name and id. Name must not be null.
     * @param name The name of the part
     * @param id The id of the part.
     * @return WSEncryptionPart.
     */
    public static WSEncryptionPart createEncryptionPart (String name, String id) {

        return createEncryptionPart(name, id, null, null, null);
    }

    /**
     * Creates an encryption part. Could be a part or could be an element pointed through xpath expression.
     * @param name Name of the element.
     * @param id The id of the element
     * @param namespace Namespace of the element.
     * @param modifier Modifier "Content" or "Element"
     * @return A WSEncryptionPart
     */
    public static WSEncryptionPart createEncryptionPart(String name, String id,
                                                         String namespace, String modifier) {

        return createEncryptionPart(name, id, namespace, modifier, null);
    }

     /**
     * Creates an encryption part. Could be a part or could be an element pointed through xpath expression.
     * @param name Name of the element.
     * @param id The id of the element
     * @param namespace Namespace of the element.
     * @param modifier Modifier "Content" or "Element"
     * @param xPath The xPath expression
      * @return A WSEncryptionPart
     */
    public static WSEncryptionPart createEncryptionPart(String name, String id,
                                                         String namespace, String modifier,String xPath) {

        // The part name must not be null !!
        assert name != null;

        WSEncryptionPart wsEncryptionPart = new WSEncryptionPart(name, namespace, modifier);
        wsEncryptionPart.setId(id);
        wsEncryptionPart.setXpath(xPath);

        return wsEncryptionPart;
    }
   
    public static List<WSEncryptionPart> getPartsAndElements(boolean sign, SOAPEnvelope envelope, boolean includeBody,
                                                             List<WSEncryptionPart> parts, List<String> elements,
                                                             HashMap decNamespaces) {

        List<OMElement> found = new ArrayList<OMElement>();
        List<WSEncryptionPart> result = new ArrayList<WSEncryptionPart>();

        // check body
        if(includeBody) {

            String wsuId = addWsuIdToElement(envelope.getBody());

            if( sign ) {
                result.add(createEncryptionPart(envelope.getBody().getLocalName(), wsuId,
                        null, null));
            } else {
                result.add(createEncryptionPart(envelope.getBody().getLocalName(), wsuId, null, "Content"));
            }

            // TODO can we remove this ?
            found.add( envelope.getBody() );
        }
       
        // Search envelope header for 'parts' from Policy (SignedParts/EncryptedParts)

        SOAPHeader header = envelope.getHeader();

        for (WSEncryptionPart part : parts) {
            if (part.getName() == null) {
                // NO name - search by namespace
                ArrayList headerList = header.getHeaderBlocksWithNSURI(part.getNamespace());

                for (Object aHeaderList : headerList) {
                    SOAPHeaderBlock shb = (SOAPHeaderBlock) aHeaderList;

                    // find reference in envelope
                    OMElement e = header.getFirstChildWithName(shb.getQName());

                    if (!found.contains(e)) {
                        // found new
                        found.add(e);

                        if (sign) {
                            result.add(createEncryptionPart(e.getLocalName(), null,
                                    part.getNamespace(), "Content"));
                        } else {

                            OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                            String wsuId = null;
                            if (wsuIdAttribute != null) {
                                wsuId = wsuIdAttribute.getAttributeValue();
                            }

                            result.add(createEncryptionPart(e.getLocalName(),wsuId,
                                    part.getNamespace(), "Element"));
                        }
                    }
                }
            } else {
                // try to find
                OMElement e = header.getFirstChildWithName(new QName(part.getNamespace(), part.getName()));
                if (e != null) {
                    if (!found.contains(e)) {
                        // found new (reuse wsep)
                        found.add(e);
                        OMAttribute wsuId = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                        if (wsuId != null) {
                            part.setEncId(wsuId.getAttributeValue());
                        }

                        result.add(part);
                    }
                }
            }
        }
       
        // ?? Search for 'Elements' here
       
        // decide what exactly is going to be used - only the default namespaces, or the list of all declared namespaces in the message !
        Set namespaces = findAllPrefixNamespaces(envelope, decNamespaces);

        for (String expression : elements) {
            try {
                XPath xp = new AXIOMXPath(expression);

                for (Object objectNamespace : namespaces) {
                    OMNamespace tmpNs = (OMNamespace) objectNamespace;
                    xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
                }

                List selectedNodes = xp.selectNodes(envelope);

                for (Object selectedNode : selectedNodes) {
                    OMElement e = (OMElement) selectedNode;
                    String localName = e.getLocalName();
                    String namespace = e.getNamespace() != null ? e.getNamespace().getNamespaceURI() : null;

                    if (sign) {

                        result.add(createEncryptionPart(localName, null, namespace, "Content", expression));

                    } else {

                        OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                        String wsuId = null;
                        if (wsuIdAttribute != null) {
                            wsuId = wsuIdAttribute.getAttributeValue();
                        }

                        result.add(createEncryptionPart(localName, wsuId, namespace, "Element", expression));
                    }
                }

            } catch (JaxenException e) {
                // This has to be changed to propagate an instance of a RampartException up
                throw new RuntimeException(e);
            }
        }

        return result;
    }
   
    /**
     * Get a element for SOAP
     * @param envelope   SOAP Envelope of which we should check required elements
     * @param decNamespaces  Declared namespaces in RequiredElements assertion
     * @param expression  XPATH expression of required elements
     * @return
     */
    public static boolean checkRequiredElements(SOAPEnvelope envelope, HashMap decNamespaces, String expression) {

        // The XPath expression must be evaluated against the SOAP header
        // http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/ws-securitypolicy-1.2-spec-os.html#_Toc161826519
        SOAPHeader header = envelope.getHeader();
        Set namespaces = findAllPrefixNamespaces(header, decNamespaces);

        try {
            XPath xp = new AXIOMXPath(expression);

            for (Object namespace : namespaces) {
                OMNamespace tmpNs = (OMNamespace) namespace;
                xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
            }

            List selectedNodes = xp.selectNodes(header);

            if (selectedNodes.size() == 0) {
                return false;
            }

        } catch (JaxenException e) {
            // This has to be changed to propagate an instance of a RampartException up
            throw new RuntimeException(e);
        }

        return true;
    }
   
   
    public static KeyGenerator getEncryptionKeyGenerator(String symEncrAlgo) throws WSSecurityException {
        KeyGenerator keyGen;
        try {
            /*
             * Assume AES as default, so initialize it
             */
            keyGen = KeyGenerator.getInstance("AES");
            if (symEncrAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
                keyGen = KeyGenerator.getInstance("DESede");
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
                keyGen.init(128);
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
                keyGen.init(192);
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
                keyGen.init(256);
            } else {
                return null;
            }
        } catch (NoSuchAlgorithmException e) {
            throw new WSSecurityException(
                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
        }
        return keyGen;
    }
   
    /**
     * Creates the unique (reproducible) id for to hold the context identifier
     * of the message exchange.
     * @return Id to hold the context identifier in the message context
     */
    public static String getContextIdentifierKey(MessageContext msgContext) {
        return msgContext.getAxisService().getName();
    }
   
   
    /**
     * Returns the map of security context token identifiers
     * @return the map of security context token identifiers
     */
    public static Hashtable getContextMap(MessageContext msgContext) {
        //Fist check whether its there
        Object map = msgContext.getConfigurationContext().getProperty(
                ConversationConstants.KEY_CONTEXT_MAP);
       
        if(map == null) {
            //If not create a new one
            map = new Hashtable();
            //Set the map globally
            msgContext.getConfigurationContext().setProperty(
                    ConversationConstants.KEY_CONTEXT_MAP, map);
        }
       
        return (Hashtable)map;
    }
   
    public static boolean isTokenValid(RampartMessageData rmd, String id) throws RampartException {
        try {
            org.apache.rahas.Token token = rmd.getTokenStorage().getToken(id);
            return token!= null && token.getState() == org.apache.rahas.Token.ISSUED;
        } catch (TrustException e) {
            throw new RampartException("errorExtractingToken");
        }
    }
   
    public static void setEncryptionUser(RampartMessageData rmd, WSSecEncryptedKey encrKeyBuilder)
            throws RampartException {
        RampartPolicyData rpd = rmd.getPolicyData();
        String encrUser = rpd.getRampartConfig().getEncryptionUser();
        setEncryptionUser(rmd, encrKeyBuilder, encrUser);
    }
   
    public static void setEncryptionUser(RampartMessageData rmd, WSSecEncryptedKey encrKeyBuilder,
            String encrUser) throws RampartException {
        RampartPolicyData rpd = rmd.getPolicyData();
       
        if (encrUser == null) {
            encrUser = rpd.getRampartConfig().getEncryptionUser();
        }
       
        if (encrUser == null || "".equals(encrUser)) {
            throw new RampartException("missingEncryptionUser");
        }
        if(encrUser.equals(WSHandlerConstants.USE_REQ_SIG_CERT)) {
            List<WSHandlerResult> resultsObj
                    = (List<WSHandlerResult>)rmd.getMsgContext().getProperty(WSHandlerConstants.RECV_RESULTS);
            if(resultsObj != null) {
                encrKeyBuilder.setUseThisCert(getReqSigCert(resultsObj));
                
                //TODO This is a hack, this should not come under USE_REQ_SIG_CERT
                if(encrKeyBuilder.isCertSet()) {
                  encrKeyBuilder.setUserInfo(getUsername(resultsObj));
                }
                 
               
            } else {
                throw new RampartException("noSecurityResults");
            }
        } else {
            encrKeyBuilder.setUserInfo(encrUser);
        }
    }
   
    /**
     * Sets the keyIdentifierType of <code>WSSecSignature</code> or <code>WSSecEncryptedKey</code>
     * according to the given <code>Token</code> and <code>RampartPolicyData</code>
     * First check the requirements specified under Token Assertion and if not found check
     * the WSS11 and WSS10 assertions
     */
   
    public static void setKeyIdentifierType(RampartMessageData rmd, WSSecBase secBase,org.apache.ws.secpolicy.model.Token token) {

        // Use a reference rather than the binary security token if: the policy never allows the token to be
        // included; or this is the recipient and the token should only be included in requests; or this is
        // the initiator and the token should only be included in responses.
        final boolean useReference = token.getInclusion() == SPConstants.INCLUDE_TOKEN_NEVER
                                     || !rmd.isInitiator() && token.getInclusion() == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT
                                     || rmd.isInitiator() && token.getInclusion() == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_INITIATOR;
        if (useReference) {

        boolean tokenTypeSet = false;
       
        if(token instanceof X509Token) {
          X509Token x509Token = (X509Token)token;
         
          if(x509Token.isRequireIssuerSerialReference()) {
            secBase.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
            tokenTypeSet = true;
          } else if (x509Token.isRequireKeyIdentifierReference()) {
            secBase.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
            tokenTypeSet = true;
          } else if (x509Token.isRequireThumbprintReference()) {
            secBase.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
            tokenTypeSet = true;
          }
        }
       
        if (!tokenTypeSet) {
                final RampartPolicyData rpd = rmd.getPolicyData();
          Wss10 wss = rpd.getWss11();
        if (wss == null) {
          wss = rpd.getWss10();
        }
       
        if (wss.isMustSupportRefKeyIdentifier()) {
          secBase.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
        } else if (wss.isMustSupportRefIssuerSerial()) {
          secBase.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
        } else if (wss instanceof Wss11
            && ((Wss11) wss).isMustSupportRefThumbprint()) {
          secBase.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
        }
        }
       
    } else {
      secBase.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
    }
    }
   
    private static X509Certificate getReqSigCert(List<WSHandlerResult> results) {
        /*
        * Scan the results for a matching actor. Use results only if the
        * receiving Actor and the sending Actor match.
        */
        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                if (actInt == WSConstants.SIGN) {
                    return (X509Certificate) wsSecEngineResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
                }
            }
        }
       
        return null;
    }
   
    /**
     * Scan through <code>WSHandlerResult<code> list for a Username token and return
     * the username if a Username Token found
     * @param results
     * @return
     */
   
    public static String getUsername(List<WSHandlerResult> results) {
        /*
         * Scan the results for a matching actor. Use results only if the
         * receiving Actor and the sending Actor match.
         */
        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for a username token. Use the username
            * of this token to set the alias for the encryption user
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                if (actInt == WSConstants.UT) {
                    WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) wsSecEngineResult.
                            get(WSSecurityEngineResult.TAG_PRINCIPAL);
                    return principal.getName();
                }
            }
        }
        
         return null;
    }

    public static String getRequestEncryptedKeyId(List<WSHandlerResult> results) {

        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                String encrKeyId = (String) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ID);
                if (actInt == WSConstants.ENCR &&
                        encrKeyId != null) {
                    return encrKeyId;
                }
            }
        }

        return null;
    }
   
    public static byte[] getRequestEncryptedKeyValue(List<WSHandlerResult> results) {

        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                byte[] decryptedKey = (byte[]) wsSecEngineResult.get(WSSecurityEngineResult.TAG_SECRET);
                if (actInt == WSConstants.ENCR &&
                        decryptedKey != null) {
                    return decryptedKey;
                }
            }
        }
       
        return null;
    }
   
    /**
     * If the child is present insert the element as a sibling after him.
     *
     * If the child is null, then prepend the element.
     *
     * @param rmd
     * @param child
     * @param elem - element mentioned above
     * @return
     */
    public static Element insertSiblingAfterOrPrepend(RampartMessageData rmd, Element child, Element elem) {
        Element retElem = null;
        if (child != null) { // child is not null so insert sibling after
            retElem = RampartUtil.insertSiblingAfter(rmd, child, elem);
        } else { //Prepend
            retElem = prependSecHeader(rmd, elem);
        }

        return retElem;
    }

    public static Element insertSiblingBeforeOrPrepend(RampartMessageData rmd, Element child, Element elem) {
        Element retElem = null;
        if (child != null && child.getPreviousSibling() != null) {
            retElem = RampartUtil.insertSiblingBefore(rmd, child, elem);
        } else { //Prepend
            retElem = prependSecHeader(rmd, elem);
        }

        return retElem;
    }

    private static Element prependSecHeader(RampartMessageData rmd, Element elem) {
        Element retElem = null;

        Element secHeaderElem = rmd.getSecHeader().getSecurityHeader();
        Node node = secHeaderElem.getOwnerDocument().importNode(
                elem, true);
        Element firstElem = (Element) secHeaderElem.getFirstChild();

        if (firstElem == null) {
            retElem = (Element) secHeaderElem.appendChild(node);
        } else {
            if (firstElem.getOwnerDocument().equals(elem.getOwnerDocument())) {
                ((OMElement) firstElem).insertSiblingBefore((OMElement) elem);
                retElem = elem;
            } else {
                Element newSib = (Element) firstElem.getOwnerDocument().importNode(elem, true);
                ((OMElement) firstElem).insertSiblingBefore((OMElement) newSib);
                retElem = newSib;
            }
        }

        return retElem;
    }
   
    /**
     * Method to check whether security header is required in incoming message
     * @param rpd
     * @return true if a security header is required in the incoming message
     */
    public static boolean isSecHeaderRequired(RampartPolicyData rpd, boolean initiator,
                                                                                boolean inflow ) {
       
        // Checking for time stamp
        if ( rpd.isIncludeTimestamp() ) {
            return true;
        }
       
        // Checking for signed parts and elements
        if (rpd.isSignBody() || rpd.getSignedParts().size() != 0 ||
                                    rpd.getSignedElements().size() != 0) {
            return true;
        }
       
        // Checking for encrypted parts and elements
        if (rpd.isEncryptBody() || rpd.getEncryptedParts().size() != 0 ||
                                    rpd.getEncryptedElements().size() != 0 ) {
            return true;
        }  
       
        // Checking for supporting tokens
        SupportingToken supportingTokens;
       
        if (!initiator && inflow || initiator && !inflow ) {
       
            List<SupportingToken> supportingToks = rpd.getSupportingTokensList();
            for (SupportingToken supportingTok : supportingToks) {
                if (supportingTok != null && supportingTok.getTokens().size() != 0) {
                    return true;
                }
            }
           
            supportingTokens = rpd.getSignedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
           
            supportingTokens = rpd.getEndorsingSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
           
            supportingTokens = rpd.getSignedEndorsingSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
      
            supportingTokens = rpd.getEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
           
            supportingTokens = rpd.getSignedEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
           
            supportingTokens = rpd.getEndorsingEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
           
            supportingTokens = rpd.getSignedEndorsingEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
        }
       
        return false;
       
    }

    public static void handleEncryptedSignedHeaders(List<WSEncryptionPart> encryptedParts,
                                                    List<WSEncryptionPart> signedParts, Document doc) {

        //TODO Is there a more efficient  way to do this ? better search algorithm
        for (WSEncryptionPart signedPart : signedParts) {
            //This signed part is not a header
            if (signedPart.getNamespace() == null || signedPart.getName() == null) {
                continue;
            }

            for (WSEncryptionPart encryptedPart : encryptedParts) {

                if (encryptedPart.getNamespace() == null || encryptedPart.getName() == null) {
                    continue;
                }

                if (signedPart.getName().equals(encryptedPart.getName()) &&
                        signedPart.getNamespace().equals(encryptedPart.getNamespace())) {

                    String encDataID = encryptedPart.getEncId();

                    // TODO Do we need to go through the whole tree to find element by id ? Verify
                    Element encDataElem = WSSecurityUtil.findElementById(doc.getDocumentElement(), encDataID, false);

                    if (encDataElem != null) {
                        Element encHeader = (Element) encDataElem.getParentNode();
                        String encHeaderId = encHeader.getAttributeNS(WSConstants.WSU_NS, "Id");

                        //For some reason the id might not be available
                        // so the part/element with empty/null id won't be recognized afterwards.
                        if (encHeaderId != null && !"".equals(encHeaderId.trim())) {
                            signedParts.remove(signedPart);

                            signedParts.add(createEncryptionPart(signedPart.getName(), encHeaderId,
                                    signedPart.getNamespace(),
                                    signedPart.getEncModifier(), signedPart.getXpath()));
                        }

                    }
                }
            }


        }

    }
   
    public static String getSigElementId(RampartMessageData rmd) {
       
        SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
       
        SOAPHeader header = envelope.getHeader();
       
        if (header == null ) {
            return null;
        }
       
        ArrayList secHeaders = header.getHeaderBlocksWithNSURI(WSConstants.WSSE_NS);
       
        if (secHeaders != null && secHeaders.size() > 0) {
            QName sigQName = new QName(Constants.SignatureSpecNS,Constants._TAG_SIGNATURE);
            QName wsuIdQName = new QName(WSConstants.WSU_NS,"Id");
            OMElement sigElem = ((SOAPHeaderBlock)secHeaders.get(0)).getFirstChildWithName(sigQName);
            OMAttribute wsuId = sigElem.getAttribute(wsuIdQName);
           
            if (wsuId != null) {
                return wsuId.getAttributeValue();
            }
           
            wsuId = sigElem.getAttribute(new QName("Id"));
           
            if (wsuId != null) {
                return wsuId.getAttributeValue();
            }
           
           
        }
       
        return null;
    }
   
    /**
     * We use this method to prevent the singleton behavior of WSSConfig
     * @return WSSConfig object with the latest settings.   
     */
   
    public static WSSConfig getWSSConfigInstance() {
       
        WSSConfig defaultWssConfig = WSSConfig.getNewInstance();
        WSSConfig wssConfig = WSSConfig.getNewInstance();
       
        wssConfig.setEnableSignatureConfirmation(defaultWssConfig.isEnableSignatureConfirmation());
        wssConfig.setTimeStampStrict(defaultWssConfig.isTimeStampStrict());
        wssConfig.setWsiBSPCompliant(defaultWssConfig.isWsiBSPCompliant());
        wssConfig.setPrecisionInMilliSeconds(defaultWssConfig.isPrecisionInMilliSeconds());
       
        return  wssConfig;
      
    }

    public static void validateTransport(RampartMessageData rmd) throws RampartException {

        RampartPolicyData rpd = rmd.getPolicyData();

        if (rpd == null) {
            return;
        }

        if (rpd.isTransportBinding() && !rmd.isInitiator()) {
            if (rpd.getTransportToken() instanceof HttpsToken) {
                String incomingTransport = rmd.getMsgContext().getIncomingTransportName();
                if (!incomingTransport.equals(org.apache.axis2.Constants.TRANSPORT_HTTPS)) {
                    throw new RampartException("invalidTransport",
                            new String[]{incomingTransport});
                }
                if (((HttpsToken) rpd.getTransportToken()).isRequireClientCertificate()) {

                    MessageContext messageContext = rmd.getMsgContext();
                    HttpServletRequest request = ((HttpServletRequest) messageContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST));
                    if (request == null || request.getAttribute("javax.servlet.request.X509Certificate") == null) {
                        throw new RampartException("clientAuthRequired");
                    }
                }

            }
        }
    }

    private static Crypto retrieveCryptoFromCache(String cryptoKey, String refreshInterval) {
        // cache hit
        if (cryptoStore.containsKey(cryptoKey)) {
            CachedCrypto cachedCrypto = cryptoStore.get(cryptoKey);
            if (refreshInterval != null) {
                if (cachedCrypto.creationTime + new Long(refreshInterval).longValue() > Calendar
                        .getInstance().getTimeInMillis()) {
                    log.debug("Cache Hit : Crypto Object was found in cache.");
                    return cachedCrypto.crypto;
                } else {
                    log.debug("Cache Miss : Crypto Object found in cache is expired.");
                    return null;
                }
            } else {
                log.debug("Cache Hit : Crypto Object was found in cache.");
                return cachedCrypto.crypto;
            }
        }
        // cache miss
        else {
            log.debug("Cache Miss : Crypto Object was not found in cache.");
            return null;
        }
    }

    private static void cacheCrypto(String cryptoKey, Crypto crypto) {
        cryptoStore.put(cryptoKey, new CachedCrypto(crypto, Calendar.getInstance()
                .getTimeInMillis()));
        log.debug("Crypto object is inserted into the Cache.");

    }

    /**
     * Returns SAML10 Assertion namespace. As follows,
     * http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID
     * @return SAML10 assertion namespace.
     */
    public static String getSAML10AssertionNamespace() {

        StringBuilder stringBuilder = new StringBuilder(WSConstants.SAMLTOKEN_NS);
        stringBuilder.append("#").append(WSConstants.SAML_ASSERTION_ID);

        return stringBuilder.toString();

    }

    /**
     * Sets encryption crypto file or crypto reference key to signature crypto file or signature
     * crypto reference.
     * @param msgContext The message context to get signature crypto properties and encryption properties
     * will be set to same message context.
     */
    public static void setEncryptionCrypto(MessageContext msgContext) {
        setEncryptionCryptoFileProperty(msgContext);
        setEncryptionCryptoReferenceProperty(msgContext);
    }

    /**
     * Sets decryption crypto file or crypto reference key to signature crypto file or signature
     * crypto reference.
     * @param msgContext The message context to get signature crypto properties and decryption properties
     * will be set to same message context.
     */
    public static void setDecryptionCrypto(MessageContext msgContext) {
        setDecryptionCryptoFileProperty(msgContext);
        setDecryptionCryptoReferenceProperty(msgContext);
    }

    /**
     * Sets encryption crypto property reference id.- WSHandlerConstants.ENC_PROP_REF_ID
     * @param msgContext The message context.
     */
    private static void setEncryptionCryptoReferenceProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_REF_ID, WSHandlerConstants.ENC_PROP_REF_ID);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.DEC_PROP_REF_ID
     * @param msgContext The message context.
     */
    private static void setDecryptionCryptoReferenceProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_REF_ID, WSHandlerConstants.DEC_PROP_REF_ID);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.ENC_PROP_FILE
     * @param msgContext The message context.
     */
    private static void setEncryptionCryptoFileProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_FILE, WSHandlerConstants.ENC_PROP_FILE);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.DEC_PROP_FILE
     * @param msgContext The message context.
     */
    private static void setDecryptionCryptoFileProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_FILE, WSHandlerConstants.DEC_PROP_FILE);
    }

    private static void setCryptoProperty(MessageContext msgContext, String signaturePropertyName,
                                          String cryptoPropertyName){

        /**
         * Encryption Crypto is loaded using WSHandlerConstants.ENC_PROP_FILE. If this is not
         * set in the message context set WSHandlerConstants.SIG_PROP_FILE as WSHandlerConstants.ENC_PROP_FILE.
         */
        if (msgContext.getProperty(cryptoPropertyName) == null) {


            String signaturePropertyFile = (String)msgContext.getProperty(signaturePropertyName);

            if (signaturePropertyFile == null) {

                if (log.isDebugEnabled()) {
                    log.debug("Signature crypto property file is not set. Property file key - "
                            + WSHandlerConstants.SIG_PROP_FILE);
                }
            } else {
                msgContext.setProperty(cryptoPropertyName, signaturePropertyFile);
            }
        }
    }

    /**
     * Returns true if needed to encrypt first.
     * @param rpd Rampart policy data
     * @return true if policy says we need to encrypt first else false.
     */
    public static boolean encryptFirst(RampartPolicyData rpd) {
        return SPConstants.ENCRYPT_BEFORE_SIGNING.equals(rpd.getProtectionOrder());
    }

}
TOP

Related Classes of org.apache.rampart.util.RampartUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.