You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2013/11/11 17:54:53 UTC

svn commit: r1540772 [4/5] - in /webservices/wss4j/trunk: parent/ ws-security-common/ ws-security-common/src/main/java/org/apache/wss4j/common/ext/ ws-security-common/src/main/java/org/apache/wss4j/common/util/ ws-security-common/src/test/java/org/apac...

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java Mon Nov 11 16:54:52 2013
@@ -18,42 +18,59 @@
  */
 package org.apache.wss4j.stax.impl.processor.input;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.security.Key;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import javax.crypto.Cipher;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
 import javax.xml.bind.JAXBElement;
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamException;
 
 import org.apache.wss4j.binding.wss10.SecurityTokenReferenceType;
 import org.apache.wss4j.common.bsp.BSPRule;
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.ext.AttachmentRequestCallback;
+import org.apache.wss4j.common.ext.AttachmentResultCallback;
 import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.util.AttachmentUtils;
 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
+import org.apache.wss4j.stax.ext.WSSConstants;
+import org.apache.wss4j.stax.ext.WSSSecurityProperties;
+import org.apache.wss4j.stax.ext.WSSUtils;
+import org.apache.wss4j.stax.securityEvent.EncryptedPartSecurityEvent;
 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
 import org.apache.xml.security.binding.xmldsig.KeyInfoType;
 import org.apache.xml.security.binding.xmldsig.TransformType;
 import org.apache.xml.security.binding.xmldsig.TransformsType;
+import org.apache.xml.security.binding.xmlenc.CipherReferenceType;
 import org.apache.xml.security.binding.xmlenc.EncryptedDataType;
 import org.apache.xml.security.binding.xmlenc.ReferenceList;
 import org.apache.xml.security.binding.xmlenc.ReferenceType;
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.stax.config.ConfigurationProperties;
 import org.apache.xml.security.stax.config.TransformerAlgorithmMapper;
-import org.apache.xml.security.stax.ext.*;
+import org.apache.xml.security.stax.ext.DocumentContext;
+import org.apache.xml.security.stax.ext.InboundSecurityContext;
+import org.apache.xml.security.stax.ext.InputProcessorChain;
+import org.apache.xml.security.stax.ext.SecurePart;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
+import org.apache.xml.security.stax.ext.XMLSecurityProperties;
+import org.apache.xml.security.stax.ext.XMLSecurityUtils;
 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.processor.input.AbstractDecryptInputProcessor;
 import org.apache.xml.security.stax.impl.util.LimitingInputStream;
 import org.apache.xml.security.stax.securityEvent.ContentEncryptedElementSecurityEvent;
 import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
 import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
-import org.apache.wss4j.stax.ext.WSSConstants;
-import org.apache.wss4j.stax.ext.WSSSecurityProperties;
-import org.apache.wss4j.stax.ext.WSSUtils;
-import org.apache.wss4j.stax.securityEvent.EncryptedPartSecurityEvent;
 import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
 import org.apache.xml.security.stax.securityToken.SecurityToken;
 
@@ -68,6 +85,8 @@ public class DecryptInputProcessor exten
     private static final Long maximumAllowedDecompressedBytes =
             Long.valueOf(ConfigurationProperties.getProperty("MaximumAllowedDecompressedBytes"));
 
+    private List<DeferredAttachment> attachmentReferences = new ArrayList<DeferredAttachment>();
+
     public DecryptInputProcessor(KeyInfoType keyInfoType, ReferenceList referenceList,
                                  WSSSecurityProperties securityProperties, WSInboundSecurityContext securityContext)
             throws XMLSecurityException {
@@ -162,6 +181,37 @@ public class DecryptInputProcessor exten
     }
 
     @Override
+    protected void handleCipherReference(InputProcessorChain inputProcessorChain, EncryptedDataType encryptedDataType,
+                                         Cipher cipher, InboundSecurityToken inboundSecurityToken) throws XMLSecurityException {
+
+        String typeStr = encryptedDataType.getType();
+        if (typeStr != null &&
+                (WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY.equals(typeStr) ||
+                        WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr))) {
+
+            CipherReferenceType cipherReferenceType = encryptedDataType.getCipherData().getCipherReference();
+            if (cipherReferenceType == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+            }
+
+            final String uri = cipherReferenceType.getURI();
+            if (uri == null || uri.length() < 5) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+            }
+            if (!uri.startsWith("cid:")) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+            }
+
+            //we need to do a deferred processing of the attachments for two reasons:
+            //1.) if an attachment is encrypted and signed the order is preserved
+            //2.) the attachments are processed after the SOAP-Document which allows us to stream everything
+            attachmentReferences.add(
+                    new DeferredAttachment(encryptedDataType, cipher, inboundSecurityToken)
+            );
+        }
+    }
+
+    @Override
     protected AbstractDecryptedEventReaderInputProcessor newDecryptedEventReaderInputProcessor(
             boolean encryptedHeader, XMLSecStartElement xmlSecStartElement, EncryptedDataType encryptedDataType,
             InboundSecurityToken inboundSecurityToken, InboundSecurityContext inboundSecurityContext) throws XMLSecurityException {
@@ -222,6 +272,102 @@ public class DecryptInputProcessor exten
             }
         }
         super.doFinal(inputProcessorChain);
