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;
- }
+
}