I have a WS-Security implementation based on xml-security and am testing
interop. When testing against WSS4J (which also uses xml-security) - both
using version 1.3.0 - I am having problems because of what appears to be
different results of Excl C14N depending on whether the input is a NodeSet
or a root node. The problem occurs when using InclusiveNamespaces.
The issue appears to be that when the input is a NodeSet, the
InclusiveNamespaces value is ignored. What happens is the following sequence
of calls:
TransformC14NExclusive.enginePerformTransform(inputWithNodeSet)
-> Canonicalizer20010315Excl.engineCanonicalize(inputWithNodeSet, "env ns0
xsi wsu")
-> _inclusiveNSSet = "env ns0 xsi wsu"
-> CanonicalizerBase.engineCanonicalize(inputWithNodeSet)
->
Canonicalizer20010315Excl.engineCanonicalizeXPathNodeSet(xpathNodeSet)
->
Canonicalizer20010315Excl.engineCanonicalizeXPathNodeSet(xpathNodeSet, "")
-> _inclusiveNSSet = ""
So the inclusive namespaces passed in originally are forgotten to be
replaced by an empty list.
When passing a root node instead of a node set, the inclusive namespace list
is used and so the result is different. In the XML below, the document
element is env:Envelope and env:Body is that target node for C14N. For the
nodeset the result on the SOAP body is (formatting added)
<env:Body
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit
y-utility-1.0.xsd"
wsu:Id="body">
<ns0:Ping
xmlns:ns0="http://xmlsoap.org/Ping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="ns0:ping">
<ns0:text xsi:type="xsd:string">hello</ns0:text>
</ns0:Ping>
</env:Body>
and for a root node (being the body element in this case)
<env:Body
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns0="http://xmlsoap.org/Ping"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit
y-utility-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
wsu:Id="body">
<ns0:Ping xsi:type="ns0:ping">
<ns0:text xsi:type="xsd:string">hello</ns0:text>
</ns0:Ping>
</env:Body>
I attach a test program that compares the 2 ways of doing this on the same
document and shows the results (the nodeset result differs from the one
above as it does not include any namespace declarations).
Is this a bug or am I not understanding the difference between processing
based on a nodeset and processing based on a root node?
Pete
/**
* Copyright Notice
*
* Copyright (c) 2000-2004, Cape Clear Software.
* All Rights Reserved
*
* This software is protected by copyright and other intellectual
* property rights and by international treaties. Any unauthorised
* reproduction or distribution of this software or any portion
* thereof is strictly prohibited.
*/
package client.wss4j;
import java.io.StringReader;
import java.util.Set;
import java.util.HashSet;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.c14n.implementations.Canonicalizer20010315Excl;
import org.apache.xml.security.c14n.implementations.Canonicalizer20010315ExclOmitComments;
import org.apache.xml.security.utils.XMLUtils;
/**
* @author Pete Hendry
* @version $Id$
*/
public class DemoINProblem {
private static final String XML =
"<env:Envelope"
+ " xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+ " xmlns:ns0=\"http://xmlsoap.org/Ping\""
+ " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">"
+ "<env:Body wsu:Id=\"body\">"
+ "<ns0:Ping xsi:type=\"ns0:ping\">"
+ "<ns0:text xsi:type=\"xsd:string\">hello</ns0:text>"
+ "</ns0:Ping>"
+ "</env:Body>"
+ "</env:Envelope>";
public static void main( String[] args )
throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(XML)));
XMLSignatureInput input =
new XMLSignatureInput(doc.getDocumentElement().getFirstChild());
// called because this happens during tracing
input.setNeedsToBeExpanded(true);
Canonicalizer20010315Excl c14n = new Canonicalizer20010315ExclOmitComments();
byte[] bytes = c14n.engineCanonicalize(input, "env ns0 xsi wsu");
System.out.println("ROOT NODE:\n" + new String(bytes) + "\n=======\n");
doc = builder.parse(new InputSource(new StringReader(XML)));
Set nodeSet = new HashSet();
XMLUtils.getSet(doc.getDocumentElement().getFirstChild(), nodeSet, null, false);
input = new XMLSignatureInput(nodeSet);
input.setNeedsToBeExpanded(true);
c14n = new Canonicalizer20010315ExclOmitComments();
bytes = c14n.engineCanonicalize(input, "env ns0 xsi wsu");
System.out.println("NODE SET:\n" + new String(bytes) + "\n=======\n");
}
}