KEYCLOAK-4315 Remove some dead/duplicate classes

This commit is contained in:
Hynek Mlnarik 2018-01-23 12:24:09 +01:00 committed by Marek Posolda
parent 5d5373454c
commit 84ea3f8cb1
24 changed files with 203 additions and 1563 deletions

View file

@ -32,6 +32,7 @@
<properties> <properties>
<timestamp>${maven.build.timestamp}</timestamp> <timestamp>${maven.build.timestamp}</timestamp>
<skip.security-manager.tests>true</skip.security-manager.tests>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format> <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties> </properties>
<dependencies> <dependencies>
@ -56,7 +57,6 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -88,6 +88,35 @@
<target>${maven.compiler.target}</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>without-security-manager</id>
<goals><goal>test</goal></goals>
<configuration></configuration>
</execution>
<execution>
<id>with-security-manager-all-permissions</id>
<goals><goal>test</goal></goals>
<configuration>
<argLine>-Dmaven.basedir=${basedir} -Djava.security.manager -Djava.security.policy=${basedir}/src/test/resources/all-permissions.policy</argLine>
<test>SecurityActionsTest</test>
<skip>${skip.security-manager.tests}</skip>
</configuration>
</execution>
<execution>
<id>with-security-manager-named-permissions</id>
<goals><goal>test</goal></goals>
<configuration>
<argLine>-Djava.security.debug=access -Dmaven.basedir=${basedir} -Djava.security.manager -Djava.security.policy=${basedir}/src/test/resources/named-permissions.policy</argLine>
<test>SecurityActionsTest</test>
<skip>${skip.security-manager.tests}</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>

View file

@ -19,6 +19,7 @@ package org.keycloak.saml.common.util;
import java.net.URL; import java.net.URL;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.PropertyPermission;
/** /**
* Privileged Blocks * Privileged Blocks
@ -28,6 +29,14 @@ import java.security.PrivilegedAction;
*/ */
public class SecurityActions { public class SecurityActions {
private static String extractPackageNameFromClassName(final String fullyQualifiedName) {
final int lastDot = fullyQualifiedName.lastIndexOf('.');
if (lastDot == -1) {
return "";
}
return fullyQualifiedName.substring(0, lastDot);
}
/** /**
* <p> Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from * <p> Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
* the specified {@link Class}, if not found it will try to load from using TCL. </p> * the specified {@link Class}, if not found it will try to load from using TCL. </p>
@ -37,11 +46,17 @@ public class SecurityActions {
* *
* @return * @return
*/ */
static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) { public static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (fullQualifiedName == null) {
return null;
}
if (sm != null) { if (sm != null) {
sm.checkPackageDefinition(extractPackageNameFromClassName(fullQualifiedName));
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() { public Class<?> run() {
ClassLoader classLoader = theClass.getClassLoader(); ClassLoader classLoader = theClass.getClassLoader();
@ -73,11 +88,17 @@ public class SecurityActions {
* *
* @return * @return
*/ */
static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) { public static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (fullQualifiedName == null) {
return null;
}
if (sm != null) { if (sm != null) {
sm.checkPackageDefinition(extractPackageNameFromClassName(fullQualifiedName));
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() { public Class<?> run() {
try { try {
return classLoader.loadClass(fullQualifiedName); return classLoader.loadClass(fullQualifiedName);
@ -103,13 +124,14 @@ public class SecurityActions {
* *
* @return * @return
*/ */
static URL loadResource(final Class<?> clazz, final String resourceName) { public static URL loadResource(final Class<?> clazz, final String resourceName) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<URL>() { return AccessController.doPrivileged(new PrivilegedAction<URL>() {
@Override
public URL run() { public URL run() {
URL url = null; URL url;
ClassLoader clazzLoader = clazz.getClassLoader(); ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName); url = clazzLoader.getResource(resourceName);
@ -122,7 +144,7 @@ public class SecurityActions {
} }
}); });
} else { } else {
URL url = null; URL url;
ClassLoader clazzLoader = clazz.getClassLoader(); ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName); url = clazzLoader.getResource(resourceName);
@ -143,11 +165,13 @@ public class SecurityActions {
* *
* @return * @return
*/ */
static void setSystemProperty(final String key, final String value) { public static void setSystemProperty(final String key, final String value) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
sm.checkPermission(new PropertyPermission(key, "write"));
AccessController.doPrivileged(new PrivilegedAction<Object>() { AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() { public Object run() {
System.setProperty(key, value); System.setProperty(key, value);
return null; return null;
@ -167,11 +191,13 @@ public class SecurityActions {
* *
* @return * @return
*/ */
static String getSystemProperty(final String key, final String defaultValue) { public static String getSystemProperty(final String key, final String defaultValue) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
sm.checkPermission(new PropertyPermission(key, "read"));
return AccessController.doPrivileged(new PrivilegedAction<String>() { return AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() { public String run() {
return System.getProperty(key, defaultValue); return System.getProperty(key, defaultValue);
} }
@ -188,7 +214,9 @@ public class SecurityActions {
*/ */
public static ClassLoader getTCCL() { public static ClassLoader getTCCL() {
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
System.getSecurityManager().checkPermission(new RuntimePermission("getClassLoader"));
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() { public ClassLoader run() {
return Thread.currentThread().getContextClassLoader(); return Thread.currentThread().getContextClassLoader();
} }
@ -205,7 +233,9 @@ public class SecurityActions {
*/ */
public static void setTCCL(final ClassLoader paramCl) { public static void setTCCL(final ClassLoader paramCl) {
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
System.getSecurityManager().checkPermission(new RuntimePermission("setContextClassLoader"));
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() { public Void run() {
Thread.currentThread().setContextClassLoader(paramCl); Thread.currentThread().setContextClassLoader(paramCl);
return null; return null;

View file

@ -46,7 +46,7 @@ public class StaxUtil {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private static ThreadLocal<Stack<String>> registeredNSStack = new ThreadLocal<Stack<String>>(); private static final ThreadLocal<Stack<String>> registeredNSStack = new ThreadLocal<Stack<String>>();
/** /**
* Flush the stream writer * Flush the stream writer
@ -341,10 +341,10 @@ public class StaxUtil {
writeStartElement(writer, domElementPrefix, domElement.getLocalName(), domElementNS); writeStartElement(writer, domElementPrefix, domElement.getLocalName(), domElementNS);
// Should we register namespace // Should we register namespace
if (domElementPrefix != "" && !registeredNSStack.get().contains(domElementNS)) { if (! domElementPrefix.isEmpty() && !registeredNSStack.get().contains(domElementNS)) {
// writeNameSpace(writer, domElementPrefix, domElementNS ); // writeNameSpace(writer, domElementPrefix, domElementNS );
registeredNSStack.get().push(domElementNS); registeredNSStack.get().push(domElementNS);
} else if (domElementPrefix == "" && domElementNS != null) { } else if (domElementPrefix.isEmpty() && ! domElementNS.isEmpty()) {
writeNameSpace(writer, "xmlns", domElementNS); writeNameSpace(writer, "xmlns", domElementNS);
} }

View file

@ -59,55 +59,6 @@ public class StringUtil {
return str == null || str.isEmpty(); return str == null || str.isEmpty();
} }
private static final Pattern PROPERTY_REPLACEMENT = Pattern.compile("(.*?)" + "\\$\\{(.*?)" + "(?:::(.*?))?\\}");
// 1: PREFIX | START 2: NAME | 3: OPTIONAL DEFAULT VALUE
/**
* <p>
* Get the system property value if the string is of the format ${sysproperty}
* </p>
* <p>
* You can insert default value when the system property is not set, by separating it at the beginning with ::
* </p>
* <p>
* <b>Examples:</b>
* </p>
*
* <p>
* ${idp} should resolve to a value if the system property "idp" is set.
* </p>
* <p>
* ${idp::http://localhost:8080} will resolve to http://localhost:8080 if the system property "idp" is not set.
* </p>
*
* @param str
*
* @return
*/
public static String getSystemPropertyAsString(String str) {
if (str == null)
throw logger.nullArgumentError("str");
Matcher m = PROPERTY_REPLACEMENT.matcher(str);
StringBuilder sb = new StringBuilder();
int lastPosition = 0;
while (m.find()) {
String propertyName = m.group(2);
String defaultValue = m.group(3);
String sysPropertyValue = SecurityActions.getSystemProperty(propertyName, defaultValue);
if (sysPropertyValue.isEmpty()) {
throw logger.systemPropertyMissingError(propertyName);
}
sb.append(m.group(1)).append(sysPropertyValue);
lastPosition = m.end();
}
return sb.append(str.substring(lastPosition)).toString();
}
/** /**
* Match two strings else throw a {@link RuntimeException} * Match two strings else throw a {@link RuntimeException}
* *
@ -118,67 +69,4 @@ public class StringUtil {
if (!first.equals(second)) if (!first.equals(second))
throw logger.notEqualError(first, second); throw logger.notEqualError(first, second);
} }
/**
* Given a comma separated string, get the tokens as a {@link List}
*
* @param str
*
* @return
*/
public static List<String> tokenize(String str) {
return tokenize(str, ",");
}
/**
* Given a delimited string, get the tokens as a {@link List}
*
* @param str
* @param delimiter the delimiter
*
* @return
*/
public static List<String> tokenize(String str, String delimiter) {
List<String> list = new ArrayList<String>();
StringTokenizer tokenizer = new StringTokenizer(str, delimiter);
while (tokenizer.hasMoreTokens()) {
list.add(tokenizer.nextToken());
}
return list;
}
/**
* Given a string that is comma delimited and contains key-value pairs
*
* @param keyValuePairString
*
* @return
*/
public static Map<String, String> tokenizeKeyValuePair(String keyValuePairString) {
Map<String, String> map = new HashMap<String, String>();
List<String> tokens = tokenize(keyValuePairString);
for (String token : tokens) {
int location = token.indexOf('=');
map.put(token.substring(0, location), token.substring(location + 1));
}
return map;
}
public static String[] split(String toSplit, String delimiter) {
if (delimiter.length() != 1) {
throw new IllegalArgumentException("Delimiter can only be one character in length");
}
int offset = toSplit.indexOf(delimiter);
if (offset < 0) {
return null;
}
String beforeDelimiter = toSplit.substring(0, offset);
String afterDelimiter = toSplit.substring(offset + 1);
return new String[]{beforeDelimiter, afterDelimiter};
}
} }

View file

@ -1,93 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.parsers.util;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Privileged Blocks
*
* @author Anil.Saldhana@redhat.com
* @since Oct 25, 2010
*/
public class SecurityActions {
/**
* <p>Returns a system property value using the specified <code>key</code>. If not found the
* <code>defaultValue</code> will be returned.</p>
*
* @param key
* @param defaultValue
*
* @return
*/
static String getSystemProperty(final String key, final String defaultValue) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key, defaultValue);
}
});
} else {
return System.getProperty(key, defaultValue);
}
}
/**
* Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
*
* @param clazz
* @param resourceName
*
* @return
*/
static URL loadResource(final Class<?> clazz, final String resourceName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<URL>() {
public URL run() {
URL url = null;
ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName);
if (url == null) {
clazzLoader = Thread.currentThread().getContextClassLoader();
url = clazzLoader.getResource(resourceName);
}
return url;
}
});
} else {
URL url = null;
ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName);
if (url == null) {
clazzLoader = Thread.currentThread().getContextClassLoader();
url = clazzLoader.getResource(resourceName);
}
return url;
}
}
}

View file

@ -1,160 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.saml.v2.util;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Privileged Blocks
*
* @author Anil.Saldhana@redhat.com
* @since Dec 9, 2008
*/
class SecurityActions {
/**
* <p>
* Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
* the
* specified {@link Class}, if not found it will try to load from using TCL.
* </p>
*
* @param theClass
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
});
} else {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
}
/**
* <p>
* Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
* </p>
*
* @param classLoader
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
});
} else {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
}
/**
* <p>Returns a system property value using the specified <code>key</code>. If not found the
* <code>defaultValue</code> will be returned.</p>
*
* @param key
* @param defaultValue
*
* @return
*/
static String getSystemProperty(final String key, final String defaultValue) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key, defaultValue);
}
});
} else {
return System.getProperty(key, defaultValue);
}
}
/**
* Get the Thread Context ClassLoader
*
* @return
*/
static ClassLoader getTCCL() {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
} else {
return Thread.currentThread().getContextClassLoader();
}
}
/**
* Set the Thread Context ClassLoader
*
* @param paramCl
*/
static void setTCCL(final ClassLoader paramCl) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
Thread.currentThread().setContextClassLoader(paramCl);
return null;
}
});
} else {
Thread.currentThread().setContextClassLoader(paramCl);
}
}
}

View file

@ -21,6 +21,7 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.SecurityActions;
import org.keycloak.saml.common.util.SystemPropertiesUtil; import org.keycloak.saml.common.util.SystemPropertiesUtil;
import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConfigurationException;

View file

@ -1,208 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.util;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType.EDTChoiceType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType.EDTDescriptorChoiceType;
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import java.util.List;
/**
* Utility for configuration
*
* @author Anil.Saldhana@redhat.com
* @since Nov 13, 2009
*/
public class CoreConfigUtil {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
/**
* Get the first metadata descriptor for an IDP
*
* @param entitiesDescriptor
*
* @return
*/
public static IDPSSODescriptorType getIDPDescriptor(EntitiesDescriptorType entitiesDescriptor) {
IDPSSODescriptorType idp = null;
List<Object> entitiesList = entitiesDescriptor.getEntityDescriptor();
for (Object theObject : entitiesList) {
if (theObject instanceof EntitiesDescriptorType) {
idp = getIDPDescriptor((EntitiesDescriptorType) theObject);
} else if (theObject instanceof EntityDescriptorType) {
idp = getIDPDescriptor((EntityDescriptorType) theObject);
}
if (idp != null) {
break;
}
}
return idp;
}
/**
* Get the IDP metadata descriptor from an entity descriptor
*
* @param entityDescriptor
*
* @return
*/
public static IDPSSODescriptorType getIDPDescriptor(EntityDescriptorType entityDescriptor) {
List<EDTChoiceType> edtChoices = entityDescriptor.getChoiceType();
for (EDTChoiceType edt : edtChoices) {
List<EDTDescriptorChoiceType> edtDescriptors = edt.getDescriptors();
for (EDTDescriptorChoiceType edtDesc : edtDescriptors) {
IDPSSODescriptorType idpSSO = edtDesc.getIdpDescriptor();
if (idpSSO != null) {
return idpSSO;
}
}
}
return null;
}
/**
* Get the SP Descriptor from an entity descriptor
*
* @param entityDescriptor
*
* @return
*/
public static SPSSODescriptorType getSPDescriptor(EntityDescriptorType entityDescriptor) {
List<EDTChoiceType> edtChoices = entityDescriptor.getChoiceType();
for (EDTChoiceType edt : edtChoices) {
List<EDTDescriptorChoiceType> edtDescriptors = edt.getDescriptors();
for (EDTDescriptorChoiceType edtDesc : edtDescriptors) {
SPSSODescriptorType spSSO = edtDesc.getSpDescriptor();
if (spSSO != null) {
return spSSO;
}
}
}
return null;
}
/**
* Given a binding uri, get the IDP identity url
*
* @param idp
* @param bindingURI
*
* @return
*/
public static String getIdentityURL(IDPSSODescriptorType idp, String bindingURI) {
String identityURL = null;
List<EndpointType> endpoints = idp.getSingleSignOnService();
for (EndpointType endpoint : endpoints) {
if (endpoint.getBinding().toString().equals(bindingURI)) {
identityURL = endpoint.getLocation().toString();
break;
}
}
return identityURL;
}
/**
* Given a binding uri, get the IDP identity url
*
* @param idp
* @param bindingURI
*
* @return
*/
public static String getLogoutURL(IDPSSODescriptorType idp, String bindingURI) {
String logoutURL = null;
List<EndpointType> endpoints = idp.getSingleLogoutService();
for (EndpointType endpoint : endpoints) {
if (endpoint.getBinding().toString().equals(bindingURI)) {
logoutURL = endpoint.getLocation().toString();
break;
}
}
return logoutURL;
}
/**
* Given a binding uri, get the IDP logout response url (used for global logouts)
*/
public static String getLogoutResponseLocation(IDPSSODescriptorType idp, String bindingURI) {
String logoutResponseLocation = null;
List<EndpointType> endpoints = idp.getSingleLogoutService();
for (EndpointType endpoint : endpoints) {
if (endpoint.getBinding().toString().equals(bindingURI)) {
if (endpoint.getResponseLocation() != null) {
logoutResponseLocation = endpoint.getResponseLocation().toString();
} else {
logoutResponseLocation = null;
}
break;
}
}
return logoutResponseLocation;
}
/**
* Get the service url for the SP
*
* @param sp
* @param bindingURI
*
* @return
*/
public static String getServiceURL(SPSSODescriptorType sp, String bindingURI) {
String serviceURL = null;
List<IndexedEndpointType> endpoints = sp.getAssertionConsumerService();
for (IndexedEndpointType endpoint : endpoints) {
if (endpoint.getBinding().toString().equals(bindingURI)) {
serviceURL = endpoint.getLocation().toString();
break;
}
}
return serviceURL;
}
private static void addAllEntityDescriptorsRecursively(List<EntityDescriptorType> resultList,
EntitiesDescriptorType entitiesDescriptorType) {
List<Object> entities = entitiesDescriptorType.getEntityDescriptor();
for (Object o : entities) {
if (o instanceof EntitiesDescriptorType) {
addAllEntityDescriptorsRecursively(resultList, (EntitiesDescriptorType) o);
} else if (o instanceof EntityDescriptorType) {
resultList.add((EntityDescriptorType) o);
} else {
throw new IllegalArgumentException("Wrong type: " + o.getClass());
}
}
}
}

View file

@ -1,49 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.util;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.GeneralSecurityException;
/**
* Utility to generate symmetric key
*
* @author Anil.Saldhana@redhat.com
* @since Feb 4, 2009
*/
public class EncryptionKeyUtil {
/**
* Generate a secret key useful for encryption/decryption
*
* @param encAlgo
* @param keySize Length of the key (if 0, defaults to 128 bits)
*
* @return
*
* @throws GeneralSecurityException
*/
public static SecretKey getSecretKey(String encAlgo, int keySize) throws GeneralSecurityException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(encAlgo);
if (keySize == 0)
keySize = 128;
keyGenerator.init(keySize);
return keyGenerator.generateKey();
}
}

View file

@ -16,6 +16,7 @@
*/ */
package org.keycloak.saml.processing.core.util; package org.keycloak.saml.processing.core.util;
import org.keycloak.saml.common.util.SecurityActions;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;

View file

@ -20,6 +20,7 @@ import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.util.SecurityActions;
import org.xml.sax.ErrorHandler; import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; import org.xml.sax.SAXParseException;
@ -48,7 +49,7 @@ public class JAXBUtil {
public static final String W3C_XML_SCHEMA_NS_URI = "http://www.w3.org/2001/XMLSchema"; public static final String W3C_XML_SCHEMA_NS_URI = "http://www.w3.org/2001/XMLSchema";
private static HashMap<String, JAXBContext> jaxbContextHash = new HashMap<String, JAXBContext>(); private static final HashMap<String, JAXBContext> jaxbContextHash = new HashMap<String, JAXBContext>();
static { static {
// Useful on Sun VMs. Harmless on other VMs. // Useful on Sun VMs. Harmless on other VMs.

View file

@ -21,6 +21,7 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.DocumentUtil; import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.SecurityActions;
import org.keycloak.saml.common.util.SystemPropertiesUtil; import org.keycloak.saml.common.util.SystemPropertiesUtil;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler; import org.xml.sax.ErrorHandler;

View file

@ -1,184 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.util;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
/**
* Utility to handle Java Keystore
*
* @author Anil.Saldhana@redhat.com
* @since Jan 12, 2009
*/
public class KeyStoreUtil {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
/**
* Get the KeyStore
*
* @param keyStoreFile
* @param storePass
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static KeyStore getKeyStore(File keyStoreFile, char[] storePass) throws GeneralSecurityException, IOException {
FileInputStream fis = new FileInputStream(keyStoreFile);
return getKeyStore(fis, storePass);
}
/**
* Get the Keystore given the url to the keystore file as a string
*
* @param fileURL
* @param storePass
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static KeyStore getKeyStore(String fileURL, char[] storePass) throws GeneralSecurityException, IOException {
if (fileURL == null)
throw logger.nullArgumentError("fileURL");
File file = new File(fileURL);
FileInputStream fis = new FileInputStream(file);
return getKeyStore(fis, storePass);
}
/**
* Get the Keystore given the URL to the keystore
*
* @param url
* @param storePass
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static KeyStore getKeyStore(URL url, char[] storePass) throws GeneralSecurityException, IOException {
if (url == null)
throw logger.nullArgumentError("url");
return getKeyStore(url.openStream(), storePass);
}
/**
* Get the Key Store <b>Note:</b> This method wants the InputStream to be not null.
*
* @param ksStream
* @param storePass
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
* @throws IllegalArgumentException if ksStream is null
*/
public static KeyStore getKeyStore(InputStream ksStream, char[] storePass) throws GeneralSecurityException, IOException {
if (ksStream == null)
throw logger.nullArgumentError("InputStream for the KeyStore");
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(ksStream, storePass);
return ks;
}
/**
* Get the Public Key from the keystore
*
* @param ks
* @param alias
* @param password
*
* @return
*
* @throws GeneralSecurityException
*/
public static PublicKey getPublicKey(KeyStore ks, String alias, char[] password) throws GeneralSecurityException {
PublicKey publicKey = null;
// Get private key
Key key = ks.getKey(alias, password);
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = ks.getCertificate(alias);
// Get public key
publicKey = cert.getPublicKey();
}
// if alias is a certificate alias, get the public key from the certificate.
if (publicKey == null) {
Certificate cert = ks.getCertificate(alias);
if (cert != null)
publicKey = cert.getPublicKey();
}
return publicKey;
}
/**
* Add a certificate to the KeyStore
*
* @param keystoreFile
* @param storePass
* @param alias
* @param cert
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static void addCertificate(File keystoreFile, char[] storePass, String alias, Certificate cert)
throws GeneralSecurityException, IOException {
KeyStore keystore = getKeyStore(keystoreFile, storePass);
// Add the certificate
keystore.setCertificateEntry(alias, cert);
// Save the new keystore contents
FileOutputStream out = null;
try {
out = new FileOutputStream(keystoreFile);
keystore.store(out, storePass);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
}

View file

@ -19,6 +19,7 @@ package org.keycloak.saml.processing.core.util;
import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.util.SecurityActions;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.Provider; import java.security.Provider;

View file

@ -1,224 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.core.util;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Privileged Blocks
*
* @author Anil.Saldhana@redhat.com
* @since Dec 9, 2008
*/
class SecurityActions {
/**
* <p>
* Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
* the
* specified {@link Class}, if not found it will try to load from using TCL.
* </p>
*
* @param theClass
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
});
} else {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
}
/**
* <p>
* Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
* </p>
*
* @param classLoader
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
});
} else {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
}
/**
* Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
*
* @param clazz
* @param resourceName
*
* @return
*/
static URL loadResource(final Class<?> clazz, final String resourceName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<URL>() {
public URL run() {
URL url = null;
ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName);
if (url == null) {
clazzLoader = Thread.currentThread().getContextClassLoader();
url = clazzLoader.getResource(resourceName);
}
return url;
}
});
} else {
URL url = null;
ClassLoader clazzLoader = clazz.getClassLoader();
url = clazzLoader.getResource(resourceName);
if (url == null) {
clazzLoader = Thread.currentThread().getContextClassLoader();
url = clazzLoader.getResource(resourceName);
}
return url;
}
}
/**
* Set the system property
*
* @param key
* @param defaultValue
*
* @return
*/
static void setSystemProperty(final String key, final String value) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
System.setProperty(key, value);
return null;
}
});
} else {
System.setProperty(key, value);
}
}
/**
* <p>Returns a system property value using the specified <code>key</code>. If not found the
* <code>defaultValue</code> will be returned.</p>
*
* @param key
* @param defaultValue
*
* @return
*/
static String getSystemProperty(final String key, final String defaultValue) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key, defaultValue);
}
});
} else {
return System.getProperty(key, defaultValue);
}
}
/**
* Get the Thread Context ClassLoader
*
* @return
*/
static ClassLoader getTCCL() {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
} else {
return Thread.currentThread().getContextClassLoader();
}
}
/**
* Set the Thread Context ClassLoader
*
* @param paramCl
*/
static void setTCCL(final ClassLoader paramCl) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
Thread.currentThread().setContextClassLoader(paramCl);
return null;
}
});
} else {
Thread.currentThread().setContextClassLoader(paramCl);
}
}
}

