Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.5.4
-
None
-
None
-
WSS4J 1.5
Description
WSS4J handlers that sign messages (for example) may fail if the SOAP
envelope namespace prefix in the original SOAP message is null.
This doesn't usually happen if SOAP is generated internally by Axis
(say) because the namespace prefix there is usually set to "soapenv".
But Axis allows SOAP to be generated by the user, then injected into the
Axis engine. If the SOAP envelope namespace in the user-generated
SOAP document is set to be the default namespace, `WSDoAllSender'
will typically fail in a couple of places.
For example when the original SOAP is like this:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope
xmlns="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Body>
<hello soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns="">
<arg0 xsi:type="soapenc:string"
xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/"
>wonderful</arg0>
</hello>
</Body>
</Envelope>
and the client Axis engine configuration is like this:
<?xml version='1.0'?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="Signature"/>
<parameter name="signaturePropFile"
value="... local crypto properties ..." />
<parameter name="user" value="omii_server"/>
<parameter name="passwordCallbackClass" value=
"... local password callback ..."/>
<parameter name="signatureKeyIdentifier"
value="DirectReference" />
</handler>
</requestFlow>
</globalConfiguration>
<transport name="http"
pivot="java:org.apache.axis.transport.http.HTTPSender"/>
</deployment>
I have encountered two problems, decribed below.
The first problem is in the file "WSSecurityUtil.java" where we have:
private static Element createElementInSameNamespace(Element parent,
String localName) {
String prefix = parent.getPrefix();
if (prefix == null)
String qName = prefix + ":" + localName;
String nsUri = parent.getNamespaceURI();
return parent.getOwnerDocument().createElementNS(nsUri, qName);
}
This is wrong if `prefix' is null. For example if `localName' is "Header"
it yields the illegal qualified name ":Header".
The symptom I encountered was an exception like:
org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
A possible fix is to replace this method definition with
private static Element createElementInSameNamespace(Element parent,
String localName) {
String prefix = parent.getPrefix();
String qName ;
if (prefix == null)
else
{ qName = prefix + ":" + localName ; } String nsUri = parent.getNamespaceURI();
return parent.getOwnerDocument().createElementNS(nsUri, qName);
}
The second place is in the file "WSSecHeader.java". The method
`insertSecurityHeader()' contains the lines
if (actor != null && actor.length() > 0)
{ securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(), soapPrefix + ":" + soapConstants.getRoleAttributeQName() .getLocalPart(), actor); }if (mustunderstand)
{ securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(), soapPrefix + ":" + WSConstants.ATTR_MUST_UNDERSTAND, soapConstants.getMustunderstand()); }If, for example `prefix' is null and the local part of the attribute name
is "mustUnderstand", this results in the incorrect qualified name
"null:mustUnderstand".
The symptom I encountered was an exception like:
org.xml.sax.SAXParseException: The prefix "null" for attribute "null:mustUnderstand" associated with an element type "wsse:Security" is not bound.
A possible fix is to replace the lines above with something like:
if (actor != null && actor.length() > 0)
{ securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(), (soapPrefix != null ? soapPrefix + ":" : "") + soapConstants.getRoleAttributeQName() .getLocalPart(), actor); }if (mustunderstand)
{ securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(), (soapPrefix != null ? soapPrefix + ":" : "") + WSConstants.ATTR_MUST_UNDERSTAND, soapConstants.getMustunderstand()); }(the deprecated version of `insertSecurityHeader()' in `WSBaseMessage' has
the same problem).
I will try to attach source files of a simple example that
demonstrates the problems. The relevant files are
"HelloClient.java", "x509-client-config.wsdd", "HelloService.java",
"deploy-x509-hello-service.wsdd". Of course you will have to modify the
WSDD according to your local setup for keystors, and provide suitable
password callbacks.