+
+        //now process the (deferred-) attachments:
+        for (int i = 0; i < attachmentReferences.size(); i++) {
+            DeferredAttachment deferredAttachment = attachmentReferences.get(i);
+
+            final EncryptedDataType encryptedDataType = deferredAttachment.getEncryptedDataType();
+            final InboundSecurityToken inboundSecurityToken = deferredAttachment.getInboundSecurityToken();
+            final Cipher cipher = deferredAttachment.getCipher();
+            final String uri = encryptedDataType.getCipherData().getCipherReference().getURI();
+            final String attachmentId = uri.substring(4);
+
+            CallbackHandler attachmentCallbackHandler =
+                ((WSSSecurityProperties) getSecurityProperties()).getAttachmentCallbackHandler();
+            if (attachmentCallbackHandler == null) {
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.INVALID_SECURITY,
+                    "empty", "no attachment callbackhandler supplied"
+                );
+            }
+
+            AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
+            attachmentRequestCallback.setAttachmentId(attachmentId);
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+            }
+            List<Attachment> attachments = attachmentRequestCallback.getAttachments();
+            if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.INVALID_SECURITY,
+                    "empty", "Attachment not found"
+                );
+            }
+
+            final Attachment attachment = attachments.get(0);
+
+            final String encAlgo = encryptedDataType.getEncryptionMethod().getAlgorithm();
+            final Key symmetricKey =
+                inboundSecurityToken.getSecretKey(encAlgo, XMLSecurityConstants.Enc, encryptedDataType.getId());
+
+            InputStream attachmentInputStream =
+                AttachmentUtils.setupAttachmentDecryptionStream(encAlgo, cipher, symmetricKey, attachment.getSourceStream());
+
+            Attachment resultAttachment = new Attachment();
+            resultAttachment.setId(attachment.getId());
+            resultAttachment.setMimeType(encryptedDataType.getMimeType());
+            resultAttachment.setSourceStream(attachmentInputStream);
+            resultAttachment.addHeaders(attachment.getHeaders());
+
+            if (WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(encryptedDataType.getType())) {
+                try {
+                    AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
+                        resultAttachment.getHeaders(), attachmentInputStream);
+                } catch (IOException e) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+                }
+            }
+
+            AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
+            attachmentResultCallback.setAttachment(resultAttachment);
+            attachmentResultCallback.setAttachmentId(resultAttachment.getId());
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+            }
+        }
+    }
+    
+    private class DeferredAttachment {
+
+        private EncryptedDataType encryptedDataType;
+        private Cipher cipher;
+        private InboundSecurityToken inboundSecurityToken;
+
+        private DeferredAttachment(
+            EncryptedDataType encryptedDataType, Cipher cipher,
+            InboundSecurityToken inboundSecurityToken) {
+
+            this.encryptedDataType = encryptedDataType;
+            this.cipher = cipher;
+            this.inboundSecurityToken = inboundSecurityToken;
+        }
+
+        private EncryptedDataType getEncryptedDataType() {
+            return encryptedDataType;
+        }
+
+        private Cipher getCipher() {
+            return cipher;
+        }
+
+        private InboundSecurityToken getInboundSecurityToken() {
+            return inboundSecurityToken;
+        }
     }
 
     /*

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/WSSSignatureReferenceVerifyInputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/WSSSignatureReferenceVerifyInputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/WSSSignatureReferenceVerifyInputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/WSSSignatureReferenceVerifyInputProcessor.java Mon Nov 11 16:54:52 2013
@@ -21,7 +21,11 @@ package org.apache.wss4j.stax.impl.proce
 import org.apache.wss4j.binding.wss10.TransformationParametersType;
 import org.apache.wss4j.common.bsp.BSPRule;
 import org.apache.wss4j.common.cache.ReplayCache;
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.ext.AttachmentRequestCallback;
+import org.apache.wss4j.common.ext.AttachmentResultCallback;
 import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.stax.impl.transformer.AttachmentContentSignatureTransform;
 import org.apache.wss4j.stax.securityToken.SecurityTokenReference;
 import org.apache.xml.security.binding.excc14n.InclusiveNamespaces;
 import org.apache.xml.security.binding.xmldsig.CanonicalizationMethodType;
@@ -33,6 +37,9 @@ import org.apache.xml.security.stax.ext.
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.processor.input.AbstractSignatureReferenceVerifyInputProcessor;
+import org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_Excl;
+import org.apache.xml.security.stax.impl.util.DigestOutputStream;
+import org.apache.xml.security.stax.impl.util.UnsynchronizedBufferedOutputStream;
 import org.apache.xml.security.stax.securityEvent.AlgorithmSuiteSecurityEvent;
 import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
 import org.apache.wss4j.stax.ext.*;
@@ -42,14 +49,15 @@ import org.apache.xml.security.stax.secu
 import org.apache.xml.security.stax.securityToken.SecurityToken;
 import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
 
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamException;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 public class WSSSignatureReferenceVerifyInputProcessor extends AbstractSignatureReferenceVerifyInputProcessor {
 
@@ -64,6 +72,108 @@ public class WSSSignatureReferenceVerify
         checkBSPCompliance((WSInboundSecurityContext)inputProcessorChain.getSecurityContext());
     }
 
+    @Override
+    protected void verifyExternalReference(
+            InputProcessorChain inputProcessorChain, InputStream inputStream,
+            final ReferenceType referenceType) throws XMLSecurityException, XMLStreamException {
+
+        if (referenceType.getURI().startsWith("cid:")) {
+
+            CallbackHandler attachmentCallbackHandler =
+                    ((WSSSecurityProperties) getSecurityProperties()).getAttachmentCallbackHandler();
+            if (attachmentCallbackHandler == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.INVALID_SECURITY,
+                        "empty", "no attachment callbackhandler supplied"
+                );
+            }
+
+            String attachmentId = referenceType.getURI().substring(4);
+
+            AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
+            attachmentRequestCallback.setAttachmentId(attachmentId);
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+            }
+            List<Attachment> attachments = attachmentRequestCallback.getAttachments();
+            if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.INVALID_SECURITY,
+                        "empty", "Attachment not found"
+                );
+            }
+
+            final Attachment attachment = attachments.get(0);
+
+            InputStream attachmentInputStream = attachment.getSourceStream();
+            if (!attachmentInputStream.markSupported()) {
+                attachmentInputStream = new BufferedInputStream(attachmentInputStream);
+            }
+            //todo workaround 2GB limit somehow?
+            attachmentInputStream.mark(Integer.MAX_VALUE); //we can process at maximum 2G with the standard jdk streams
+
+            try {
+                DigestOutputStream digestOutputStream =
+                        createMessageDigestOutputStream(referenceType, inputProcessorChain.getSecurityContext());
+                UnsynchronizedBufferedOutputStream bufferedDigestOutputStream =
+                        new UnsynchronizedBufferedOutputStream(digestOutputStream);
+
+                if (referenceType.getTransforms() != null) {
+                    Transformer transformer =
+                            buildTransformerChain(referenceType, bufferedDigestOutputStream, inputProcessorChain, null);
+                    if (!(transformer instanceof AttachmentContentSignatureTransform)) {
+                        throw new WSSecurityException(
+                                WSSecurityException.ErrorCode.INVALID_SECURITY,
+                                "empty", "First transform must be Attachment[Content|Complete]SignatureTransform"
+                        );
+                    }
+                    Map<String, Object> transformerProperties = new HashMap<String, Object>(2);
+                    transformerProperties.put(
+                            AttachmentContentSignatureTransform.ATTACHMENT, attachment);
+                    transformer.setProperties(transformerProperties);
+
+                    transformer.transform(attachmentInputStream);
+
+                    bufferedDigestOutputStream.close();
+                } else {
+                    XMLSecurityUtils.copy(attachmentInputStream, bufferedDigestOutputStream);
+                    bufferedDigestOutputStream.close();
+                }
+                compareDigest(digestOutputStream.getDigestValue(), referenceType);
+
+                //reset the inputStream to be able to reuse it
+                attachmentInputStream.reset();
+
+            } catch (IOException e) {
+                throw new XMLSecurityException(e);
+            }
+
+            //create a new attachment and do the result callback
+            final Attachment resultAttachment = new Attachment();
+            resultAttachment.setId(attachmentId);
+            resultAttachment.setMimeType(attachment.getMimeType());
+            resultAttachment.addHeaders(attachment.getHeaders());
+            resultAttachment.setSourceStream(attachmentInputStream);
+
+            AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
+            attachmentResultCallback.setAttachmentId(attachmentId);
+            attachmentResultCallback.setAttachment(resultAttachment);
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+            }
+
+        } else {
+            super.verifyExternalReference(
+                    inputProcessorChain, inputStream, referenceType);
+        }
+    }
+
     private void checkBSPCompliance(WSInboundSecurityContext securityContext) throws WSSecurityException {
         List<ReferenceType> references = getSignatureType().getSignedInfo().getReference();
         for (int i = 0; i < references.size(); i++) {
@@ -225,11 +335,20 @@ public class WSSSignatureReferenceVerify
                         XMLSecurityUtils.getQNameType(transformationParametersType.getAny(), WSSConstants.TAG_dsig_CanonicalizationMethod);
                 if (canonicalizationMethodType != null) {
 
+                    algorithm = canonicalizationMethodType.getAlgorithm();
+
                     InclusiveNamespaces inclusiveNamespacesType =
                             XMLSecurityUtils.getQNameType(canonicalizationMethodType.getContent(), XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
-                    List<String> inclusiveNamespaces = inclusiveNamespacesType != null ? inclusiveNamespacesType.getPrefixList() : null;
-                    algorithm = canonicalizationMethodType.getAlgorithm();
-                    parentTransformer = WSSUtils.getTransformer(inclusiveNamespaces, outputStream, algorithm, XMLSecurityConstants.DIRECTION.IN);
+
+                    Map<String, Object> transformerProperties = null;
+                    if (inclusiveNamespacesType != null) {
+                        transformerProperties = new HashMap<String, Object>();
+                        transformerProperties.put(
+                                Canonicalizer20010315_Excl.INCLUSIVE_NAMESPACES_PREFIX_LIST,
+                                inclusiveNamespacesType.getPrefixList());
+                    }
+                    parentTransformer = WSSUtils.getTransformer(
+                            null, outputStream, transformerProperties, algorithm, XMLSecurityConstants.DIRECTION.IN);
                 }
             }
             algorithm = transformType.getAlgorithm();
@@ -239,13 +358,23 @@ public class WSSSignatureReferenceVerify
             algorithmSuiteSecurityEvent.setCorrelationID(referenceType.getId());
             inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);
 
-            InclusiveNamespaces inclusiveNamespacesType = XMLSecurityUtils.getQNameType(transformType.getContent(), XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
-            List<String> inclusiveNamespaces = inclusiveNamespacesType != null ? inclusiveNamespacesType.getPrefixList() : null;
+            InclusiveNamespaces inclusiveNamespacesType =
+                    XMLSecurityUtils.getQNameType(transformType.getContent(), XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
+
+            Map<String, Object> transformerProperties = null;
+            if (inclusiveNamespacesType != null) {
+                transformerProperties = new HashMap<String, Object>();
+                transformerProperties.put(
+                        Canonicalizer20010315_Excl.INCLUSIVE_NAMESPACES_PREFIX_LIST,
+                        inclusiveNamespacesType.getPrefixList());
+            }
 
             if (parentTransformer != null) {
-                parentTransformer = WSSUtils.getTransformer(parentTransformer, inclusiveNamespaces, algorithm, XMLSecurityConstants.DIRECTION.IN);
+                parentTransformer = WSSUtils.getTransformer(
+                        parentTransformer, null, transformerProperties, algorithm, XMLSecurityConstants.DIRECTION.IN);
             } else {
-                parentTransformer = WSSUtils.getTransformer(inclusiveNamespaces, outputStream, algorithm, XMLSecurityConstants.DIRECTION.IN);
+                parentTransformer = WSSUtils.getTransformer(
+                        null, outputStream, transformerProperties, algorithm, XMLSecurityConstants.DIRECTION.IN);
             }
         }
 

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptEndingOutputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptEndingOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptEndingOutputProcessor.java Mon Nov 11 16:54:52 2013
@@ -22,6 +22,7 @@ import org.apache.wss4j.stax.impl.Securi
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.stax.ext.OutputProcessorChain;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.impl.EncryptionPartDef;
 import org.apache.xml.security.stax.impl.processor.output.AbstractEncryptEndingOutputProcessor;
 import org.apache.wss4j.stax.ext.WSSConstants;
 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
@@ -49,6 +50,9 @@ public class EncryptEndingOutputProcesso
             || !((WSSSecurityProperties)getSecurityProperties()).isEncryptSymmetricEncrytionKey()) {
             WSSUtils.createReferenceListStructureForEncryption(this, subOutputProcessorChain);
         }
+        if (attachmentCount(outputProcessorChain) > 0) {
+            WSSUtils.createEncryptedDataStructureForAttachments(this, subOutputProcessorChain);
+        }
     }
 
     @Override
@@ -71,6 +75,11 @@ public class EncryptEndingOutputProcesso
                             WSSUtils.updateSecurityHeaderOrder(
                                     outputProcessorChain, WSSConstants.TAG_xenc_ReferenceList, getAction(), true);                            
                         }
+                        int attachmentCount = attachmentCount(outputProcessorChain);
+                        for (int i = 0; i < attachmentCount; i++) {
+                            WSSUtils.updateSecurityHeaderOrder(
+                                    outputProcessorChain, WSSConstants.TAG_xenc_EncryptedData, getAction(), true);
+                        }
                         List<SecurityHeaderOrder> securityHeaderOrderList = 
                                 outputProcessorChain.getSecurityContext().getAsList(SecurityHeaderOrder.class);
                         List<SecurityHeaderOrder> tmpList = null;
@@ -94,4 +103,23 @@ public class EncryptEndingOutputProcesso
         }
         super.flushBufferAndCallbackAfterHeader(outputProcessorChain, xmlSecEventDeque);
     }
+
+    private int attachmentCount(OutputProcessorChain outputProcessorChain) {
+        List<EncryptionPartDef> encryptionPartDefs =
+                outputProcessorChain.getSecurityContext().getAsList(EncryptionPartDef.class);
+        if (encryptionPartDefs == null) {
+            return 0;
+        }
+
+        int count = 0;
+        Iterator<EncryptionPartDef> encryptionPartDefIterator = encryptionPartDefs.iterator();
+        while (encryptionPartDefIterator.hasNext()) {
+            EncryptionPartDef encryptionPartDef = encryptionPartDefIterator.next();
+
+            if (encryptionPartDef.getCipherReferenceId() != null) {
+                count++;
+            }
+        }
+        return count;
+    }
 }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java Mon Nov 11 16:54:52 2013
@@ -18,23 +18,31 @@
  */
 package org.apache.wss4j.stax.impl.processor.output;
 
