KEYCLOAK-4315 Remove some dead/duplicate classes
This commit is contained in:
parent
5d5373454c
commit
84ea3f8cb1
24 changed files with 203 additions and 1563 deletions
|
@ -32,6 +32,7 @@
|
|||
|
||||
<properties>
|
||||
<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>
|
||||
</properties>
|
||||
<dependencies>
|
||||
|
@ -56,7 +57,6 @@
|
|||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -88,6 +88,35 @@
|
|||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.saml.common.util;
|
|||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.PropertyPermission;
|
||||
|
||||
/**
|
||||
* Privileged Blocks
|
||||
|
@ -28,6 +29,14 @@ import java.security.PrivilegedAction;
|
|||
*/
|
||||
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
|
||||
* the specified {@link Class}, if not found it will try to load from using TCL. </p>
|
||||
|
@ -37,11 +46,17 @@ public class SecurityActions {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
|
||||
public static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
if (fullQualifiedName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (sm != null) {
|
||||
sm.checkPackageDefinition(extractPackageNameFromClassName(fullQualifiedName));
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
ClassLoader classLoader = theClass.getClassLoader();
|
||||
|
||||
|
@ -73,11 +88,17 @@ public class SecurityActions {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
|
||||
public static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
if (fullQualifiedName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (sm != null) {
|
||||
sm.checkPackageDefinition(extractPackageNameFromClassName(fullQualifiedName));
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
try {
|
||||
return classLoader.loadClass(fullQualifiedName);
|
||||
|
@ -103,13 +124,14 @@ public class SecurityActions {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
static URL loadResource(final Class<?> clazz, final String resourceName) {
|
||||
public static URL loadResource(final Class<?> clazz, final String resourceName) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
if (sm != null) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<URL>() {
|
||||
@Override
|
||||
public URL run() {
|
||||
URL url = null;
|
||||
URL url;
|
||||
ClassLoader clazzLoader = clazz.getClassLoader();
|
||||
url = clazzLoader.getResource(resourceName);
|
||||
|
||||
|
@ -122,7 +144,7 @@ public class SecurityActions {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
URL url = null;
|
||||
URL url;
|
||||
ClassLoader clazzLoader = clazz.getClassLoader();
|
||||
url = clazzLoader.getResource(resourceName);
|
||||
|
||||
|
@ -143,11 +165,13 @@ public class SecurityActions {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
static void setSystemProperty(final String key, final String value) {
|
||||
public static void setSystemProperty(final String key, final String value) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new PropertyPermission(key, "write"));
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
System.setProperty(key, value);
|
||||
return null;
|
||||
|
@ -167,11 +191,13 @@ public class SecurityActions {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
static String getSystemProperty(final String key, final String defaultValue) {
|
||||
public static String getSystemProperty(final String key, final String defaultValue) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new PropertyPermission(key, "read"));
|
||||
return AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getProperty(key, defaultValue);
|
||||
}
|
||||
|
@ -188,7 +214,9 @@ public class SecurityActions {
|
|||
*/
|
||||
public static ClassLoader getTCCL() {
|
||||
if (System.getSecurityManager() != null) {
|
||||
System.getSecurityManager().checkPermission(new RuntimePermission("getClassLoader"));
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
|
||||
@Override
|
||||
public ClassLoader run() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
@ -205,7 +233,9 @@ public class SecurityActions {
|
|||
*/
|
||||
public static void setTCCL(final ClassLoader paramCl) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
System.getSecurityManager().checkPermission(new RuntimePermission("setContextClassLoader"));
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
Thread.currentThread().setContextClassLoader(paramCl);
|
||||
return null;
|
||||
|
|
|
@ -46,7 +46,7 @@ public class StaxUtil {
|
|||
|
||||
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
|
||||
|
@ -341,10 +341,10 @@ public class StaxUtil {
|
|||
writeStartElement(writer, domElementPrefix, domElement.getLocalName(), domElementNS);
|
||||
|
||||
// Should we register namespace
|
||||
if (domElementPrefix != "" && !registeredNSStack.get().contains(domElementNS)) {
|
||||
if (! domElementPrefix.isEmpty() && !registeredNSStack.get().contains(domElementNS)) {
|
||||
// writeNameSpace(writer, domElementPrefix, domElementNS );
|
||||
registeredNSStack.get().push(domElementNS);
|
||||
} else if (domElementPrefix == "" && domElementNS != null) {
|
||||
} else if (domElementPrefix.isEmpty() && ! domElementNS.isEmpty()) {
|
||||
writeNameSpace(writer, "xmlns", domElementNS);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,55 +59,6 @@ public class StringUtil {
|
|||
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}
|
||||
*
|
||||
|
@ -118,67 +69,4 @@ public class StringUtil {
|
|||
if (!first.equals(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};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ 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.util.SecurityActions;
|
||||
import org.keycloak.saml.common.util.SystemPropertiesUtil;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.util;
|
||||
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.keycloak.saml.common.PicketLinkLogger;
|
|||
import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
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";
|
||||
|
||||
private static HashMap<String, JAXBContext> jaxbContextHash = new HashMap<String, JAXBContext>();
|
||||
private static final HashMap<String, JAXBContext> jaxbContextHash = new HashMap<String, JAXBContext>();
|
||||
|
||||
static {
|
||||
// Useful on Sun VMs. Harmless on other VMs.
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
|||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.exceptions.ProcessingException;
|
||||
import org.keycloak.saml.common.util.DocumentUtil;
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import org.keycloak.saml.common.util.SystemPropertiesUtil;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.keycloak.saml.processing.core.util;
|
|||
import org.keycloak.saml.common.PicketLinkLogger;
|
||||
import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
||||
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Provider;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,6 +88,7 @@ import javax.xml.crypto.KeySelectorResult;
|
|||
import javax.xml.crypto.XMLCryptoContext;
|
||||
import javax.xml.crypto.dsig.keyinfo.KeyName;
|
||||
import org.keycloak.rotation.KeyLocator;
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import org.keycloak.saml.processing.api.util.KeyInfoTools;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.util;
|
||||
|
||||
import org.keycloak.saml.common.util.SecurityActions;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
|
3
saml-core/src/test/resources/all-permissions.policy
Normal file
3
saml-core/src/test/resources/all-permissions.policy
Normal file
|
@ -0,0 +1,3 @@
|
|||
grant {
|
||||
permission java.security.AllPermission;
|
||||
};
|
15
saml-core/src/test/resources/named-permissions.policy
Normal file
15
saml-core/src/test/resources/named-permissions.policy
Normal 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";
|
||||
};
|
|
@ -21,6 +21,8 @@ import org.keycloak.Config;
|
|||
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.EDTDescriptorChoiceType;
|
||||
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
||||
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.processing.core.parsers.saml.SAMLParser;
|
||||
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.InputStream;
|
||||
|
@ -46,6 +47,7 @@ import java.util.HashMap;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @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()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Object metadata;
|
||||
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_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
|
||||
attributes.put(SamlConfigAttributes.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
|
||||
SPSSODescriptorType spDescriptorType = CoreConfigUtil.getSPDescriptor(entity);
|
||||
SPSSODescriptorType spDescriptorType = getSPDescriptor(entity);
|
||||
if (spDescriptorType.isWantAssertionsSigned()) {
|
||||
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());
|
||||
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) {
|
||||
attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE, 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) {
|
||||
attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE, 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) {
|
||||
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) {
|
||||
redirectUris.add(assertionConsumerServicePaosBinding);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue