keycloak-aplcache

Changes

saml-core/pom.xml 31(+30 -1)

saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java 93(+0 -93)

saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java 160(+0 -160)

saml-core/src/main/java/org/keycloak/saml/processing/core/util/CoreConfigUtil.java 208(+0 -208)

saml-core/src/main/java/org/keycloak/saml/processing/core/util/EncryptionKeyUtil.java 49(+0 -49)

saml-core/src/main/java/org/keycloak/saml/processing/core/util/KeyStoreUtil.java 184(+0 -184)

saml-core/src/main/java/org/keycloak/saml/processing/core/util/SecurityActions.java 224(+0 -224)

saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingSignatureUtil.java 344(+0 -344)

saml-core/src/main/java/org/keycloak/saml/processing/web/util/SecurityActions.java 124(+0 -124)

saml-core/src/test/java/org/keycloak/saml/common/util/StringUtilTest.java 47(+0 -47)

Details

saml-core/pom.xml 31(+30 -1)

diff --git a/saml-core/pom.xml b/saml-core/pom.xml
index a198733..0914083 100755
--- a/saml-core/pom.xml
+++ b/saml-core/pom.xml
@@ -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>
 
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java
index b36adb4..b4a6279 100755
--- a/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java
@@ -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;
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java
index 3c5cd38..f10ecf5 100755
--- a/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java
@@ -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);
         }
 
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
index 23fb45f..366d739 100755
--- a/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
@@ -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};
-    }
 }
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java
index 8510d47..7b45cae 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java
@@ -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;
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java
index 299ddaa..fdfa448 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java
@@ -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;
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java
index be255e2..bf2ecfe 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java
@@ -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.
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java
index 49e6ce3..49d531c 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java
@@ -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;
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java
index 5918737..e4369a2 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java
@@ -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;
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
index 85ddf2c..6c07790 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
@@ -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;
 
 /**
diff --git a/saml-core/src/test/java/org/keycloak/saml/common/util/SecurityActionsTest.java b/saml-core/src/test/java/org/keycloak/saml/common/util/SecurityActionsTest.java
new file mode 100644
index 0000000..0b0a0a6
--- /dev/null
+++ b/saml-core/src/test/java/org/keycloak/saml/common/util/SecurityActionsTest.java
@@ -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());
+    }
+
+}
diff --git a/saml-core/src/test/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolverTest.java b/saml-core/src/test/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolverTest.java
index 48d6a0e..ecd8e6e 100644
--- a/saml-core/src/test/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolverTest.java
+++ b/saml-core/src/test/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolverTest.java
@@ -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;
diff --git a/saml-core/src/test/resources/all-permissions.policy b/saml-core/src/test/resources/all-permissions.policy
new file mode 100644
index 0000000..5d74bde
--- /dev/null
+++ b/saml-core/src/test/resources/all-permissions.policy
@@ -0,0 +1,3 @@
+grant {
+    permission java.security.AllPermission;
+};
\ No newline at end of file
diff --git a/saml-core/src/test/resources/named-permissions.policy b/saml-core/src/test/resources/named-permissions.policy
new file mode 100644
index 0000000..0d4ba1d
--- /dev/null
+++ b/saml-core/src/test/resources/named-permissions.policy
@@ -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";
+};
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java b/services/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java
index d3cd904..59e32ef 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java
@@ -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);
         }