mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
264
src/java.base/share/classes/sun/security/jca/GetInstance.java
Normal file
264
src/java.base/share/classes/sun/security/jca/GetInstance.java
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.Provider.Service;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to facilitate implementing getInstance()
|
||||
* methods in the JCA/JCE/JSSE/... framework.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
public class GetInstance {
|
||||
|
||||
private GetInstance() {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Static inner class representing a newly created instance.
|
||||
*/
|
||||
public static final class Instance {
|
||||
// public final fields, access directly without accessors
|
||||
public final Provider provider;
|
||||
public final Object impl;
|
||||
private Instance(Provider provider, Object impl) {
|
||||
this.provider = provider;
|
||||
this.impl = impl;
|
||||
}
|
||||
// Return Provider and implementation as an array as used in the
|
||||
// old Security.getImpl() methods.
|
||||
public Object[] toArray() {
|
||||
return new Object[] {impl, provider};
|
||||
}
|
||||
}
|
||||
|
||||
public static Service getService(String type, String algorithm)
|
||||
throws NoSuchAlgorithmException {
|
||||
ProviderList list = Providers.getProviderList();
|
||||
Service s = list.getService(type, algorithm);
|
||||
if (s == null) {
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " " + type + " not available");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static Service getService(String type, String algorithm,
|
||||
String provider) throws NoSuchAlgorithmException,
|
||||
NoSuchProviderException {
|
||||
if ((provider == null) || (provider.length() == 0)) {
|
||||
throw new IllegalArgumentException("missing provider");
|
||||
}
|
||||
Provider p = Providers.getProviderList().getProvider(provider);
|
||||
if (p == null) {
|
||||
throw new NoSuchProviderException("no such provider: " + provider);
|
||||
}
|
||||
Service s = p.getService(type, algorithm);
|
||||
if (s == null) {
|
||||
throw new NoSuchAlgorithmException("no such algorithm: "
|
||||
+ algorithm + " for provider " + provider);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static Service getService(String type, String algorithm,
|
||||
Provider provider) throws NoSuchAlgorithmException {
|
||||
if (provider == null) {
|
||||
throw new IllegalArgumentException("missing provider");
|
||||
}
|
||||
Service s = provider.getService(type, algorithm);
|
||||
if (s == null) {
|
||||
throw new NoSuchAlgorithmException("no such algorithm: "
|
||||
+ algorithm + " for provider " + provider.getName());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a List of all the available Services that implement
|
||||
* (type, algorithm). Note that the list is initialized lazily
|
||||
* and Provider loading and lookup is only trigered when
|
||||
* necessary.
|
||||
*/
|
||||
public static List<Service> getServices(String type, String algorithm) {
|
||||
ProviderList list = Providers.getProviderList();
|
||||
return list.getServices(type, algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method exists for compatibility with JCE only. It will be removed
|
||||
* once JCE has been changed to use the replacement method.
|
||||
* @deprecated use {@code getServices(List<ServiceId>)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<Service> getServices(String type,
|
||||
List<String> algorithms) {
|
||||
ProviderList list = Providers.getProviderList();
|
||||
return list.getServices(type, algorithms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a List of all the available Services that implement any of
|
||||
* the specified algorithms. See getServices(String, String) for detals.
|
||||
*/
|
||||
public static List<Service> getServices(List<ServiceId> ids) {
|
||||
ProviderList list = Providers.getProviderList();
|
||||
return list.getServices(ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* For all the getInstance() methods below:
|
||||
* @param type the type of engine (e.g. MessageDigest)
|
||||
* @param clazz the Spi class that the implementation must subclass
|
||||
* (e.g. MessageDigestSpi.class) or null if no superclass check
|
||||
* is required
|
||||
* @param algorithm the name of the algorithm (or alias), e.g. MD5
|
||||
* @param provider the provider (String or Provider object)
|
||||
* @param param the parameter to pass to the Spi constructor
|
||||
* (for CertStores)
|
||||
*
|
||||
* There are overloaded methods for all the permutations.
|
||||
*/
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm) throws NoSuchAlgorithmException {
|
||||
// in the almost all cases, the first service will work
|
||||
// avoid taking long path if so
|
||||
ProviderList list = Providers.getProviderList();
|
||||
Service firstService = list.getService(type, algorithm);
|
||||
if (firstService == null) {
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " " + type + " not available");
|
||||
}
|
||||
NoSuchAlgorithmException failure;
|
||||
try {
|
||||
return getInstance(firstService, clazz);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
failure = e;
|
||||
}
|
||||
// if we cannot get the service from the preferred provider,
|
||||
// fail over to the next
|
||||
for (Service s : list.getServices(type, algorithm)) {
|
||||
if (s == firstService) {
|
||||
// do not retry initial failed service
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
return getInstance(s, clazz);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
failure = e;
|
||||
}
|
||||
}
|
||||
throw failure;
|
||||
}
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm, Object param) throws NoSuchAlgorithmException {
|
||||
List<Service> services = getServices(type, algorithm);
|
||||
NoSuchAlgorithmException failure = null;
|
||||
for (Service s : services) {
|
||||
try {
|
||||
return getInstance(s, clazz, param);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
failure = e;
|
||||
}
|
||||
}
|
||||
if (failure != null) {
|
||||
throw failure;
|
||||
} else {
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " " + type + " not available");
|
||||
}
|
||||
}
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm, String provider) throws NoSuchAlgorithmException,
|
||||
NoSuchProviderException {
|
||||
return getInstance(getService(type, algorithm, provider), clazz);
|
||||
}
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm, Object param, String provider)
|
||||
throws NoSuchAlgorithmException, NoSuchProviderException {
|
||||
return getInstance(getService(type, algorithm, provider), clazz, param);
|
||||
}
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm, Provider provider)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getInstance(getService(type, algorithm, provider), clazz);
|
||||
}
|
||||
|
||||
public static Instance getInstance(String type, Class<?> clazz,
|
||||
String algorithm, Object param, Provider provider)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getInstance(getService(type, algorithm, provider), clazz, param);
|
||||
}
|
||||
|
||||
/*
|
||||
* The two getInstance() methods below take a service. They are
|
||||
* intended for classes that cannot use the standard methods, e.g.
|
||||
* because they implement delayed provider selection like the
|
||||
* Signature class.
|
||||
*/
|
||||
|
||||
public static Instance getInstance(Service s, Class<?> clazz)
|
||||
throws NoSuchAlgorithmException {
|
||||
Object instance = s.newInstance(null);
|
||||
checkSuperClass(s, instance.getClass(), clazz);
|
||||
return new Instance(s.getProvider(), instance);
|
||||
}
|
||||
|
||||
public static Instance getInstance(Service s, Class<?> clazz,
|
||||
Object param) throws NoSuchAlgorithmException {
|
||||
Object instance = s.newInstance(param);
|
||||
checkSuperClass(s, instance.getClass(), clazz);
|
||||
return new Instance(s.getProvider(), instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check is subClass is a subclass of superClass. If not,
|
||||
* throw a NoSuchAlgorithmException.
|
||||
*/
|
||||
public static void checkSuperClass(Service s, Class<?> subClass,
|
||||
Class<?> superClass) throws NoSuchAlgorithmException {
|
||||
if (superClass == null) {
|
||||
return;
|
||||
}
|
||||
if (superClass.isAssignableFrom(subClass) == false) {
|
||||
throw new NoSuchAlgorithmException
|
||||
("class configured for " + s.getType() + ": "
|
||||
+ s.getClassName() + " not a " + s.getType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
72
src/java.base/share/classes/sun/security/jca/JCAUtil.java
Normal file
72
src/java.base/share/classes/sun/security/jca/JCAUtil.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
import java.lang.ref.*;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
/**
|
||||
* Collection of static utility methods used by the security framework.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
public final class JCAUtil {
|
||||
|
||||
private JCAUtil() {
|
||||
// no instantiation
|
||||
}
|
||||
|
||||
// size of the temporary arrays we use. Should fit into the CPU's 1st
|
||||
// level cache and could be adjusted based on the platform
|
||||
private static final int ARRAY_SIZE = 4096;
|
||||
|
||||
/**
|
||||
* Get the size of a temporary buffer array to use in order to be
|
||||
* cache efficient. totalSize indicates the total amount of data to
|
||||
* be buffered. Used by the engineUpdate(ByteBuffer) methods.
|
||||
*/
|
||||
public static int getTempArraySize(int totalSize) {
|
||||
return Math.min(ARRAY_SIZE, totalSize);
|
||||
}
|
||||
|
||||
// cached SecureRandom instance
|
||||
private static class CachedSecureRandomHolder {
|
||||
public static SecureRandom instance = new SecureRandom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a SecureRandom instance. This method should be used by JDK
|
||||
* internal code in favor of calling "new SecureRandom()". That needs to
|
||||
* iterate through the provider table to find the default SecureRandom
|
||||
* implementation, which is fairly inefficient.
|
||||
*/
|
||||
public static SecureRandom getSecureRandom() {
|
||||
return CachedSecureRandomHolder.instance;
|
||||
}
|
||||
|
||||
}
|
425
src/java.base/share/classes/sun/security/jca/ProviderConfig.java
Normal file
425
src/java.base/share/classes/sun/security/jca/ProviderConfig.java
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
import sun.security.util.PropertyExpander;
|
||||
|
||||
/**
|
||||
* Class representing a configured provider which encapsulates configuration
|
||||
* (provider name + optional argument), the provider loading logic, and
|
||||
* the loaded Provider object itself.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
final class ProviderConfig {
|
||||
|
||||
private static final sun.security.util.Debug debug =
|
||||
sun.security.util.Debug.getInstance("jca", "ProviderConfig");
|
||||
|
||||
// suffix for identifying the SunPKCS11-Solaris provider
|
||||
private static final String P11_SOL_NAME = "SunPKCS11";
|
||||
|
||||
// config file argument of the SunPKCS11-Solaris provider
|
||||
private static final String P11_SOL_ARG =
|
||||
"${java.home}/conf/security/sunpkcs11-solaris.cfg";
|
||||
|
||||
// maximum number of times to try loading a provider before giving up
|
||||
private static final int MAX_LOAD_TRIES = 30;
|
||||
|
||||
// could be provider name (module) or provider class name (legacy)
|
||||
private final String provName;
|
||||
|
||||
// argument to the Provider.configure() call, never null
|
||||
private final String argument;
|
||||
|
||||
// number of times we have already tried to load this provider
|
||||
private int tries;
|
||||
|
||||
// Provider object, if loaded
|
||||
private volatile Provider provider;
|
||||
|
||||
// flag indicating if we are currently trying to load the provider
|
||||
// used to detect recursion
|
||||
private boolean isLoading;
|
||||
|
||||
ProviderConfig(String provName, String argument) {
|
||||
if (provName.endsWith(P11_SOL_NAME) && argument.equals(P11_SOL_ARG)) {
|
||||
checkSunPKCS11Solaris();
|
||||
}
|
||||
this.provName = provName;
|
||||
this.argument = expand(argument);
|
||||
}
|
||||
|
||||
ProviderConfig(String provName) {
|
||||
this(provName, "");
|
||||
}
|
||||
|
||||
ProviderConfig(Provider provider) {
|
||||
this.provName = provider.getName();
|
||||
this.argument = "";
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
// check if we should try to load the SunPKCS11-Solaris provider
|
||||
// avoid if not available (pre Solaris 10) to reduce startup time
|
||||
// or if disabled via system property
|
||||
private void checkSunPKCS11Solaris() {
|
||||
Boolean o = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
File file = new File("/usr/lib/libpkcs11.so");
|
||||
if (file.exists() == false) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(System.getProperty
|
||||
("sun.security.pkcs11.enable-solaris"))) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
});
|
||||
if (o == Boolean.FALSE) {
|
||||
tries = MAX_LOAD_TRIES;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasArgument() {
|
||||
return argument.length() != 0;
|
||||
}
|
||||
|
||||
// should we try to load this provider?
|
||||
private boolean shouldLoad() {
|
||||
return (tries < MAX_LOAD_TRIES);
|
||||
}
|
||||
|
||||
// do not try to load this provider again
|
||||
private void disableLoad() {
|
||||
tries = MAX_LOAD_TRIES;
|
||||
}
|
||||
|
||||
boolean isLoaded() {
|
||||
return (provider != null);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof ProviderConfig == false) {
|
||||
return false;
|
||||
}
|
||||
ProviderConfig other = (ProviderConfig)obj;
|
||||
return this.provName.equals(other.provName)
|
||||
&& this.argument.equals(other.argument);
|
||||
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return provName.hashCode() + argument.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (hasArgument()) {
|
||||
return provName + "('" + argument + "')";
|
||||
} else {
|
||||
return provName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider object. Loads the provider if it is not already loaded.
|
||||
*/
|
||||
// com.sun.net.ssl.internal.ssl.Provider has been deprecated since JDK 9
|
||||
@SuppressWarnings("deprecation")
|
||||
synchronized Provider getProvider() {
|
||||
// volatile variable load
|
||||
Provider p = provider;
|
||||
if (p != null) {
|
||||
return p;
|
||||
}
|
||||
if (shouldLoad() == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create providers which are in java.base directly
|
||||
if (provName.equals("SUN") || provName.equals("sun.security.provider.Sun")) {
|
||||
p = new sun.security.provider.Sun();
|
||||
} else if (provName.equals("SunRsaSign") || provName.equals("sun.security.rsa.SunRsaSign")) {
|
||||
p = new sun.security.rsa.SunRsaSign();
|
||||
} else if (provName.equals("SunJCE") || provName.equals("com.sun.crypto.provider.SunJCE")) {
|
||||
p = new com.sun.crypto.provider.SunJCE();
|
||||
} else if (provName.equals("SunJSSE") || provName.equals("com.sun.net.ssl.internal.ssl.Provider")) {
|
||||
p = new com.sun.net.ssl.internal.ssl.Provider();
|
||||
} else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) {
|
||||
// need to use reflection since this class only exists on MacOsx
|
||||
p = AccessController.doPrivileged(new PrivilegedAction<Provider>() {
|
||||
public Provider run() {
|
||||
try {
|
||||
Class<?> c = Class.forName("apple.security.AppleProvider");
|
||||
if (Provider.class.isAssignableFrom(c)) {
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = c.newInstance();
|
||||
return (Provider) tmp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (debug != null) {
|
||||
debug.println("Error loading provider Apple");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (isLoading) {
|
||||
// because this method is synchronized, this can only
|
||||
// happen if there is recursion.
|
||||
if (debug != null) {
|
||||
debug.println("Recursion loading provider: " + this);
|
||||
new Exception("Call trace").printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
isLoading = true;
|
||||
tries++;
|
||||
p = doLoadProvider();
|
||||
} finally {
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
provider = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and instantiate the Provider described by this class.
|
||||
*
|
||||
* NOTE use of doPrivileged().
|
||||
*
|
||||
* @return null if the Provider could not be loaded
|
||||
*
|
||||
* @throws ProviderException if executing the Provider's constructor
|
||||
* throws a ProviderException. All other Exceptions are ignored.
|
||||
*/
|
||||
private Provider doLoadProvider() {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Provider>() {
|
||||
public Provider run() {
|
||||
if (debug != null) {
|
||||
debug.println("Loading provider " + ProviderConfig.this);
|
||||
}
|
||||
try {
|
||||
Provider p = ProviderLoader.INSTANCE.load(provName);
|
||||
if (p != null) {
|
||||
if (hasArgument()) {
|
||||
p = p.configure(argument);
|
||||
}
|
||||
if (debug != null) {
|
||||
debug.println("Loaded provider " + p.getName());
|
||||
}
|
||||
} else {
|
||||
if (debug != null) {
|
||||
debug.println("Error loading provider " +
|
||||
ProviderConfig.this);
|
||||
}
|
||||
disableLoad();
|
||||
}
|
||||
return p;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ProviderException) {
|
||||
// pass up
|
||||
throw e;
|
||||
} else {
|
||||
if (debug != null) {
|
||||
debug.println("Error loading provider " +
|
||||
ProviderConfig.this);
|
||||
e.printStackTrace();
|
||||
}
|
||||
disableLoad();
|
||||
return null;
|
||||
}
|
||||
} catch (ExceptionInInitializerError err) {
|
||||
// no sufficient permission to initialize provider class
|
||||
if (debug != null) {
|
||||
debug.println("Error loading provider " + ProviderConfig.this);
|
||||
err.printStackTrace();
|
||||
}
|
||||
disableLoad();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform property expansion of the provider value.
|
||||
*
|
||||
* NOTE use of doPrivileged().
|
||||
*/
|
||||
private static String expand(final String value) {
|
||||
// shortcut if value does not contain any properties
|
||||
if (value.contains("${") == false) {
|
||||
return value;
|
||||
}
|
||||
return AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
try {
|
||||
return PropertyExpander.expand(value);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new ProviderException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Inner class for loading security providers listed in java.security file
|
||||
private static final class ProviderLoader {
|
||||
static final ProviderLoader INSTANCE = new ProviderLoader();
|
||||
|
||||
private final ServiceLoader<Provider> services;
|
||||
|
||||
private ProviderLoader() {
|
||||
// VM should already been booted at this point, if not
|
||||
// - Only providers in java.base should be loaded, don't use
|
||||
// ServiceLoader
|
||||
// - ClassLoader.getSystemClassLoader() will throw InternalError
|
||||
services = ServiceLoader.load(java.security.Provider.class,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the provider with the specified class name.
|
||||
*
|
||||
* @param name the name of the provider
|
||||
* @return the Provider, or null if it cannot be found or loaded
|
||||
* @throws ProviderException all other exceptions are ignored
|
||||
*/
|
||||
public Provider load(String pn) {
|
||||
if (debug != null) {
|
||||
debug.println("Attempt to load " + pn + " using SL");
|
||||
}
|
||||
Iterator<Provider> iter = services.iterator();
|
||||
while (iter.hasNext()) {
|
||||
try {
|
||||
Provider p = iter.next();
|
||||
String pName = p.getName();
|
||||
if (debug != null) {
|
||||
debug.println("Found SL Provider named " + pName);
|
||||
}
|
||||
if (pName.equals(pn)) {
|
||||
return p;
|
||||
}
|
||||
} catch (SecurityException | ServiceConfigurationError |
|
||||
InvalidParameterException ex) {
|
||||
// if provider loading fail due to security permission,
|
||||
// log it and move on to next provider
|
||||
if (debug != null) {
|
||||
debug.println("Encountered " + ex +
|
||||
" while iterating through SL, ignore and move on");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// No success with ServiceLoader. Try loading provider the legacy,
|
||||
// i.e. pre-module, way via reflection
|
||||
try {
|
||||
return legacyLoad(pn);
|
||||
} catch (ProviderException pe) {
|
||||
// pass through
|
||||
throw pe;
|
||||
} catch (Exception ex) {
|
||||
// logged and ignored
|
||||
if (debug != null) {
|
||||
debug.println("Encountered " + ex +
|
||||
" during legacy load of " + pn);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Provider legacyLoad(String classname) {
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Loading legacy provider: " + classname);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> provClass =
|
||||
ClassLoader.getSystemClassLoader().loadClass(classname);
|
||||
|
||||
// only continue if the specified class extends Provider
|
||||
if (!Provider.class.isAssignableFrom(provClass)) {
|
||||
if (debug != null) {
|
||||
debug.println(classname + " is not a provider");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Provider p = AccessController.doPrivileged
|
||||
(new PrivilegedExceptionAction<Provider>() {
|
||||
@SuppressWarnings("deprecation") // Class.newInstance
|
||||
public Provider run() throws Exception {
|
||||
return (Provider) provClass.newInstance();
|
||||
}
|
||||
});
|
||||
return p;
|
||||
} catch (Exception e) {
|
||||
Throwable t;
|
||||
if (e instanceof InvocationTargetException) {
|
||||
t = ((InvocationTargetException)e).getCause();
|
||||
} else {
|
||||
t = e;
|
||||
}
|
||||
if (debug != null) {
|
||||
debug.println("Error loading legacy provider " + classname);
|
||||
t.printStackTrace();
|
||||
}
|
||||
// provider indicates fatal error, pass through exception
|
||||
if (t instanceof ProviderException) {
|
||||
throw (ProviderException) t;
|
||||
}
|
||||
return null;
|
||||
} catch (ExceptionInInitializerError | NoClassDefFoundError err) {
|
||||
// no sufficient permission to access/initialize provider class
|
||||
if (debug != null) {
|
||||
debug.println("Error loading legacy provider " + classname);
|
||||
err.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
767
src/java.base/share/classes/sun/security/jca/ProviderList.java
Normal file
767
src/java.base/share/classes/sun/security/jca/ProviderList.java
Normal file
|
@ -0,0 +1,767 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Provider;
|
||||
import java.security.Provider.Service;
|
||||
import java.security.Security;
|
||||
|
||||
/**
|
||||
* List of Providers. Used to represent the provider preferences.
|
||||
*
|
||||
* The system starts out with a ProviderList that only has the names
|
||||
* of the Providers.
|
||||
* When using ServiceLoader to load the providers, Providers are created
|
||||
* semi-eagerly as we iterate through them looking for a match.
|
||||
*
|
||||
* For compatibility reasons, Providers that could not be loaded are ignored
|
||||
* and internally presented as the instance EMPTY_PROVIDER. However, those
|
||||
* objects cannot be presented to applications. Call the convert() method
|
||||
* to force all Providers to be loaded and to obtain a ProviderList with
|
||||
* invalid entries removed. All this is handled by the Security class.
|
||||
*
|
||||
* Note that all indices used by this class are 0-based per general Java
|
||||
* convention. These must be converted to the 1-based indices used by the
|
||||
* Security class externally when needed.
|
||||
*
|
||||
* Instances of this class are immutable. This eliminates the need for
|
||||
* cloning and synchronization in consumers. The add() and remove() style
|
||||
* methods are static in order to avoid confusion about the immutability.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
public final class ProviderList {
|
||||
|
||||
static final sun.security.util.Debug debug =
|
||||
sun.security.util.Debug.getInstance("jca", "ProviderList");
|
||||
|
||||
private static final ProviderConfig[] PC0 = new ProviderConfig[0];
|
||||
|
||||
private static final Provider[] P0 = new Provider[0];
|
||||
|
||||
// constant for an ProviderList with no elements
|
||||
static final ProviderList EMPTY = new ProviderList(PC0, true);
|
||||
|
||||
// list of all jdk.security.provider.preferred entries
|
||||
static private PreferredList preferredPropList = null;
|
||||
|
||||
// dummy provider object to use during initialization
|
||||
// used to avoid explicit null checks in various places
|
||||
private static final Provider EMPTY_PROVIDER =
|
||||
new Provider("##Empty##", "1.0", "initialization in progress") {
|
||||
private static final long serialVersionUID = 1151354171352296389L;
|
||||
// override getService() to return null slightly faster
|
||||
public Service getService(String type, String algorithm) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// construct a ProviderList from the security properties
|
||||
// (static provider configuration in the java.security file)
|
||||
static ProviderList fromSecurityProperties() {
|
||||
// doPrivileged() because of Security.getProperty()
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<ProviderList>() {
|
||||
public ProviderList run() {
|
||||
return new ProviderList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static ProviderList add(ProviderList providerList, Provider p) {
|
||||
return insertAt(providerList, p, -1);
|
||||
}
|
||||
|
||||
public static ProviderList insertAt(ProviderList providerList, Provider p,
|
||||
int position) {
|
||||
if (providerList.getProvider(p.getName()) != null) {
|
||||
return providerList;
|
||||
}
|
||||
List<ProviderConfig> list = new ArrayList<>
|
||||
(Arrays.asList(providerList.configs));
|
||||
int n = list.size();
|
||||
if ((position < 0) || (position > n)) {
|
||||
position = n;
|
||||
}
|
||||
list.add(position, new ProviderConfig(p));
|
||||
return new ProviderList(list.toArray(PC0), true);
|
||||
}
|
||||
|
||||
public static ProviderList remove(ProviderList providerList, String name) {
|
||||
// make sure provider exists
|
||||
if (providerList.getProvider(name) == null) {
|
||||
return providerList;
|
||||
}
|
||||
// copy all except matching to new list
|
||||
ProviderConfig[] configs = new ProviderConfig[providerList.size() - 1];
|
||||
int j = 0;
|
||||
for (ProviderConfig config : providerList.configs) {
|
||||
if (config.getProvider().getName().equals(name) == false) {
|
||||
configs[j++] = config;
|
||||
}
|
||||
}
|
||||
return new ProviderList(configs, true);
|
||||
}
|
||||
|
||||
// Create a new ProviderList from the specified Providers.
|
||||
// This method is for use by SunJSSE.
|
||||
public static ProviderList newList(Provider ... providers) {
|
||||
ProviderConfig[] configs = new ProviderConfig[providers.length];
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
configs[i] = new ProviderConfig(providers[i]);
|
||||
}
|
||||
return new ProviderList(configs, true);
|
||||
}
|
||||
|
||||
// configuration of the providers
|
||||
private final ProviderConfig[] configs;
|
||||
|
||||
// flag indicating whether all configs have been loaded successfully
|
||||
private volatile boolean allLoaded;
|
||||
|
||||
// List returned by providers()
|
||||
private final List<Provider> userList = new AbstractList<Provider>() {
|
||||
public int size() {
|
||||
return configs.length;
|
||||
}
|
||||
public Provider get(int index) {
|
||||
return getProvider(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ProviderList from an array of configs
|
||||
*/
|
||||
private ProviderList(ProviderConfig[] configs, boolean allLoaded) {
|
||||
this.configs = configs;
|
||||
this.allLoaded = allLoaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new ProviderList parsed from the java.security Properties.
|
||||
*/
|
||||
private ProviderList() {
|
||||
List<ProviderConfig> configList = new ArrayList<>();
|
||||
String entry;
|
||||
int i = 1;
|
||||
|
||||
while ((entry = Security.getProperty("security.provider." + i)) != null) {
|
||||
entry = entry.trim();
|
||||
if (entry.length() == 0) {
|
||||
System.err.println("invalid entry for " +
|
||||
"security.provider." + i);
|
||||
break;
|
||||
}
|
||||
int k = entry.indexOf(' ');
|
||||
ProviderConfig config;
|
||||
if (k == -1) {
|
||||
config = new ProviderConfig(entry);
|
||||
} else {
|
||||
String provName = entry.substring(0, k);
|
||||
String argument = entry.substring(k + 1).trim();
|
||||
config = new ProviderConfig(provName, argument);
|
||||
}
|
||||
|
||||
// Get rid of duplicate providers.
|
||||
if (configList.contains(config) == false) {
|
||||
configList.add(config);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
configs = configList.toArray(PC0);
|
||||
|
||||
// Load config entries for use when getInstance is called
|
||||
entry = Security.getProperty("jdk.security.provider.preferred");
|
||||
if (entry != null && (entry = entry.trim()).length() > 0) {
|
||||
String[] entries = entry.split(",");
|
||||
if (ProviderList.preferredPropList == null) {
|
||||
ProviderList.preferredPropList = new PreferredList();
|
||||
}
|
||||
|
||||
for (String e : entries) {
|
||||
i = e.indexOf(':');
|
||||
if (i < 0) {
|
||||
if (debug != null) {
|
||||
debug.println("invalid preferred entry skipped. " +
|
||||
"Missing colon delimiter \"" + e + "\"");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ProviderList.preferredPropList.add(new PreferredEntry(
|
||||
e.substring(0, i).trim(), e.substring(i + 1).trim()));
|
||||
}
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("provider configuration: " + configList);
|
||||
debug.println("config configuration: " +
|
||||
ProviderList.preferredPropList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a special ProviderList for JAR verification. It consists
|
||||
* of the providers specified via jarClassNames, which must be on the
|
||||
* bootclasspath and cannot be in signed JAR files. This is to avoid
|
||||
* possible recursion and deadlock during verification.
|
||||
*/
|
||||
ProviderList getJarList(String[] jarProvNames) {
|
||||
List<ProviderConfig> newConfigs = new ArrayList<>();
|
||||
for (String provName : jarProvNames) {
|
||||
ProviderConfig newConfig = new ProviderConfig(provName);
|
||||
for (ProviderConfig config : configs) {
|
||||
// if the equivalent object is present in this provider list,
|
||||
// use the old object rather than the new object.
|
||||
// this ensures that when the provider is loaded in the
|
||||
// new thread local list, it will also become available
|
||||
// in this provider list
|
||||
if (config.equals(newConfig)) {
|
||||
newConfig = config;
|
||||
break;
|
||||
}
|
||||
}
|
||||
newConfigs.add(newConfig);
|
||||
}
|
||||
ProviderConfig[] configArray = newConfigs.toArray(PC0);
|
||||
return new ProviderList(configArray, false);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return configs.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Provider at the specified index. Returns EMPTY_PROVIDER
|
||||
* if the provider could not be loaded at this time.
|
||||
*/
|
||||
Provider getProvider(int index) {
|
||||
Provider p = configs[index].getProvider();
|
||||
return (p != null) ? p : EMPTY_PROVIDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an unmodifiable List of all Providers in this List. The
|
||||
* individual Providers are loaded on demand. Elements that could not
|
||||
* be initialized are replaced with EMPTY_PROVIDER.
|
||||
*/
|
||||
public List<Provider> providers() {
|
||||
return userList;
|
||||
}
|
||||
|
||||
private ProviderConfig getProviderConfig(String name) {
|
||||
int index = getIndex(name);
|
||||
return (index != -1) ? configs[index] : null;
|
||||
}
|
||||
|
||||
// return the Provider with the specified name or null
|
||||
public Provider getProvider(String name) {
|
||||
ProviderConfig config = getProviderConfig(name);
|
||||
return (config == null) ? null : config.getProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index at which the provider with the specified name is
|
||||
* installed or -1 if it is not present in this ProviderList.
|
||||
*/
|
||||
public int getIndex(String name) {
|
||||
for (int i = 0; i < configs.length; i++) {
|
||||
Provider p = getProvider(i);
|
||||
if (p.getName().equals(name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// attempt to load all Providers not already loaded
|
||||
private int loadAll() {
|
||||
if (allLoaded) {
|
||||
return configs.length;
|
||||
}
|
||||
if (debug != null) {
|
||||
debug.println("Loading all providers");
|
||||
new Exception("Call trace").printStackTrace();
|
||||
}
|
||||
int n = 0;
|
||||
for (int i = 0; i < configs.length; i++) {
|
||||
Provider p = configs[i].getProvider();
|
||||
if (p != null) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (n == configs.length) {
|
||||
allLoaded = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load all Providers and return the ProviderList. If one or
|
||||
* more Providers could not be loaded, a new ProviderList with those
|
||||
* entries removed is returned. Otherwise, the method returns this.
|
||||
*/
|
||||
ProviderList removeInvalid() {
|
||||
int n = loadAll();
|
||||
if (n == configs.length) {
|
||||
return this;
|
||||
}
|
||||
ProviderConfig[] newConfigs = new ProviderConfig[n];
|
||||
for (int i = 0, j = 0; i < configs.length; i++) {
|
||||
ProviderConfig config = configs[i];
|
||||
if (config.isLoaded()) {
|
||||
newConfigs[j++] = config;
|
||||
}
|
||||
}
|
||||
return new ProviderList(newConfigs, true);
|
||||
}
|
||||
|
||||
// return the providers as an array
|
||||
public Provider[] toArray() {
|
||||
return providers().toArray(P0);
|
||||
}
|
||||
|
||||
// return a String representation of this ProviderList
|
||||
public String toString() {
|
||||
return Arrays.asList(configs).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Service describing an implementation of the specified
|
||||
* algorithm from the Provider with the highest precedence that
|
||||
* supports that algorithm. Return null if no Provider supports this
|
||||
* algorithm.
|
||||
*/
|
||||
public Service getService(String type, String name) {
|
||||
ArrayList<PreferredEntry> pList = null;
|
||||
int i;
|
||||
|
||||
// Preferred provider list
|
||||
if (preferredPropList != null &&
|
||||
(pList = preferredPropList.getAll(type, name)) != null) {
|
||||
for (i = 0; i < pList.size(); i++) {
|
||||
Provider p = getProvider(pList.get(i).provider);
|
||||
Service s = p.getService(type, name);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < configs.length; i++) {
|
||||
Provider p = getProvider(i);
|
||||
Service s = p.getService(type, name);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a List containing all the Services describing implementations
|
||||
* of the specified algorithms in precedence order. If no implementation
|
||||
* exists, this method returns an empty List.
|
||||
*
|
||||
* The elements of this list are determined lazily on demand.
|
||||
*
|
||||
* The List returned is NOT thread safe.
|
||||
*/
|
||||
public List<Service> getServices(String type, String algorithm) {
|
||||
return new ServiceList(type, algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method exists for compatibility with JCE only. It will be removed
|
||||
* once JCE has been changed to use the replacement method.
|
||||
* @deprecated use {@code getServices(List<ServiceId>)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public List<Service> getServices(String type, List<String> algorithms) {
|
||||
List<ServiceId> ids = new ArrayList<>();
|
||||
for (String alg : algorithms) {
|
||||
ids.add(new ServiceId(type, alg));
|
||||
}
|
||||
return getServices(ids);
|
||||
}
|
||||
|
||||
public List<Service> getServices(List<ServiceId> ids) {
|
||||
return new ServiceList(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for a List of Services. Custom List implementation in
|
||||
* order to delay Provider initialization and lookup.
|
||||
* Not thread safe.
|
||||
*/
|
||||
private final class ServiceList extends AbstractList<Service> {
|
||||
|
||||
// type and algorithm for simple lookup
|
||||
// avoid allocating/traversing the ServiceId list for these lookups
|
||||
private final String type;
|
||||
private final String algorithm;
|
||||
|
||||
// list of ids for parallel lookup
|
||||
// if ids is non-null, type and algorithm are null
|
||||
private final List<ServiceId> ids;
|
||||
|
||||
// first service we have found
|
||||
// it is stored in a separate variable so that we can avoid
|
||||
// allocating the services list if we do not need the second service.
|
||||
// this is the case if we don't failover (failovers are typically rare)
|
||||
private Service firstService;
|
||||
|
||||
// list of the services we have found so far
|
||||
private List<Service> services;
|
||||
|
||||
// index into config[] of the next provider we need to query
|
||||
private int providerIndex = 0;
|
||||
|
||||
// Matching preferred provider list for this ServiceList
|
||||
ArrayList<PreferredEntry> preferredList = null;
|
||||
private int preferredIndex = 0;
|
||||
|
||||
ServiceList(String type, String algorithm) {
|
||||
this.type = type;
|
||||
this.algorithm = algorithm;
|
||||
this.ids = null;
|
||||
}
|
||||
|
||||
ServiceList(List<ServiceId> ids) {
|
||||
this.type = null;
|
||||
this.algorithm = null;
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
private void addService(Service s) {
|
||||
if (firstService == null) {
|
||||
firstService = s;
|
||||
} else {
|
||||
if (services == null) {
|
||||
services = new ArrayList<Service>(4);
|
||||
services.add(firstService);
|
||||
}
|
||||
services.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
private Service tryGet(int index) {
|
||||
Provider p;
|
||||
|
||||
// If preferred providers are configured, check for matches with
|
||||
// the requested service.
|
||||
if (preferredPropList != null && preferredList == null) {
|
||||
preferredList = preferredPropList.getAll(this);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if ((index == 0) && (firstService != null)) {
|
||||
return firstService;
|
||||
} else if ((services != null) && (services.size() > index)) {
|
||||
return services.get(index);
|
||||
}
|
||||
if (providerIndex >= configs.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If there were matches with a preferred provider, iterate
|
||||
// through the list first before going through the
|
||||
// ordered list (java.security.provider.#)
|
||||
if (preferredList != null &&
|
||||
preferredIndex < preferredList.size()) {
|
||||
PreferredEntry entry = preferredList.get(preferredIndex++);
|
||||
// Look for the provider name in the PreferredEntry
|
||||
p = getProvider(entry.provider);
|
||||
if (p == null) {
|
||||
if (debug != null) {
|
||||
debug.println("No provider found with name: " +
|
||||
entry.provider);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// check all algorithms in this provider before moving on
|
||||
p = getProvider(providerIndex++);
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
// simple lookup
|
||||
Service s = p.getService(type, algorithm);
|
||||
if (s != null) {
|
||||
addService(s);
|
||||
}
|
||||
} else {
|
||||
// parallel lookup
|
||||
for (ServiceId id : ids) {
|
||||
Service s = p.getService(id.type, id.algorithm);
|
||||
if (s != null) {
|
||||
addService(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Service get(int index) {
|
||||
Service s = tryGet(index);
|
||||
if (s == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
int n;
|
||||
if (services != null) {
|
||||
n = services.size();
|
||||
} else {
|
||||
n = (firstService != null) ? 1 : 0;
|
||||
}
|
||||
while (tryGet(n) != null) {
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// override isEmpty() and iterator() to not call size()
|
||||
// this avoids loading + checking all Providers
|
||||
|
||||
public boolean isEmpty() {
|
||||
return (tryGet(0) == null);
|
||||
}
|
||||
|
||||
public Iterator<Service> iterator() {
|
||||
return new Iterator<Service>() {
|
||||
int index;
|
||||
|
||||
public boolean hasNext() {
|
||||
return tryGet(index) != null;
|
||||
}
|
||||
|
||||
public Service next() {
|
||||
Service s = tryGet(index);
|
||||
if (s == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
index++;
|
||||
return s;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Provider list defined by jdk.security.provider.preferred entry
|
||||
static final class PreferredList {
|
||||
ArrayList<PreferredEntry> list = new ArrayList<PreferredEntry>();
|
||||
|
||||
/*
|
||||
* Return a list of all preferred entries that match the passed
|
||||
* ServiceList.
|
||||
*/
|
||||
ArrayList<PreferredEntry> getAll(ServiceList s) {
|
||||
if (s.ids == null) {
|
||||
return getAll(s.type, s.algorithm);
|
||||
|
||||
}
|
||||
|
||||
ArrayList<PreferredEntry> l = new ArrayList<PreferredEntry>();
|
||||
for (ServiceId id : s.ids) {
|
||||
implGetAll(l, id.type, id.algorithm);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a list of all preferred entries that match the passed
|
||||
* type and algorithm.
|
||||
*/
|
||||
ArrayList<PreferredEntry> getAll(String type, String algorithm) {
|
||||
ArrayList<PreferredEntry> l = new ArrayList<PreferredEntry>();
|
||||
implGetAll(l, type, algorithm);
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare each preferred entry against the passed type and
|
||||
* algorithm, putting any matches in the passed ArrayList.
|
||||
*/
|
||||
private void implGetAll(ArrayList<PreferredEntry> l, String type,
|
||||
String algorithm) {
|
||||
PreferredEntry e;
|
||||
|
||||
for (int i = 0; i < size(); i++) {
|
||||
e = list.get(i);
|
||||
if (e.match(type, algorithm)) {
|
||||
l.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PreferredEntry get(int i) {
|
||||
return list.get(i);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public boolean add(PreferredEntry e) {
|
||||
return list.add(e);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = "";
|
||||
for (PreferredEntry e: list) {
|
||||
s += e.toString();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Defined Groups for jdk.security.provider.preferred */
|
||||
private static final String SHA2Group[] = { "SHA-224", "SHA-256",
|
||||
"SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256" };
|
||||
private static final String HmacSHA2Group[] = { "HmacSHA224",
|
||||
"HmacSHA256", "HmacSHA384", "HmacSHA512"};
|
||||
private static final String SHA2RSAGroup[] = { "SHA224withRSA",
|
||||
"SHA256withRSA", "SHA384withRSA", "SHA512withRSA"};
|
||||
private static final String SHA2DSAGroup[] = { "SHA224withDSA",
|
||||
"SHA256withDSA", "SHA384withDSA", "SHA512withDSA"};
|
||||
private static final String SHA2ECDSAGroup[] = { "SHA224withECDSA",
|
||||
"SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA"};
|
||||
private static final String SHA3Group[] = { "SHA3-224", "SHA3-256",
|
||||
"SHA3-384", "SHA3-512" };
|
||||
private static final String HmacSHA3Group[] = { "HmacSHA3-224",
|
||||
"HmacSHA3-256", "HmacSHA3-384", "HmacSHA3-512"};
|
||||
|
||||
// Individual preferred property entry from jdk.security.provider.preferred
|
||||
private static class PreferredEntry {
|
||||
private String type = null;
|
||||
private String algorithm;
|
||||
private String provider;
|
||||
private String alternateNames[] = null;
|
||||
private boolean group = false;
|
||||
|
||||
PreferredEntry(String t, String p) {
|
||||
int i = t.indexOf('.');
|
||||
if (i > 0) {
|
||||
type = t.substring(0, i);
|
||||
algorithm = t.substring(i + 1);
|
||||
} else {
|
||||
algorithm = t;
|
||||
}
|
||||
|
||||
provider = p;
|
||||
// Group definitions
|
||||
if (type != null && type.compareToIgnoreCase("Group") == 0) {
|
||||
// Currently intrinsic algorithm groups
|
||||
if (algorithm.compareToIgnoreCase("SHA2") == 0) {
|
||||
alternateNames = SHA2Group;
|
||||
} else if (algorithm.compareToIgnoreCase("HmacSHA2") == 0) {
|
||||
alternateNames = HmacSHA2Group;
|
||||
} else if (algorithm.compareToIgnoreCase("SHA2RSA") == 0) {
|
||||
alternateNames = SHA2RSAGroup;
|
||||
} else if (algorithm.compareToIgnoreCase("SHA2DSA") == 0) {
|
||||
alternateNames = SHA2DSAGroup;
|
||||
} else if (algorithm.compareToIgnoreCase("SHA2ECDSA") == 0) {
|
||||
alternateNames = SHA2ECDSAGroup;
|
||||
} else if (algorithm.compareToIgnoreCase("SHA3") == 0) {
|
||||
alternateNames = SHA3Group;
|
||||
} else if (algorithm.compareToIgnoreCase("HmacSHA3") == 0) {
|
||||
alternateNames = HmacSHA3Group;
|
||||
}
|
||||
if (alternateNames != null) {
|
||||
group = true;
|
||||
}
|
||||
|
||||
// If the algorithm name given is SHA1
|
||||
} else if (algorithm.compareToIgnoreCase("SHA1") == 0) {
|
||||
alternateNames = new String[] { "SHA-1" };
|
||||
} else if (algorithm.compareToIgnoreCase("SHA-1") == 0) {
|
||||
alternateNames = new String[] { "SHA1" };
|
||||
}
|
||||
}
|
||||
|
||||
boolean match(String t, String a) {
|
||||
if (debug != null) {
|
||||
debug.println("Config check: " + toString() + " == " +
|
||||
print(t, a, null));
|
||||
}
|
||||
|
||||
// Compare service type if configured
|
||||
if (type != null && !group && type.compareToIgnoreCase(t) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare the algorithm string.
|
||||
if (!group && a.compareToIgnoreCase(algorithm) == 0) {
|
||||
if (debug != null) {
|
||||
debug.println("Config entry matched: " + toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (alternateNames != null) {
|
||||
for (String alt : alternateNames) {
|
||||
if (debug != null) {
|
||||
debug.println("AltName check: " + print(type, alt,
|
||||
provider));
|
||||
}
|
||||
if (a.compareToIgnoreCase(alt) == 0) {
|
||||
if (debug != null) {
|
||||
debug.println("AltName entry matched: " +
|
||||
provider);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No match
|
||||
return false;
|
||||
}
|
||||
|
||||
// Print debugging output of PreferredEntry
|
||||
private String print(String t, String a, String p) {
|
||||
return "[" + ((t != null) ? t : "" ) + ", " + a +
|
||||
((p != null) ? " : " + p : "" ) + "] ";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return print(type, algorithm, provider);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
247
src/java.base/share/classes/sun/security/jca/Providers.java
Normal file
247
src/java.base/share/classes/sun/security/jca/Providers.java
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
/**
|
||||
* Collection of methods to get and set provider list. Also includes
|
||||
* special code for the provider list during JAR verification.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Providers {
|
||||
|
||||
private static final ThreadLocal<ProviderList> threadLists =
|
||||
new InheritableThreadLocal<>();
|
||||
|
||||
// number of threads currently using thread-local provider lists
|
||||
// tracked to allow an optimization if == 0
|
||||
private static volatile int threadListsUsed;
|
||||
|
||||
// current system-wide provider list
|
||||
// Note volatile immutable object, so no synchronization needed.
|
||||
private static volatile ProviderList providerList;
|
||||
|
||||
static {
|
||||
// set providerList to empty list first in case initialization somehow
|
||||
// triggers a getInstance() call (although that should not happen)
|
||||
providerList = ProviderList.EMPTY;
|
||||
providerList = ProviderList.fromSecurityProperties();
|
||||
}
|
||||
|
||||
private Providers() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// After the switch to modules, JDK providers are all in modules and JDK
|
||||
// no longer needs to load signed jars during start up.
|
||||
//
|
||||
// However, for earlier releases, it need special handling to resolve
|
||||
// circularities when loading signed JAR files during startup. The code
|
||||
// below is part of that.
|
||||
//
|
||||
// Basically, before we load data from a signed JAR file, we parse
|
||||
// the PKCS#7 file and verify the signature. We need a
|
||||
// CertificateFactory, Signatures, etc. to do that. We have to make
|
||||
// sure that we do not try to load the implementation from the JAR
|
||||
// file we are just verifying.
|
||||
//
|
||||
// To avoid that, we use different provider settings during JAR
|
||||
// verification. However, we do not want those provider settings to
|
||||
// interfere with other parts of the system. Therefore, we make them local
|
||||
// to the Thread executing the JAR verification code.
|
||||
//
|
||||
// The code here is used by sun.security.util.SignatureFileVerifier.
|
||||
// See there for details.
|
||||
|
||||
// Hardcoded names of providers to use for JAR verification.
|
||||
// MUST NOT be on the bootclasspath and not in signed JAR files.
|
||||
private static final String[] jarVerificationProviders = {
|
||||
"SUN",
|
||||
"SunRsaSign",
|
||||
// Note: when SunEC is in a signed JAR file, it's not signed
|
||||
// by EC algorithms. So it's still safe to be listed here.
|
||||
"SunEC",
|
||||
};
|
||||
|
||||
// Return Sun provider.
|
||||
// This method should only be called by
|
||||
// sun.security.util.ManifestEntryVerifier and java.security.SecureRandom.
|
||||
public static Provider getSunProvider() {
|
||||
return new sun.security.provider.Sun();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start JAR verification. This sets a special provider list for
|
||||
* the current thread. You MUST save the return value from this
|
||||
* method and you MUST call stopJarVerification() with that object
|
||||
* once you are done.
|
||||
*/
|
||||
public static Object startJarVerification() {
|
||||
ProviderList currentList = getProviderList();
|
||||
ProviderList jarList = currentList.getJarList(jarVerificationProviders);
|
||||
if (jarList.getProvider("SUN") == null) {
|
||||
// add backup provider
|
||||
Provider p;
|
||||
try {
|
||||
p = new sun.security.provider.VerificationProvider();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Missing provider for jar verification", e);
|
||||
}
|
||||
ProviderList.add(jarList, p);
|
||||
}
|
||||
// return the old thread-local provider list, usually null
|
||||
return beginThreadProviderList(jarList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop JAR verification. Call once you have completed JAR verification.
|
||||
*/
|
||||
public static void stopJarVerification(Object obj) {
|
||||
// restore old thread-local provider list
|
||||
endThreadProviderList((ProviderList)obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current ProviderList. If the thread-local list is set,
|
||||
* it is returned. Otherwise, the system wide list is returned.
|
||||
*/
|
||||
public static ProviderList getProviderList() {
|
||||
ProviderList list = getThreadProviderList();
|
||||
if (list == null) {
|
||||
list = getSystemProviderList();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current ProviderList. Affects the thread-local list if set,
|
||||
* otherwise the system wide list.
|
||||
*/
|
||||
public static void setProviderList(ProviderList newList) {
|
||||
if (getThreadProviderList() == null) {
|
||||
setSystemProviderList(newList);
|
||||
} else {
|
||||
changeThreadProviderList(newList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full provider list with invalid providers (those that
|
||||
* could not be loaded) removed. This is the list we need to
|
||||
* present to applications.
|
||||
*/
|
||||
public static ProviderList getFullProviderList() {
|
||||
ProviderList list;
|
||||
synchronized (Providers.class) {
|
||||
list = getThreadProviderList();
|
||||
if (list != null) {
|
||||
ProviderList newList = list.removeInvalid();
|
||||
if (newList != list) {
|
||||
changeThreadProviderList(newList);
|
||||
list = newList;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
list = getSystemProviderList();
|
||||
ProviderList newList = list.removeInvalid();
|
||||
if (newList != list) {
|
||||
setSystemProviderList(newList);
|
||||
list = newList;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static ProviderList getSystemProviderList() {
|
||||
return providerList;
|
||||
}
|
||||
|
||||
private static void setSystemProviderList(ProviderList list) {
|
||||
providerList = list;
|
||||
}
|
||||
|
||||
public static ProviderList getThreadProviderList() {
|
||||
// avoid accessing the threadlocal if none are currently in use
|
||||
// (first use of ThreadLocal.get() for a Thread allocates a Map)
|
||||
if (threadListsUsed == 0) {
|
||||
return null;
|
||||
}
|
||||
return threadLists.get();
|
||||
}
|
||||
|
||||
// Change the thread local provider list. Use only if the current thread
|
||||
// is already using a thread local list and you want to change it in place.
|
||||
// In other cases, use the begin/endThreadProviderList() methods.
|
||||
private static void changeThreadProviderList(ProviderList list) {
|
||||
threadLists.set(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods to manipulate the thread local provider list. It is for use by
|
||||
* JAR verification (see above) and the SunJSSE FIPS mode only.
|
||||
*
|
||||
* It should be used as follows:
|
||||
*
|
||||
* ProviderList list = ...;
|
||||
* ProviderList oldList = Providers.beginThreadProviderList(list);
|
||||
* try {
|
||||
* // code that needs thread local provider list
|
||||
* } finally {
|
||||
* Providers.endThreadProviderList(oldList);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
public static synchronized ProviderList beginThreadProviderList(ProviderList list) {
|
||||
if (ProviderList.debug != null) {
|
||||
ProviderList.debug.println("ThreadLocal providers: " + list);
|
||||
}
|
||||
ProviderList oldList = threadLists.get();
|
||||
threadListsUsed++;
|
||||
threadLists.set(list);
|
||||
return oldList;
|
||||
}
|
||||
|
||||
public static synchronized void endThreadProviderList(ProviderList list) {
|
||||
if (list == null) {
|
||||
if (ProviderList.debug != null) {
|
||||
ProviderList.debug.println("Disabling ThreadLocal providers");
|
||||
}
|
||||
threadLists.remove();
|
||||
} else {
|
||||
if (ProviderList.debug != null) {
|
||||
ProviderList.debug.println
|
||||
("Restoring previous ThreadLocal providers: " + list);
|
||||
}
|
||||
threadLists.set(list);
|
||||
}
|
||||
threadListsUsed--;
|
||||
}
|
||||
|
||||
}
|
45
src/java.base/share/classes/sun/security/jca/ServiceId.java
Normal file
45
src/java.base/share/classes/sun/security/jca/ServiceId.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.jca;
|
||||
|
||||
/**
|
||||
* Simple class encapsulating a service type and algorithm for lookup.
|
||||
* Put in a separate file rather than nested to allow import via ...jca.*.
|
||||
*
|
||||
* @author Andreas Sterbenz
|
||||
* @since 1.5
|
||||
*/
|
||||
public final class ServiceId {
|
||||
|
||||
public final String type;
|
||||
public final String algorithm;
|
||||
|
||||
public ServiceId(String type, String algorithm) {
|
||||
this.type = type;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue