Author: dkulp
Date: Fri Jun 6 11:19:26 2008
New Revision: 664068
URL: http://svn.apache.org/viewvc?rev=664068&view=rev
Log:
Merged revisions 664065 via svnmerge from
https://svn.apache.org/repos/asf/cxf/trunk
........
r664065 | dkulp | 2008-06-06 14:10:04 -0400 (Fri, 06 Jun 2008) | 2 lines
[CXF-1632] WS-Security fault handling improvements. Patch from Colm applied
........
Added:
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
(with props)
Modified:
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
Modified:
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java?rev=664068&r1=664067&r2=664068&view=diff
==============================================================================
---
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
(original)
+++
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
Fri Jun 6 11:19:26 2008
@@ -113,7 +113,7 @@
return HEADERS;
}
- public Map getProperties() {
+ public Map<String, Object> getProperties() {
return properties;
}
Modified:
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
URL:
http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties?rev=664068&r1=664067&r2=664068&view=diff
==============================================================================
---
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
(original)
+++
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
Fri Jun 6 11:19:26 2008
@@ -18,11 +18,9 @@
# under the License.
#
#
+
+# OutInterceptor error messages
NO_SAAJ_DOC: No SOAPMessage DOM was found. Please enable the SAAJInInterceptor.
-ACTION_MISMATCH: Security processing failed (actions mismatch)
-INVALID_TIMESTAMP: The timestamp could not be validated.
-UNTRUSTED_CERT: The certificate used for the signature is not trusted.
-NO_SECURITY: Request does not contain required Security header.
-SECURITY_FAILED: Security processing failed.
NO_ACTION: No security action was defined.
-NO_USERNAME: Empty username for specified action.
\ No newline at end of file
+NO_USERNAME: Empty username for specified action.
+SECURITY_FAILED: Security processing failed.
Modified:
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=664068&r1=664067&r2=664068&view=diff
==============================================================================
---
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
(original)
+++
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
Fri Jun 6 11:19:26 2008
@@ -101,7 +101,7 @@
SoapVersion version = msg.getVersion();
if (doDebug) {
- LOG.fine("WSS4JInSecurityHandler: enter invoke()");
+ LOG.fine("WSS4JInInterceptor: enter handleMessage()");
}
long t0 = 0;
@@ -147,18 +147,13 @@
t1 = System.currentTimeMillis();
}
- try {
- wsResult = getSecurityEngine().processSecurityHeader(
- doc.getSOAPPart(),
- actor,
- cbHandler,
- reqData.getSigCrypto(),
- reqData.getDecCrypto()
- );
- } catch (WSSecurityException ex) {
- LOG.log(Level.WARNING, "", ex);
- throw new SoapFault(new Message("SECURITY_FAILED", LOG), ex,
version.getSender());
- }
+ wsResult = getSecurityEngine().processSecurityHeader(
+ doc.getSOAPPart(),
+ actor,
+ cbHandler,
+ reqData.getSigCrypto(),
+ reqData.getDecCrypto()
+ );
if (doTimeLog) {
t2 = System.currentTimeMillis();
@@ -169,7 +164,7 @@
return;
} else {
LOG.warning("Request does not contain required Security
header");
- throw new SoapFault(new Message("NO_SECURITY", LOG),
version.getSender());
+ throw new
WSSecurityException(WSSecurityException.INVALID_SECURITY);
}
}
@@ -196,7 +191,7 @@
if (returnCert != null && !verifyTrust(returnCert, reqData)) {
LOG.warning("The certificate used for the signature is not
trusted");
- throw new SoapFault(new Message("UNTRUSTED_CERT", LOG),
version.getSender());
+ throw new
WSSecurityException(WSSecurityException.FAILED_CHECK);
}
msg.put(SIGNATURE_RESULT, actionResult);
}
@@ -218,7 +213,7 @@
if (timestamp != null && !verifyTimestamp(timestamp,
decodeTimeToLive(reqData))) {
LOG.warning("The timestamp could not be validated");
- throw new SoapFault(new Message("INVALID_TIMESTAMP", LOG),
version.getSender());
+ throw new
WSSecurityException(WSSecurityException.MESSAGE_EXPIRED);
}
msg.put(TIMESTAMP_RESULT, actionResult);
}
@@ -228,8 +223,7 @@
*/
if (!checkReceiverResults(wsResult, actions)) {
LOG.warning("Security processing failed (actions mismatch)");
- throw new SoapFault(new Message("ACTION_MISMATCH", LOG),
version.getSender());
-
+ throw new
WSSecurityException(WSSecurityException.INVALID_SECURITY);
}
doResults(msg, actor, doc, wsResult);
@@ -243,12 +237,13 @@
}
if (doDebug) {
- LOG.fine("WSS4JInHandler: exit invoke()");
+ LOG.fine("WSS4JInInterceptor: exit handleMessage()");
}
} catch (WSSecurityException e) {
LOG.log(Level.WARNING, "", e);
- throw new SoapFault(new Message("WSSECURITY_EX", LOG), e,
version.getSender());
+ SoapFault fault = createSoapFault(version, e);
+ throw fault;
} catch (XMLStreamException e) {
throw new SoapFault(new Message("STAX_EX", LOG), e,
version.getSender());
} catch (SOAPException e) {
@@ -360,4 +355,31 @@
ret.setWssConfig(config);
return ret;
}
+
+
+ /**
+ * Create a SoapFault from a WSSecurityException, following the SOAP
Message Security
+ * 1.1 specification, chapter 12 "Error Handling".
+ *
+ * When the Soap version is 1.1 then set the Fault/Code/Value from the
fault code
+ * specified in the WSSecurityException (if it exists).
+ *
+ * Otherwise set the Fault/Code/Value to env:Sender and the
Fault/Code/Subcode/Value
+ * as the fault code from the WSSecurityException.
+ */
+ private SoapFault
+ createSoapFault(SoapVersion version, WSSecurityException e) {
+ SoapFault fault;
+ javax.xml.namespace.QName faultCode = e.getFaultCode();
+ if (version.getVersion() == 1.1 && faultCode != null) {
+ fault = new SoapFault(e.getMessage(), e, faultCode);
+ } else {
+ fault = new SoapFault(e.getMessage(), e, version.getSender());
+ if (version.getVersion() != 1.1 && faultCode != null) {
+ fault.setSubCode(faultCode);
+ }
+ }
+ return fault;
+ }
+
}
Modified:
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java?rev=664068&r1=664067&r2=664068&view=diff
==============================================================================
---
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
(original)
+++
cxf/branches/2.0.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
Fri Jun 6 11:19:26 2008
@@ -74,7 +74,7 @@
}
if (doDebug) {
- LOG.fine("WSDoAllSender: enter invoke()");
+ LOG.fine("WSS4JOutInterceptor: enter invoke()");
}
RequestData reqData = new RequestData();
@@ -178,7 +178,7 @@
}
if (doDebug) {
- LOG.fine("WSDoAllSender: exit invoke()");
+ LOG.fine("WSS4JOutInterceptor: exit invoke()");
}
} catch (WSSecurityException e) {
throw new SoapFault(new Message("SECURITY_FAILED", LOG), e, version
Added:
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java?rev=664068&view=auto
==============================================================================
---
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
(added)
+++
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
Fri Jun 6 11:19:26 2008
@@ -0,0 +1,255 @@
+/**
+ * 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.cxf.ws.security.wss4j;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMSource;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.binding.soap.SoapFault;
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.helpers.DOMUtils.NullResolver;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.handler.WSHandlerConstants;
+
+import org.junit.Test;
+
+
+/**
+ * A number of tests for fault codes that are thrown from WSS4JInInterceptor.
+ */
+public class WSS4JFaultCodeTest extends AbstractSecurityTest {
+
+ public WSS4JFaultCodeTest() {
+ }
+
+ /**
+ * Test for WSS4JInInterceptor when it receives a message with no security
header.
+ */
+ @Test
+ public void testNoSecurity() throws Exception {
+ Document doc = readDocument("wsse-request-clean.xml");
+
+ SoapMessage msg = new SoapMessage(new MessageImpl());
+ Exchange ex = new ExchangeImpl();
+ ex.setInMessage(msg);
+
+ SOAPMessage saajMsg = MessageFactory.newInstance().createMessage();
+ SOAPPart part = saajMsg.getSOAPPart();
+ part.setContent(new DOMSource(doc));
+ saajMsg.saveChanges();
+
+ msg.setContent(SOAPMessage.class, saajMsg);
+ doc = part;
+
+ byte[] docbytes = getMessageBytes(doc);
+ XMLStreamReader reader = StaxUtils.createXMLStreamReader(new
ByteArrayInputStream(docbytes));
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ dbf.setValidating(false);
+ dbf.setIgnoringComments(false);
+ dbf.setIgnoringElementContentWhitespace(true);
+ dbf.setNamespaceAware(true);
+
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ db.setEntityResolver(new NullResolver());
+ doc = StaxUtils.read(db, reader, false);
+
+ WSS4JInInterceptor inHandler = new WSS4JInInterceptor();
+
+ SoapMessage inmsg = new SoapMessage(new MessageImpl());
+ ex.setInMessage(inmsg);
+ inmsg.setContent(SOAPMessage.class, saajMsg);
+
+ inHandler.setProperty(WSHandlerConstants.ACTION,
WSHandlerConstants.ENCRYPT);
+ inHandler.setProperty(WSHandlerConstants.DEC_PROP_FILE,
"META-INF/cxf/insecurity.properties");
+ inHandler.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,
TestPwdCallback.class.getName());
+
+ try {
+ inHandler.handleMessage(inmsg);
+ fail("Expected failure on an message with no security header");
+ } catch (SoapFault fault) {
+ assertTrue(fault.getReason().startsWith(
+ "An error was discovered processing the <wsse:Security>
header"));
+ QName faultCode = new QName(WSConstants.WSSE_NS,
"InvalidSecurity");
+ assertTrue(fault.getFaultCode().equals(faultCode));
+ }
+ }
+
+ /**
+ * Test that an invalid Timestamp gets mapped to a proper fault code
+ */
+ @Test
+ public void testInvalidTimestamp() throws Exception {
+ Document doc = readDocument("wsse-request-clean.xml");
+
+ WSS4JOutInterceptor handler = new WSS4JOutInterceptor();
+
+ SoapMessage msg = new SoapMessage(new MessageImpl());
+ Exchange ex = new ExchangeImpl();
+ ex.setInMessage(msg);
+
+ SOAPMessage saajMsg = MessageFactory.newInstance().createMessage();
+ SOAPPart part = saajMsg.getSOAPPart();
+ part.setContent(new DOMSource(doc));
+ saajMsg.saveChanges();
+
+ msg.setContent(SOAPMessage.class, saajMsg);
+
+ msg.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP);
+ msg.put(WSHandlerConstants.TTL_TIMESTAMP, "1");
+
+ handler.handleMessage(msg);
+
+ doc = part;
+
+ assertValid("//wsse:Security", doc);
+
+ byte[] docbytes = getMessageBytes(doc);
+ XMLStreamReader reader = StaxUtils.createXMLStreamReader(new
ByteArrayInputStream(docbytes));
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ dbf.setValidating(false);
+ dbf.setIgnoringComments(false);
+ dbf.setIgnoringElementContentWhitespace(true);
+ dbf.setNamespaceAware(true);
+
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ db.setEntityResolver(new NullResolver());
+ doc = StaxUtils.read(db, reader, false);
+
+ WSS4JInInterceptor inHandler = new WSS4JInInterceptor();
+
+ SoapMessage inmsg = new SoapMessage(new MessageImpl());
+ ex.setInMessage(inmsg);
+ inmsg.setContent(SOAPMessage.class, saajMsg);
+
+ inHandler.setProperty(WSHandlerConstants.ACTION,
WSHandlerConstants.TIMESTAMP);
+ inHandler.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "1");
+
+ try {
+ //
+ // Sleep for over a second to make the timestamp invalid
+ //
+ Thread.sleep(1001);
+ inHandler.handleMessage(inmsg);
+ fail("Expected failure on an invalid Timestamp");
+ } catch (SoapFault fault) {
+ assertTrue(fault.getReason().startsWith(
+ "The message has expired"));
+ QName faultCode = new QName(WSConstants.WSSE_NS, "MessageExpired");
+ assertTrue(fault.getFaultCode().equals(faultCode));
+ }
+ }
+
+ /**
+ * Test that an action mismatch gets mapped to a proper fault code
+ */
+ @Test
+ public void testActionMismatch() throws Exception {
+ Document doc = readDocument("wsse-request-clean.xml");
+
+ WSS4JOutInterceptor handler = new WSS4JOutInterceptor();
+
+ SoapMessage msg = new SoapMessage(new MessageImpl());
+ Exchange ex = new ExchangeImpl();
+ ex.setInMessage(msg);
+
+ SOAPMessage saajMsg = MessageFactory.newInstance().createMessage();
+ SOAPPart part = saajMsg.getSOAPPart();
+ part.setContent(new DOMSource(doc));
+ saajMsg.saveChanges();
+
+ msg.setContent(SOAPMessage.class, saajMsg);
+
+ msg.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP);
+
+ handler.handleMessage(msg);
+
+ doc = part;
+
+ assertValid("//wsse:Security", doc);
+
+ byte[] docbytes = getMessageBytes(doc);
+ XMLStreamReader reader = StaxUtils.createXMLStreamReader(new
ByteArrayInputStream(docbytes));
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ dbf.setValidating(false);
+ dbf.setIgnoringComments(false);
+ dbf.setIgnoringElementContentWhitespace(true);
+ dbf.setNamespaceAware(true);
+
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ db.setEntityResolver(new NullResolver());
+ doc = StaxUtils.read(db, reader, false);
+
+ WSS4JInInterceptor inHandler = new WSS4JInInterceptor();
+
+ SoapMessage inmsg = new SoapMessage(new MessageImpl());
+ ex.setInMessage(inmsg);
+ inmsg.setContent(SOAPMessage.class, saajMsg);
+
+ inHandler.setProperty(WSHandlerConstants.ACTION,
+ WSHandlerConstants.TIMESTAMP + " " +
WSHandlerConstants.USERNAME_TOKEN);
+ inHandler.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,
TestPwdCallback.class.getName());
+
+ try {
+ inHandler.handleMessage(inmsg);
+ fail("Expected failure on an action mismatch");
+ } catch (SoapFault fault) {
+ assertTrue(fault.getReason().startsWith(
+ "An error was discovered processing the <wsse:Security>
header"));
+ QName faultCode = new QName(WSConstants.WSSE_NS,
"InvalidSecurity");
+ assertTrue(fault.getFaultCode().equals(faultCode));
+ }
+ }
+
+
+ private byte[] getMessageBytes(Document doc) throws Exception {
+ // XMLOutputFactory factory = XMLOutputFactory.newInstance();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ // XMLStreamWriter byteArrayWriter =
+ // factory.createXMLStreamWriter(outputStream);
+ XMLStreamWriter byteArrayWriter =
StaxUtils.createXMLStreamWriter(outputStream);
+
+ StaxUtils.writeDocument(doc, byteArrayWriter, false);
+
+ byteArrayWriter.flush();
+ return outputStream.toByteArray();
+ }
+}
Propchange:
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/branches/2.0.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date