You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2009/02/24 17:06:49 UTC

svn commit: r747408 - in /cxf/trunk: api/src/main/java/org/apache/cxf/phase/ common/common/src/main/java/org/apache/cxf/staxutils/ rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/ rt/ws/security/src/main/java/org/apache/cxf/...

Author: dkulp
Date: Tue Feb 24 16:06:45 2009
New Revision: 747408

URL: http://svn.apache.org/viewvc?rev=747408&view=rev
Log:
Round trip of WS-SecureCoverstation now working

Modified:
    cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
    cxf/trunk/common/common/src/main/java/org/apache/cxf/staxutils/W3CDOMStreamWriter.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java

Modified: cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
URL: http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java?rev=747408&r1=747407&r2=747408&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java (original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java Tue Feb 24 16:06:45 2009
@@ -57,6 +57,7 @@
 
     private static final Logger LOG = LogUtils.getL7dLogger(PhaseInterceptorChain.class); 
 
+    private static final ThreadLocal<Message> CURRENT_MESSAGE = new ThreadLocal<Message>();
     
     private final Map<String, Integer> nameMap;
     private final Phase phases[];
@@ -85,6 +86,7 @@
     private boolean faultOccurred;
     
     
+    
     private PhaseInterceptorChain(PhaseInterceptorChain src) {
         //only used for clone
         state = State.EXECUTING;
@@ -139,6 +141,10 @@
         }
     }
     
