|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.jca; |
|
|
|
import java.security.Provider; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class Providers { |
|
|
|
private static final ThreadLocal<ProviderList> threadLists = |
|
new InheritableThreadLocal<>(); |
|
|
|
// 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 |
|
} |
|
|
|
// we 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. |
|
|
|
private static final String BACKUP_PROVIDER_CLASSNAME = |
|
"sun.security.provider.VerificationProvider"; |
|
|
|
// Hardcoded classnames of providers to use for JAR verification. |
|
|
|
private static final String[] jarVerificationProviders = { |
|
"sun.security.provider.Sun", |
|
"sun.security.rsa.SunRsaSign", |
|
// Note: SunEC *is* in a signed JAR file, but it's not signed |
|
|
|
"sun.security.ec.SunEC", |
|
BACKUP_PROVIDER_CLASSNAME, |
|
}; |
|
|
|
// Return to Sun provider or its backup. |
|
// This method should only be called by |
|
|
|
public static Provider getSunProvider() { |
|
try { |
|
Class<?> clazz = Class.forName(jarVerificationProviders[0]); |
|
return (Provider)clazz.newInstance(); |
|
} catch (Exception e) { |
|
try { |
|
Class<?> clazz = Class.forName(BACKUP_PROVIDER_CLASSNAME); |
|
return (Provider)clazz.newInstance(); |
|
} catch (Exception ee) { |
|
throw new RuntimeException("Sun provider not found", e); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Object startJarVerification() { |
|
ProviderList currentList = getProviderList(); |
|
ProviderList jarList = currentList.getJarList(jarVerificationProviders); |
|
|
|
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); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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) 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--; |
|
} |
|
|
|
} |