|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.jca; |
|
|
|
import java.security.Provider; |
|
import sun.security.x509.AlgorithmId; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class Providers { |
|
|
|
private static final ThreadLocal<ProviderList> threadLists = |
|
new ThreadLocal<>(); |
|
|
|
// number of threads currently using thread-local provider lists |
|
|
|
private static volatile int threadListsUsed; |
|
|
|
// current system-wide provider list |
|
|
|
private static volatile ProviderList providerList; |
|
|
|
static { |
|
// set providerList to empty list first in case initialization somehow |
|
|
|
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. |
|
|
|
private static final String[] jarVerificationProviders = { |
|
"SUN", |
|
"SunRsaSign", |
|
// Note: when SunEC is in a signed JAR file, it's not signed |
|
|
|
"SunEC", |
|
"SunJCE", |
|
}; |
|
|
|
// Return Sun provider. |
|
// This method should only be called by |
|
|
|
public static Provider getSunProvider() { |
|
return new sun.security.provider.Sun(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Object startJarVerification() { |
|
ProviderList currentList = getProviderList(); |
|
ProviderList jarList = currentList.getJarList(jarVerificationProviders); |
|
if (jarList.getProvider("SUN") == null) { |
|
|
|
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 beginThreadProviderList(jarList); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void stopJarVerification(Object obj) { |
|
|
|
endThreadProviderList((ProviderList)obj); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static ProviderList getProviderList() { |
|
ProviderList list = getThreadProviderList(); |
|
if (list == null) { |
|
list = getSystemProviderList(); |
|
} |
|
return list; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void setProviderList(ProviderList newList) { |
|
if (getThreadProviderList() == null) { |
|
setSystemProviderList(newList); |
|
} else { |
|
changeThreadProviderList(newList); |
|
} |
|
clearCachedValues(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static void clearCachedValues() { |
|
JCAUtil.clearDefSecureRandom(); |
|
AlgorithmId.clearAliasOidsTable(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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 |
|
|
|
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. |
|
|
|
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). |
|
* |
|
* 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--; |
|
} |
|
|
|
} |