cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject svn commit: r1470962 - in /cxf/fediz/trunk/plugins/core/src: main/java/org/apache/cxf/fediz/core/ main/java/org/apache/cxf/fediz/core/config/ main/resources/schemas/ test/java/org/apache/cxf/fediz/core/ test/resources/
Date Tue, 23 Apr 2013 13:54:51 GMT
Author: coheigea
Date: Tue Apr 23 13:54:51 2013
New Revision: 1470962

URL: http://svn.apache.org/r1470962
Log:
[FEDIZ-2] - Support encrypted tokens in plugin

Modified:
    cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
    cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationContext.java
    cxf/fediz/trunk/plugins/core/src/main/resources/schemas/FedizConfig.xsd
    cxf/fediz/trunk/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
    cxf/fediz/trunk/plugins/core/src/test/resources/fediz_test_config.xml

Modified: cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java?rev=1470962&r1=1470961&r2=1470962&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
(original)
+++ cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
Tue Apr 23 13:54:51 2013
@@ -20,16 +20,19 @@
 package org.apache.cxf.fediz.core;
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.text.DateFormat;
 import java.text.ParseException;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.servlet.http.HttpServletRequest;
 
 import org.w3c.dom.Document;
@@ -37,6 +40,7 @@ import org.w3c.dom.Element;
 
 import org.apache.cxf.fediz.core.config.FederationContext;
 import org.apache.cxf.fediz.core.config.FederationProtocol;
+import org.apache.cxf.fediz.core.config.KeyManager;
 import org.apache.cxf.fediz.core.exception.ProcessingException;
 import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
 import org.apache.cxf.fediz.core.metadata.MetadataWriter;
@@ -46,12 +50,21 @@ import org.apache.cxf.fediz.core.spi.IDP
 import org.apache.cxf.fediz.core.spi.WAuthCallback;
 import org.apache.cxf.fediz.core.util.DOMUtils;
 import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.processor.EncryptedDataProcessor;
+import org.apache.ws.security.processor.Processor;
 import org.apache.ws.security.util.XmlSchemaDateFormat;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 public class FederationProcessorImpl implements FederationProcessor {
 
     private static final Logger LOG = LoggerFactory.getLogger(FederationProcessorImpl.class);
@@ -160,7 +173,16 @@ public class FederationProcessorImpl imp
                 throw new ProcessingException(TYPE.TOKEN_INVALID);
             }
         }
-
+        
+        // Check to see if RST is encrypted
+        if ("EncryptedData".equals(rst.getLocalName())
+            && WSConstants.ENC_NS.equals(rst.getNamespaceURI())) {
+            Element decryptedRST = decryptEncryptedRST(rst, config);
+            if (decryptedRST != null) {
+                rst = decryptedRST;
+            }
+        }
+        
         TokenValidatorResponse validatorResponse = null;
         List<TokenValidator> validators = ((FederationProtocol)config.getProtocol()).getTokenValidators();
         for (TokenValidator validator : validators) {
@@ -223,6 +245,56 @@ public class FederationProcessorImpl imp
 
         return fedResponse;
     }