View file

@ -88,6 +88,7 @@ import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext; import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dsig.keyinfo.KeyName; import javax.xml.crypto.dsig.keyinfo.KeyName;
import org.keycloak.rotation.KeyLocator; import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.common.util.SecurityActions;
import org.keycloak.saml.processing.api.util.KeyInfoTools; import org.keycloak.saml.processing.api.util.KeyInfoTools;
/** /**

View file

@ -1,344 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.web.util;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
import org.keycloak.saml.processing.core.saml.v2.util.SignatureUtil;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import static org.keycloak.saml.common.util.StringUtil.isNotNull;
/**
* Signature Support for the HTTP/Redirect binding
*
* @author Anil.Saldhana@redhat.com
* @since Dec 16, 2008
*/
public class RedirectBindingSignatureUtil {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
/**
* Get the URL for the SAML request that contains the signature and signature algorithm
*
* @param authRequest
* @param relayState
* @param signingKey
*
* @return
*
* @throws SAXException
* @throws IOException
* @throws GeneralSecurityException
*/
public static String getSAMLRequestURLWithSignature(AuthnRequestType authRequest, String relayState, PrivateKey signingKey)
throws SAXException, IOException, GeneralSecurityException {
SAML2Request saml2Request = new SAML2Request();
// Deal with the original request
StringWriter sw = new StringWriter();
saml2Request.marshall(authRequest, sw);
// URL Encode the Request
String urlEncodedRequest = RedirectBindingUtil.deflateBase64URLEncode(sw.toString());
String urlEncodedRelayState = null;
if (isNotNull(relayState))
urlEncodedRelayState = URLEncoder.encode(relayState, GeneralConstants.SAML_CHARSET_NAME);
byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
signingKey);
// Now construct the URL
return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState, sigValue, signingKey.getAlgorithm());
}
/**
* Get the URL for the SAML request that contains the signature and signature algorithm
*
* @param responseType
* @param relayState
* @param signingKey
*
* @return
*
* @throws IOException
* @throws GeneralSecurityException
*/
public static String getSAMLResponseURLWithSignature(ResponseType responseType, String relayState, PrivateKey signingKey)
throws IOException, GeneralSecurityException {
SAML2Response saml2Response = new SAML2Response();
Document responseDoc = saml2Response.convert(responseType);
// URL Encode the Request
String responseString = DocumentUtil.getDocumentAsString(responseDoc);
String urlEncodedResponse = RedirectBindingUtil.deflateBase64URLEncode(responseString);
String urlEncodedRelayState = null;
if (isNotNull(relayState))
urlEncodedRelayState = URLEncoder.encode(relayState, GeneralConstants.SAML_CHARSET_NAME);
byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
signingKey);
// Now construct the URL
return getResponseRedirectURLWithSignature(urlEncodedResponse, urlEncodedRelayState, sigValue,
signingKey.getAlgorithm());
}
/**
* Given an url-encoded saml request and relay state and a private key, compute the url
*
* @param urlEncodedRequest
* @param urlEncodedRelayState
* @param signingKey
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static String getSAMLRequestURLWithSignature(String urlEncodedRequest, String urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException {
byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
signingKey);
return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState, sigValue, signingKey.getAlgorithm());
}
/**
* Given an url-encoded saml response and relay state and a private key, compute the url
*
* @param urlEncodedResponse
* @param urlEncodedRelayState
* @param signingKey
*
* @return
*
* @throws GeneralSecurityException
* @throws IOException
*/
public static String getSAMLResponseURLWithSignature(String urlEncodedResponse, String urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException {
byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
signingKey);
return getResponseRedirectURLWithSignature(urlEncodedResponse, urlEncodedRelayState, sigValue,
signingKey.getAlgorithm());
}
/**
* From the SAML Request URL, get the Request object
*
* @param signedURL
*
* @return
*
* @throws IOException
* @throws ParsingException
* @throws org.keycloak.saml.common.exceptions.ProcessingException
* @throws ConfigurationException
*/
public static AuthnRequestType getRequestFromSignedURL(String signedURL) throws ConfigurationException,
ProcessingException, ParsingException, IOException {
String samlRequestTokenValue = getTokenValue(signedURL, GeneralConstants.SAML_REQUEST_KEY);
SAML2Request saml2Request = new SAML2Request();
return saml2Request.getAuthnRequestType(RedirectBindingUtil.urlBase64DeflateDecode(samlRequestTokenValue));
}
/**
* Get the signature value from the url
*
* @param signedURL
*
* @return
*
* @throws IOException
*/
public static byte[] getSignatureValueFromSignedURL(String signedURL) throws IOException {
String sigValueTokenValue = getTokenValue(signedURL, GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
if (sigValueTokenValue == null)
throw new IllegalStateException(logger.samlHandlerSignatureNotPresentError());
return RedirectBindingUtil.urlBase64Decode(sigValueTokenValue);
}
/**
* From the query string that contains key/value pairs, get the value of a key <b>Note:</b> if the token is null, a
* null
* value is returned
*
* @param queryString
* @param token
*
* @return
*/
public static String getTokenValue(String queryString, String token) {
return getTokenValue(getToken(queryString, token));
}
public static boolean validateSignature(String queryString, PublicKey validatingKey, byte[] sigValue)
throws UnsupportedEncodingException, GeneralSecurityException {
// Construct the url again
StringBuilder sb = new StringBuilder();
if (isRequestQueryString(queryString)) {
addParameter(sb, GeneralConstants.SAML_REQUEST_KEY,
RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_REQUEST_KEY));
} else {
addParameter(sb, GeneralConstants.SAML_RESPONSE_KEY,
RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_RESPONSE_KEY));
}
String relayStateFromURL = RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.RELAY_STATE);
if (isNotNull(relayStateFromURL)) {
addParameter(sb, GeneralConstants.RELAY_STATE, relayStateFromURL);
}
addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY,
RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY));
return SignatureUtil.validate(sb.toString().getBytes(GeneralConstants.SAML_CHARSET), sigValue, validatingKey);
}
private static boolean isRequestQueryString(String queryString) {
return RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_REQUEST_KEY) != null;
}
// ***************** Private Methods **************
private static byte[] computeSignature(String samlParameter, String urlEncoded, String urlEncodedRelayState,
PrivateKey signingKey) throws IOException, GeneralSecurityException {
StringBuilder sb = new StringBuilder();
addParameter(sb, samlParameter, urlEncoded);
if (isNotNull(urlEncodedRelayState)) {
addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
}
// SigAlg
String algo = signingKey.getAlgorithm();
String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(algo);
sigAlg = URLEncoder.encode(sigAlg, GeneralConstants.SAML_CHARSET_NAME);
addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
byte[] sigValue = SignatureUtil.sign(sb.toString(), signingKey);
return sigValue;
}
private static String getRequestRedirectURLWithSignature(String urlEncodedRequest, String urlEncodedRelayState,
byte[] signature, String sigAlgo) throws IOException {
return getRedirectURLWithSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
signature, sigAlgo);
}
private static String getResponseRedirectURLWithSignature(String urlEncodedResponse, String urlEncodedRelayState,
byte[] signature, String sigAlgo) throws IOException {
return getRedirectURLWithSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
signature, sigAlgo);
}
private static String getRedirectURLWithSignature(String samlParameter, String urlEncoded, String urlEncodedRelayState,
byte[] signature, String sigAlgo) throws IOException {
StringBuilder sb = new StringBuilder();
addParameter(sb, samlParameter, urlEncoded);
if (isNotNull(urlEncodedRelayState)) {
addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
}
// SigAlg
String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(sigAlgo);
sigAlg = URLEncoder.encode(sigAlg, GeneralConstants.SAML_CHARSET_NAME);
addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
// Encode the signature value
String encodedSig = RedirectBindingUtil.base64URLEncode(signature);
addParameter(sb, GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
return sb.toString();
}
private static void addParameter(StringBuilder queryString, String paramName, String paramValue) {
String parameterSeparator = "&";
if (queryString.length() == 0) {
parameterSeparator = "";
}
queryString.append(parameterSeparator).append(paramName).append("=").append(paramValue);
}
private static String getToken(String queryString, String token) {
if (queryString == null)
throw logger.nullArgumentError("queryString");
token += "=";
int start = queryString.indexOf(token);
if (start < 0)
return null;
int end = queryString.indexOf("&", start);
if (end == -1)
return queryString.substring(start);
return queryString.substring(start, end);
}
private static String getTokenValue(String token) {
if (token == null)
return token;
int eq = token.indexOf('=');
if (eq == -1)
return token;
else
return token.substring(eq + 1);
}
}

