To be COMPLETELY honest with you, CXF doesn't really support WS-Security stuff properly when MTOM is enabled. That is why, by default, we turn MTOM off if WS-Security interceptors are enabled. More inline.
On Thursday 18 November 2010 10:56:50 am Nigel Gay wrote: > We're running web services using CXF 2.2.7 which specify a > ws-securitypolicy file that states that: > 1) requests must include a timestamp > 2) the timestamp, body and a custom token we pass in a SOAP header to > maintain session state must all be signed by the client's cert, but no > encryption is required > > We have multiple endpoints, some of which have MTOM enabled and some don't. > For the MTOM services, we expect the body containing the href to the MTOM > content ID to be signed, but the actual attachment data won't be signed. This is the problem. Per spec, the MTOM attachment data MUST be part of the signature. Basically, the full infoset needs to be considered/processed when calculating the signature. .NET is likely doing this correctly and the signature is properly considering the attachment data. CXF, on the other hand, is just passing the XML SOAP message as is to WSS4J for signature processing. It just treats everything in it as XML and signs it that way. The reason CXF <-> CXF works is cause both sides are doing it wrong. :-) What would need to be done (to make is work using current versions of WSS4J) would be process the SAAJ message to find any XOP elements, find the Attachment that matches, read in the Attachment data, base64 encode it into a string, and replace the XOP elements with the data. If you write an interceptor that does that, I bet the .NET clients will start working, but it would break the CXF clients as the CXF clients wouldn't be doing that, although the CXF clients, by default, wouldn't be sending MTOM if WS-Security is enabled. If you want CXF clients to do it "correctly", you would need to un-XOP things, sign everything, then restore the XOP elements. The DOWNSIDE to that, of course, is you pretty much kill the entire idea of the streaming attachments and the low memory footprint that implies. You need to have EVERYTHING in memory. The other downside is it's much more processor intensive as you need to base64 everything for the signature. Thus, you really lose the lower processing requirements that MTOM also brings. I've chatted with Colm about this a little bit about some possible enhancements to WSS4J/Santaurio to have it callback somehow when it gets to a XOP node to get an InputStream for the data and let it do something a bit smarter, but definitely not there yet. Dan > > Any calls from a CXF to any of the services work fine, and calls from .NET > clients to the non-MTOM services work fine. What I see in the server log > when a .NET client tries to call one of the services using MTOM and pass > through an attachment is: > > 2010-11-12 13:53:42,958 [http-8081-1] DEBUG > security.utils.DigesterOutputStream - Pre-digested input: > 2010-11-12 13:53:42,958 [http-8081-1] DEBUG > security.utils.DigesterOutputStream - <s:Body > xmlns:s="http://www.w3.org/2003/05/soap-envelope" > xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity > -utility-1.0.xsd" u:Id="_1"><billingImportFile > xmlns="http://ournamespace/types"><format xmlns="">XXX</format><file > xmlns=""><xop:Include > xmlns:xop="http://www.w3.org/2004/08/xop/include" > href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634251668229234000"></xop:Include> > </file></billingImportFile></s:Body> 2010-11-12 13:53:42,958 [http-8081-1] > WARN security.signature.Reference - Verification failed for URI "#_1" > 2010-11-12 13:53:42,958 [http-8081-1] WARN security.signature.Reference - > Expected Digest: 6IZwMBl/AMcyVV5ksiYAnSmmvUE= > 2010-11-12 13:53:42,958 [http-8081-1] WARN security.signature.Reference - > Actual Digest: abGeLOONSYqCqf3/irH9QuTNiiY= > > So the signature digests don't match and the call fails. I took a guess > that what might be going on is: > 1) .NET generates the content ID like http://tempuri... > 2) .NET calculates the signature digest on the body, with the content ID > like http://tempuri... > 3) .NET then encodes the content ID turning it into http%3A%2F%2Ftempuri... > 4) Java then receives the request, and calculates the signature digest on > the body, with the content ID like http%3A%2F%2Ftempuri... > and so because one signature digest was calculated based on > http://tempuri... and the other based on http%3A%2F%2Ftempuri..., the two > don't match and hence the error. > > so I wrote an interceptor in CXF that would find the MTOM content ID and > deocde it prior to CXF calculating the signature digest, but the digests > still don't match, so I'm stumped. I've searched to try to see if anyone > else has ran into this but not found anything. > > FYI I ran tcpTrace to examine the request coming in, and even if I do not > run my interceptor I notice subtle differences in the request on the wire > and how it appears in the debug log above when CXF calculates the signature > digest. On the wire the MTOM link looks like this: > <xop:Include href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634251668229234000" > xmlns:xop="http://www.w3.org/2004/08/xop/include"/> > but when CXF calculates the signature digest, it appears in the log like > so, with the attribute order reversed and the closing tag style different: > <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" > href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634251668229234000"></xop:Include> > > I'm not sure whether those differences are sufficient to cause a different > signature digest to be calculated? Perhaps this is the problem, rather > than that the content ID contains encoded characters? > > Many thanks for any advise or direction anyone may be able to offer on > this, Nigel Gay. -- Daniel Kulp [email protected] http://dankulp.com/blog
