You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2011/10/07 18:07:44 UTC
svn commit: r1180086 - in /cxf/trunk/services/sts/sts-core/src:
main/java/org/apache/cxf/sts/ main/java/org/apache/cxf/sts/token/provider/
main/java/org/apache/cxf/sts/token/validator/
test/java/org/apache/cxf/sts/token/validator/
Author: coheigea
Date: Fri Oct 7 16:07:43 2011
New Revision: 1180086
URL: http://svn.apache.org/viewvc?rev=1180086&view=rev
Log:
[CXF-2850] - SAML and UsernameToken validation should validate the realm of the incoming token against cached tokens
- Patch applied, thanks
Added:
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/CacheSAMLRealmCodec.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorCachedRealmTest.java
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSConstants.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SCTProvider.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSConstants.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSConstants.java?rev=1180086&r1=1180085&r2=1180086&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSConstants.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSConstants.java Fri Oct 7 16:07:43 2011
@@ -124,6 +124,11 @@ public final class STSConstants {
public static final String INVALID_REASON =
"The Trust service did not successfully validate the input";
+ /**
+ * Constant to store the realms in cached Security Token properties.
+ */
+ public static final String TOKEN_REALM = "org.apache.cxf.sts.token.realm";
+
private STSConstants() {
// complete
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java?rev=1180086&r1=1180085&r2=1180086&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java Fri Oct 7 16:07:43 2011
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -127,6 +128,14 @@ public class SAMLTokenProvider implement
hash = Arrays.hashCode(signatureValue);
securityToken.setAssociatedHash(hash);
}
+ if (tokenParameters.getRealm() != null) {
+ Properties props = securityToken.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.setProperty(STSConstants.TOKEN_REALM, tokenParameters.getRealm());
+ securityToken.setProperties(props);
+ }
Integer timeToLive = (int)(conditionsProvider.getLifetime() * 1000);
tokenParameters.getTokenStore().add(securityToken, timeToLive);
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SCTProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SCTProvider.java?rev=1180086&r1=1180085&r2=1180086&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SCTProvider.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SCTProvider.java Fri Oct 7 16:07:43 2011
@@ -19,6 +19,7 @@
package org.apache.cxf.sts.token.provider;
+import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -26,6 +27,7 @@ import org.w3c.dom.Document;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
@@ -131,6 +133,14 @@ public class SCTProvider implements Toke
SecurityToken token = new SecurityToken(sct.getIdentifier());
token.setSecret(keyHandler.getSecret());
token.setPrincipal(tokenParameters.getPrincipal());
+ if (tokenParameters.getRealm() != null) {
+ Properties props = token.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.setProperty(STSConstants.TOKEN_REALM, tokenParameters.getRealm());
+ token.setProperties(props);
+ }
if (lifetime > 0) {
Integer lifetimeInteger = new Integer(Long.valueOf(lifetime).intValue());
tokenParameters.getTokenStore().add(token, lifetimeInteger);
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java?rev=1180086&r1=1180085&r2=1180086&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java Fri Oct 7 16:07:43 2011
@@ -21,6 +21,7 @@ package org.apache.cxf.sts.token.validat
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
+import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -29,6 +30,7 @@ import javax.security.auth.callback.Call
import org.w3c.dom.Element;
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.request.TokenRequirements;
@@ -182,6 +184,16 @@ public class SAMLTokenValidator implemen
String tokenRealm = null;
if (samlRealmCodec != null) {
tokenRealm = samlRealmCodec.getRealmFromToken(assertion);
+ // verify the realm against the cached token
+ if (secToken != null) {
+ Properties props = secToken.getProperties();
+ if (props != null) {
+ String cachedRealm = props.getProperty(STSConstants.TOKEN_REALM);
+ if (!tokenRealm.equals(cachedRealm)) {
+ return response;
+ }
+ }
+ }
}
response.setValid(true);
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java?rev=1180086&r1=1180085&r2=1180086&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java Fri Oct 7 16:07:43 2011
@@ -19,6 +19,7 @@
package org.apache.cxf.sts.token.validator;
import java.security.Principal;
+import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -34,6 +35,7 @@ import org.w3c.dom.Element;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.request.TokenRequirements;
@@ -182,6 +184,16 @@ public class UsernameTokenValidator impl
String tokenRealm = null;
if (usernameTokenRealmCodec != null) {
tokenRealm = usernameTokenRealmCodec.getRealmFromToken(ut);
+ // verify the realm against the cached token
+ if (secToken != null) {
+ Properties props = secToken.getProperties();
+ if (props != null) {
+ String cachedRealm = props.getProperty(STSConstants.TOKEN_REALM);
+ if (!tokenRealm.equals(cachedRealm)) {
+ return response;
+ }
+ }
+ }
}
response.setPrincipal(principal);
Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/CacheSAMLRealmCodec.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/CacheSAMLRealmCodec.java?rev=1180086&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/CacheSAMLRealmCodec.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/CacheSAMLRealmCodec.java Fri Oct 7 16:07:43 2011
@@ -0,0 +1,44 @@
+/**
+ * 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.sts.token.validator;
+
+import org.apache.cxf.sts.token.realm.SAMLRealmCodec;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+
+
+/**
+ * This class returns a realm associated with a SAML Assertion depending on the issuer.
+ */
+public class CacheSAMLRealmCodec implements SAMLRealmCodec {
+
+ /**
+ * Get the realm associated with the AssertionWrapper parameter
+ * @param assertion a SAML Assertion wrapper object
+ * @return the realm associated with the AssertionWrapper parameter
+ */
+ public String getRealmFromToken(AssertionWrapper assertion) {
+ if ("A-Issuer".equals(assertion.getIssuerString())) {
+ return "C";
+ } else if ("B-Issuer".equals(assertion.getIssuerString())) {
+ return "D";
+ }
+ return null;
+ }
+}
Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorCachedRealmTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorCachedRealmTest.java?rev=1180086&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorCachedRealmTest.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorCachedRealmTest.java Fri Oct 7 16:07:43 2011
@@ -0,0 +1,247 @@
+/**
+ * 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.sts.token.validator;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.jaxws.context.WebServiceContextImpl;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.cache.DefaultInMemoryTokenStore;
+import org.apache.cxf.sts.cache.STSTokenStore;
+import org.apache.cxf.sts.common.PasswordCallbackHandler;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProviderParameters;
+import org.apache.cxf.sts.token.provider.TokenProviderResponse;
+import org.apache.cxf.sts.token.realm.SAMLRealm;
+import org.apache.cxf.sts.token.realm.SAMLRealmCodec;
+import org.apache.ws.security.CustomTokenPrincipal;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.junit.BeforeClass;
+
+
+/**
+ * Some unit tests for validating a SAML token with a realm against the cached tokens realm.
+ */
+public class SAMLTokenValidatorCachedRealmTest extends org.junit.Assert {
+
+ private static STSTokenStore tokenStore;
+
+ @BeforeClass
+ public static void init() {
+ tokenStore = new DefaultInMemoryTokenStore();
+ }
+
+ /**
+ * Test a SAML Assertion with valid cached realm.
+ */
+ @org.junit.Test
+ public void testValidCachedRealm() throws Exception {
+ TokenValidator samlTokenValidator = new SAMLTokenValidator();
+ TokenValidatorParameters validatorParameters = createValidatorParameters();
+ TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
+
+ // Create a ValidateTarget consisting of a SAML Assertion
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler, "A");
+ Document doc = samlToken.getOwnerDocument();
+ samlToken = (Element)doc.appendChild(samlToken);
+
+ ReceivedToken validateTarget = new ReceivedToken(samlToken);
+ tokenRequirements.setValidateTarget(validateTarget);
+
+ // Now set the SAMLRealmCodec implementation on the Validator
+ SAMLRealmCodec samlRealmCodec = new IssuerSAMLRealmCodec();
+ ((SAMLTokenValidator)samlTokenValidator).setSamlRealmCodec(samlRealmCodec);
+
+ TokenValidatorResponse validatorResponse = samlTokenValidator.validateToken(validatorParameters);
+ assertTrue(validatorResponse != null);
+ assertTrue(validatorResponse.isValid());
+ assertTrue(validatorResponse.getTokenRealm().equals("A"));
+
+ }
+
+ /**
+ * Test a SAML Assertion with invalid cached realm.
+ */
+ @org.junit.Test
+ public void testInValidCachedRealm() throws Exception {
+ TokenValidator samlTokenValidator = new SAMLTokenValidator();
+ TokenValidatorParameters validatorParameters = createValidatorParameters();
+ TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
+
+ // Create a ValidateTarget consisting of a SAML Assertion
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler, "A");
+ Document doc = samlToken.getOwnerDocument();
+ samlToken = (Element)doc.appendChild(samlToken);
+
+ ReceivedToken validateTarget = new ReceivedToken(samlToken);
+ tokenRequirements.setValidateTarget(validateTarget);
+
+ // Now set the SAMLRealmCodec implementation on the Validator
+ SAMLRealmCodec samlRealmCodec = new CacheSAMLRealmCodec();
+ ((SAMLTokenValidator)samlTokenValidator).setSamlRealmCodec(samlRealmCodec);
+
+ TokenValidatorResponse validatorResponse = samlTokenValidator.validateToken(validatorParameters);
+ assertTrue(validatorResponse != null);
+ assertFalse(validatorResponse.isValid());
+ assertNull(validatorResponse.getTokenRealm());
+
+ }
+
+ private TokenValidatorParameters createValidatorParameters() throws WSSecurityException {
+ TokenValidatorParameters parameters = new TokenValidatorParameters();
+
+ TokenRequirements tokenRequirements = new TokenRequirements();
+ tokenRequirements.setTokenType(STSConstants.STATUS);
+ parameters.setTokenRequirements(tokenRequirements);
+
+ KeyRequirements keyRequirements = new KeyRequirements();
+ parameters.setKeyRequirements(keyRequirements);
+
+ parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+ parameters.setWebServiceContext(webServiceContext);
+
+ // Add STSProperties object
+ StaticSTSProperties stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setEncryptionCrypto(crypto);
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS-2");
+ parameters.setStsProperties(stsProperties);
+ parameters.setTokenStore(tokenStore);
+ return parameters;
+ }
+
+ private Element createSAMLAssertion(
+ String tokenType,
+ Crypto crypto,
+ String signatureUsername,
+ CallbackHandler callbackHandler,
+ String realm
+ ) throws WSSecurityException {
+ TokenProvider samlTokenProvider = new SAMLTokenProvider();
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ tokenType, STSConstants.BEARER_KEY_KEYTYPE, crypto, signatureUsername, callbackHandler
+ );
+ providerParameters.setRealm(realm);
+
+ // Create Realms
+ Map<String, SAMLRealm> samlRealms = getSamlRealms();
+ ((SAMLTokenProvider)samlTokenProvider).setRealmMap(samlRealms);
+
+ TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ return providerResponse.getToken();
+ }
+
+ private Map<String, SAMLRealm> getSamlRealms() {
+ // Create Realms
+ Map<String, SAMLRealm> samlRealms = new HashMap<String, SAMLRealm>();
+ SAMLRealm samlRealm = new SAMLRealm();
+ samlRealm.setIssuer("A-Issuer");
+ samlRealms.put("A", samlRealm);
+ samlRealm = new SAMLRealm();
+ samlRealm.setIssuer("B-Issuer");
+ samlRealms.put("B", samlRealm);
+ return samlRealms;
+ }
+
+ private TokenProviderParameters createProviderParameters(
+ String tokenType, String keyType, Crypto crypto,
+ String signatureUsername, CallbackHandler callbackHandler
+ ) throws WSSecurityException {
+ TokenProviderParameters parameters = new TokenProviderParameters();
+
+ TokenRequirements tokenRequirements = new TokenRequirements();
+ tokenRequirements.setTokenType(tokenType);
+ parameters.setTokenRequirements(tokenRequirements);
+
+ KeyRequirements keyRequirements = new KeyRequirements();
+ keyRequirements.setKeyType(keyType);
+ parameters.setKeyRequirements(keyRequirements);
+
+ parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+ parameters.setWebServiceContext(webServiceContext);
+
+ parameters.setAppliesToAddress("http://dummy-service.com/dummy");
+
+ // Add STSProperties object
+ StaticSTSProperties stsProperties = new StaticSTSProperties();
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setSignatureUsername(signatureUsername);
+ stsProperties.setCallbackHandler(callbackHandler);
+ stsProperties.setIssuer("STS");
+ parameters.setStsProperties(stsProperties);
+
+ parameters.setEncryptionProperties(new EncryptionProperties());
+ parameters.setTokenStore(tokenStore);
+ return parameters;
+ }
+
+ private Properties getEncryptionProperties() {
+ Properties properties = new Properties();
+ properties.put(
+ "org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin"
+ );
+ properties.put("org.apache.ws.security.crypto.merlin.keystore.password", "stsspass");
+ properties.put("org.apache.ws.security.crypto.merlin.keystore.file", "stsstore.jks");
+
+ return properties;
+ }
+
+
+}
\ No newline at end of file