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

com.sun.xml.wss.impl.dsig.WSSPolicyConsumerImpl Maven / Gradle / Ivy

There is a newer version: 4.0.4
Show newest version
/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * 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
 */

/*
 * WSSPolicyConsumerImpl.java
 *
 * Created on January 18, 2005, 1:50 PM
 */

package com.sun.xml.wss.impl.dsig;

import com.sun.xml.wss.WSITXMLFactory;
import com.sun.xml.wss.impl.FilterProcessingContext;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.SecurableSoapMessage;
import com.sun.xml.wss.core.SecurityTokenReference;
import com.sun.xml.wss.impl.XMLUtil;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.PolicyTypeUtil;
import com.sun.xml.wss.impl.misc.SecurityUtil;
import com.sun.xml.wss.util.NodeListImpl;
import com.sun.xml.wss.impl.policy.MLSPolicy;
import com.sun.xml.wss.impl.policy.PolicyGenerationException;
import com.sun.xml.wss.impl.policy.mls.AuthenticationTokenPolicy;
import com.sun.xml.wss.impl.policy.mls.DerivedTokenKeyBinding;
import com.sun.xml.wss.impl.policy.mls.Parameter;
import com.sun.xml.wss.impl.policy.mls.SymmetricKeyBinding;
import com.sun.xml.wss.impl.policy.mls.SignaturePolicy;
import com.sun.xml.wss.impl.policy.mls.SignatureTarget;
import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.logging.impl.dsig.LogStringsMessages;

import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;

import javax.xml.crypto.URIDereferencer;
import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;

import java.security.spec.AlgorithmParameterSpec;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec;
import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPException;
import javax.xml.transform.dom.DOMSource;

import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;

import javax.xml.xpath.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;


/**
 *
 * @author [email protected]
 */

/*
 * WSSPolicyConsumerImpl is to be used as a helper class to construct JSR105 objects from signaturePolicy.
 * To see if document templates are more efficient
 */
public class WSSPolicyConsumerImpl {
    private static Logger logger = Logger.getLogger(LogDomainConstants.IMPL_SIGNATURE_DOMAIN_BUNDLE,
            LogDomainConstants.IMPL_SIGNATURE_DOMAIN_BUNDLE);
    public static final String defaultJSR105Provider = "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI";
    //public static final String ibmProvider ="com.ibm.xml.crypto.IBMXMLCryptoProvider";

    private String providerName = null;
    private String pMT = null;
    private static volatile WSSPolicyConsumerImpl wpcInstance = null;
    private URIDereferencer externalURIResolver = null;
    private Provider provider = null;
    //private static final String javavendor = System.getProperty("java.vendor");
    //IBM Corporation
    //private static final boolean vendorIsIBM = javavendor.startsWith("IBM");

