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/03/04 21:46:29 UTC

svn commit: r750151 - in /cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security: ./ policy/builders/ tokenstore/ trust/ wss4j/policyhandlers/

Author: dkulp
Date: Wed Mar  4 20:46:28 2009
New Revision: 750151

URL: http://svn.apache.org/viewvc?rev=750151&view=rev
Log:
Wire in the new KeyValue stuff Colm added to WSS4J
We now pass 100% MS InteropPlugFest ws-trust10 cxf client -> MS services

Modified:
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/KeyValueTokenBuilder.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=750151&r1=750150&r2=750151&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java Wed Mar  4 20:46:28 2009
@@ -43,16 +43,21 @@
 
     public static final String TOKEN = "ws-security.token";
     public static final String TOKEN_ID = "ws-security.token.id";
-    
+
     public static final String STS_CLIENT = "ws-security.sts.client";
     
     /**
      * WCF's trust server sometimes will encrypt the token in the response IN ADDITION TO
      * the full security on the message. These properties control the way the STS client
      * will decrypt the EncryptedData elements in the response
+     * 
+     * These are also used by the STSClient to send/process any RSA/DSAKeyValue tokens 
+     * used if the KeyType is "PublicKey" 
      */
     public static final String STS_TOKEN_CRYPTO = "ws-security.sts.token.crypto";
     public static final String STS_TOKEN_PROPERTIES = "ws-security.sts.token.properties";
+    public static final String STS_TOKEN_USERNAME = "ws-security.sts.token.username";
+    
     
 
     public static final Set<String> ALL_PROPERTIES;

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/KeyValueTokenBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/KeyValueTokenBuilder.java?rev=750151&r1=750150&r2=750151&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/KeyValueTokenBuilder.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/builders/KeyValueTokenBuilder.java Wed Mar  4 20:46:28 2009
@@ -25,6 +25,7 @@
 
 import org.w3c.dom.Element;
 
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.ws.policy.AssertionBuilder;
 import org.apache.cxf.ws.policy.PolicyAssertion;
