cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dk...@apache.org
Subject svn commit: r664065 - in /cxf/trunk/rt/ws/security/src: main/java/org/apache/cxf/ws/security/wss4j/ test/java/org/apache/cxf/ws/security/wss4j/
Date Fri, 06 Jun 2008 18:10:05 GMT
Author: dkulp
Date: Fri Jun  6 11:10:04 2008
New Revision: 664065

URL: http://svn.apache.org/viewvc?rev=664065&view=rev
Log:
[CXF-1632] WS-Security fault handling improvements.  Patch from Colm applied

Added:
    cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
  (with props)
Modified:
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java?rev=664065&r1=664064&r2=664065&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
Fri Jun  6 11:10:04 2008
@@ -113,7 +113,7 @@
         return HEADERS;
     }
 
-    public Map getProperties() {
+    public Map<String, Object> getProperties() {
         return properties;
     }
 

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties?rev=664065&r1=664064&r2=664065&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/Messages.properties
Fri Jun  6 11:10:04 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/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=664065&r1=664064&r2=664065&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
Fri Jun  6 11:10:04 2008
@@ -108,7 +108,7 @@
 
         SoapVersion version = msg.getVersion();
         if (doDebug) {
-            LOG.fine("WSS4JInSecurityHandler: enter invoke()");
+            LOG.fine("WSS4JInInterceptor: enter handleMessage()");
         }
 
         long t0 = 0;
@@ -148,18 +148,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();
@@ -170,7 +165,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);
                 }
             }
 
@@ -197,7 +192,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);
             }
@@ -219,7 +214,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);
             }
@@ -229,8 +224,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);
@@ -244,12 +238,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) {
@@ -361,4 +356,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/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java?rev=664065&r1=664064&r2=664065&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
(original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java
Fri Jun  6 11:10:04 2008
@@ -103,7 +103,7 @@
             }
     
             if (doDebug) {
-                LOG.fine("WSDoAllSender: enter invoke()");
+                LOG.fine("WSS4JOutInterceptor: enter handleMessage()");
             }
     
             RequestData reqData = new RequestData();
@@ -207,7 +207,7 @@
                 }
     
                 if (doDebug) {
-                    LOG.fine("WSDoAllSender: exit invoke()");
+                    LOG.fine("WSS4JOutInterceptor: exit handleMessage()");
                 }
             } catch (WSSecurityException e) {
                 throw new SoapFault(new Message("SECURITY_FAILED", LOG), e, version

Added: cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java?rev=664065&view=auto
==============================================================================
--- cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
(added)
+++ cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
Fri Jun  6 11:10:04 2008
@@ -0,0 +1,258 @@
+/**
+ * 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.phase.PhaseInterceptor;
+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 ohandler = new WSS4JOutInterceptor();
+        PhaseInterceptor<SoapMessage> handler = ohandler.createEndingInterceptor();
+
+        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 ohandler = new WSS4JOutInterceptor();
+        PhaseInterceptor<SoapMessage> handler = ohandler.createEndingInterceptor();
+
+        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/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JFaultCodeTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



Mime
View raw message