-import java.io.OutputStream;
+import java.io.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.Attribute;
 
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.ext.AttachmentRequestCallback;
+import org.apache.wss4j.common.ext.AttachmentResultCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.util.AttachmentUtils;
 import org.apache.wss4j.stax.ext.WSSConstants;
 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
 import org.apache.wss4j.stax.ext.WSSUtils;
 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
 import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
 import org.apache.xml.security.stax.config.TransformerAlgorithmMapper;
 import org.apache.xml.security.stax.ext.OutputProcessorChain;
 import org.apache.xml.security.stax.ext.SecurePart;
@@ -120,6 +128,122 @@ public class EncryptOutputProcessor exte
         outputProcessorChain.processEvent(xmlSecEvent);
     }
 
+    @Override
+    public void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
+        setupAttachmentEncryptionStreams(outputProcessorChain);
+        super.doFinalInternal(outputProcessorChain);
+    }
+
+    protected void setupAttachmentEncryptionStreams(OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
+
+        SecurePart attachmentSecurePart = null;
+
+        Map<Object, SecurePart> dynamicSecureParts = outputProcessorChain.getSecurityContext().getAsMap(XMLSecurityConstants.ENCRYPTION_PARTS);
+        Iterator<Map.Entry<Object, SecurePart>> securePartsMapIterator = dynamicSecureParts.entrySet().iterator();
+        while (securePartsMapIterator.hasNext()) {
+            Map.Entry<Object, SecurePart> securePartEntry = securePartsMapIterator.next();
+            final SecurePart securePart = securePartEntry.getValue();
+            final String externalReference = securePart.getExternalReference();
+            if (externalReference != null && "cid:Attachments".equals(externalReference)) {
+                attachmentSecurePart = securePart;
+                break;
+            }
+        }
+        if (attachmentSecurePart == null) {
+            return;
+        }
+
+        CallbackHandler attachmentCallbackHandler =
+                ((WSSSecurityProperties) getSecurityProperties()).getAttachmentCallbackHandler();
+        if (attachmentCallbackHandler == null) {
+            throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE,
+                    "empty", "no attachment callbackhandler supplied"
+            );
+        }
+
+        AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
+        try {
+            attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
+        } catch (Exception e) {
+            throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE, e
+            );
+        }
+        List<Attachment> attachments = attachmentRequestCallback.getAttachments();
+        if (attachments == null || attachments.isEmpty()) {
+            throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE,
+                    "noEncElement"
+            );
+        }
+
+        for (int i = 0; i < attachments.size(); i++) {
+            final Attachment attachment = attachments.get(i);
+            final String attachmentId = attachment.getId();
+
+            String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
+            SecurityTokenProvider<OutboundSecurityToken> securityTokenProvider =
+                    outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+            OutboundSecurityToken securityToken = securityTokenProvider.getSecurityToken();
+            EncryptionPartDef encryptionPartDef = new EncryptionPartDef();
+            encryptionPartDef.setSecurePart(attachmentSecurePart);
+            encryptionPartDef.setModifier(attachmentSecurePart.getModifier());
+            encryptionPartDef.setCipherReferenceId(attachment.getId());
+            encryptionPartDef.setMimeType(attachment.getMimeType());
+            encryptionPartDef.setEncRefId(IDGenerator.generateID(null));
+            encryptionPartDef.setKeyId(securityTokenProvider.getId());
+            encryptionPartDef.setSymmetricKey(securityToken.getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm()));
+            outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef);
+
+            final Attachment resultAttachment = new Attachment();
+            resultAttachment.setId(attachmentId);
+            resultAttachment.setMimeType("application/octet-stream");
+
+            String encryptionSymAlgorithm = getSecurityProperties().getEncryptionSymAlgorithm();
+            String jceAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(encryptionSymAlgorithm);
+            if (jceAlgorithm == null) {
+                throw new XMLSecurityException("algorithms.NoSuchMap", encryptionSymAlgorithm);
+            }
+            //initialize the cipher
+            Cipher cipher = null;
+            try {
+                cipher = Cipher.getInstance(jceAlgorithm);
+
+                // The Spec mandates a 96-bit IV for GCM algorithms
+                if ("AES/GCM/NoPadding".equals(cipher.getAlgorithm())) {
+                    byte[] temp = new byte[12];
+                    XMLSecurityConstants.secureRandom.nextBytes(temp);
+                    IvParameterSpec ivParameterSpec = new IvParameterSpec(temp);
+                    cipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey(), ivParameterSpec);
+                } else {
+                    cipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey());
+                }
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+            }
+
+            final Map<String, String> headers = new HashMap<String, String>();
+            headers.putAll(attachment.getHeaders());
+            resultAttachment.setSourceStream(
+                    AttachmentUtils.setupAttachmentEncryptionStream(
+                            cipher,
+                            SecurePart.Modifier.Element == encryptionPartDef.getModifier(),
+                            attachment, headers
+                    ));
+            resultAttachment.addHeaders(headers);
+
+            final AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
+            attachmentResultCallback.setAttachmentId(attachmentId);
+            attachmentResultCallback.setAttachment(resultAttachment);
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+            }
+        }
+    }
+
     /**
      * Processor which handles the effective encryption of the data
      */

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SecurityHeaderOutputProcessor.java Mon Nov 11 16:54:52 2013
@@ -181,7 +181,11 @@ public class SecurityHeaderOutputProcess
     }
     
     private SecurePart convertSecurePart(SecurePart securePart, String soapVersion) {
-        QName secureName = securePart.getName();
+        final QName secureName = securePart.getName();
+        if (secureName == null) {
+            return securePart;
+        }
+
         QName newName = secureName;
         
         if (WSSConstants.NS_SOAP11.equals(secureName.getNamespaceURI())

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java Mon Nov 11 16:54:52 2013
@@ -213,7 +213,10 @@ public class WSSSignatureEndingOutputPro
                     attributes.add(createAttribute(WSSConstants.ATT_NULL_Algorithm, transform));
                     createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transform, false, attributes);
 
-                    if (getSecurityProperties().isAddExcC14NInclusivePrefixes()) {
+                    if (getSecurityProperties().isAddExcC14NInclusivePrefixes()
+                            && !WSSConstants.SWA_ATTACHMENT_CONTENT_SIG_TRANS.equals(transform)
+                            && !WSSConstants.SWA_ATTACHMENT_COMPLETE_SIG_TRANS.equals(transform))
+                    {
                         attributes = new ArrayList<XMLSecAttribute>(1);
                         attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_PrefixList, signaturePartDef.getInclusiveNamespacesPrefixes()));
                         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces, true, attributes);

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureOutputProcessor.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureOutputProcessor.java Mon Nov 11 16:54:52 2013
@@ -18,32 +18,41 @@
  */
 package org.apache.wss4j.stax.impl.processor.output;
 