@@ -36,21 +37,30 @@
 
 
 public class KeyValueTokenBuilder implements AssertionBuilder {
+    private static final String MS_NS = "http://schemas.microsoft.com/ws/2005/07/securitypolicy";
     private static final List<QName> KNOWN_ELEMENTS 
-        = Arrays.asList(SP12Constants.KEYVALUE_TOKEN);
+        = Arrays.asList(SP12Constants.KEYVALUE_TOKEN,
+                        new QName(MS_NS, "RsaToken"));
 
     public KeyValueTokenBuilder() {
     }
     
     public PolicyAssertion build(Element element) {
         
-        SPConstants consts = SP11Constants.SP_NS.equals(element.getNamespaceURI())
+        SPConstants consts = MS_NS.equals(element.getNamespaceURI())
             ? SP11Constants.INSTANCE : SP12Constants.INSTANCE;
 
         KeyValueToken token = new KeyValueToken(consts);
 
         String attribute = element.getAttributeNS(element.getNamespaceURI(), SPConstants.ATTR_INCLUDE_TOKEN);
-        if (attribute != null) {
+        if (StringUtils.isEmpty(attribute)) {
+            attribute = element.getAttributeNS(consts.getNamespace(), SPConstants.ATTR_INCLUDE_TOKEN);
+        }
+        if (StringUtils.isEmpty(attribute)) {
+            attribute = element.getAttributeNS(SP11Constants.INSTANCE.getNamespace(),
+                                               SPConstants.ATTR_INCLUDE_TOKEN);
+        }
+        if (!StringUtils.isEmpty(attribute)) {
             token.setInclusion(consts.getInclusionFromAttributeValue(attribute));
         }
 

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java?rev=750151&r1=750150&r2=750151&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java Wed Mar  4 20:46:28 2009
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.ws.security.tokenstore;
 
+import java.security.cert.X509Certificate;
 import java.util.Calendar;
 import java.util.Properties;
 
@@ -31,6 +32,7 @@
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.staxutils.W3CDOMStreamWriter;
 import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.message.token.Reference;
 
 
@@ -126,6 +128,10 @@
      * The tokenType
      */
     private String tokenType;
+
+    private X509Certificate x509cert;
+
+    private Crypto crypto;
     
     public SecurityToken() {
         
@@ -399,6 +405,16 @@
         }
         return null;
     }
+    public void setX509Certificate(X509Certificate cert, Crypto cpt) {
+        x509cert = cert;
+        crypto = cpt;
+    }
+    public X509Certificate getX509Certificate() {
+        return x509cert;
+    }
+    public Crypto getCrypto() {
+        return crypto;
+    }
 
 
 } 

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java?rev=750151&r1=750150&r2=750151&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java Wed Mar  4 20:46:28 2009
@@ -21,7 +21,10 @@
 
 import java.io.IOException;
 import java.net.URL;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
 import java.util.Date;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -80,6 +83,7 @@
 import org.apache.neethi.Policy;
 import org.apache.neethi.PolicyComponent;
 import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
 import org.apache.ws.security.WSSecurityException;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoFactory;
@@ -91,6 +95,8 @@
 import org.apache.ws.security.util.Base64;
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.apache.xml.security.keys.content.keyvalues.DSAKeyValue;
+import org.apache.xml.security.keys.content.keyvalues.RSAKeyValue;
 
 /**
  * 
@@ -309,22 +315,11 @@
         writer.writeCharacters(namespace + requestType);
         writer.writeEndElement();        
         addAppliesTo(writer, appliesTo);
-        if (isSecureConv) {
-            addLifetime(writer);
-            if (keyType == null) {
-                writer.writeStartElement("wst", "TokenType", namespace);
-                writer.writeCharacters(STSUtils.getTokenTypeSCT(namespace));
-                writer.writeEndElement();
-                keyType = namespace + "/SymmetricKey";
-            }
-        } else if (keyType == null) {
-            writer.writeStartElement("wst", "KeyType", namespace);
-            writer.writeCharacters(namespace + "/SymmetricKey");
-            writer.writeEndElement();
-            keyType = namespace + "/SymmetricKey";
-        }
+        keyType = writeKeyType(writer, keyType);
         
         byte[] requestorEntropy = null;
+        X509Certificate cert = null;
+        Crypto crypto = null;
         
         if (keyType.endsWith("SymmetricKey")) {
             if (!wroteKeySize && !isSecureConv) {
@@ -352,14 +347,17 @@
             writer.writeStartElement("wst", "UseKey", namespace);
             writer.writeStartElement("http://www.w3.org/2000/09/xmldsig#", "KeyInfo");
             writer.writeStartElement("http://www.w3.org/2000/09/xmldsig#", "KeyValue");
-            
-            /*
-            //REVISIT - KeyValueToken support - how to get the key?
-            RSAPublicKey key = getPublicKey();
-            
-            RSAKeyValue value = new RSAKeyValue(writer.getDocument(), key);
-            StaxUtils.copy(value.getElement(), writer);
-            */
+            crypto = createCrypto(false);
+            cert = getCert(crypto);
+            PublicKey key = cert.getPublicKey();
+            String pubKeyAlgo = key.getAlgorithm();
+            if ("DSA".equalsIgnoreCase(pubKeyAlgo)) {
+                DSAKeyValue dsaKeyValue = new DSAKeyValue(writer.getDocument(), key);
+                writer.getCurrentNode().appendChild(dsaKeyValue.getElement());
+            } else if ("RSA".equalsIgnoreCase(pubKeyAlgo)) {
+                RSAKeyValue rsaKeyValue = new RSAKeyValue(writer.getDocument(), key);
+                writer.getCurrentNode().appendChild(rsaKeyValue.getElement());
+            }
             
             writer.writeEndElement();
             writer.writeEndElement();
@@ -379,7 +377,11 @@
         Object obj[] = client.invoke(boi,
                                      new DOMSource(writer.getDocument().getDocumentElement()));
         
-        return createSecurityToken((Document)((DOMSource)obj[0]).getNode(), requestorEntropy);
+        SecurityToken token = createSecurityToken((Document)((DOMSource)obj[0]).getNode(), requestorEntropy);
+        if (cert != null) {
+            token.setX509Certificate(cert, crypto);
+        }
+        return token;
     }
     public void renewSecurityToken(SecurityToken tok) throws Exception {
         String action = null;
@@ -388,7 +390,40 @@
         }
         requestSecurityToken(tok.getIssuerAddress(), action, "/Renew", tok);
     }