View file

@ -1,124 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.processing.web.util;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Privileged Blocks
*
* @author Anil.Saldhana@redhat.com
* @since Dec 9, 2008
*/
class SecurityActions {
/**
* <p>
* Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
* the
* specified {@link Class}, if not found it will try to load from using TCL.
* </p>
*
* @param theClass
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
});
} else {
ClassLoader classLoader = theClass.getClassLoader();
Class<?> clazz = loadClass(classLoader, fullQualifiedName);
if (clazz == null) {
classLoader = Thread.currentThread().getContextClassLoader();
clazz = loadClass(classLoader, fullQualifiedName);
}
return clazz;
}
}
/**
* <p>
* Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
* </p>
*
* @param classLoader
* @param fullQualifiedName
*
* @return
*/
static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
public Class<?> run() {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
});
} else {
try {
return classLoader.loadClass(fullQualifiedName);
} catch (ClassNotFoundException e) {
}
return null;
}
}
/**
* <p>Returns a system property value using the specified <code>key</code>. If not found the
* <code>defaultValue</code> will be returned.</p>
*
* @param key
* @param defaultValue
*
* @return
*/
static String getSystemProperty(final String key, final String defaultValue) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key, defaultValue);
}
});
} else {
return System.getProperty(key, defaultValue);
}
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.saml.common.util;
import java.security.AccessControlException;
import java.security.AllPermission;
import java.security.Policy;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
*
* @author hmlnarik
*/
public class SecurityActionsTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private static final boolean RESTRICTED = System.getSecurityManager() != null && ! Policy.getPolicy().implies(SecurityActionsTest.class.getProtectionDomain(), new AllPermission());
@Test
public void testLoadClass() {
SecurityActions.loadClass(SecurityActionsTest.class, "java.lang.String");
if (RESTRICTED) {
expectedException.expect(SecurityException.class);
}
// Must be a class from a package listed in package.definition property in java.security properties file
SecurityActions.loadClass(SecurityActions.class, "sun.misc.Unsafe");
}
@Test
public void testGetTCCL() {
if (RESTRICTED) {
expectedException.expect(AccessControlException.class);
}
SecurityActions.getTCCL();
}
@Test
public void testSetTCCL() {
if (RESTRICTED) {
expectedException.expect(AccessControlException.class);
}
SecurityActions.setTCCL(ClassLoader.getSystemClassLoader());
}
}

