blob: 46e1ba150ecde429d9435872eb855055d5ab5433 [file] [log] [blame]
/**
* 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.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;
import org.apache.wss4j.common.util.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Applies message transformations to the tests in
* org.apache.wss4j.dom.message.RequireSignedEncryptedDataElementsTest
*/
public class TestMessageTransformer {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(TestMessageTransformer.class);
public static Element duplicateEncryptedDataInWsseHeader(Element saaj, boolean moveReferenceList) throws TransformerException, IOException {
if (moveReferenceList) {
moveReferenceList(saaj);
}
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = createNewEncryptedData(encData);
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element wsseHeader = getFirstChildElement(sh,
new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security"), true);
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
String newId = newEncData.getAttributeNS(null, "Id");
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
newWsseHeader.appendChild(newEncData);
if (!moveReferenceList) {
updateEncryptedKeyRefList(newWsseHeader, newId);
}
Node parent = wsseHeader.getParentNode();
parent.removeChild(wsseHeader);
parent.appendChild(newWsseHeader);
print(saaj.getOwnerDocument());
return newEncData;
}
public static Element duplicateEncryptedDataInWsseWrapperHeader(Element saaj, boolean moveReferenceList) throws TransformerException, IOException {
if (moveReferenceList) {
moveReferenceList(saaj);
}
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = createNewEncryptedData(encData);
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
"Signature"), true);
Node wsseHeader = signature.getParentNode();
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
String newId = newEncData.getAttributeNS(null, "Id");
while (!cur.isSameNode(signature)) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
wrapper.appendChild(newEncData);
newWsseHeader.appendChild(wrapper);
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
if (!moveReferenceList) {
updateEncryptedKeyRefList(newWsseHeader, newId);
}
Node parent = wsseHeader.getParentNode();
parent.removeChild(wsseHeader);
parent.appendChild(newWsseHeader);
print(saaj.getOwnerDocument());
return newEncData;
}
public static Element duplicateEncryptedDataInWrapperBody(Element saaj) throws TransformerException, IOException {
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = createNewEncryptedData(encData);
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
"Signature"), true);
Node wsseHeader = signature.getParentNode();
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
String newId = newEncData.getAttributeNS(null, "Id");
while (!cur.isSameNode(signature)) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
wrapper.appendChild(newEncData);
body.appendChild(wrapper);
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
updateEncryptedKeyRefList(newWsseHeader, newId);
Node parent = wsseHeader.getParentNode();
parent.removeChild(wsseHeader);
parent.appendChild(newWsseHeader);
print(saaj.getOwnerDocument());
return newEncData;
}
public static Element duplicateEncryptedDataAfterWrapperBody(Element saaj) throws TransformerException, IOException {
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = createNewEncryptedData(encData);
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
"Signature"), true);
Node wsseHeader = signature.getParentNode();
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
String newId = newEncData.getAttributeNS(null, "Id");
while (!cur.isSameNode(signature)) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
Node clonedBody = body.cloneNode(false);
clonedBody.appendChild(newEncData);
wrapper.appendChild(clonedBody);
body.getParentNode().appendChild(wrapper);
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
updateEncryptedKeyRefList(newWsseHeader, newId);
Node parent = wsseHeader.getParentNode();
parent.removeChild(wsseHeader);
parent.appendChild(newWsseHeader);
print(saaj.getOwnerDocument());
return newEncData;
}
public static Element duplicateEncryptedDataInExternalWrapperElement(Element saaj,
boolean moveReferenceList) throws TransformerException, IOException {
if (moveReferenceList) {
moveReferenceList(saaj);
}
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = createNewEncryptedData(encData);
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element wsseHeader = getFirstChildElement(sh,
new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security"), true);
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
String newId = newEncData.getAttributeNS(null, "Id");
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
sh.removeChild(wsseHeader);
sh.appendChild(newWsseHeader);
if (!moveReferenceList) {
updateEncryptedKeyRefList(newWsseHeader, newId);
}
Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
wrapper.setAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "mustUnderstand", "0");
wrapper.setAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "actor", "foo");
wrapper.appendChild(newEncData);
sh.appendChild(wrapper);
print(saaj.getOwnerDocument());
return newEncData;
}
public static Element addEncryptedDataWithEmbeddedEncryptedKeyInWsseHeader(Element saaj) throws TransformerException, IOException {
moveReferenceList(saaj);
Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Body"), true);
Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedData"), true);
Element newEncData = (Element)encData.cloneNode(true);
String newId = newEncData.getAttributeNS(null, "Id") + "b";
newEncData.setAttributeNS(null, "Id", newId);
Element encKey = getFirstChildElement(saaj, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedKey"), true);
Element newEncKey = (Element)encKey.cloneNode(true);
String newEcId = newEncKey.getAttributeNS(null, "Id") + "b";
newEncKey.setAttributeNS(null, "Id", newEcId);
Element keyInfo = getFirstChildElement(newEncData, new QName("http://www.w3.org/2000/09/xmldsig#",
"KeyInfo"), true);
Element str = getFirstChildElement(newEncData,
new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"SecurityTokenReference"), true);
keyInfo.replaceChild(newEncKey, str);
Element wsseHeader = getFirstChildElement(saaj,
new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security"), true);
Node newWsseHeader = wsseHeader.cloneNode(false);
Node cur = wsseHeader.getFirstChild();
while (cur != null) {
cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
}
newWsseHeader.appendChild(newEncData);
Node parent = wsseHeader.getParentNode();
parent.removeChild(wsseHeader);
parent.appendChild(newWsseHeader);
print(saaj.getOwnerDocument());
return newEncData;
}
private static void moveReferenceList(Element saaj) {
Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
"Header"), true);
Element encKey = getFirstChildElement(sh, new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedKey"), true);
Element refList = getFirstChildElement(encKey, new QName("http://www.w3.org/2001/04/xmlenc#",
"ReferenceList"), true);
Node wsseHeader = encKey.getParentNode();
encKey.removeChild(refList);
wsseHeader.appendChild(refList);
}
private static void updateEncryptedKeyRefList(Node wsseHeader, String newId) {
Element encryptedKey = getFirstChildElement(wsseHeader,
new QName("http://www.w3.org/2001/04/xmlenc#",
"EncryptedKey"), true);
Element ref = getFirstChildElement(encryptedKey, new QName("http://www.w3.org/2001/04/xmlenc#",
"DataReference"), true);
Element newRef = (Element)ref.cloneNode(true);
newRef.setAttributeNS(null, "URI", "#" + newId);
ref.getParentNode().appendChild(newRef);
}
private static void print(Document doc) throws TransformerException, IOException {
if (LOG.isDebugEnabled()) {
LOG.debug("After transformation....");
String outputString = XMLUtils.prettyDocumentToString(doc);
LOG.debug(outputString);
}
}
private static Element createNewEncryptedData(Element encData) {
Element newEncData = (Element)encData.cloneNode(true);
String id = newEncData.getAttributeNS(null, "Id");
String newId = id + "b";
newEncData.setAttributeNS(null, "Id", newId);
return newEncData;
}
private static Node copyHeadersAndUpdateRefList(Node cur, Node dest, String newId) {
Node temp = cur.cloneNode(true);
dest.appendChild(temp);
if (newId != null && temp.getNodeType() == Node.ELEMENT_NODE) {
Element t = (Element)temp;
if (t.getLocalName().equals("ReferenceList")) {
Element ref = getFirstChildElement(t, new QName("http://www.w3.org/2001/04/xmlenc#",
"DataReference"), true);
Element newRef = (Element)ref.cloneNode(true);
newRef.setAttributeNS(null, "URI", "#" + newId);
t.appendChild(newRef);
}
}
return cur.getNextSibling();
}
private static Element getFirstChildElement(Node node, QName nodeName, boolean recursive) {
Element childElement = null;
Iterator<Element> it = getChildElements(node, nodeName, recursive).iterator();
if (it.hasNext()) {
childElement = it.next();
}
return childElement;
}
private static List<Element> getChildElements(Node node, QName nodeName, boolean recursive) {
List<Element> list = new LinkedList<>();
NodeList nlist = node.getChildNodes();
int len = nlist.getLength();
for (int i = 0; i < len; i++) {
Node child = nlist.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
search(list, (Element)child, nodeName, recursive);
}
}
return list;
}
private static void search(List<Element> list, Element baseElement, QName nodeName, boolean recursive) {
if (nodeName == null) {
list.add(baseElement);
} else {
QName qname;
if (nodeName.getNamespaceURI().length() > 0) {
qname = new QName(baseElement.getNamespaceURI(), baseElement.getLocalName());
} else {
qname = new QName(baseElement.getLocalName());
}
if (qname.equals(nodeName)) {
list.add(baseElement);
}
}
if (recursive) {
NodeList nlist = baseElement.getChildNodes();
int len = nlist.getLength();
for (int i = 0; i < len; i++) {
Node child = nlist.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
search(list, (Element)child, nodeName, recursive);
}
}
}
}
}