-
+    
+    private String writeKeyType(W3CDOMStreamWriter writer, String keyType) throws XMLStreamException {
+        if (isSecureConv) {
+            addLifetime(writer);
+            if (keyType == null) {
+                writer.writeStartElement("wst", "TokenType", namespace);
+                writer.writeCharacters(STSUtils.getTokenTypeSCT(namespace));
+                writer.writeEndElement();
+                keyType = namespace + "/SymmetricKey";
+            }
+        } else if (keyType == null) {
+            writer.writeStartElement("wst", "KeyType", namespace);
+            writer.writeCharacters(namespace + "/SymmetricKey");
+            writer.writeEndElement();
+            keyType = namespace + "/SymmetricKey";
+        }
+        return keyType;
+    }
+    private X509Certificate getCert(Crypto crypto) throws Exception {
+        String alias = (String)getProperty(SecurityConstants.STS_TOKEN_USERNAME);
+        if (alias == null) {
+            alias = crypto.getDefaultX509Alias();
+        }
+        if (alias == null) {
+            Enumeration<String> as = crypto.getKeyStore().aliases();
+            if (as.hasMoreElements()) {
+                alias = as.nextElement();
+            }
+            if (as.hasMoreElements()) {
+                throw new Fault("No alias specified for retrieving PublicKey", LOG);
+            }
+        }
+        return crypto.getCertificates(alias)[0];
+    }
     private void addLifetime(XMLStreamWriter writer) throws XMLStreamException {
         Date creationTime = new Date();
         Date expirationTime = new Date();
@@ -417,7 +452,8 @@
         }
     }
 
-    private SecurityToken createSecurityToken(Document document, byte[] requestorEntropy) 
+    private SecurityToken createSecurityToken(Document document, 
+                                              byte[] requestorEntropy) 
         throws WSSecurityException {
         
         Element el = document.getDocumentElement();
@@ -460,17 +496,14 @@
         } catch (IOException e1) {
             throw new TrustException(e1);
         }
-        
         String id = findID(rar, rur, rstDec);
         if (StringUtils.isEmpty(id)) {
             throw new TrustException(new Message("NO_ID", LOG));
-        }
-        
+        }        
         SecurityToken token = new SecurityToken(id, rstDec, lte);
         token.setAttachedReference(rar);
         token.setUnattachedReference(rur);
         token.setIssuerAddress(location);
-                
         
         byte[] secret = null;
 
@@ -487,7 +520,7 @@
 
                     EncryptedKeyProcessor processor = new EncryptedKeyProcessor();
 
-                    processor.handleToken(child, null, createCrypto(),
+                    processor.handleToken(child, null, createCrypto(true),
                                           createHandler(), null, new Vector(),
                                           null);
 
@@ -526,21 +559,20 @@
             secret = requestorEntropy;
         }
         token.setSecret(secret);