-import java.io.OutputStream;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.Attribute;
 
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.ext.AttachmentRequestCallback;
+import org.apache.wss4j.common.ext.AttachmentResultCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.stax.ext.WSSConstants;
+import org.apache.wss4j.stax.ext.WSSSecurityProperties;
 import org.apache.wss4j.stax.ext.WSSUtils;
+import org.apache.wss4j.stax.impl.transformer.AttachmentContentSignatureTransform;
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.stax.ext.OutputProcessorChain;
 import org.apache.xml.security.stax.ext.SecurePart;
 import org.apache.xml.security.stax.ext.Transformer;
 import org.apache.xml.security.stax.ext.XMLSecurityConstants;
-import org.apache.xml.security.stax.ext.XMLSecurityUtils;
 import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.SignaturePartDef;
 import org.apache.xml.security.stax.impl.processor.output.AbstractSignatureOutputProcessor;
-import org.apache.xml.security.stax.impl.transformer.TransformIdentity;
+import org.apache.xml.security.stax.impl.util.DigestOutputStream;
 import org.apache.xml.security.stax.impl.util.IDGenerator;
+import org.apache.xml.security.utils.Base64;
 
 public class WSSSignatureOutputProcessor extends AbstractSignatureOutputProcessor {
 
@@ -77,12 +86,14 @@ public class WSSSignatureOutputProcessor
                     SignaturePartDef signaturePartDef = new SignaturePartDef();
                     signaturePartDef.setSecurePart(securePart);
                     signaturePartDef.setTransforms(securePart.getTransforms());
+                    if (signaturePartDef.getTransforms() == null) {
+                        signaturePartDef.setTransforms(new String[]{XMLSecurityConstants.NS_C14N_EXCL_OMIT_COMMENTS});
+                    }
                     signaturePartDef.setExcludeVisibleC14Nprefixes(true);
-                    String digestMethod = securePart.getDigestMethod();
-                    if (digestMethod == null) {
-                        digestMethod = getSecurityProperties().getSignatureDigestAlgorithm();
+                    signaturePartDef.setDigestAlgo(securePart.getDigestMethod());
+                    if (signaturePartDef.getDigestAlgo() == null) {
+                        signaturePartDef.setDigestAlgo(getSecurityProperties().getSignatureDigestAlgorithm());
                     }
-                    signaturePartDef.setDigestAlgo(digestMethod);
 
                     if (securePart.getIdToSign() == null) {
                         signaturePartDef.setGenerateXPointer(securePart.isGenerateXPointer());
@@ -133,6 +144,116 @@ public class WSSSignatureOutputProcessor
     }
 
     @Override
+    protected void digestExternalReference(
+            OutputProcessorChain outputProcessorChain, SecurePart securePart)
+            throws XMLSecurityException, XMLStreamException {
+
+        if ("cid:Attachments".equals(securePart.getExternalReference())) {
+
+            CallbackHandler attachmentCallbackHandler =
+                    ((WSSSecurityProperties) getSecurityProperties()).getAttachmentCallbackHandler();
+            if (attachmentCallbackHandler == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILED_SIGNATURE,
+                        "empty", "no attachment callbackhandler supplied"
+                );
+            }
+
+            AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
+            try {
+                attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
+            } catch (Exception e) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILED_SIGNATURE, e
+                );
+            }
+            List<Attachment> attachments = attachmentRequestCallback.getAttachments();
+            if (attachments == null || attachments.isEmpty()) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILED_SIGNATURE,
+                        "noEncElement"
+                );
+            }
+
+            for (int i = 0; i < attachments.size(); i++) {
+                final Attachment attachment = attachments.get(i);
+
+                SignaturePartDef signaturePartDef = new SignaturePartDef();
+                signaturePartDef.setSecurePart(securePart);
+                signaturePartDef.setSigRefId("cid:" + attachment.getId());
+                signaturePartDef.setExternalResource(true);
+                signaturePartDef.setTransforms(securePart.getTransforms());
+                if (signaturePartDef.getTransforms() == null) {
+                    if (securePart.getModifier() == SecurePart.Modifier.Element) {
+                        signaturePartDef.setTransforms(new String[]{WSSConstants.SWA_ATTACHMENT_COMPLETE_SIG_TRANS});
+                    } else {
+                        signaturePartDef.setTransforms(new String[]{WSSConstants.SWA_ATTACHMENT_CONTENT_SIG_TRANS});
+                    }
+                }
+                signaturePartDef.setExcludeVisibleC14Nprefixes(true);
+                signaturePartDef.setDigestAlgo(securePart.getDigestMethod());
+                if (signaturePartDef.getDigestAlgo() == null) {
+                    signaturePartDef.setDigestAlgo(getSecurityProperties().getSignatureDigestAlgorithm());
+                }
+
+                DigestOutputStream digestOutputStream = createMessageDigestOutputStream(signaturePartDef.getDigestAlgo());
+                InputStream inputStream = attachment.getSourceStream();
+                if (!inputStream.markSupported()) {
+                    inputStream = new BufferedInputStream(inputStream);
+                }
+                inputStream.mark(Integer.MAX_VALUE); //we can process at maximum 2G with the standard jdk streams
+
+                try {
+                    Transformer transformer = buildTransformerChain(digestOutputStream, signaturePartDef, null);
+
+                    Map<String, Object> transformerProperties = new HashMap<String, Object>(2);
+                    transformerProperties.put(
+                            AttachmentContentSignatureTransform.ATTACHMENT, attachment);
+                    transformer.setProperties(transformerProperties);
+                    transformer.transform(inputStream);
+                    transformer.doFinal();
+
+                    digestOutputStream.close();
+
+                    //reset the inputStream to be able to reuse it
+                    inputStream.reset();
+                } catch (IOException e) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+                } catch (XMLStreamException e) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+                }
+
+                String calculatedDigest = new String(Base64.encode(digestOutputStream.getDigestValue()));
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Calculated Digest: " + calculatedDigest);
+                }
+
+                signaturePartDef.setDigestValue(calculatedDigest);
+
+                //create a new attachment and do the result callback
+                Attachment resultAttachment = new Attachment();
+                resultAttachment.setId(attachment.getId());
+                resultAttachment.setMimeType(attachment.getMimeType());
+                resultAttachment.addHeaders(attachment.getHeaders());
+                resultAttachment.setSourceStream(inputStream);
+
+                AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
+                attachmentResultCallback.setAttachmentId(resultAttachment.getId());
+                attachmentResultCallback.setAttachment(resultAttachment);
+                try {
+                    attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
+                } catch (Exception e) {
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+                }
+
+                getSignaturePartDefList().add(signaturePartDef);
+            }
+        } else {
+            super.digestExternalReference(outputProcessorChain, securePart);
+        }
+    }
+
+    @Override
     protected SecurePart securePartMatches(XMLSecStartElement xmlSecStartElement, Map<Object, SecurePart> secureParts) {
         SecurePart securePart = secureParts.get(xmlSecStartElement.getName());
         if (securePart == null) {
@@ -171,56 +292,6 @@ public class WSSSignatureOutputProcessor
         return securePart;
     }
 
-    @Override
-    protected Transformer buildTransformerChain(
-            OutputStream outputStream, SignaturePartDef signaturePartDef, XMLSecStartElement xmlSecStartElement)
-            throws XMLSecurityException {
-
-        String[] transforms = signaturePartDef.getTransforms();
-
-        if (transforms == null || transforms.length == 0) {
-            Transformer transformer = new TransformIdentity();
-            transformer.setOutputStream(outputStream);
-            return transformer;
-        }
-
-        List<String> inclusiveNamespacePrefixes = null;
-
-        Transformer parentTransformer = null;
-        for (int i = transforms.length - 1; i >= 0; i--) {
-            String transform = transforms[i];
-
-            if (getSecurityProperties().isAddExcC14NInclusivePrefixes() &&
-                    XMLSecurityConstants.NS_C14N_EXCL.equals(transform)) {
-
-                Set<String> prefixSet = XMLSecurityUtils.getExcC14NInclusiveNamespacePrefixes(xmlSecStartElement, signaturePartDef.isExcludeVisibleC14Nprefixes());
-                inclusiveNamespacePrefixes = new ArrayList<String>(prefixSet.size());
-
-                StringBuilder prefixes = new StringBuilder();
-                for (Iterator<String> iterator = prefixSet.iterator(); iterator.hasNext(); ) {
-                    String prefix = iterator.next();
-                    if (!inclusiveNamespacePrefixes.contains(prefix)) {
-                        inclusiveNamespacePrefixes.add(prefix);
-                    }
-                    if (prefixes.length() != 0) {
-                        prefixes.append(" ");
-                    }
-                    prefixes.append(prefix);
-                }
-                signaturePartDef.setInclusiveNamespacesPrefixes(prefixes.toString());
-            }
-
-            if (parentTransformer != null) {
-                parentTransformer = XMLSecurityUtils.getTransformer(
-                        parentTransformer, null, transform, XMLSecurityConstants.DIRECTION.OUT);
-            } else {
-                parentTransformer = XMLSecurityUtils.getTransformer(
-                        inclusiveNamespacePrefixes, outputStream, transform, XMLSecurityConstants.DIRECTION.OUT);
-            }
-        }
-        return parentTransformer;
-    }
-
     class InternalWSSSignatureOutputProcessor extends InternalSignatureOutputProcessor {
 
         public InternalWSSSignatureOutputProcessor(SignaturePartDef signaturePartDef, XMLSecStartElement xmlSecStartElement) throws XMLSecurityException {

Added: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/resourceResolvers/ResolverAttachment.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/resourceResolvers/ResolverAttachment.java?rev=1540772&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/resourceResolvers/ResolverAttachment.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/resourceResolvers/ResolverAttachment.java Mon Nov 11 16:54:52 2013
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.wss4j.stax.impl.resourceResolvers;
+
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.stax.ext.ResourceResolver;
+import org.apache.xml.security.stax.ext.ResourceResolverLookup;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
+
+import java.io.InputStream;
+
+/**
+ * Fake Resolver for SwA (SOAP with Attachment)
+ */
+public class ResolverAttachment implements ResourceResolver, ResourceResolverLookup {
+
+    @Override
+    public ResourceResolverLookup canResolve(String uri, String baseURI) {
+        if (uri == null) {
+            return null;
+        }
+        if (uri.startsWith("cid:")) {
+            return this;
+        }
+        return null;
+    }
+
+    @Override
+    public ResourceResolver newInstance(String uri, String baseURI) {
+        return new ResolverAttachment();
+    }
+
+    @Override
+    public boolean isSameDocumentReference() {
+        return false;
+    }
+
+    @Override
+    public boolean matches(XMLSecStartElement xmlSecStartElement) {
+        return false;
+    }
+
+    @Override
+    public InputStream getInputStreamFromExternalReference() throws XMLSecurityException {
+        return null;
+    }
+}

Added: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentCompleteSignatureTransform.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentCompleteSignatureTransform.java?rev=1540772&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentCompleteSignatureTransform.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentCompleteSignatureTransform.java Mon Nov 11 16:54:52 2013
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.wss4j.stax.impl.transformer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.wss4j.common.util.AttachmentUtils;
+import org.apache.xml.security.stax.impl.util.MultiInputStream;
+
+public class AttachmentCompleteSignatureTransform extends AttachmentContentSignatureTransform {
+
+    @Override
+    public void transform(InputStream inputStream) throws XMLStreamException {
+        InputStream is = inputStream;
+        try {
+            OutputStream outputStream = getOutputStream();
+            if (outputStream == null) {
+                outputStream = new ByteArrayOutputStream();
+                is = new MultiInputStream(
+                        new ByteArrayInputStream(
+                                ((ByteArrayOutputStream) outputStream).toByteArray()),
+                        inputStream
+                );
+            }
+            AttachmentUtils.canonizeMimeHeaders(outputStream, getAttachment().getHeaders());
+        } catch (IOException e) {
+            throw new XMLStreamException(e);
+        }
+        super.transform(is);
+    }
+}

Added: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentContentSignatureTransform.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentContentSignatureTransform.java?rev=1540772&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentContentSignatureTransform.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/AttachmentContentSignatureTransform.java Mon Nov 11 16:54:52 2013
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.wss4j.stax.impl.transformer;
+
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.util.CRLFOutputStream;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
+import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.impl.transformer.TransformIdentity;
+import org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_ExclOmitCommentsTransformer;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.InputStream;
+import java.util.Map;
+
+public class AttachmentContentSignatureTransform extends TransformIdentity {
+
+    public static final String ATTACHMENT = "attachment";
+
+    private Attachment attachment;
+
+    @Override
+    public XMLSecurityConstants.TransformMethod getPreferredTransformMethod(XMLSecurityConstants.TransformMethod forInput) {
+        switch (forInput) {
+            case XMLSecEvent:
+                return XMLSecurityConstants.TransformMethod.InputStream;
+            case InputStream:
+                return XMLSecurityConstants.TransformMethod.InputStream;
+            default:
+                throw new IllegalArgumentException("Unsupported class " + forInput.name());
+        }
+    }
+
+    @Override
+    public void setProperties(Map<String, Object> properties) throws XMLSecurityException {
+        this.attachment = (Attachment) properties.get(ATTACHMENT);
+    }
+
+    protected Attachment getAttachment() {
+        return attachment;
+    }
+
+    /*
+             * http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-SwAProfile-v1.1.1-os.html
+             * 5.2 Referencing Attachments
+             * This profile assumes, since it is not defined in RFC 2396 Section 4.2, that
+             * all cid: references are not same-document references and that therefore, under
+             * XMLDSIG, dereferencing a cid: URI always yields an octet stream as input to the
+             * transform chain [RFC2396], [XMLDSIG].
+             */
+    @Override
+    public void transform(XMLSecEvent xmlSecEvent) throws XMLStreamException {
+        throw new UnsupportedOperationException("transform(XMLSecEvent) not allowed");
+    }
+
+    @Override
+    public void transform(InputStream inputStream) throws XMLStreamException {
+        String mimeType = getAttachment().getMimeType();
+        if ("text/xml".equalsIgnoreCase(mimeType) ||
+                "application/xml".equals(mimeType) ||
+                mimeType != null && mimeType.endsWith("+xml")) {    //e.g. Application/mathml+xml
+                   /* 5.4.2:
+                    * Content of an XML Content-Type MUST be XML canonicalized using
+                    * Exclusive XML Canonicalization without comments,as specified by
+                    * the URI http://www.w3.org/2001/10/xml-exc-c14n# [Excl-Canon].
+                    * The reason for requiring Exclusive Canonicalization is that many
+                    * implementations will support Exclusive Canonicalization for other
+                    * XML Signature purposes, since this form of canonicalization
+                    * supports context changes. The InclusiveNamespace PrefixList
+                    * attribute SHOULD be empty or not present.
+                    */
+            Canonicalizer20010315_ExclOmitCommentsTransformer canon =
+                    new Canonicalizer20010315_ExclOmitCommentsTransformer();
+            try {
+                canon.setOutputStream(getOutputStream());
+            } catch (XMLSecurityException e) {
+                throw new XMLStreamException(e);
+            }
+            canon.transform(inputStream);
+
+        } else if (mimeType != null && mimeType.startsWith("text/")) {
+            CRLFOutputStream crlfOutputStream = new CRLFOutputStream(getOutputStream());
+            try {
+                setOutputStream(crlfOutputStream);
+            } catch (XMLSecurityException e) {
+                throw new XMLStreamException(e);
+            }
+            super.transform(inputStream);
+        } else {
+            super.transform(inputStream);
+        }
+    }
+}

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/STRTransformer.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/STRTransformer.java?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/STRTransformer.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/transformer/STRTransformer.java Mon Nov 11 16:54:52 2013
@@ -25,7 +25,9 @@ import org.apache.xml.security.stax.impl
 import org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_Excl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class STRTransformer extends TransformIdentity {
 
@@ -34,15 +36,14 @@ public class STRTransformer extends Tran
         if (!(transformer instanceof Canonicalizer20010315_Excl)) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
         }
-        ((Canonicalizer20010315_Excl) transformer).setPropagateDefaultNamespace(true);
         List<String> inclusiveNamespacesPrefixList = new ArrayList<String>();
         inclusiveNamespacesPrefixList.add("#default");
-        transformer.setList(inclusiveNamespacesPrefixList);
+        Map<String, Object> transformerProperties = new HashMap<String, Object>();
+        transformerProperties.put(
+            Canonicalizer20010315_Excl.INCLUSIVE_NAMESPACES_PREFIX_LIST, inclusiveNamespacesPrefixList);
+        transformerProperties.put(Canonicalizer20010315_Excl.PROPAGATE_DEFAULT_NAMESPACE, Boolean.TRUE);
+        transformer.setProperties(transformerProperties);
         super.setTransformer(transformer);
     }
 
-    @Override
-    public void setList(@SuppressWarnings("rawtypes") List list) throws XMLSecurityException {
-        throw new UnsupportedOperationException();
-    }
 }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/resources/wss/wss-config.xml
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/resources/wss/wss-config.xml?rev=1540772&r1=1540771&r2=1540772&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/resources/wss/wss-config.xml (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/resources/wss/wss-config.xml Mon Nov 11 16:54:52 2013
@@ -5,6 +5,7 @@
         <Property NAME="securityTokenFactory" VAL="org.apache.wss4j.stax.impl.securityToken.SecurityTokenFactoryImpl"/>
         <Property NAME="MaximumAllowedDecompressedBytes" VAL="104857600"/>
         <xi:include href="security-config.xml" xpointer="xmlns(c=http://www.xmlsecurity.org/NS/configuration)xpointer(/c:Configuration/c:Properties/c:Property[@NAME!='securityTokenFactory'])"/>
+        <Property NAME="AllowNotSameDocumentReferences" VAL="true"/>
     </Properties>
     <SecurityHeaderHandlers>
         <Handler NAME="BinarySecurityToken"
@@ -58,6 +59,11 @@
        <TransformAlgorithm URI="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform"
                           JAVACLASS="org.apache.wss4j.stax.impl.transformer.STRTransformer" />
 
+       <TransformAlgorithm URI="http://docs.oasis-open.org/wss/oasis-wss-SwAProfile-1.1#Attachment-Content-Signature-Transform"
+                           JAVACLASS="org.apache.wss4j.stax.impl.transformer.AttachmentContentSignatureTransform" />
+       <TransformAlgorithm URI="http://docs.oasis-open.org/wss/oasis-wss-SwAProfile-1.1#Attachment-Complete-Signature-Transform"
+                           JAVACLASS="org.apache.wss4j.stax.impl.transformer.AttachmentCompleteSignatureTransform" />
+
        <!-- The compress-transformations are disabled by default because its not standard
        and could introduce potential security issues -->
        <!--
@@ -89,6 +95,8 @@
                   DESCRIPTION="A simple resolver for requests of same-document URIs"/>
         <Resolver JAVACLASS="org.apache.wss4j.stax.impl.resourceResolvers.ResolverXPointer"
                   DESCRIPTION="A simple resolver for requests of XPointer fragents"/>
+        <Resolver JAVACLASS="org.apache.wss4j.stax.impl.resourceResolvers.ResolverAttachment"
+                  DESCRIPTION="A simple resolver for SwA"/>
         <xi:include href="security-config.xml"
                     xpointer="xmlns(c=http://www.xmlsecurity.org/NS/configuration)xpointer(/c:Configuration/c:ResourceResolvers/c:Resolver[@JAVACLASS!='org.apache.xml.security.stax.impl.resourceResolvers.ResolverSameDocument' and @JAVACLASS!='org.apache.xml.security.stax.impl.resourceResolvers.ResolverXPointer'])"/>
     </ResourceResolvers>