/* * 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.security.AccessController; import java.security.PrivilegedAction; import java.security.Provider; import java.security.Security; /** * Utility dealing with the Santuario (XMLSec) providers registration for PicketLink * * @author alessio.soldano@jboss.com * @since 07-May-2012 */ public class ProvidersUtil { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); /** * No-op call such that the default system properties are set */ public static synchronized void ensure() { AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { // register Apache Santuario 1.5.x XMLDSig version addXMLDSigRI(); // register BC provider if available (to have additional encryption algorithms, etc.) addJceProvider("BC", "org.bouncycastle.jce.provider.BouncyCastleProvider"); return true; } }); } private static void addXMLDSigRI() { try { Class<?> clazz = SecurityActions .loadClass(XMLSignatureUtil.class, "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI"); if (clazz == null) throw logger.classNotLoadedError("org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI"); addJceProvider("ApacheXMLDSig", (Provider) clazz.newInstance()); } catch (Throwable t) { // ignore - may be a NoClassDefFound if XMLDSigRI isn't avail return; } } /** * Add a new JCE security provider to use for PicketLink. * * @param name The name string of the provider (this may not be the real name of the provider) * @param provider A subclass of <code>java.security.Provider</code> * * @return Returns the actual name of the provider that was loaded */ private static String addJceProvider(String name, Provider provider) { Provider currentProvider = Security.getProvider(name); if (currentProvider == null) { try { // // Install the provider after the SUN provider (see WSS-99) // Otherwise fall back to the old behaviour of inserting // the provider in position 2. For AIX, install it after // the IBMJCE provider. // int ret = 0; Provider[] provs = Security.getProviders(); for (int i = 0; i < provs.length; i++) { if ("SUN".equals(provs[i].getName()) || "IBMJCE".equals(provs[i].getName())) { ret = Security.insertProviderAt(provider, i + 2); break; } } if (ret == 0) { ret = Security.insertProviderAt(provider, 2); } if (logger.isDebugEnabled()) { logger.debug("The provider " + provider.getName() + " - " + provider.getVersion() + " was added at position: " + ret); } return provider.getName(); } catch (Throwable t) { if (logger.isDebugEnabled()) { logger.jceProviderCouldNotBeLoaded(name, t); } return null; } } return currentProvider.getName(); } private static String addJceProvider(String name, String className) { Provider currentProvider = Security.getProvider(name); if (currentProvider == null) { try { // Class<? extends Provider> clazz = Loader.loadClass(className, false, Provider.class); Class<? extends Provider> clazz = Class.forName(className).asSubclass(Provider.class); Provider provider = clazz.newInstance(); return addJceProvider(name, provider); } catch (Throwable t) { if (logger.isDebugEnabled()) { logger.jceProviderCouldNotBeLoaded(name, t); } return null; } } return currentProvider.getName(); } }