+    
+    private Element decryptEncryptedRST(
+        Element encryptedRST,
+        FederationContext config
+    ) throws ProcessingException {
+
+        KeyManager decryptionKeyManager = config.getDecryptionKey();
+        if (decryptionKeyManager == null || decryptionKeyManager.getCrypto() == null) {
+            LOG.debug(
+                "We must have a decryption Crypto instance configured to decrypt encrypted
tokens"
+            );
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+        String keyPassword = decryptionKeyManager.getKeyPassword();
+        if (keyPassword == null) {
+            LOG.debug(
+                "We must have a decryption key password to decrypt encrypted tokens"
+            );
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+        
+        EncryptedDataProcessor proc = new EncryptedDataProcessor();
+        WSDocInfo docInfo = new WSDocInfo(encryptedRST.getOwnerDocument());
+        RequestData data = new RequestData();
+        
+        // Disable WSS4J processing of the (decrypted) SAML Token
+        WSSConfig wssConfig = WSSConfig.getNewInstance();
+        wssConfig.setProcessor(WSSecurityEngine.SAML_TOKEN, new NOOpProcessor());
+        wssConfig.setProcessor(WSSecurityEngine.SAML2_TOKEN, new NOOpProcessor());
+        data.setWssConfig(wssConfig);
+        
+        data.setDecCrypto(decryptionKeyManager.getCrypto());
+        data.setCallbackHandler(new DecryptionCallbackHandler(keyPassword));
+        try {
+            List<WSSecurityEngineResult> result =
+                proc.handleToken(encryptedRST, data, docInfo);
+            if (result.size() > 0) {
+                @SuppressWarnings("unchecked")
+                List<WSDataRef> dataRefs = 
+                    (List<WSDataRef>)result.get(result.size() - 1).get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+                if (dataRefs != null && dataRefs.size() > 0) {
+                    return dataRefs.get(0).getProtectedElement();
+                }
+            }
+        } catch (WSSecurityException e) {
+            LOG.debug(e.getMessage(), e);
+            throw new ProcessingException(TYPE.TOKEN_INVALID);
+        }
+        return null;
+    }
 
     private LifeTime processLifeTime(Element lifetimeElem) throws ProcessingException {
         try {
@@ -417,6 +489,37 @@ public class FederationProcessorImpl imp
         }
         return result;
     }
+    
+    private static class DecryptionCallbackHandler implements CallbackHandler {
+        
+        private final String password;
+        
+        public DecryptionCallbackHandler(String password) {
+            this.password = password;
+        }
 
+        @Override
+        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
+            for (int i = 0; i < callbacks.length; i++) {
+                if (callbacks[i] instanceof WSPasswordCallback) {
+                    WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                    pc.setPassword(password);
+                } else {
+                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+                }
+            }
+        }
+        
+    }
+
+    private static class NOOpProcessor implements Processor {
+
+        @Override
+        public List<WSSecurityEngineResult> handleToken(Element arg0, RequestData arg1,
WSDocInfo arg2)
+            throws WSSecurityException {
+            return new ArrayList<WSSecurityEngineResult>();
+        }
+        
+    }
 
 }

Modified: cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationContext.java
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationContext.java?rev=1470962&r1=1470961&r2=1470962&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationContext.java
(original)
+++ cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationContext.java
Tue Apr 23 13:54:51 2013
@@ -62,6 +62,7 @@ public class FederationContext implement
     private FederationProtocol protocol;
     private List<TrustManager> certificateStores;
     private KeyManager keyManager;
+    private KeyManager decryptionKeyManager;
     
 
     public FederationContext(ContextConfig config) {
@@ -161,6 +162,26 @@ public class FederationContext implement
         return keyManager; 
         
     }