-        
+
         return token;
     }
 
     protected Element decrypt(Element firstElement) throws IOException {
         if ("EncryptedData".equals(firstElement.getLocalName())
             && "http://www.w3.org/2001/04/xmlenc#".equals(firstElement.getNamespaceURI())) {
-            
             Node parent = firstElement.getParentNode();
             Node prev = firstElement.getPreviousSibling();
             
             //encrypted even more.  WCF seems to do this periodically
             EncryptedDataProcessor processor = new EncryptedDataProcessor();
 
-            processor.handleToken(firstElement, null, createCrypto(),
+            processor.handleToken(firstElement, null, createCrypto(true),
                                   createHandler(), null, new Vector(),
                                   null);
             
@@ -549,7 +581,6 @@
             } else {
                 firstElement = (Element)prev.getNextSibling();
             }
-
         }
         return firstElement;
     }
@@ -582,14 +613,15 @@
         return o;
     }
     
-    private Crypto createCrypto() throws IOException {
-        Crypto crypto = (Crypto)getProperty(SecurityConstants.STS_TOKEN_CRYPTO);
+    private Crypto createCrypto(boolean decrypt) throws IOException {
+        WSSConfig.getDefaultWSConfig();
+        Crypto crypto = (Crypto)getProperty(SecurityConstants.STS_TOKEN_CRYPTO + (decrypt ? ".decrypt" : ""));
         if (crypto != null) {
             return crypto;
         }
         
         
-        Object o = getProperty(SecurityConstants.STS_TOKEN_PROPERTIES); 
+        Object o = getProperty(SecurityConstants.STS_TOKEN_PROPERTIES + (decrypt ? ".decrypt" : "")); 
         Properties properties = null;
         if (o instanceof Properties) {
             properties = (Properties)o;
@@ -613,6 +645,9 @@
         if (properties != null) {
             return CryptoFactory.getInstance(properties);
         }
+        if (decrypt) {
+            return createCrypto(false);
+        }
         return null;
     }
 

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java?rev=750151&r1=750150&r2=750151&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java Wed Mar  4 20:46:28 2009
@@ -61,6 +61,7 @@
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.helpers.MapNamespaceContext;
+import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.resource.ResourceManager;
 import org.apache.cxf.ws.policy.AssertionInfo;
@@ -75,6 +76,7 @@
 import org.apache.cxf.ws.security.policy.model.Binding;
 import org.apache.cxf.ws.security.policy.model.Header;
 import org.apache.cxf.ws.security.policy.model.IssuedToken;
+import org.apache.cxf.ws.security.policy.model.KeyValueToken;
 import org.apache.cxf.ws.security.policy.model.Layout;
 import org.apache.cxf.ws.security.policy.model.SecureConversationToken;
 import org.apache.cxf.ws.security.policy.model.SignedEncryptedElements;
@@ -417,8 +419,49 @@
                     this.encryptedTokensIdList.add(secToken.getId());
                 }
         
-                //Add the extracted token
-                ret.put(token, new WSSecurityTokenHolder(secToken));
+                if (secToken.getX509Certificate() == null) {
+                    //Add the extracted token
+                    ret.put(token, new WSSecurityTokenHolder(secToken));
+                } else {
+                    WSSecSignature sig = new WSSecSignature();                    
+                    sig.setX509Certificate(secToken.getX509Certificate());
+                    sig.setCustomTokenId(secToken.getId());
+                    sig.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
+                    if (secToken.getTokenType() == null) {
+                        sig.setCustomTokenValueType(WSConstants.WSS_SAML_NS
+                                                    + WSConstants.SAML_ASSERTION_ID);
+                    } else {
+                        sig.setCustomTokenValueType(secToken.getTokenType());
+                    }
+                    sig.setSignatureAlgorithm(binding.getAlgorithmSuite().getAsymmetricSignature());
+                    sig.setSigCanonicalization(binding.getAlgorithmSuite().getInclusiveC14n());
+                    
+                    Crypto crypto = secToken.getCrypto();
+                    String uname = null;
+                    try {
+                        uname = crypto.getKeyStore().getCertificateAlias(secToken.getX509Certificate());
+                    } catch (KeyStoreException e1) {
+                        throw new Fault(e1);
+                    }
+
+                    String password = getPassword(uname, token, WSPasswordCallback.SIGNATURE);
+                    if (password == null) {
+                        password = "";
+                    }
+                    sig.setUserInfo(uname, password);
+                    try {
+                        sig.prepare(saaj.getSOAPPart(),
+                                    secToken.getCrypto(), 
+                                    secHeader);
+                    } catch (WSSecurityException e) {
+                        throw new Fault(e);
+                    }
+                    
+                    if (suppTokens.isEncryptedToken()) {
+                        encryptedTokensIdList.add(sig.getBSTTokenId());
+                    }
+                    ret.put(token, sig);                
+                }
 
             } else if (token instanceof X509Token) {
                 //We have to use a cert
@@ -432,7 +475,13 @@
                     encryptedTokensIdList.add(sig.getBSTTokenId());
                 }
                 ret.put(token, sig);
