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 2015/05/22 15:46:34 UTC
svn commit: r1681118 - in /webservices/wss4j/trunk:
ws-security-common/src/main/java/org/apache/wss4j/common/
ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/
ws-security-dom/src/main/java/org/apache/wss4j/dom/util/
ws-security-dom/src/tes...
Author: coheigea
Date: Fri May 22 13:46:33 2015
New Revision: 1681118
URL: http://svn.apache.org/r1681118
Log:
Initial support added to the DOM code to support xop:Include processing
Added:
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
- copied, changed from r1680505, webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java
- copied, changed from r1680505, webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/X509Util.java
webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/XOPAttachmentTest.java
Removed:
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/X509Util.java
Modified:
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/WSS4JConstants.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/WSS4JConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/WSS4JConstants.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/WSS4JConstants.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/WSS4JConstants.java Fri May 22 13:46:33 2015
@@ -98,6 +98,7 @@ public class WSS4JConstants {
"http://docs.oasis-open.org/wss/oasis-wss-SwAProfile-1.1#Attachment-Content-Only";
public static final String SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE =
"http://docs.oasis-open.org/wss/oasis-wss-SwAProfile-1.1#Attachment-Complete";
+ public static final String XOP_NS = "http://www.w3.org/2004/08/xop/include";
public static final String KEYTRANSPORT_RSA15 =
"http://www.w3.org/2001/04/xmlenc#rsa-1_5";
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java Fri May 22 13:46:33 2015
@@ -46,7 +46,9 @@ import org.apache.wss4j.dom.str.STRParse
import org.apache.wss4j.dom.str.STRParserParameters;
import org.apache.wss4j.dom.str.STRParserResult;
import org.apache.wss4j.dom.str.SecurityTokenRefSTRParser;
+import org.apache.wss4j.dom.util.EncryptionUtils;
import org.apache.wss4j.dom.util.WSSecurityUtil;
+import org.apache.wss4j.dom.util.X509Util;
import org.w3c.dom.Element;
/**
@@ -146,7 +148,7 @@ public class EncryptedDataProcessor impl
algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
}
- WSDataRef dataRef = ReferenceListProcessor.decryptEncryptedData(
+ WSDataRef dataRef = EncryptionUtils.decryptEncryptedData(
elem.getOwnerDocument(), encryptedDataId, elem, key, symEncAlgo, request);
WSSecurityEngineResult result =
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java Fri May 22 13:46:33 2015
@@ -35,12 +35,17 @@ import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.bsp.BSPEnforcer;
import org.apache.wss4j.common.bsp.BSPRule;
import org.apache.wss4j.common.crypto.AlgorithmSuite;
import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
import org.apache.wss4j.common.crypto.CryptoType;
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.ext.AttachmentRequestCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.token.DOMX509IssuerSerial;
import org.apache.wss4j.common.token.SecurityTokenReference;
@@ -55,10 +60,13 @@ import org.apache.wss4j.dom.str.Encrypte
import org.apache.wss4j.dom.str.STRParser;
import org.apache.wss4j.dom.str.STRParserParameters;
import org.apache.wss4j.dom.str.STRParserResult;
+import org.apache.wss4j.dom.util.EncryptionUtils;
import org.apache.wss4j.dom.util.WSSecurityUtil;
+import org.apache.wss4j.dom.util.X509Util;
import org.apache.xml.security.algorithms.JCEMapper;
import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.utils.Base64;
+import org.apache.xml.security.utils.JavaUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -231,8 +239,16 @@ public class EncryptedKeyProcessor imple
byte[] encryptedEphemeralKey = null;
byte[] decryptedBytes = null;
+
try {
- encryptedEphemeralKey = getDecodedBase64EncodedData(xencCipherValue);
+ // Get the key bytes from CipherValue directly or via an attachment
+ String xopUri = EncryptionUtils.getXOPURIFromCipherValue(xencCipherValue);
+ if (xopUri != null && xopUri.startsWith("cid:")) {
+ encryptedEphemeralKey = getDecryptedKeyBytesFromAttachment(xopUri, data);
+ } else {
+ encryptedEphemeralKey = getDecodedBase64EncodedData(xencCipherValue);
+ }
+
String keyAlgorithm = JCEMapper.translateURItoJCEID(encryptedKeyTransportMethod);
decryptedBytes = cipher.unwrap(encryptedEphemeralKey, keyAlgorithm, Cipher.SECRET_KEY).getEncoded();
} catch (IllegalStateException ex) {
@@ -264,6 +280,39 @@ public class EncryptedKeyProcessor imple
return Collections.singletonList(result);
}
+ private byte[] getDecryptedKeyBytesFromAttachment(
+ String xopUri, RequestData data
+ ) throws WSSecurityException {
+ CallbackHandler attachmentCallbackHandler = data.getAttachmentCallbackHandler();
+ if (attachmentCallbackHandler == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+ }
+
+ final String attachmentId = xopUri.substring(4);
+
+ AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
+ attachmentRequestCallback.setAttachmentId(attachmentId);
+
+ try {
+ attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
+
+ 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"
+ );
+ }
+ Attachment attachment = attachments.get(0);
+ InputStream inputStream = attachment.getSourceStream();
+
+ return JavaUtils.getBytesFromStream(inputStream);
+ } catch (UnsupportedCallbackException | IOException e) {
+ throw new WSSecurityException(
+ WSSecurityException.ErrorCode.FAILED_CHECK, e);
+ }
+ }
+
/**
* Generates a random secret key using the algorithm specified in the
* first DataReference URI
@@ -276,7 +325,7 @@ public class EncryptedKeyProcessor imple
if (uri != null) {
Element ee =
- ReferenceListProcessor.findEncryptedDataElement(refList.getOwnerDocument(),
+ EncryptionUtils.findEncryptedDataElement(refList.getOwnerDocument(),
wsDocInfo, uri);
String algorithmURI = X509Util.getEncAlgo(ee);
alg = JCEMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
@@ -512,7 +561,7 @@ public class EncryptedKeyProcessor imple
// Find the encrypted data element referenced by dataRefURI
//
Element encryptedDataElement =
- ReferenceListProcessor.findEncryptedDataElement(doc, docInfo, dataRefURI);
+ EncryptionUtils.findEncryptedDataElement(doc, docInfo, dataRefURI);
if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
List<WSSecurityEngineResult> signedResults =
docInfo.getResultsByTag(WSConstants.SIGN);
@@ -555,7 +604,7 @@ public class EncryptedKeyProcessor imple
algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
}
- return ReferenceListProcessor.decryptEncryptedData(
+ return EncryptionUtils.decryptEncryptedData(
doc, dataRefURI, encryptedDataElement, symmetricKey, symEncAlgo, data
);
}
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java Fri May 22 13:46:33 2015
@@ -19,32 +19,24 @@
package org.apache.wss4j.dom.processor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
import org.apache.wss4j.common.bsp.BSPEnforcer;
import org.apache.wss4j.common.bsp.BSPRule;
import org.apache.wss4j.common.crypto.AlgorithmSuite;
import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
-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.principal.WSDerivedKeyTokenPrincipal;
import org.apache.wss4j.common.token.SecurityTokenReference;
-import org.apache.wss4j.common.util.AttachmentUtils;
import org.apache.wss4j.common.util.KeyUtils;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
@@ -52,19 +44,13 @@ import org.apache.wss4j.dom.WSDataRef;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
-import org.apache.wss4j.dom.message.CallbackLookup;
import org.apache.wss4j.dom.str.STRParser;
import org.apache.wss4j.dom.str.STRParserParameters;
import org.apache.wss4j.dom.str.STRParserResult;
import org.apache.wss4j.dom.str.SecurityTokenRefSTRParser;
+import org.apache.wss4j.dom.util.EncryptionUtils;
import org.apache.wss4j.dom.util.WSSecurityUtil;
-import org.apache.xml.security.algorithms.JCEMapper;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
+import org.apache.wss4j.dom.util.X509Util;
public class ReferenceListProcessor implements Processor {
private static final org.slf4j.Logger LOG =
@@ -141,7 +127,8 @@ public class ReferenceListProcessor impl
//
// Find the encrypted data element referenced by dataRefURI
//
- Element encryptedDataElement = findEncryptedDataElement(doc, wsDocInfo, dataRefURI);
+ Element encryptedDataElement =
+ EncryptionUtils.findEncryptedDataElement(doc, wsDocInfo, dataRefURI);
if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
List<WSSecurityEngineResult> signedResults =
@@ -211,7 +198,7 @@ public class ReferenceListProcessor impl
}
return
- decryptEncryptedData(
+ EncryptionUtils.decryptEncryptedData(
doc, dataRefURI, encryptedDataElement, symmetricKey, symEncAlgo, data
);
}
@@ -261,269 +248,5 @@ public class ReferenceListProcessor impl
}
}
- /**
- * Look up the encrypted data. First try Id="someURI". If no such Id then try
- * wsu:Id="someURI".
- *
- * @param doc The document in which to find EncryptedData
- * @param wsDocInfo The WSDocInfo object to use
- * @param dataRefURI The URI of EncryptedData
- * @return The EncryptedData element
- * @throws WSSecurityException if the EncryptedData element referenced by dataRefURI is
- * not found
- */
- public static Element
- findEncryptedDataElement(
- Document doc,
- WSDocInfo wsDocInfo,
- String dataRefURI
- ) throws WSSecurityException {
- CallbackLookup callbackLookup = wsDocInfo.getCallbackLookup();
- Element encryptedDataElement =
- callbackLookup.getElement(dataRefURI, null, true);
- if (encryptedDataElement == null) {
- throw new WSSecurityException(
- WSSecurityException.ErrorCode.INVALID_SECURITY, "dataRef",
- new Object[] {dataRefURI});
- }
- if (encryptedDataElement.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
- && encryptedDataElement.getNamespaceURI().equals(WSConstants.WSSE11_NS)) {
- Node child = encryptedDataElement.getFirstChild();
- while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
- child = child.getNextSibling();
- }
- return (Element)child;
- }
- return encryptedDataElement;
- }
-
-
- /**
- * Decrypt the EncryptedData argument using a SecretKey.
- * @param doc The (document) owner of EncryptedData
- * @param dataRefURI The URI of EncryptedData
- * @param encData The EncryptedData element
- * @param symmetricKey The SecretKey with which to decrypt EncryptedData
- * @param symEncAlgo The symmetric encryption algorithm to use
- * @throws WSSecurityException
- */
- public static WSDataRef
- decryptEncryptedData(
- Document doc,
- String dataRefURI,
- Element encData,
- SecretKey symmetricKey,
- String symEncAlgo,
- RequestData requestData
- ) throws WSSecurityException {
-
- WSDataRef dataRef = new WSDataRef();
- dataRef.setEncryptedElement(encData);
- dataRef.setWsuId(dataRefURI);
- dataRef.setAlgorithm(symEncAlgo);
-
- // See if it is an attachment, and handle that differently
- String typeStr = encData.getAttributeNS(null, "Type");
- if (typeStr != null &&
- (WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY.equals(typeStr) ||
- WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr))) {
-
- return decryptAttachment(dataRefURI, encData, symmetricKey, symEncAlgo, requestData);
- }
-
- boolean content = X509Util.isContent(encData);
- dataRef.setContent(content);
-
- Node parent = encData.getParentNode();
- Node previousSibling = encData.getPreviousSibling();
- if (content) {
- encData = (Element) encData.getParentNode();
- parent = encData.getParentNode();
- }
-
- XMLCipher xmlCipher = null;
- try {
- xmlCipher = XMLCipher.getInstance(symEncAlgo);
- xmlCipher.setSecureValidation(true);
- xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
- } catch (XMLEncryptionException ex) {
- throw new WSSecurityException(
- WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex
- );
- }
-
- try {
- xmlCipher.doFinal(doc, encData, content);
- } catch (Exception ex) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
- }
-
- if (parent.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
- && parent.getNamespaceURI().equals(WSConstants.WSSE11_NS)
- || parent.getLocalName().equals(WSConstants.ENCRYPED_ASSERTION_LN)
- && parent.getNamespaceURI().equals(WSConstants.SAML2_NS)) {
-
- Node decryptedHeader = parent.getFirstChild();
- Node soapHeader = parent.getParentNode();
- soapHeader.replaceChild(decryptedHeader, parent);
-
- dataRef.setProtectedElement((Element)decryptedHeader);
- dataRef.setXpath(getXPath(decryptedHeader));
- } else if (content) {
- dataRef.setProtectedElement(encData);
- dataRef.setXpath(getXPath(encData));
- } else {
- Node decryptedNode;
- if (previousSibling == null) {
- decryptedNode = parent.getFirstChild();
- } else {
- decryptedNode = previousSibling.getNextSibling();
- }
- if (decryptedNode != null && Node.ELEMENT_NODE == decryptedNode.getNodeType()) {
- dataRef.setProtectedElement((Element)decryptedNode);
- }
- dataRef.setXpath(getXPath(decryptedNode));
- }
-
- return dataRef;
- }
-
- private static WSDataRef
- decryptAttachment(
- String dataRefURI,
- Element encData,
- SecretKey symmetricKey,
- String symEncAlgo,
- RequestData requestData
- ) throws WSSecurityException {
- WSDataRef dataRef = new WSDataRef();
- dataRef.setWsuId(dataRefURI);
- dataRef.setAlgorithm(symEncAlgo);
-
- try {
- Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
- if (cipherData == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- Element cipherReference = XMLUtils.getDirectChildElement(cipherData, "CipherReference", WSConstants.ENC_NS);
- if (cipherReference == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- String uri = cipherReference.getAttributeNS(null, "URI");
- if (uri == null || uri.length() < 5) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- if (!uri.startsWith("cid:")) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- dataRef.setWsuId(uri);
- dataRef.setAttachment(true);
-
- CallbackHandler attachmentCallbackHandler = requestData.getAttachmentCallbackHandler();
- if (attachmentCallbackHandler == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
-
- final String attachmentId = uri.substring(4);
-
- AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
- attachmentRequestCallback.setAttachmentId(attachmentId);
-
- attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
- List<Attachment> attachments = attachmentRequestCallback.getAttachments();
- if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
- throw new WSSecurityException(
- WSSecurityException.ErrorCode.INVALID_SECURITY,
- "empty", new Object[] {"Attachment not found"}
- );
- }
- Attachment attachment = attachments.get(0);
-
- final String encAlgo = X509Util.getEncAlgo(encData);
- final String jceAlgorithm =
- JCEMapper.translateURItoJCEID(encAlgo);
- final Cipher cipher = Cipher.getInstance(jceAlgorithm);
-
- InputStream attachmentInputStream =
- AttachmentUtils.setupAttachmentDecryptionStream(
- encAlgo, cipher, symmetricKey, attachment.getSourceStream());
-
- Attachment resultAttachment = new Attachment();
- resultAttachment.setId(attachment.getId());
- resultAttachment.setMimeType(encData.getAttributeNS(null, "MimeType"));
- resultAttachment.setSourceStream(attachmentInputStream);
- resultAttachment.addHeaders(attachment.getHeaders());
-
- String typeStr = encData.getAttributeNS(null, "Type");
- if (WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr)) {
- AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
- resultAttachment.getHeaders(), attachmentInputStream);
- }
-
- AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
- attachmentResultCallback.setAttachment(resultAttachment);
- attachmentResultCallback.setAttachmentId(resultAttachment.getId());
- attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
-
- } catch (UnsupportedCallbackException | IOException
- | NoSuchAlgorithmException | NoSuchPaddingException e) {
- throw new WSSecurityException(
- WSSecurityException.ErrorCode.FAILED_CHECK, e);
- }
-
- dataRef.setContent(true);
- // Remove this EncryptedData from the security header to avoid processing it again
- encData.getParentNode().removeChild(encData);
-
- return dataRef;
- }
-
- /**
- * @param decryptedNode the decrypted node
- * @return a fully built xpath
- * (eg. "/soapenv:Envelope/soapenv:Body/ns:decryptedElement")
- * if the decryptedNode is an Element or an Attr node and is not detached
- * from the document. <code>null</code> otherwise
- */
- public static String getXPath(Node decryptedNode) {
- if (decryptedNode == null) {
- return null;
- }
-
- String result = "";
- if (Node.ELEMENT_NODE == decryptedNode.getNodeType()) {
- result = decryptedNode.getNodeName();
- result = prependFullPath(result, decryptedNode.getParentNode());
- } else if (Node.ATTRIBUTE_NODE == decryptedNode.getNodeType()) {
- result = "@" + decryptedNode.getNodeName();
- result = prependFullPath(result, ((Attr)decryptedNode).getOwnerElement());
- } else {
- return null;
- }
-
- return result;
- }
-
-
- /**
- * Recursively build an absolute xpath (starting with the root "/")
- *
- * @param xpath the xpath expression built so far
- * @param node the current node whose name is to be prepended
- * @return a fully built xpath
- */
- private static String prependFullPath(String xpath, Node node) {
- if (node == null) {
- // probably a detached node... not really useful
- return null;
- } else if (Node.ELEMENT_NODE == node.getNodeType()) {
- xpath = node.getNodeName() + "/" + xpath;
- return prependFullPath(xpath, node.getParentNode());
- } else if (Node.DOCUMENT_NODE == node.getNodeType()) {
- return "/" + xpath;
- } else {
- return prependFullPath(xpath, node.getParentNode());
- }
- }
-
}
+
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java Fri May 22 13:46:33 2015
@@ -47,6 +47,7 @@ import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
+import org.apache.wss4j.dom.util.EncryptionUtils;
import org.apache.wss4j.dom.validate.Credential;
import org.apache.wss4j.dom.validate.Validator;
import org.opensaml.xmlsec.signature.KeyInfo;
@@ -265,7 +266,7 @@ public class SAMLTokenProcessor implemen
}
ref.setTransformAlgorithms(transformAlgorithms);
- ref.setXpath(ReferenceListProcessor.getXPath(token));
+ ref.setXpath(EncryptionUtils.getXPath(token));
protectedRefs.add(ref);
}
}
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java?rev=1681118&r1=1681117&r2=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java Fri May 22 13:46:33 2015
@@ -82,6 +82,7 @@ import org.apache.wss4j.dom.str.Signatur
import org.apache.wss4j.dom.transform.AttachmentContentSignatureTransform;
import org.apache.wss4j.dom.transform.STRTransform;
import org.apache.wss4j.dom.transform.STRTransformUtil;
+import org.apache.wss4j.dom.util.EncryptionUtils;
import org.apache.wss4j.dom.util.XmlSchemaDateFormat;
import org.apache.wss4j.dom.validate.Credential;
import org.apache.wss4j.dom.validate.Validator;
@@ -568,7 +569,7 @@ public class SignatureProcessor implemen
}
ref.setTransformAlgorithms(transformAlgorithms);
- ref.setXpath(ReferenceListProcessor.getXPath(se));
+ ref.setXpath(EncryptionUtils.getXPath(se));
protectedRefs.add(ref);
}
}
Copied: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java (from r1680505, webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java)
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java?p2=webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java&p1=webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java&r1=1680505&r2=1681118&rev=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java Fri May 22 13:46:33 2015
@@ -17,14 +17,11 @@
* under the License.
*/
-package org.apache.wss4j.dom.processor;
+package org.apache.wss4j.dom.util;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import javax.crypto.Cipher;
@@ -33,31 +30,20 @@ import javax.crypto.SecretKey;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
-import org.apache.wss4j.common.bsp.BSPEnforcer;
-import org.apache.wss4j.common.bsp.BSPRule;
-import org.apache.wss4j.common.crypto.AlgorithmSuite;
-import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
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.principal.WSDerivedKeyTokenPrincipal;
-import org.apache.wss4j.common.token.SecurityTokenReference;
import org.apache.wss4j.common.util.AttachmentUtils;
-import org.apache.wss4j.common.util.KeyUtils;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.WSDataRef;
import org.apache.wss4j.dom.WSDocInfo;
-import org.apache.wss4j.dom.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.message.CallbackLookup;
-import org.apache.wss4j.dom.str.STRParser;
-import org.apache.wss4j.dom.str.STRParserParameters;
-import org.apache.wss4j.dom.str.STRParserResult;
-import org.apache.wss4j.dom.str.SecurityTokenRefSTRParser;
-import org.apache.wss4j.dom.util.WSSecurityUtil;
import org.apache.xml.security.algorithms.JCEMapper;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
@@ -65,200 +51,12 @@ import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
-public class ReferenceListProcessor implements Processor {
- private static final org.slf4j.Logger LOG =
- org.slf4j.LoggerFactory.getLogger(ReferenceListProcessor.class);
+public final class EncryptionUtils {
- public List<WSSecurityEngineResult> handleToken(
- Element elem,
- RequestData data,
- WSDocInfo wsDocInfo
- ) throws WSSecurityException {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Found reference list element");
- }
- List<WSDataRef> dataRefs = handleReferenceList(elem, data, wsDocInfo);
- WSSecurityEngineResult result =
- new WSSecurityEngineResult(WSConstants.ENCR, dataRefs);
- String tokenId = elem.getAttributeNS(null, "Id");
- if (!"".equals(tokenId)) {
- result.put(WSSecurityEngineResult.TAG_ID, tokenId);
- }
- wsDocInfo.addTokenElement(elem);
- wsDocInfo.addResult(result);
- return Collections.singletonList(result);
- }
-
- /**
- * Dereferences and decodes encrypted data elements.
- *
- * @param elem contains the <code>ReferenceList</code> to the encrypted
- * data elements
- */
- private List<WSDataRef> handleReferenceList(
- Element elem,
- RequestData data,
- WSDocInfo wsDocInfo
- ) throws WSSecurityException {
- List<WSDataRef> dataRefs = new ArrayList<>();
- for (Node node = elem.getFirstChild();
- node != null;
- node = node.getNextSibling()
- ) {
- if (Node.ELEMENT_NODE == node.getNodeType()
- && WSConstants.ENC_NS.equals(node.getNamespaceURI())
- && "DataReference".equals(node.getLocalName())) {
- String dataRefURI = ((Element) node).getAttributeNS(null, "URI");
- dataRefURI = XMLUtils.getIDFromReference(dataRefURI);
-
- // See whether we have already processed the encrypted node
- if (!wsDocInfo.hasResult(WSConstants.ENCR, dataRefURI)) {
- WSDataRef dataRef =
- decryptDataRefEmbedded(
- elem.getOwnerDocument(), dataRefURI, data, wsDocInfo);
- dataRefs.add(dataRef);
- }
- }
- }
-
- return dataRefs;
- }
-
-
- /**
- * Decrypt an (embedded) EncryptedData element referenced by dataRefURI.
- */
- private WSDataRef decryptDataRefEmbedded(
- Document doc,
- String dataRefURI,
- RequestData data,
- WSDocInfo wsDocInfo
- ) throws WSSecurityException {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Found data reference: " + dataRefURI);
- }
- //
- // Find the encrypted data element referenced by dataRefURI
- //
- Element encryptedDataElement = findEncryptedDataElement(doc, wsDocInfo, dataRefURI);
-
- if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
- List<WSSecurityEngineResult> signedResults =
- wsDocInfo.getResultsByTag(WSConstants.SIGN);
- WSSecurityUtil.verifySignedElement(encryptedDataElement, signedResults);
- }
- //
- // Prepare the SecretKey object to decrypt EncryptedData
- //
- String symEncAlgo = X509Util.getEncAlgo(encryptedDataElement);
- Element keyInfoElement =
- XMLUtils.getDirectChildElement(
- encryptedDataElement, "KeyInfo", WSConstants.SIG_NS
- );
- // KeyInfo cannot be null
- if (keyInfoElement == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noKeyinfo");
- }
- // Check BSP compliance
- checkBSPCompliance(keyInfoElement, symEncAlgo, data.getBSPEnforcer());
-
- //
- // Try to get a security reference token, if none found try to get a
- // shared key using a KeyName.
- //
- Element secRefToken =
- XMLUtils.getDirectChildElement(
- keyInfoElement, "SecurityTokenReference", WSConstants.WSSE_NS
- );
- SecretKey symmetricKey = null;
- Principal principal = null;
- if (secRefToken == null) {
- symmetricKey = X509Util.getSharedKey(keyInfoElement, symEncAlgo, data.getCallbackHandler());
- } else {
- STRParserParameters parameters = new STRParserParameters();
- parameters.setData(data);
- parameters.setWsDocInfo(wsDocInfo);
- parameters.setStrElement(secRefToken);
- if (symEncAlgo != null) {
- parameters.setDerivationKeyLength(KeyUtils.getKeyLength(symEncAlgo));
- }
-
- STRParser strParser = new SecurityTokenRefSTRParser();
- STRParserResult parserResult = strParser.parseSecurityTokenReference(parameters);
- byte[] secretKey = parserResult.getSecretKey();
- principal = parserResult.getPrincipal();
- symmetricKey = KeyUtils.prepareSecretKey(symEncAlgo, secretKey);
- }
-
- // Check for compliance against the defined AlgorithmSuite
- AlgorithmSuite algorithmSuite = data.getAlgorithmSuite();
- if (algorithmSuite != null) {
- AlgorithmSuiteValidator algorithmSuiteValidator = new
- AlgorithmSuiteValidator(algorithmSuite);
-
- if (principal instanceof WSDerivedKeyTokenPrincipal) {
- algorithmSuiteValidator.checkDerivedKeyAlgorithm(
- ((WSDerivedKeyTokenPrincipal)principal).getAlgorithm()
- );
- algorithmSuiteValidator.checkEncryptionDerivedKeyLength(
- ((WSDerivedKeyTokenPrincipal)principal).getLength()
- );
- }
-
- algorithmSuiteValidator.checkSymmetricKeyLength(symmetricKey.getEncoded().length);
- algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
- }
-
- return
- decryptEncryptedData(
- doc, dataRefURI, encryptedDataElement, symmetricKey, symEncAlgo, data
- );
- }
-
- /**
- * Check for BSP compliance
- * @param keyInfoElement The KeyInfo element child
- * @param encAlgo The encryption algorithm
- * @throws WSSecurityException
- */
- private static void checkBSPCompliance(
- Element keyInfoElement,
- String encAlgo,
- BSPEnforcer bspEnforcer
- ) throws WSSecurityException {
- // We can only have one token reference
- int result = 0;
- Node node = keyInfoElement.getFirstChild();
- Element child = null;
- while (node != null) {
- if (Node.ELEMENT_NODE == node.getNodeType()) {
- result++;
- child = (Element)node;
- }
- node = node.getNextSibling();
- }
- if (result != 1) {
- bspEnforcer.handleBSPRule(BSPRule.R5424);
- }
-
- if (child == null || !WSConstants.WSSE_NS.equals(child.getNamespaceURI()) ||
- !SecurityTokenReference.SECURITY_TOKEN_REFERENCE.equals(child.getLocalName())) {
- bspEnforcer.handleBSPRule(BSPRule.R5426);
- }
-
- // EncryptionAlgorithm cannot be null
- if (encAlgo == null) {
- bspEnforcer.handleBSPRule(BSPRule.R5601);
- }
- // EncryptionAlgorithm must be 3DES, or AES128, or AES256
- if (!WSConstants.TRIPLE_DES.equals(encAlgo)
- && !WSConstants.AES_128.equals(encAlgo)
- && !WSConstants.AES_128_GCM.equals(encAlgo)
- && !WSConstants.AES_256.equals(encAlgo)
- && !WSConstants.AES_256_GCM.equals(encAlgo)) {
- bspEnforcer.handleBSPRule(BSPRule.R5620);
- }
+ private EncryptionUtils() {
+ // complete
}
/**
@@ -283,8 +81,7 @@ public class ReferenceListProcessor impl
callbackLookup.getElement(dataRefURI, null, true);
if (encryptedDataElement == null) {
throw new WSSecurityException(
- WSSecurityException.ErrorCode.INVALID_SECURITY, "dataRef",
- new Object[] {dataRefURI});
+ WSSecurityException.ErrorCode.INVALID_SECURITY, "dataRef", dataRefURI);
}
if (encryptedDataElement.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
&& encryptedDataElement.getNamespaceURI().equals(WSConstants.WSSE11_NS)) {
@@ -324,11 +121,24 @@ public class ReferenceListProcessor impl
// See if it is an attachment, and handle that differently
String typeStr = encData.getAttributeNS(null, "Type");
+ String xopURI = getXOPURIFromEncryptedData(encData);
if (typeStr != null &&
(WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY.equals(typeStr) ||
WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr))) {
- return decryptAttachment(dataRefURI, encData, symmetricKey, symEncAlgo, requestData);
+ Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
+ if (cipherData == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+ }
+ Element cipherReference = XMLUtils.getDirectChildElement(cipherData, "CipherReference", WSConstants.ENC_NS);
+ if (cipherReference == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+ }
+ String uri = cipherReference.getAttributeNS(null, "URI");
+
+ return decryptAttachment(dataRefURI, uri, false, encData, symmetricKey, symEncAlgo, requestData);
+ } else if (xopURI != null) {
+ return decryptAttachment(dataRefURI, xopURI, true, encData, symmetricKey, symEncAlgo, requestData);
}
boolean content = X509Util.isContent(encData);
@@ -388,9 +198,36 @@ public class ReferenceListProcessor impl
return dataRef;
}
+ private static String getXOPURIFromEncryptedData(Element encData) {
+ Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
+ if (cipherData != null) {
+ Element cipherValue =
+ XMLUtils.getDirectChildElement(cipherData, "CipherValue", WSConstants.ENC_NS);
+ return getXOPURIFromCipherValue(cipherValue);
+ }
+
+ return null;
+ }
+
+ public static String getXOPURIFromCipherValue(Element cipherValue) {
+ if (cipherValue != null && cipherValue.hasAttributeNS(WSConstants.XMLNS_NS, "xop")
+ && WSConstants.XOP_NS.equals(cipherValue.getAttributeNS(WSConstants.XMLNS_NS, "xop"))) {
+ Element cipherValueChild =
+ XMLUtils.getDirectChildElement(cipherValue, "Include", WSConstants.XOP_NS);
+ if (cipherValueChild != null && cipherValueChild.hasAttributeNS(null, "href")) {
+ return cipherValueChild.getAttributeNS(null, "href");
+ }
+ }
+
+ return null;
+ }
+
+
private static WSDataRef
decryptAttachment(
String dataRefURI,
+ String uri,
+ boolean xop,
Element encData,
SecretKey symmetricKey,
String symEncAlgo,
@@ -401,19 +238,7 @@ public class ReferenceListProcessor impl
dataRef.setAlgorithm(symEncAlgo);
try {
- Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
- if (cipherData == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- Element cipherReference = XMLUtils.getDirectChildElement(cipherData, "CipherReference", WSConstants.ENC_NS);
- if (cipherReference == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- String uri = cipherReference.getAttributeNS(null, "URI");
- if (uri == null || uri.length() < 5) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
- }
- if (!uri.startsWith("cid:")) {
+ if (uri == null || uri.length() < 5 || !uri.startsWith("cid:")) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
dataRef.setWsuId(uri);
@@ -434,7 +259,7 @@ public class ReferenceListProcessor impl
if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.INVALID_SECURITY,
- "empty", new Object[] {"Attachment not found"}
+ "empty", "Attachment not found"
);
}
Attachment attachment = attachments.get(0);
@@ -447,7 +272,18 @@ public class ReferenceListProcessor impl
InputStream attachmentInputStream =
AttachmentUtils.setupAttachmentDecryptionStream(
encAlgo, cipher, symmetricKey, attachment.getSourceStream());
-
+
+ // For the xop:Include case, we need to replace the xop:Include Element with the
+ // decrypted Element
+ if (xop) {
+ DocumentBuilder db =
+ org.apache.xml.security.utils.XMLUtils.createDocumentBuilder(false);
+ Document doc = db.parse(attachmentInputStream);
+ Node importedNode = encData.getOwnerDocument().importNode(doc.getDocumentElement(), true);
+ encData.getParentNode().appendChild(importedNode);
+ org.apache.xml.security.utils.XMLUtils.repoolDocumentBuilder(db);
+ }
+
Attachment resultAttachment = new Attachment();
resultAttachment.setId(attachment.getId());
resultAttachment.setMimeType(encData.getAttributeNS(null, "MimeType"));
@@ -466,7 +302,8 @@ public class ReferenceListProcessor impl
attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
} catch (UnsupportedCallbackException | IOException
- | NoSuchAlgorithmException | NoSuchPaddingException e) {
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | ParserConfigurationException | SAXException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e);
}
Copied: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java (from r1680505, webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/X509Util.java)
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java?p2=webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java&p1=webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/X509Util.java&r1=1680505&r2=1681118&rev=1681118&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/X509Util.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java Fri May 22 13:46:33 2015
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.wss4j.dom.processor;
+package org.apache.wss4j.dom.util;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.common.ext.WSPasswordCallback;
@@ -72,7 +72,7 @@ public final class X509Util {
return symEncAlgo;
}
- protected static SecretKey getSharedKey(
+ public static SecretKey getSharedKey(
Element keyInfoElem,
String algorithm,
CallbackHandler cb
Added: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/XOPAttachmentTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/XOPAttachmentTest.java?rev=1681118&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/XOPAttachmentTest.java (added)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/XOPAttachmentTest.java Fri May 22 13:46:33 2015
@@ -0,0 +1,185 @@
+/**
+ * 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.dom.message;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.wss4j.common.WSEncryptionPart;
+import org.apache.wss4j.common.WSS4JConstants;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.Attachment;
+import org.apache.wss4j.common.util.XMLUtils;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.WSSConfig;
+import org.apache.wss4j.dom.WSSecurityEngine;
+import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
+import org.apache.wss4j.dom.common.SOAPUtil;
+import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.handler.WSHandlerResult;
+import org.apache.wss4j.dom.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Test for processing an xop:Include inside a CipherValue Element
+ */
+public class XOPAttachmentTest extends org.junit.Assert {
+
+ private static final String SOAP_BODY =
+ "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
+ + "<value xmlns=\"\">15</value>"
+ + "</add>";
+
+ private static final org.slf4j.Logger LOG =
+ org.slf4j.LoggerFactory.getLogger(XOPAttachmentTest.class);
+
+ private WSSecurityEngine secEngine = new WSSecurityEngine();
+ private Crypto crypto = null;
+
+ public XOPAttachmentTest() throws Exception {
+ WSSConfig.init();
+ crypto = CryptoFactory.getInstance();
+ }
+
+ protected byte[] readInputStream(InputStream inputStream) throws IOException {
+ try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
+ int read = 0;
+ byte[] buf = new byte[4096];
+ while ((read = inputStream.read(buf)) != -1) {
+ byteArrayOutputStream.write(buf, 0, read);
+ }
+ return byteArrayOutputStream.toByteArray();
+ }
+ }
+
+ // Set up a test to encrypt the SOAP Body + an attachment, which is the same content as
+ // the SOAP Body. Then replace the encrypted SOAP Body with a xop:Include to the attachment,
+ // and modify the request to remove the encryption stuff pointing to the attachment.
+ @org.junit.Test
+ public void testEncryptedSOAPBody() throws Exception {
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecEncrypt encrypt = new WSSecEncrypt();
+ encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+ encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ encrypt.getParts().add(new WSEncryptionPart("Body", "http://schemas.xmlsoap.org/soap/envelope/", "Content"));
+ encrypt.getParts().add(new WSEncryptionPart("cid:Attachments", "Content"));
+
+ String attachmentId = UUID.randomUUID().toString();
+ final Attachment attachment = new Attachment();
+ attachment.setId(attachmentId);
+ attachment.setSourceStream(new ByteArrayInputStream(SOAP_BODY.getBytes("UTF-8")));
+
+ AttachmentCallbackHandler attachmentCallbackHandler =
+ new AttachmentCallbackHandler(Collections.singletonList(attachment));
+ encrypt.setAttachmentCallbackHandler(attachmentCallbackHandler);
+ List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
+
+ Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
+
+ // Find the SOAP Body + replace with a xop:Include to the attachment!
+ Element soapBody = WSSecurityUtil.findBodyElement(encryptedDoc);
+ assertNotNull(soapBody);
+ Element encryptedData =
+ XMLUtils.getDirectChildElement(soapBody, "EncryptedData", WSConstants.ENC_NS);
+ encryptedData.removeAttributeNS(null, "Type");
+ Element cipherData =
+ XMLUtils.getDirectChildElement(encryptedData, "CipherData", WSConstants.ENC_NS);
+ assertNotNull(cipherData);
+ Element cipherValue =
+ XMLUtils.getDirectChildElement(cipherData, "CipherValue", WSConstants.ENC_NS);
+ assertNotNull(cipherValue);
+
+ XMLUtils.setNamespace(cipherValue, WSS4JConstants.XOP_NS, "xop");
+
+ Element cipherValueChild = encryptedDoc.createElementNS(WSConstants.XOP_NS, "Include");
+ cipherValueChild.setAttributeNS(null, "href", "cid:" + encryptedAttachments.get(0).getId());
+ cipherValue.replaceChild(cipherValueChild, cipherValue.getFirstChild());
+
+ // Remove EncryptedData structure from the security header (which encrypted the attachment
+ // in the first place)
+ Element securityHeader =
+ WSSecurityUtil.findWsseSecurityHeaderBlock(encryptedDoc, encryptedDoc.getDocumentElement(), false);
+ Element encryptedAttachmentData =
+ XMLUtils.getDirectChildElement(securityHeader, "EncryptedData", WSConstants.ENC_NS);
+ assertNotNull(encryptedAttachmentData);
+ String encryptedDataId = encryptedAttachmentData.getAttributeNS(null, "Id");
+ securityHeader.removeChild(encryptedAttachmentData);
+
+ // Now get EncryptedKey + remove the reference to the EncryptedData above
+ Element encryptedKey =
+ XMLUtils.getDirectChildElement(securityHeader, "EncryptedKey", WSConstants.ENC_NS);
+ assertNotNull(encryptedKey);
+ Element referenceList =
+ XMLUtils.getDirectChildElement(encryptedKey, "ReferenceList", WSConstants.ENC_NS);
+ assertNotNull(referenceList);
+ Node child = referenceList.getFirstChild();
+ while (child != null) {
+ if (child instanceof Element && "DataReference".equals(child.getLocalName())
+ && WSConstants.ENC_NS.equals(child.getNamespaceURI())) {
+ String uri = ((Element)child).getAttributeNS(null, "URI");
+ if (uri.equals("#" + encryptedDataId)) {
+ referenceList.removeChild(child);
+ break;
+ }
+ }
+ child = child.getNextSibling();
+ }
+
+ if (LOG.isDebugEnabled()) {
+ String outputString = XMLUtils.PrettyDocumentToString(encryptedDoc);
+ LOG.debug(outputString);
+ //System.out.println(outputString);
+ }
+
+ attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
+ verify(encryptedDoc, attachmentCallbackHandler);
+
+ String processedDoc = XMLUtils.PrettyDocumentToString(encryptedDoc);
+ assertTrue(processedDoc.contains(SOAP_BODY));
+ }
+
+ /**
+ * Verifies the soap envelope.
+ * This method verifies all the signature generated.
+ *
+ * @throws java.lang.Exception Thrown when there is a problem in verification
+ */
+ private WSHandlerResult verify(Document doc, CallbackHandler attachmentCallbackHandler) throws Exception {
+ RequestData requestData = new RequestData();
+ requestData.setAttachmentCallbackHandler(attachmentCallbackHandler);
+ requestData.setSigVerCrypto(crypto);
+ requestData.setDecCrypto(crypto);
+ requestData.setCallbackHandler(new KeystoreCallbackHandler());
+ return secEngine.processSecurityHeader(doc, requestData);
+ }
+}