View file

@ -1,47 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.keycloak.saml.common.util;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
/**
*
* @author hmlnarik
*/
public class StringUtilTest {
public StringUtilTest() {
}
@Test
public void testGetSystemPropertyAsString() {
System.setProperty("StringUtilTest.prop1", "value1");
System.setProperty("StringUtilTest.prop2", "value2");
assertThat(StringUtil.getSystemPropertyAsString("a"), is("a"));
assertThat(StringUtil.getSystemPropertyAsString("a ${StringUtilTest.prop1}"), is("a value1"));
assertThat(
StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1"),
is("a" + "value1" + "StringUtilTest.prop1")
);
assertThat(
StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}"),
is("a" + "value1" + "StringUtilTest.prop1" + "value2")
);
assertThat(
StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}" + "${StringUtilTest.prop3::abc}"),
is("a" + "value1" + "StringUtilTest.prop1" + "value2" + "abc")
);
assertThat(
StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}" + "${StringUtilTest.prop3::abc}" + "end"),
is("a" + "value1" + "StringUtilTest.prop1" + "value2" + "abc" + "end")
);
}
}

View file

@ -16,6 +16,7 @@
*/ */
package org.keycloak.saml.processing.core.util; package org.keycloak.saml.processing.core.util;
import org.keycloak.saml.common.util.SecurityActions;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;