+    
+    public KeyManager getDecryptionKey() {
+        if (decryptionKeyManager != null) {
+            return decryptionKeyManager;
+        }
+        decryptionKeyManager = new KeyManager(config.getTokenDecryptionKey());
+        Properties decProperties = createCryptoProperties(config.getTokenDecryptionKey());
+        Crypto crypto;
+        try {
+            crypto = CryptoFactory.getInstance(decProperties);
+            decryptionKeyManager.setCrypto(crypto);
+        } catch (WSSecurityException e) {
+            decryptionKeyManager = null;
+            LOG.error("Failed to load keystore '" + decryptionKeyManager.getName() + "'",
e);
+            throw new IllegalConfigurationException("Failed to load keystore '" + decryptionKeyManager.getName()
+ "'");
+        }
+        
+        return decryptionKeyManager; 
+        
+    }
 
     @SuppressWarnings("unchecked")
     public TokenReplayCache<String> getTokenReplayCache() {

Modified: cxf/fediz/trunk/plugins/core/src/main/resources/schemas/FedizConfig.xsd
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/main/resources/schemas/FedizConfig.xsd?rev=1470962&r1=1470961&r2=1470962&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/main/resources/schemas/FedizConfig.xsd (original)
+++ cxf/fediz/trunk/plugins/core/src/main/resources/schemas/FedizConfig.xsd Tue Apr 23 13:54:51
2013
@@ -20,6 +20,7 @@
 				<xs:element ref="tokenReplayCache" />
 				<xs:element ref="serviceCertificate" />
 				<xs:element ref="signingKey" />
+				<xs:element ref="tokenDecryptionKey" />
 				<xs:element ref="trustedIssuers" />
 				<xs:element ref="protocol" />
 			</xs:sequence>
@@ -77,6 +78,8 @@
 	<xs:element name="serviceCertificate" type="KeyManagersType" />
 	
 	<xs:element name="signingKey" type="KeyManagersType" />
+	
+	<xs:element name="tokenDecryptionKey" type="KeyManagersType" />
 
 	<xs:element name="protocol" type="protocolType" />
 

Modified: cxf/fediz/trunk/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java?rev=1470962&r1=1470961&r2=1470962&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
(original)
+++ cxf/fediz/trunk/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
Tue Apr 23 13:54:51 2013
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.net.URL;
+import java.util.Collections;
 import java.util.List;
 
 import javax.security.auth.callback.CallbackHandler;
@@ -42,10 +43,13 @@ import org.apache.cxf.fediz.core.config.
 import org.apache.cxf.fediz.core.config.FederationProtocol;
 import org.apache.cxf.fediz.core.exception.ProcessingException;
 import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
 import org.apache.ws.security.WSPasswordCallback;
 import org.apache.ws.security.WSSecurityException;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
 import org.apache.ws.security.saml.ext.AssertionWrapper;
 import org.apache.ws.security.saml.ext.SAMLParms;
 import org.apache.ws.security.saml.ext.bean.ConditionsBean;
@@ -57,7 +61,6 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.opensaml.common.SAMLVersion;
 
-
 import static org.junit.Assert.fail;
 
 public class FederationProcessorTest {
@@ -947,6 +950,88 @@ public class FederationProcessorTest {
         Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
     }
     
+    /**
+     * Validate an encrypted SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateEncryptedSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        cp.setAudienceURI(TEST_AUDIENCE);
+        callbackHandler.setConditions(cp);
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+        
+        String rstr = encryptAndSignToken(assertion);
+        
+        FederationRequest wfReq = new FederationRequest();
+        wfReq.setWa(FederationConstants.ACTION_SIGNIN);
+        wfReq.setWresult(rstr);
+        
+        configurator = null;
+        FederationContext config = 
+            getFederationConfigurator().getFederationContext("ROOT_DECRYPTION");
+        
+        FederationProcessor wfProc = new FederationProcessorImpl();
+        FederationResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    private String encryptAndSignToken(
+        AssertionWrapper assertion
+    ) throws Exception {
+        
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        assertion.signAssertion("mystskey", password, crypto, false);
+        
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        Element token = assertion.toDOM(doc);
+
+        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+        
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("mystskey");
+        
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        builder.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSA15);
+        builder.setEmbedEncryptedKey(true);
+        
+        WSEncryptionPart encryptionPart = new WSEncryptionPart(assertion.getId(), "Element");
+        encryptionPart.setElement(token);
+        
+        Crypto encrCrypto = CryptoFactory.getInstance("signature.properties");
+        builder.prepare(token.getOwnerDocument(), encrCrypto);
+        builder.encryptForRef(null, Collections.singletonList(encryptionPart));
+        
+        // return doc.getDocumentElement();
+        return DOM2Writer.nodeToString(doc);
+    }
     
     private String createSamlToken(AssertionWrapper assertion, String alias, boolean sign)
         throws IOException, UnsupportedCallbackException, WSSecurityException, Exception
{

Modified: cxf/fediz/trunk/plugins/core/src/test/resources/fediz_test_config.xml
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/test/resources/fediz_test_config.xml?rev=1470962&r1=1470961&r2=1470962&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/test/resources/fediz_test_config.xml (original)
+++ cxf/fediz/trunk/plugins/core/src/test/resources/fediz_test_config.xml Tue Apr 23 13:54:51
2013
@@ -206,5 +206,41 @@
 				<claimType type="a particular claim type" optional="true" />
 			</claimTypesRequested>
 		</protocol>
-	</contextConfig>	
+	</contextConfig>
+	
+	<contextConfig name="ROOT_DECRYPTION">
+        <audienceUris>
+            <audienceItem>http://host_one:port/url</audienceItem>
+        </audienceUris>
+        <certificateStores>
+            <trustManager>
+                <keyStore file="stsstore.jks" password="stsspass"
+                    type="JKS" />
+            </trustManager>     
+        </certificateStores>
+        <trustedIssuers>
+            <issuer subject=".*CN=www.sts.com.*" certificateValidation="ChainTrust"
+                name="FedizSTSIssuer" />                
+        </trustedIssuers>
+        <tokenDecryptionKey keyPassword="stskpass">
+             <keyStore file="stsstore.jks" password="stsspass" type="JKS" />
+        </tokenDecryptionKey>
+
+        <maximumClockSkew>1000</maximumClockSkew>
+        <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:type="federationProtocolType" version="1.2">
+            <realm>target realm</realm>
+            <issuer>http://url_to_the_issuer</issuer>
+            <roleDelimiter>;</roleDelimiter>
+            <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+            <authenticationType value="some auth type" type="String" />
+            <homeRealm type="Class">org.apache.fediz.realm.MyHomeRealm.class</homeRealm>
+            <freshness>10000</freshness>
+            <reply>reply value</reply>
+            <request>REQUEST</request>
+            <claimTypesRequested>
+                <claimType type="a particular claim type" optional="true" />
+            </claimTypesRequested>
+        </protocol>
+    </contextConfig>	
 </FedizConfig>



Mime
View raw message