-            }         
+            } else if (token instanceof KeyValueToken) {
+                WSSecSignature sig = getSignatureBuider(suppTokens, token, endorse);
+                if (suppTokens.isEncryptedToken()) {
+                    encryptedTokensIdList.add(sig.getBSTTokenId());
+                }
+                ret.put(token, sig);                
+            }
             
         }
         return ret;
@@ -880,7 +929,10 @@
                     secBase.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
                     tokenTypeSet = true;
                 }
-            } 
+            } else if (token instanceof KeyValueToken) {
+                secBase.setKeyIdentifierType(WSConstants.KEY_VALUE);
+                tokenTypeSet = true;
+            }
             
             if (!tokenTypeSet) {
                 policyAsserted(token);
@@ -1104,7 +1156,8 @@
     }
 
     protected void doEndorsedSignatures(Map<Token, WSSecBase> tokenMap,
-                                          boolean isTokenProtection) {
+                                          boolean isTokenProtection,
+                                          boolean isSigProtect) {
         
         for (Map.Entry<Token, WSSecBase> ent : tokenMap.entrySet()) {
             WSSecBase tempTok = ent.getValue();
@@ -1123,6 +1176,9 @@
                     sig.appendToHeader(secHeader);
                     
                     signatures.add(sig.getSignatureValue());
+                    if (isSigProtect) {
+                        encryptedTokensIdList.add(sig.getId());
+                    }
                 } catch (WSSecurityException e) {
                     policyNotAsserted(ent.getKey(), e);
                 }
@@ -1344,20 +1400,23 @@
 
     protected void doEndorse() {
         boolean tokenProtect = false;
+        boolean sigProtect = false;
         if (binding instanceof AsymmetricBinding) {
             tokenProtect = ((AsymmetricBinding)binding).isTokenProtection();
+            sigProtect = ((AsymmetricBinding)binding).isSignatureProtection();            
         } else if (binding instanceof SymmetricBinding) {
             tokenProtect = ((SymmetricBinding)binding).isTokenProtection();
+            sigProtect = ((SymmetricBinding)binding).isSignatureProtection();            
         }
         // Adding the endorsing encrypted supporting tokens to endorsing supporting tokens
         endSuppTokMap.putAll(endEncSuppTokMap);
         // Do endorsed signatures
-        doEndorsedSignatures(endSuppTokMap, tokenProtect);
+        doEndorsedSignatures(endSuppTokMap, tokenProtect, sigProtect);
 
         //Adding the signed endorsed encrypted tokens to signed endorsed supporting tokens
         sgndEndSuppTokMap.putAll(sgndEndEncSuppTokMap);
         // Do signed endorsing signatures
-        doEndorsedSignatures(sgndEndSuppTokMap, tokenProtect);
+        doEndorsedSignatures(sgndEndSuppTokMap, tokenProtect, sigProtect);
     } 
 
     protected void addSignatureConfirmation(Vector<WSEncryptionPart> sigParts) {