+    public static Message getCurrentMessage() {
+        return CURRENT_MESSAGE.get();
+    }
+    
     // this method should really be on the InterceptorChain interface
     public State getState() {
         return state;
@@ -216,71 +222,78 @@
         updateIterator();
         boolean isFineLogging = LOG.isLoggable(Level.FINE);
         pausedMessage = message;
-        while (state == State.EXECUTING && iterator.hasNext()) {
-            try {
-                Interceptor currentInterceptor = iterator.next();
-                if (isFineLogging) {
-                    LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
-                }
-                //System.out.println("-----------" + currentInterceptor);
-                currentInterceptor.handleMessage(message);
-            } catch (SuspendedInvocationException ex) {
-                // we need to resume from the same interceptor the exception got originated from
-                if (iterator.hasPrevious()) {
-                    iterator.previous();
-                }
-                pause();
-                throw ex;
-            } catch (RuntimeException ex) {
-                if (!faultOccurred) {
- 
-                    faultOccurred = true;
-                                        
-                    FaultMode mode = message.get(FaultMode.class);
-                    if (mode == FaultMode.CHECKED_APPLICATION_FAULT) {
-                        if (LOG.isLoggable(Level.FINE)) { 
-                            LogUtils.log(LOG, Level.FINE,
-                                         "Application has thrown exception, unwinding now", ex);
+
+        Message oldMessage = CURRENT_MESSAGE.get();
+        try {
+            CURRENT_MESSAGE.set(message);
+            while (state == State.EXECUTING && iterator.hasNext()) {
+                try {
+                    Interceptor currentInterceptor = iterator.next();
+                    if (isFineLogging) {
+                        LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
+                    }
+                    //System.out.println("-----------" + currentInterceptor);
+                    currentInterceptor.handleMessage(message);
+                } catch (SuspendedInvocationException ex) {
+                    // we need to resume from the same interceptor the exception got originated from
+                    if (iterator.hasPrevious()) {
+                        iterator.previous();
+                    }
+                    pause();
+                    throw ex;
+                } catch (RuntimeException ex) {
+                    if (!faultOccurred) {
+     
+                        faultOccurred = true;
+                                            
+                        FaultMode mode = message.get(FaultMode.class);
+                        if (mode == FaultMode.CHECKED_APPLICATION_FAULT) {
+                            if (LOG.isLoggable(Level.FINE)) { 
+                                LogUtils.log(LOG, Level.FINE,
+                                             "Application has thrown exception, unwinding now", ex);
+                            } else if (LOG.isLoggable(Level.INFO)) {
+                                Throwable t = ex;
+                                if (ex instanceof Fault
+                                    && ex.getCause() != null) {
+                                    t = ex.getCause();
+                                }                            
+                                
+                                LogUtils.log(LOG, Level.INFO,
+                                             "Application has thrown exception, unwinding now: "
+                                             + t.getClass().getName() 
+                                             + ": " + ex.getMessage());
+                            }
                         } else if (LOG.isLoggable(Level.INFO)) {
-                            Throwable t = ex;
-                            if (ex instanceof Fault
-                                && ex.getCause() != null) {
-                                t = ex.getCause();
-                            }                            
-                            
-                            LogUtils.log(LOG, Level.INFO,
-                                         "Application has thrown exception, unwinding now: "
-                                         + t.getClass().getName() 
-                                         + ": " + ex.getMessage());
+                            if (mode == FaultMode.UNCHECKED_APPLICATION_FAULT) {
+                                LogUtils.log(LOG, Level.INFO,
+                                             "Application has thrown exception, unwinding now", ex);
+                            } else {
+                                LogUtils.log(LOG, Level.INFO,
+                                             "Interceptor has thrown exception, unwinding now", ex);
+                            }
                         }
-                    } else if (LOG.isLoggable(Level.INFO)) {
-                        if (mode == FaultMode.UNCHECKED_APPLICATION_FAULT) {
-                            LogUtils.log(LOG, Level.INFO,
-                                         "Application has thrown exception, unwinding now", ex);
-                        } else {
-                            LogUtils.log(LOG, Level.INFO,
-                                         "Interceptor has thrown exception, unwinding now", ex);
+    
+                        message.setContent(Exception.class, ex);
+                        if (message.getExchange() != null) {
+                            message.getExchange().put(Exception.class, ex);
+                        }                    
+                        unwind(message);
+                        
+                        if (faultObserver != null) {
+                            faultObserver.onMessage(message);
                         }
                     }
-
-                    message.setContent(Exception.class, ex);
-                    if (message.getExchange() != null) {
-                        message.getExchange().put(Exception.class, ex);
-                    }                    
-                    unwind(message);
-                    
-                    if (faultObserver != null) {
-                        faultObserver.onMessage(message);
-                    }
-                }
-                state = State.ABORTED;
-            } 
-        }
-        if (state == State.EXECUTING) {
-            state = State.COMPLETE;
-            pausedMessage = null;
+                    state = State.ABORTED;
+                } 
+            }
+            if (state == State.EXECUTING) {
+                state = State.COMPLETE;
+                pausedMessage = null;
+            }
+            return state == State.COMPLETE;
+        } finally {
+            CURRENT_MESSAGE.set(oldMessage);
         }
-        return state == State.COMPLETE;
     }
     
     /**

Modified: cxf/trunk/common/common/src/main/java/org/apache/cxf/staxutils/W3CDOMStreamWriter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/staxutils/W3CDOMStreamWriter.java?rev=747408&r1=747407&r2=747408&view=diff
==============================================================================
--- cxf/trunk/common/common/src/main/java/org/apache/cxf/staxutils/W3CDOMStreamWriter.java (original)
+++ cxf/trunk/common/common/src/main/java/org/apache/cxf/staxutils/W3CDOMStreamWriter.java Tue Feb 24 16:06:45 2009
@@ -61,7 +61,11 @@
         currentNode = e;
         ((W3CNamespaceContext)context).setElement(e);
     }
-
+    
+    public Element getCurrentNode() {
+        return currentNode;
+    }
+    
     public void setNsRepairing(boolean b) {
         nsRepairing = b;
     }

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java?rev=747408&r1=747407&r2=747408&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/SecureConversationTokenInterceptorProvider.java Tue Feb 24 16:06:45 2009
@@ -19,12 +19,17 @@
 
 package org.apache.cxf.ws.security.policy.interceptors;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Vector;
 import java.util.logging.Logger;
 
+import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.dom.DOMSource;
 
 import org.w3c.dom.Document;
@@ -39,7 +44,6 @@
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.DOMUtils;
-import org.apache.cxf.helpers.XMLUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.interceptor.Interceptor;
 import org.apache.cxf.message.Exchange;
@@ -49,6 +53,7 @@
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.invoker.Invoker;
+import org.apache.cxf.staxutils.W3CDOMStreamWriter;
 import org.apache.cxf.transport.Destination;
 import org.apache.cxf.ws.addressing.AddressingProperties;
 import org.apache.cxf.ws.addressing.policy.MetadataConstants;
@@ -70,9 +75,24 @@
 import org.apache.cxf.ws.security.tokenstore.TokenStore;
 import org.apache.cxf.ws.security.trust.STSClient;
 import org.apache.cxf.ws.security.trust.STSUtils;
+import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
 import org.apache.neethi.All;
 import org.apache.neethi.ExactlyOne;
 import org.apache.neethi.Policy;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.conversation.dkalgo.P_SHA1;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.apache.xml.security.utils.Base64;
 
 /**
  * 
@@ -260,7 +280,35 @@
         }
 
     }
-    
+    static class SecureConversationTokenFinderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
+        public SecureConversationTokenFinderInterceptor() {
+            super(Phase.PRE_PROTOCOL);
+            addAfter(WSS4JInInterceptor.class.getName());
+        }
+
+        public void handleMessage(SoapMessage message) throws Fault {
+            //Find the SC token
+            Vector results = (Vector)message.get(WSHandlerConstants.RECV_RESULTS);
+            for (int i = 0; i < results.size(); i++) {
+                WSHandlerResult rResult =
+                        (WSHandlerResult) results.get(i);
+
+                Vector wsSecEngineResults = rResult.getResults();
+
+                for (int j = 0; j < wsSecEngineResults.size(); j++) {
+                    WSSecurityEngineResult wser =
+                            (WSSecurityEngineResult) wsSecEngineResults.get(j);
+                    Integer actInt = (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
+                    if (actInt.intValue() == WSConstants.SCT) {
+                        SecurityContextToken tok
+                            = (SecurityContextToken)wser
+                                .get(WSSecurityEngineResult.TAG_SECURITY_CONTEXT_TOKEN);
+                        message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getIdentifier());
+                    }
+                }
+            }
+        }
+    }
     static class SecureConversationInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
         public SecureConversationInInterceptor() {
             super(Phase.PRE_PROTOCOL);
@@ -301,6 +349,8 @@
                             ns = STSUtils.WST_NS_05_02;
                         }
                         recalcEffectivePolicy(message, ns, pol);
+                    } else {
+                        message.getInterceptorChain().add(new SecureConversationTokenFinderInterceptor());
                     }
                 } else {
                     //client side should be checked on the way out
@@ -321,12 +371,19 @@
             }
             Destination destination = ex.getDestination();
             try {
-                Endpoint endpoint = STSUtils.createSTSEndpoint(bus, 
-                                                           namespace,
-                                                           null,
-                                                           destination.getAddress().getAddress().getValue(),
-                                                           message.getVersion().getBindingId(), 
-                                                           policy);
+                Endpoint endpoint = message.getExchange().get(Endpoint.class);
+                TokenStore store = (TokenStore)message.getContextualProperty(TokenStore.class.getName());
+                if (store == null) {
+                    store = new MemoryTokenStore();
+                    endpoint.getEndpointInfo().setProperty(TokenStore.class.getName(), store);
+                }
+                endpoint = STSUtils.createSTSEndpoint(bus, 
+                                                      namespace,
+                                                      null,
+                                                      destination.getAddress().getAddress().getValue(),
+                                                      message.getVersion().getBindingId(), 
+                                                      policy);
+                endpoint.getEndpointInfo().setProperty(TokenStore.class.getName(), store);
             
                 EndpointPolicy ep = pe.getServerEndpointPolicy(endpoint.getEndpointInfo(), destination);
                 List<Interceptor> interceptors = ep.getInterceptors();
@@ -366,23 +423,167 @@
                 } else {
                     el = (Element)nd;
                 }
-                String name = el.getLocalName();
-                if ("RequestSecurityToken".equals(name)) {
-                    XMLUtils.printDOM(el);
-                    el = DOMUtils.getFirstElement(el);
-                    while (el != null) {
+                String namespace = el.getNamespaceURI();
+                String prefix = el.getPrefix();
+                byte clientEntropy[] = null;
+                int keySize = 256;
+                int ttl = 300000;
+                String tokenType = null;
+                if ("RequestSecurityToken".equals(el.getLocalName())) {
+                    try {
+                        el = DOMUtils.getFirstElement(el);
+                        while (el != null) {
+                            String localName = el.getLocalName();
+                            if (namespace.equals(el.getNamespaceURI())) {
+                                if ("Entropy".equals(localName)) {
+                                    Element bs = DOMUtils.getFirstElement(el);
+                                    if (bs != null) {
+                                        clientEntropy = Base64.decode(bs.getTextContent());
+                                    }
+                                } else if ("KeySize".equals(localName)) {
+                                    keySize = Integer.parseInt(el.getTextContent());
+                                } else if ("TokenType".equals(localName)) {
+                                    tokenType = el.getTextContent();
+                                }
+                            }
+                            
+                            el = DOMUtils.getNextElement(el);
+                        }
+                        
+                        W3CDOMStreamWriter writer = new W3CDOMStreamWriter();
+                        writer.setNsRepairing(true);
+                        writer.writeStartElement(prefix, "RequestSecurityTokenResponse", namespace);
+                        writer.writeStartElement(prefix, "RequestedSecurityToken", namespace);
+                        SecurityContextToken sct =
+                            new SecurityContextToken(getWSCVersion(tokenType), writer.getDocument());
+                        
+                        Calendar created = Calendar.getInstance();
+                        Calendar expires = Calendar.getInstance();
+                        expires.setTimeInMillis(System.currentTimeMillis() + ttl);
+
+                        SecurityToken token = new SecurityToken(sct.getIdentifier(), created, expires);
+                        token.setToken(sct.getElement());
+                        
+                        writer.getCurrentNode().appendChild(sct.getElement());
+                        writer.writeEndElement();        
+                        
+                        writer.writeStartElement(prefix, "RequestedAttachedReference", namespace);
+                        token.setAttachedReference(writeSecurityTokenReference(writer,
+                                                                               "#" + sct.getID(), 
+                                                                               tokenType));
+                        writer.writeEndElement();
                         
+                        writer.writeStartElement(prefix, "RequestedUnattachedReference", namespace);
+                        token.setUnattachedReference(writeSecurityTokenReference(writer,
+                                                                                 sct.getIdentifier(),
+                                                                                 tokenType));
+                        writer.writeEndElement();
                         
-                        el = DOMUtils.getNextElement(el);
+                        XmlSchemaDateFormat fmt = new XmlSchemaDateFormat();
+                        writer.writeStartElement(prefix, "Lifetime", namespace);
+                        writer.writeNamespace("wsu", WSConstants.WSU_NS);
+                        writer.writeStartElement("wsu", "Created", WSConstants.WSU_NS);
+                        writer.writeCharacters(fmt.format(created.getTime()));
+                        writer.writeEndElement();
+                        
+                        writer.writeStartElement("wsu", "Expires", WSConstants.WSU_NS);
+                        writer.writeCharacters(fmt.format(expires.getTime()));
+                        writer.writeEndElement();
+                        writer.writeEndElement();
+
+                        byte[] secret = writeProofToken(prefix, 
+                                                        namespace,
+                                                        writer,
+                                                        clientEntropy, 
+                                                        keySize);
+                        token.setSecret(secret);
+                        ((TokenStore)exchange.get(Endpoint.class).getEndpointInfo()
+                                .getProperty(TokenStore.class.getName())).add(token);
+                        writer.writeEndElement();
+                        return new MessageContentsList(new DOMSource(writer.getDocument()));
+                    } catch (RuntimeException ex) {
+                        throw ex;
+                    } catch (Exception ex) {
+                        throw new Fault(ex);
                     }
-                    
-                    
-                    return lst;
                 } else {
-                    throw new Fault("Unknown SecureConversation request type: " + name, LOG);
+                    throw new Fault("Unknown SecureConversation request type: " + el.getLocalName(), LOG);
                 }
             }
 
         }
     }
+    private static byte[] writeProofToken(String prefix, 
+                                          String namespace,
+                                          W3CDOMStreamWriter writer,
+                                          byte[] clientEntropy,
+                                          int keySize) 
+        throws NoSuchAlgorithmException, WSSecurityException, ConversationException, XMLStreamException {
+        byte secret[] = null; 
+        writer.writeStartElement(prefix, "RequestedProofToken", namespace);
+        if (clientEntropy == null) {
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            secret = new byte[keySize / 8];
+            random.nextBytes(secret);
+            
+            writer.writeStartElement(prefix, "BinarySecret", namespace);
+            writer.writeAttribute("", namespace + "/Nonce");
+            writer.writeCharacters(Base64.encode(secret));
+            writer.writeEndElement();
+        } else {
+            byte entropy[] = WSSecurityUtil.generateNonce(keySize / 8);
+            P_SHA1 psha1 = new P_SHA1();
+            secret = psha1.createKey(clientEntropy,
+                                     entropy,
+                                     0,
+                                     keySize / 8);
+
+            writer.writeStartElement(prefix, "ComputedKey", namespace);
+            writer.writeCharacters(namespace + "/CK/PSHA1");            
+            writer.writeEndElement();
+            writer.writeEndElement();
+
+            writer.writeStartElement(prefix, "Entropy", namespace);
+            writer.writeStartElement(prefix, "BinarySecret", namespace);
+            writer.writeAttribute("Type", namespace + "/Nonce");
+            writer.writeCharacters(Base64.encode(entropy));
+            writer.writeEndElement();
+            
+        }
+        writer.writeEndElement();
+        return secret;
+    }
+    
+    private static Element writeSecurityTokenReference(W3CDOMStreamWriter writer,
+                                                    String id,
+                                                    String refValueType) {
+
+        Reference ref = new Reference(writer.getDocument());
+        ref.setURI(id);
+        if (refValueType != null) {
+            ref.setValueType(refValueType);
+        }
+        SecurityTokenReference str = new SecurityTokenReference(writer.getDocument());
+        str.setReference(ref);
+
+        writer.getCurrentNode().appendChild(str.getElement());
+        return str.getElement();
+    }
+
+    
+    private static int getWSCVersion(String tokenTypeValue) throws ConversationException {
+
+        if (tokenTypeValue == null) {
+            return ConversationConstants.DEFAULT_VERSION;
+        }
+
+        if (tokenTypeValue.startsWith(ConversationConstants.WSC_NS_05_02)) {
+            return ConversationConstants.getWSTVersion(ConversationConstants.WSC_NS_05_02);
+        } else if (tokenTypeValue.startsWith(ConversationConstants.WSC_NS_05_12)) {
+            return ConversationConstants.getWSTVersion(ConversationConstants.WSC_NS_05_12);
+        } else {
+            throw new ConversationException("unsupportedSecConvVersion");
+        }
+    }
+
 }

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java?rev=747408&r1=747407&r2=747408&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java Tue Feb 24 16:06:45 2009
@@ -131,7 +131,8 @@
                         SignedEncryptedParts signdParts = sgndSuppTokens.getSignedParts();
 
                         for (Token token : sgndSuppTokens.getTokens()) {
-                            if (token instanceof IssuedToken) {
+                            if (token instanceof IssuedToken
+                                || token instanceof SecureConversationToken) {
                                 signatureValues.add(doIssuedTokenSignature(token, signdParts,
                                                                            sgndSuppTokens));
                             } else if (token instanceof X509Token) {
@@ -162,16 +163,14 @@
                     
                     if (sgndSuppTokens != null) {
                         for (Token token : sgndSuppTokens.getTokens()) {
-                            if (token instanceof IssuedToken) {
+                            if (token instanceof IssuedToken
+                                || token instanceof SecureConversationToken) {
                                 signatureValues.add(doIssuedTokenSignature(token, null, 
                                                                            sgndSuppTokens));
                             } else if (token instanceof X509Token) {
                                 signatureValues.add(doX509TokenSignature(token, 
                                                                          sgndSuppTokens.getSignedParts(), 
                                                                          sgndSuppTokens));
-                            } else if (token instanceof SecureConversationToken) {
-                                signatureValues.add(doSecureConversationSignature(token,
-                                                                                  null));
                             } else if (token instanceof KeyValueToken) {
                                 //
                             }
@@ -386,12 +385,7 @@
             return sig.getSignatureValue();
         }
     }
-    
-    private byte[] doSecureConversationSignature(Token token, 
-                                                 SignedEncryptedParts signdParts) 
-        throws Exception {
-        return null;
-    }
+
 
 
 }