    /** Creates a new instance of WSSPolicyConsumerImpl */
    private WSSPolicyConsumerImpl() {
        //Cannot use XMLSignatureFactory.getInstance().getProvider()
        //since this code needs to compile with JDK5 and on JDK5
        // XMLSignatureFactory.getInstance().getProvider() would throw
        //NoSuchMechanismException: Mechanism type DOM not available
    	  
    	//Replace of jsr105 implementation with Apache XML Security 
        providerName = /*vendorIsIBM ? ibmProvider :*/
                System.getProperty("jsr105Provider", defaultJSR105Provider);
        pMT = System.getProperty("jsr105MechanismType","DOM");

        try {
            
            ClassLoader loader = this.getClass().getClassLoader();
            Class providerClass = Class.forName(providerName, true, loader);
            provider = (Provider) providerClass.newInstance();
        } catch (Exception ex1) {
            try {
                ClassLoader tccl = Thread.currentThread().getContextClassLoader();
                Class providerClass = Class.forName(providerName, true, tccl);
                provider = (Provider) providerClass.newInstance();
            }catch (Exception ex) {
                logger.log(Level.WARNING, LogStringsMessages.WSS_1324_DSIG_FACTORY(), ex);
            }
        }

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "JSR 105 provider is : " + providerName);
            logger.log(Level.FINEST, "JSR 105 provider mechanism is : " + pMT);
        }
        
        AccessController.doPrivileged(new java.security.PrivilegedAction() {
            public Object run() {
                try {
                    Security.insertProviderAt(provider, 5);
                    Security.insertProviderAt(new WSSProvider(), 6);
                } catch (SecurityException ex) {
                    Security.addProvider(provider);
                    Security.addProvider(new WSSProvider());
                }
                return null;
            }
        });
    }
    
    /**
     * @return instance of WSSPolicyConsumerImpl
     */
    public static WSSPolicyConsumerImpl getInstance(){
        if(wpcInstance == null){
            synchronized(WSSPolicyConsumerImpl.class){
                if(wpcInstance == null){
                    wpcInstance = new WSSPolicyConsumerImpl();
                }
            }
        }
        return wpcInstance;
    }
    
    /**
     *
     * @return
     * @throws PolicyGenerationException
     * @throws NoSuchAlgorithmException
     * @throws InvalidAlgorithmParameterException
     * @throws XWSSecurityException
     */
    public SignedInfo constructSignedInfo(FilterProcessingContext fpContext)throws
            PolicyGenerationException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,XWSSecurityException {
        
        if(PolicyTypeUtil.signaturePolicy(fpContext.getSecurityPolicy())) {
            SignedInfo signInfo = generateSignedInfo(fpContext);
            return signInfo;
        }
        return null;
    }
    
    /**
     *
     * @param signInfo
     * @param keyInfo
     * @return XMLSignature
     */
    public XMLSignature constructSignature(SignedInfo signInfo,KeyInfo keyInfo){
        return getSignatureFactory().newXMLSignature(signInfo,keyInfo);
    }

    /**
     *
     * @param signInfo
     * @param keyInfo
     * @param id
     * @return XMLSignature
     */
    public XMLSignature constructSignature(SignedInfo signInfo,KeyInfo keyInfo, String id){
        return getSignatureFactory().newXMLSignature(signInfo,keyInfo, null, id, null);
    }
    
    /**
     *
     * @param signaturePolicy
     * @param reference
     * @throws PolicyGenerationException
     * @throws SOAPException
     * @throws XWSSecurityException
     * @return KeyInfo
     */
    public KeyInfo constructKeyInfo(MLSPolicy signaturePolicy,SecurityTokenReference reference) throws PolicyGenerationException,SOAPException,XWSSecurityException {
        
        if(PolicyTypeUtil.signaturePolicy(signaturePolicy)) {
            //SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding)signaturePolicy.getFeatureBinding();
            //WSSPolicy keyBinding =(WSSPolicy) signaturePolicy.getKeyBinding();
            KeyInfoFactory keyFactory = getKeyInfoFactory();
            
            DOMStructure domKeyInfo = new DOMStructure(reference.getAsSoapElement());
            
            KeyInfo keyInfo = keyFactory.newKeyInfo(Collections.singletonList(domKeyInfo));
            return keyInfo;
            
        }
        
        return null;
        
    }
    
    /**
     *
     * @param signaturePolicy
     * @param KeyName
     * @throws PolicyGenerationException
     * @throws SOAPException
     * @throws XWSSecurityException
     * @return KeyInfo
     */
     @SuppressWarnings("unchecked")
    public KeyInfo constructKeyInfo(MLSPolicy signaturePolicy,String KeyName) throws PolicyGenerationException,SOAPException,XWSSecurityException {
        
        if(PolicyTypeUtil.signaturePolicy(signaturePolicy)) {
            //SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding)signaturePolicy.getFeatureBinding();
            //WSSPolicy keyBinding =(WSSPolicy) signaturePolicy.getKeyBinding();
            KeyInfoFactory keyFactory = getKeyInfoFactory();
            javax.xml.crypto.dsig.keyinfo.KeyName keyName = keyFactory.newKeyName(KeyName);
            java.util.List list = new java.util.ArrayList();
            list.add(keyName);
            
            KeyInfo keyInfo = keyFactory.newKeyInfo(list);
            
            return keyInfo;
            
        }
        
        return null;
        
    }
    
    /**
     *
     * @return XMLSignatureFactory
     */
    public XMLSignatureFactory getSignatureFactory() {
        try {
            
            return XMLSignatureFactory.getInstance("DOM",provider);
            //XMLSignatureFactory.getInstance (pMT,providerName);
        }catch(Exception ex) {
            logger.log(Level.SEVERE,LogStringsMessages.WSS_1324_DSIG_FACTORY(),ex);
            throw new RuntimeException(ex);
        }
    }
    
    /**
     *
     * @return KeyInfoFactory
     */
    public KeyInfoFactory getKeyInfoFactory() {
        try {
            return getSignatureFactory().getKeyInfoFactory();
        }catch(Exception ex) {
            logger.log(Level.SEVERE,LogStringsMessages.WSS_1323_DSIG_KEYINFO_FACTORY(),ex);
            throw new RuntimeException(ex);
        }
    }
    
    /**
     * @param signedInfo
     * @return SignaturePolicy
     */
    public SignaturePolicy constructSignaturePolicy(SignedInfo signedInfo, boolean isBSP){
        SignaturePolicy policy = new SignaturePolicy();
        constructSignaturePolicy(signedInfo,isBSP,policy);
        return policy;
    }
    
    public void constructSignaturePolicy(SignedInfo signedInfo, boolean isBSP,SignaturePolicy policy){
        List referencesList = signedInfo.getReferences();
        //SignatureMethod sm = signedInfo.getSignatureMethod();
        CanonicalizationMethod cm = signedInfo.getCanonicalizationMethod();
        
        policy.isBSP(isBSP);
        SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding )policy.getFeatureBinding();
        featureBinding.setCanonicalizationAlgorithm(cm.getAlgorithm());
        Iterator itr = referencesList.iterator();
        while(itr.hasNext()){
            Reference ref = (Reference) itr.next();
            SignatureTarget.Transform transform = getSignatureTransform(ref);
            SignatureTarget target = new SignatureTarget();
            target.isBSP(isBSP);
            if(transform != null){
                target.addTransform(transform);
            }
            target.setDigestAlgorithm(ref.getDigestMethod().getAlgorithm());
			if(ref.getURI().length() >0){
               target.setValue(SecurableSoapMessage.getIdFromFragmentRef(ref.getURI()));
			}else{
               target.setValue(ref.getURI());
			}
            target.setType(SignatureTarget.TARGET_TYPE_VALUE_URI);
            featureBinding.addTargetBinding(target);
        }
    }
    
    public void constructSignaturePolicy(SignedInfo signedInfo, SignaturePolicy policy,
            SecurableSoapMessage secMsg) throws XWSSecurityException{
        List referencesList = signedInfo.getReferences();
        //SignatureMethod sm = signedInfo.getSignatureMethod();
        CanonicalizationMethod cm = signedInfo.getCanonicalizationMethod();
        
        //policy.isBSP(isBSP);
        SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding )policy.getFeatureBinding();
        featureBinding.setCanonicalizationAlgorithm(cm.getAlgorithm());
        Iterator itr = referencesList.iterator();
        while(itr.hasNext()){
            Reference ref = (Reference) itr.next();
            SignatureTarget.Transform transform = getSignatureTransform(ref);
            SignatureTarget target = new SignatureTarget();
            //target.isBSP(isBSP);
            if(transform != null){
                target.addTransform(transform);
            }
            target.setDigestAlgorithm(ref.getDigestMethod().getAlgorithm());
            if(ref.getURI().length() >0){
                String Id = SecurableSoapMessage.getIdFromFragmentRef(ref.getURI());
                //SOAPElement se = secMsg.getElementByWsuId(Id);
                SOAPElement se = (SOAPElement) secMsg.getElementById(Id);
                if(se != null){
                    if(se.getNamespaceURI().equals(MessageConstants.WSSE_NS) ||
                            se.getNamespaceURI().equals(MessageConstants.WSSE11_NS) ||
                            se.getNamespaceURI().equals(MessageConstants.WSSC_NS) ||
                            se.getNamespaceURI().equals(MessageConstants.WSU_NS)){
                        target.setValue("#" + Id);
                        target.setType(SignatureTarget.TARGET_TYPE_VALUE_URI);
                        
                    } else{
                        QName qname = new QName(se.getNamespaceURI(), se.getLocalName());
                        target.setQName(qname);
                        target.setType(SignatureTarget.TARGET_TYPE_VALUE_QNAME);
                    }
                } else{
                    logger.log(Level.SEVERE, LogStringsMessages.WSS_1376_FAILED_VERIFY_POLICY_NO_ELEMENTBY_ID());
                    throw new XWSSecurityException("Policy verification for Signature failed: Element with Id: " + Id
                            + "not found in message" );
                }
	    }
            
            featureBinding.addTargetBinding(target);
        }
    }
    
    /**
     *
     * @param reference
     * @return Transform
     */
    public SignatureTarget.Transform getSignatureTransform(Reference reference ){
        List transformList = reference.getTransforms();
        Iterator transformItr = transformList.iterator();
        SignatureTarget.Transform transform = null;
        while(transformItr.hasNext()){
            Transform trObj = (Transform)transformItr.next();
            String algorithm = trObj.getAlgorithm();
            transform = new SignatureTarget.Transform();
            transform.setTransform(algorithm);
            AlgorithmParameterSpec paramSpec = trObj.getParameterSpec();
            // ArrayList paramList = new HashMap();
            //  addCanonicalizationParams(paramSpec,paramList);
            transform.setAlgorithmParameters(paramSpec);
        }
        return transform;
    }
    
    /**
     *
     * @param algoSpec
     * @param paramList
     */
     @SuppressWarnings("unchecked")
    public void addCanonicalizationParams(AlgorithmParameterSpec algoSpec,HashMap paramList){
        //TODO::FixMe:  Fill this appropriately.
        if(algoSpec instanceof XPathFilterParameterSpec){
            XPathFilterParameterSpec spec = (XPathFilterParameterSpec)algoSpec;
            paramList.put("XPATH",spec.getXPath());
        }else if(algoSpec instanceof XPathFilter2ParameterSpec){
            XPathFilter2ParameterSpec spec = (XPathFilter2ParameterSpec)algoSpec;
            paramList.put("XPATH2",spec.getXPathList());
        }
    }
    
    private SignedInfo generateSignedInfo(FilterProcessingContext fpContext)
    throws PolicyGenerationException,NoSuchAlgorithmException,InvalidAlgorithmParameterException ,XWSSecurityException{
        SignaturePolicy signaturePolicy = (SignaturePolicy) fpContext.getSecurityPolicy();
        SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding)signaturePolicy.getFeatureBinding();
        MLSPolicy keyBinding = signaturePolicy.getKeyBinding();
        XMLSignatureFactory signatureFactory = getSignatureFactory();
        SecurableSoapMessage secureMessage = fpContext.getSecurableSoapMessage();
        String canonicalAlgo = featureBinding.getCanonicalizationAlgorithm();
        boolean disableInclusivePrefix = featureBinding.getDisableInclusivePrefix();
        //String digestAlgo = featureBinding.getDigestAlgorithm();
        ArrayList targetList = featureBinding.getTargetBindings();
        String keyAlgo = null;
        String algo = MessageConstants.RSA_SHA1;
        if (fpContext.getAlgorithmSuite() != null) {
            algo = fpContext.getAlgorithmSuite().getSignatureAlgorithm();
        }

        keyAlgo = SecurityUtil.getKeyAlgo(algo);
                
        if(PolicyTypeUtil.x509CertificateBinding(keyBinding)) {
            AuthenticationTokenPolicy.X509CertificateBinding certificateBinding =
                    (AuthenticationTokenPolicy.X509CertificateBinding)keyBinding;
            if (!"".equals(certificateBinding.getKeyAlgorithm())) {
                keyAlgo = certificateBinding.getKeyAlgorithm();
            }
        } else if (PolicyTypeUtil.samlTokenPolicy(keyBinding)) {
            AuthenticationTokenPolicy.SAMLAssertionBinding samlBinding =
                    (AuthenticationTokenPolicy.SAMLAssertionBinding)keyBinding;
            if (!"".equals(samlBinding.getKeyAlgorithm())) {
                keyAlgo = samlBinding.getKeyAlgorithm();
            }
        }else if(PolicyTypeUtil.symmetricKeyBinding(keyBinding)){
            SymmetricKeyBinding symmetricKeybinding = (SymmetricKeyBinding)keyBinding;
            if (!"".equals(symmetricKeybinding.getKeyAlgorithm())) {
                keyAlgo = symmetricKeybinding.getKeyAlgorithm();
            } else {
                keyAlgo = MessageConstants.HMAC_SHA1_SIGMETHOD;
            }     
        } else if (PolicyTypeUtil.secureConversationTokenKeyBinding(keyBinding)) {
            keyAlgo = MessageConstants.HMAC_SHA1_SIGMETHOD;
        } else if (PolicyTypeUtil.derivedTokenKeyBinding(keyBinding)) {
           keyAlgo = MessageConstants.HMAC_SHA1_SIGMETHOD;
           if(PolicyTypeUtil.issuedTokenKeyBinding(((DerivedTokenKeyBinding)keyBinding).getOriginalKeyBinding())){
               if(fpContext.getTrustContext().getProofKey() == null){
                   keyAlgo = MessageConstants.RSA_SHA1_SIGMETHOD;
               }                           
           }
       } else if (PolicyTypeUtil.issuedTokenKeyBinding(keyBinding)) {
           //TODO: verify if this is always correct
           keyAlgo = MessageConstants.HMAC_SHA1_SIGMETHOD;
           if(fpContext.getTrustContext().getProofKey() == null){
               keyAlgo = MessageConstants.RSA_SHA1_SIGMETHOD;
           }
       } else { 
            logger.log(Level.SEVERE, LogStringsMessages.WSS_1335_UNSUPPORTED_KEYBINDING_SIGNATUREPOLICY());
            throw new XWSSecurityException("Unsupported KeyBinding for SignaturePolicy");
       }
        
        C14NMethodParameterSpec spec = null;
        if (MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS.equalsIgnoreCase(canonicalAlgo)) {
            //List inc = getInclusiveNamespacePrefixes(secureMessage.findSecurityHeader(), false);
            //spec = new ExcC14NParameterSpec(inc);
            //NOTE: looking at BSP flag on sending side just for
            //ExC14N parameterList. Because XWSS11(xmlsec.jar) cannot
            //process the PrefixList, thereby breaking BC
            if (featureBinding.isBSP() || !disableInclusivePrefix) {
                List inc = getInclusiveNamespacePrefixes(secureMessage.findSecurityHeader(), false);
                spec = new ExcC14NParameterSpec(inc);
            } else {
                spec = null;
            }

        }
        CanonicalizationMethod canonicalMethod=
                signatureFactory.newCanonicalizationMethod(canonicalAlgo,spec);
        
        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(keyAlgo, null);
        //Note : Signature algorithm parameters null for now , fix me.
        SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalMethod,signatureMethod,
                generateReferenceList(targetList,signatureFactory,secureMessage,fpContext,false, featureBinding.isEndorsingSignature()),null);
        //Note : Id is now null , check ?,
        return signedInfo;
    }
   
     /*
      * Calculate the list of inclusive namespace prefixes.
      * Inclusive Prefixes are those that are not not visibly utilized.
      */
     @SuppressWarnings("unchecked")
    public static List getInclusiveNamespacePrefixes(Element target,
            boolean excludeVisiblePrefixes) {
        ArrayList result = new ArrayList();
        NamedNodeMap attributes;
        Node attribute;
        Node parent = target;
        
        while (!(parent instanceof Document)) {
            attributes = parent.getAttributes();
            for (int i = 0; i < attributes.getLength(); i++) {
                attribute = attributes.item(i);
                if (attribute.getNamespaceURI() != null &&
                        attribute.getNamespaceURI().equals(MessageConstants.NAMESPACES_NS)) {
                    result.add(attribute.getLocalName());
                }
            }
            parent = parent.getParentNode();
        }
         /*
        if (excludeVisiblePrefixes == true) {
            attributes = target.getAttributes();
            for (int i = 0; i < attributes.getLength(); i++) {
                attribute = attributes.item(i);
                if (attribute.getNamespaceURI() != null &&
attribute.getNamespaceURI().equals(MessageConstants.NAMESPACES_NS)) {
                        result.remove(attribute.getLocalName());
                }
                if (attribute.getPrefix() != null) {
                      result.remove(attribute.getLocalName());
                }
            }
          
            if (target.getPrefix() == null) {
                result.remove(MessageConstants.XMLNS_TAG);
            } else {
                result.remove(target.getPrefix());
            }
        }
          */
        return result;
    }
    
    
     /*
      * Calculate the list of visible namespace prefixes in target.
      * to be included in ds:Reference.
      */
    public static List getReferenceNamespacePrefixes(Node target) {
        ArrayList result = new ArrayList();
        
        traverseSubtree(target , result);
        
        return result;
    }
     @SuppressWarnings("unchecked")
    private static void traverseSubtree(Node node, List result) {
        SOAPElement element = (SOAPElement) node;
        Iterator visible =  element.getVisibleNamespacePrefixes();
        
        while (visible.hasNext()) {
            String  prefix = (String)visible.next();
            if (!result.contains(prefix)) {
                result.add(prefix);
            }
        }
        Iterator children = element.getChildElements();
        
        while (children.hasNext()) {
            Node child = (Node)children.next();
            if (!(child instanceof javax.xml.soap.Text)) {
                traverseSubtree(child, result);
            }
        }
    }
    
    public List generateReferenceList(List targetList,SecurableSoapMessage secureMessage,FilterProcessingContext fpContext,
            boolean verify, boolean isEndorsing)
    throws PolicyGenerationException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,XWSSecurityException {
        XMLSignatureFactory factory = getSignatureFactory();
        return generateReferenceList(targetList,factory,secureMessage,fpContext,verify, isEndorsing);
    }
    
    //Time to refactor this method
    //bloated toomuch.
     @SuppressWarnings("unchecked")
    private List generateReferenceList(List targetList,XMLSignatureFactory signatureFactory,
            SecurableSoapMessage secureMessage,FilterProcessingContext fpContext,boolean verify, 
            boolean isEndorsing)
            throws PolicyGenerationException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,XWSSecurityException {
        
        SignaturePolicy signaturePolicy = (SignaturePolicy) fpContext.getSecurityPolicy();
        SignaturePolicy.FeatureBinding featureBinding = (SignaturePolicy.FeatureBinding)signaturePolicy.getFeatureBinding();
        ListIterator iterator = targetList.listIterator();
        ArrayList references = new ArrayList();
        if(logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "Number of Targets is"+targetList.size());
        }
        
        while(iterator.hasNext()) {
            
            SignatureTarget signatureTarget = (SignatureTarget)iterator.next();
            String digestAlgo = signatureTarget.getDigestAlgorithm();
            if(logger.isLoggable(Level.FINEST)){
                logger.log(Level.FINEST, "Digest Algorithm is "+digestAlgo);
                logger.log(Level.FINEST, "Targets is"+signatureTarget.getValue());
            }
            DigestMethod digestMethod =null;
            try{
                digestMethod = signatureFactory.newDigestMethod(digestAlgo, null);
            }catch(Exception ex){
                logger.log(Level.SEVERE,LogStringsMessages.WSS_1301_INVALID_DIGEST_ALGO(digestAlgo),ex);
                throw new XWSSecurityException(ex.getMessage());
            }
            
            boolean exclTransformToBeAdded = false;
            ArrayList transforms = signatureTarget.getTransforms();
            ListIterator transformIterator = transforms.listIterator();
            ArrayList transformList = new ArrayList(2);
            boolean disableInclusivePrefix = false;
            while(transformIterator.hasNext()) {
                SignatureTarget.Transform transformInfo = (SignatureTarget.Transform)transformIterator.next();
                String transformAlgo = transformInfo.getTransform();
                Transform transform = null;
                
                if(logger.isLoggable(Level.FINEST))
                    logger.log(Level.FINEST, "Transform Algorithm is "+transformAlgo);
                if(transformAlgo == Transform.XPATH || transformAlgo.equals(Transform.XPATH)){
                    TransformParameterSpec spec =(TransformParameterSpec) transformInfo.getAlgorithmParameters();
                    //XPathFilterParameterSpec spec = null;
                    
                    if(spec == null){
                        logger.log(Level.SEVERE,LogStringsMessages.WSS_1367_ILLEGAL_XPATH());
                        throw new XWSSecurityException("XPATH parameters cannot be null");
                        
                    }
                    //XPATH2,XSLTC , ..
                    transform = signatureFactory.newTransform(transformAlgo,spec);
                    
                }else if(transformAlgo == Transform.XPATH2 || transformAlgo.equals(Transform.XPATH2)){
                    TransformParameterSpec transformParams = (TransformParameterSpec)transformInfo.getAlgorithmParameters();
                    transform= signatureFactory.newTransform(transformAlgo,transformParams);
                }else if (transformAlgo == MessageConstants.STR_TRANSFORM_URI || transformAlgo.equals(MessageConstants.STR_TRANSFORM_URI)){
                    Parameter transformParams =(Parameter) transformInfo.getAlgorithmParameters();
                    String  algo = null;
                    if(transformParams.getParamName().equals("CanonicalizationMethod")){
                        algo = transformParams.getParamValue();
                    }
                    if(algo == null){
                        logger.log(Level.SEVERE, LogStringsMessages.WSS_1368_ILLEGAL_STR_CANONCALIZATION());
                        throw new XWSSecurityException("STR Transform must have a"+
                                "canonicalization method specified");
                    }
                    if(logger.isLoggable(Level.FINEST)){
                        logger.log(Level.FINEST, "CanonicalizationMethod is " + algo);
                    }
                    CanonicalizationMethod cm = null;
                    C14NMethodParameterSpec spec = null;
                    try{
                        Document doc = WSITXMLFactory.createDocumentBuilderFactory(WSITXMLFactory.DISABLE_SECURE_PROCESSING).newDocumentBuilder().newDocument();
                        Element tp = doc.createElementNS(MessageConstants.WSSE_NS, "wsse:TransformationParameters");
                        Element cem = doc.createElementNS(MessageConstants.DSIG_NS, "ds:CanonicalizationMethod");
                        tp.appendChild(cem);
                        cem.setAttribute("Algorithm",algo);
                        doc.appendChild(tp);
                        XMLStructure transformSpec = new DOMStructure(tp);
                        transform = signatureFactory.newTransform(transformAlgo,transformSpec);
                    }catch(Exception ex){
                        logger.log(Level.SEVERE,LogStringsMessages.WSS_1300_DSIG_TRANSFORM_PARAM_ERROR(),ex);
                        throw new XWSSecurityException(ex.getMessage());
                    }
                } else if (MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS.equalsIgnoreCase(transformAlgo)) {
                    // should be there by default...
                    // As per R 5412, last child of ds:Transforms must be either excl-c14n, or attachment-content only or attachment-complete transform
                    exclTransformToBeAdded = true;
                    disableInclusivePrefix = transformInfo.getDisableInclusivePrefix();
                } else {
                    //                    XMLStructure transformSpec = null;
                    //                    transform = signatureFactory.newTransform(transformAlgo,transformSpec);
                    //                    Workaround for JSR105 bug
                    transform = signatureFactory.newTransform(transformAlgo,(TransformParameterSpec) null);
                }
                if (!MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS.equalsIgnoreCase(transformAlgo)) {
                    // will add c14n transform in the end; later
                    transformList.add(transform);
                }
            }
            String targetURI = "";
            String signatureType = signatureTarget.getType();
            SOAPMessage msg = secureMessage.getSOAPMessage();
            boolean headersOnly = signatureTarget.isSOAPHeadersOnly();
            if(signatureType.equals(SignatureTarget.TARGET_TYPE_VALUE_QNAME) || signatureType.equals(SignatureTarget.TARGET_TYPE_VALUE_XPATH)){
                
                String expr = null;
                NodeList nodes  = null;
                if( signatureType == SignatureTarget.TARGET_TYPE_VALUE_QNAME){
                    String targetValue = signatureTarget.getValue();
                    boolean optimized = false;
                    if(fpContext.getConfigType() == MessageConstants.SIGN_BODY || fpContext.getConfigType() == MessageConstants.SIGN_ENCRYPT_BODY){
                        optimized = true;
                    }
//                    if(targetValue.equals(SignatureTarget.BODY) && optimized){
//                        Reference ref =  new JAXWSDigestProcessor(fpContext,signatureTarget , digestMethod, signatureFactory).handleJAXWSSOAPBody();
//                        references.add(ref);
//                        continue;
//                    }
                    
                    
                    if(targetValue.equals(SignatureTarget.BODY )){
                        try{
                            
                            final SOAPElement se = msg.getSOAPBody();
                            
                            nodes = new NodeList(){
                                Node node = se;
                                public int getLength(){
                                    if(node == null){
                                        return 0;
                                    }else{
                                        return 1;
                                    }
                                }
                                public Node item(int num){
                                    if(num == 0){
                                        return node;
                                    }else{
                                        return null;
                                    }
                                }
                            };
                        }catch(SOAPException se){
                            logger.log(Level.SEVERE, LogStringsMessages.WSS_1369_UNABLE_GET_SIGNATURE_TARGET_BY_URI());
                            throw new XWSSecurityException("SignatureTarget with URI "+targetValue+
                                   " is not in the message");
                             //logger.log(
                             //   Level.WARNING, "Signed Part with QName " + targetValue + " is not in the message");
                             //continue;
                        }
                    }else{
                        
                        QName name = QName.valueOf(targetValue);
                        if(!headersOnly){
                            if("".equals(name.getNamespaceURI())){
                                nodes =msg.getSOAPPart().getElementsByTagName(name.getLocalPart());
                            }else{
                                if(!"".equals(name.getLocalPart()))
                                    nodes = msg.getSOAPPart().getElementsByTagNameNS(name.getNamespaceURI(), name.getLocalPart());
                                else
                                    nodes = msg.getSOAPPart().getElementsByTagNameNS(name.getNamespaceURI(), "*");                            
                            }
                        } else{
                            //process headers of soap message
                            try{
                                nodes = new NodeListImpl();
                                NodeList hdrChilds = msg.getSOAPHeader().getChildNodes();
                                for(int i = 0; i < hdrChilds.getLength(); i++){
                                    Node child = hdrChilds.item(i);
                                    if(child.getNodeType() ==  Node.ELEMENT_NODE){
                                       if("".equals(name.getNamespaceURI())){
                                           if(name.getLocalPart().equals(child.getLocalName()))
                                               ((NodeListImpl)nodes).add(child);
                                       } else{
                                           // FIXME: Hack to get addressing members from both namespaces, as microsoft uses both of them in a soap message
                                           if(name.getNamespaceURI().equals(MessageConstants.ADDRESSING_MEMBER_SUBMISSION_NAMESPACE) ||
                                                   name.getNamespaceURI().equals(MessageConstants.ADDRESSING_W3C_NAMESPACE)){
                                               if((child.getNamespaceURI().equals(MessageConstants.ADDRESSING_MEMBER_SUBMISSION_NAMESPACE) || 
                                                       child.getNamespaceURI().equals(MessageConstants.ADDRESSING_W3C_NAMESPACE))) {
                                                   if(!"".equals(name.getLocalPart())){
                                                       if(name.getLocalPart().equals(child.getLocalName()))
                                                           ((NodeListImpl)nodes).add(child);
                                                   } else{
                                                       ((NodeListImpl)nodes).add(child);
                                                   }
                                               }
                                           } else{
                                               if(!"".equals(name.getLocalPart())){
                                                   if(name.getNamespaceURI().equals(child.getNamespaceURI()) && 
                                                           name.getLocalPart().equals(child.getLocalName()))
                                                       ((NodeListImpl)nodes).add(child);
                                               } else{
                                                   if(name.getNamespaceURI().equals(child.getNamespaceURI()))
                                                       ((NodeListImpl)nodes).add(child);
                                               }
                                           }
                                       } 
                                    }
                                }
                            } catch (SOAPException se){
                                logger.log(Level.SEVERE, LogStringsMessages.WSS_1370_FAILED_PROCESS_HEADER());
                                throw new XWSSecurityException(se);
                            }
                        }
                    }
                }else{
                    
                    expr = signatureTarget.getValue();
                    
                    try{
                        XPathFactory xpathFactory = WSITXMLFactory.createXPathFactory(WSITXMLFactory.DISABLE_SECURE_PROCESSING);
                        XPath xpath = xpathFactory.newXPath();
                        xpath.setNamespaceContext(secureMessage.getNamespaceContext());
                        //              XPathExpression expr = xpath.compile("//*[@wsu:Id]");
                        //XPathExpression expr = xpath.compile("//*");
                        XPathExpression xpathExpr = xpath.compile(expr);
                        if(logger.isLoggable(Level.FINEST)){
                            logger.log(Level.FINEST, "++++++++++++++++++++++++++++++");
                            logger.log(Level.FINEST, "Expr is "+expr);
                            printDocument((Node)secureMessage.getSOAPPart());
                        }
                        nodes = (NodeList)xpathExpr.evaluate((Object)secureMessage.getSOAPPart(),XPathConstants.NODESET);
                    }catch(XPathExpressionException xpe){
                        logger.log(Level.SEVERE,LogStringsMessages.WSS_1371_FAILED_RESOLVE_X_PATH()+expr,xpe);
                        throw new XWSSecurityException(xpe);
                    }
                }
                int i=0;
                if(nodes == null || nodes.getLength() <= 0){
                    if(signatureTarget.getEnforce()){
                        logger.log(Level.SEVERE, LogStringsMessages.WSS_1369_UNABLE_GET_SIGNATURE_TARGET_BY_URI());
                        throw new XWSSecurityException("SignatureTarget with URI "+signatureTarget.getValue()+
                               " is not in the message");
                    } else{
                        continue;
                    }
                    
                     // we dont throw error since WSSecurityPolicy allows this
                     //logger.log(Level.WARNING, "Signed Part with QName/XPath " + signatureTarget.getValue() +
                     //  " is not in the message");
                     //continue;
                }
                if(logger.isLoggable(Level.FINEST)){
                    logger.log(Level.FINEST, "Number of nodes "+nodes.getLength());
                    logger.log(Level.FINEST, "+++++++++++++++END+++++++++++++++");
                }
                HashMap elementCache = null;
                if(fpContext != null ){
                    elementCache = fpContext.getElementCache();
                }
                while(i < nodes.getLength()){
                    if(logger.isLoggable(Level.FINEST))
                        logger.log(Level.FINEST, "Nodes is "+nodes.item(i));
                    Node nodeRef = nodes.item(i++);
                    if(nodeRef.getNodeType() != Node.ELEMENT_NODE) {
                        logger.log (Level.SEVERE, LogStringsMessages.WSS_1371_FAILED_RESOLVE_X_PATH());
                        throw new XWSSecurityException(
                                "XPath does not correspond to a DOM Element");
                    }
                    ArrayList clonedTransformList = (ArrayList) transformList.clone();
                    if (exclTransformToBeAdded) {
                        // exc-14-nl must be one of the last transforms under ReferenceList by default.
                        String transformAlgo  = MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS;
                        ExcC14NParameterSpec spec = null;
                        if((featureBinding != null && featureBinding.isBSP()) || !disableInclusivePrefix){
                            spec = new ExcC14NParameterSpec(getReferenceNamespacePrefixes(nodeRef));
                        }
                        Transform transform = signatureFactory.newTransform(transformAlgo,spec);
                        clonedTransformList.add(transform);
                    }
                    boolean w3cElem = false;
                    // Assume only elements with wsu:Id are signed
                    String id = ((Element)nodeRef).getAttributeNS(MessageConstants.WSU_NS, "Id");
                    if(id == null || id.equals("")){
                        if(nodeRef.getNamespaceURI() == MessageConstants.DSIG_NS ||
                                nodeRef.getNamespaceURI() == MessageConstants.XENC_NS){
                            w3cElem = true;
                            id = ((Element)nodeRef).getAttribute("Id");
                        }
                        
                    }
                    
                    if (id == null || id.equals("")) {
                        id = secureMessage.generateId();
                        if(!verify){
                            if(w3cElem){
                                XMLUtil.setIdAttr((Element)nodeRef, id);
                            }else{
                                XMLUtil.setWsuIdAttr((Element)nodeRef, id);
                            }
                        }else{
                            //add to context. dont modify the message.
                            elementCache.put(id, nodeRef);
                        }
                    }
                    
                    if(logger.isLoggable(Level.FINEST))
                        logger.log(Level.FINEST, "SignedInfo val id "+id);
                    
                    targetURI = "#"+id;
                    
                    byte [] digestValue = fpContext.getDigestValue();
                    Reference reference = null;
                    if(!verify && digestValue != null){
                        reference = signatureFactory.newReference(targetURI,digestMethod,clonedTransformList,null,null,digestValue);
                    }else{
                        reference = signatureFactory.newReference(targetURI,digestMethod,clonedTransformList,null,null);
                    }
                    references.add(reference);
                }
                continue;   
            }else if(signatureType ==SignatureTarget.TARGET_TYPE_VALUE_URI){
                targetURI = signatureTarget.getValue();
                
                if(targetURI == null){
                    targetURI="";
                }
                if(targetURI == MessageConstants.PROCESS_ALL_ATTACHMENTS){
                    Iterator itr = secureMessage.getAttachments();
                    if ( !itr.hasNext()) {
                        logger.log(Level.SEVERE, LogStringsMessages.WSS_1372_NO_ATTACHMENT_FOUND());
                        throw new XWSSecurityException("No attachment present in the message");
                        //logger.log(Level.WARNING, "No Attachment Part present in the message to be secured");
                        //continue;
                    }
                    while(itr.hasNext()){
                        String cid = null;
                        AttachmentPart ap = (AttachmentPart)itr.next();
                        String _cid = ap.getContentId();
                        if (_cid.charAt(0) == '<' && _cid.charAt(_cid.length()-1) == '>'){
                            int lindex = _cid.lastIndexOf('>');
                            int sindex = _cid.indexOf('<');
                            if(lindex < sindex || lindex == sindex){
                                //log error
                                logger.log(Level.SEVERE,LogStringsMessages.WSS_1303_CID_ERROR());
                            }
                            cid = "cid:"+_cid.substring(sindex+1,lindex);
                        }else{
                            cid = "cid:"+_cid;
                        }
                        Reference reference = signatureFactory.newReference(cid,digestMethod,transformList,null,null);
                        references.add(reference);
                    }
                    continue;
                }else{
                    if (exclTransformToBeAdded) {
                        // exc-14-n must be one of the last transforms under ReferenceList by default.
//                        String transformAlgo  = MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS;
//                        ExcC14NParameterSpec spec = null;
//                        Transform transform = signatureFactory.newTransform(transformAlgo,spec);
//                        transformList.add(transform);
                        SOAPElement dataElement = null;
                        if (featureBinding != null && featureBinding.isBSP()) {
                            
//                            try {
                                String _uri = targetURI;
                                if(targetURI.length() > 0 && targetURI.charAt(0)=='#'){
                                    _uri = targetURI.substring(1);
                                }
                                dataElement =(SOAPElement) secureMessage.getElementById(_uri);
//                            } catch (TransformerException te) {
//                                logger.log(Level.SEVERE, "WSS1373.failedto.resolve.elementbyID", te);
//                                throw new XWSSecurityException(te.getMessage(), te);
//                            }
                        }
                        String transformAlgo  = MessageConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS;
                        ExcC14NParameterSpec spec = null;
                        if(dataElement != null && !disableInclusivePrefix){
                            spec =   new ExcC14NParameterSpec(getReferenceNamespacePrefixes(dataElement));
                        }
                        Transform transform = signatureFactory.newTransform(transformAlgo,spec);
                        transformList.add(transform);
                    }
                    if(targetURI.equals(SignatureTarget.ALL_MESSAGE_HEADERS)){
                        SOAPHeader soapHeader=null;
                        try{
                            soapHeader = secureMessage.getSOAPHeader();
                        }catch(SOAPException se) {
                            se.printStackTrace();
                        }
                        NodeList headers = soapHeader.getChildNodes();
                        Reference reference = null;
                        for(int i=0;i