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>