View file

@ -0,0 +1,3 @@
grant {
permission java.security.AllPermission;
};

View file

@ -0,0 +1,15 @@
grant {
permission java.io.FilePermission "<<ALL FILES>>", "read";
permission java.io.FilePermission "${maven.basedir}${/}-", "read,write,delete";
// SUREFIRE-859
permission "java.util.PropertyPermission" "*", "read,write";
permission "java.lang.RuntimePermission" "accessDeclaredMembers";
permission "java.lang.RuntimePermission" "getProtectionDomain";
permission "java.lang.RuntimePermission" "setIO";
permission "java.lang.RuntimePermission" "defineClassInPackage.java.lang";
permission "java.security.SecurityPermission" "getPolicy";
};

View file

@ -21,6 +21,8 @@ import org.keycloak.Config;
import org.keycloak.dom.saml.v2.metadata.EndpointType; import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType; import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType; import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType.EDTDescriptorChoiceType;
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType; import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
import org.keycloak.dom.saml.v2.metadata.KeyTypes; import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
@ -37,7 +39,6 @@ import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser; import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.processing.core.saml.v2.util.SAMLMetadataUtil; import org.keycloak.saml.processing.core.saml.v2.util.SAMLMetadataUtil;
import org.keycloak.saml.processing.core.util.CoreConfigUtil;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
@ -46,6 +47,7 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -66,6 +68,41 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo
return loadEntityDescriptors(new ByteArrayInputStream(description.getBytes())); return loadEntityDescriptors(new ByteArrayInputStream(description.getBytes()));
} }
/**
* Get the SP Descriptor from an entity descriptor
*
* @param entityDescriptor
*
* @return
*/
public static SPSSODescriptorType getSPDescriptor(EntityDescriptorType entityDescriptor) {
return entityDescriptor.getChoiceType().stream()
.flatMap(d -> d.getDescriptors().stream())
.map(EDTDescriptorChoiceType::getSpDescriptor)
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
/**
* Get the service url for the SP
*
* @param sp
* @param bindingURI
*
* @return
*/
public static String getServiceURL(SPSSODescriptorType sp, String bindingURI) {
List<IndexedEndpointType> endpoints = sp.getAssertionConsumerService();
for (IndexedEndpointType endpoint : endpoints) {
if (Objects.equals(endpoint.getBinding().toString(), bindingURI)) {
return endpoint.getLocation().toString();
}
}
return null;
}
private static ClientRepresentation loadEntityDescriptors(InputStream is) { private static ClientRepresentation loadEntityDescriptors(InputStream is) {
Object metadata; Object metadata;
try { try {
@ -104,7 +141,7 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo
attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE_KEYINFO_EXT, SamlProtocol.ATTRIBUTE_FALSE_VALUE); // default to false attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE_KEYINFO_EXT, SamlProtocol.ATTRIBUTE_FALSE_VALUE); // default to false
attributes.put(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString()); attributes.put(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
attributes.put(SamlConfigAttributes.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE); attributes.put(SamlConfigAttributes.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
SPSSODescriptorType spDescriptorType = CoreConfigUtil.getSPDescriptor(entity); SPSSODescriptorType spDescriptorType = getSPDescriptor(entity);
if (spDescriptorType.isWantAssertionsSigned()) { if (spDescriptorType.isWantAssertionsSigned()) {
attributes.put(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); attributes.put(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
} }
@ -113,21 +150,21 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo
String logoutRedirect = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get()); String logoutRedirect = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
if (logoutRedirect != null) attributes.put(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, logoutRedirect); if (logoutRedirect != null) attributes.put(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, logoutRedirect);
String assertionConsumerServicePostBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get()); String assertionConsumerServicePostBinding = getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
if (assertionConsumerServicePostBinding != null) { if (assertionConsumerServicePostBinding != null) {
attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE, assertionConsumerServicePostBinding); attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE, assertionConsumerServicePostBinding);
redirectUris.add(assertionConsumerServicePostBinding); redirectUris.add(assertionConsumerServicePostBinding);
} }
String assertionConsumerServiceRedirectBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get()); String assertionConsumerServiceRedirectBinding = getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
if (assertionConsumerServiceRedirectBinding != null) { if (assertionConsumerServiceRedirectBinding != null) {
attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE, assertionConsumerServiceRedirectBinding); attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE, assertionConsumerServiceRedirectBinding);
redirectUris.add(assertionConsumerServiceRedirectBinding); redirectUris.add(assertionConsumerServiceRedirectBinding);
} }
String assertionConsumerServiceSoapBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_SOAP_BINDING.get()); String assertionConsumerServiceSoapBinding = getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_SOAP_BINDING.get());
if (assertionConsumerServiceSoapBinding != null) { if (assertionConsumerServiceSoapBinding != null) {
redirectUris.add(assertionConsumerServiceSoapBinding); redirectUris.add(assertionConsumerServiceSoapBinding);
} }
String assertionConsumerServicePaosBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_PAOS_BINDING.get()); String assertionConsumerServicePaosBinding = getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_PAOS_BINDING.get());
if (assertionConsumerServicePaosBinding != null) { if (assertionConsumerServicePaosBinding != null) {
redirectUris.add(assertionConsumerServicePaosBinding); redirectUris.add(assertionConsumerServicePaosBinding);
} }