Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jca/Providers.java
38831 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.jca;2627import java.security.Provider;2829/**30* Collection of methods to get and set provider list. Also includes31* special code for the provider list during JAR verification.32*33* @author Andreas Sterbenz34* @since 1.535*/36public class Providers {3738private static final ThreadLocal<ProviderList> threadLists =39new InheritableThreadLocal<>();4041// number of threads currently using thread-local provider lists42// tracked to allow an optimization if == 043private static volatile int threadListsUsed;4445// current system-wide provider list46// Note volatile immutable object, so no synchronization needed.47private static volatile ProviderList providerList;4849static {50// set providerList to empty list first in case initialization somehow51// triggers a getInstance() call (although that should not happen)52providerList = ProviderList.EMPTY;53providerList = ProviderList.fromSecurityProperties();54}5556private Providers() {57// empty58}5960// we need special handling to resolve circularities when loading61// signed JAR files during startup. The code below is part of that.6263// Basically, before we load data from a signed JAR file, we parse64// the PKCS#7 file and verify the signature. We need a65// CertificateFactory, Signatures, etc. to do that. We have to make66// sure that we do not try to load the implementation from the JAR67// file we are just verifying.68//69// To avoid that, we use different provider settings during JAR70// verification. However, we do not want those provider settings to71// interfere with other parts of the system. Therefore, we make them local72// to the Thread executing the JAR verification code.73//74// The code here is used by sun.security.util.SignatureFileVerifier.75// See there for details.7677private static final String BACKUP_PROVIDER_CLASSNAME =78"sun.security.provider.VerificationProvider";7980// Hardcoded classnames of providers to use for JAR verification.81// MUST NOT be on the bootclasspath and not in signed JAR files.82private static final String[] jarVerificationProviders = {83"sun.security.provider.Sun",84"sun.security.rsa.SunRsaSign",85// Note: SunEC *is* in a signed JAR file, but it's not signed86// by EC itself. So it's still safe to be listed here.87"sun.security.ec.SunEC",88BACKUP_PROVIDER_CLASSNAME,89};9091// Return to Sun provider or its backup.92// This method should only be called by93// sun.security.util.ManifestEntryVerifier and java.security.SecureRandom.94public static Provider getSunProvider() {95try {96Class<?> clazz = Class.forName(jarVerificationProviders[0]);97return (Provider)clazz.newInstance();98} catch (Exception e) {99try {100Class<?> clazz = Class.forName(BACKUP_PROVIDER_CLASSNAME);101return (Provider)clazz.newInstance();102} catch (Exception ee) {103throw new RuntimeException("Sun provider not found", e);104}105}106}107108/**109* Start JAR verification. This sets a special provider list for110* the current thread. You MUST save the return value from this111* method and you MUST call stopJarVerification() with that object112* once you are done.113*/114public static Object startJarVerification() {115ProviderList currentList = getProviderList();116ProviderList jarList = currentList.getJarList(jarVerificationProviders);117// return the old thread-local provider list, usually null118return beginThreadProviderList(jarList);119}120121/**122* Stop JAR verification. Call once you have completed JAR verification.123*/124public static void stopJarVerification(Object obj) {125// restore old thread-local provider list126endThreadProviderList((ProviderList)obj);127}128129/**130* Return the current ProviderList. If the thread-local list is set,131* it is returned. Otherwise, the system wide list is returned.132*/133public static ProviderList getProviderList() {134ProviderList list = getThreadProviderList();135if (list == null) {136list = getSystemProviderList();137}138return list;139}140141/**142* Set the current ProviderList. Affects the thread-local list if set,143* otherwise the system wide list.144*/145public static void setProviderList(ProviderList newList) {146if (getThreadProviderList() == null) {147setSystemProviderList(newList);148} else {149changeThreadProviderList(newList);150}151}152153/**154* Get the full provider list with invalid providers (those that155* could not be loaded) removed. This is the list we need to156* present to applications.157*/158public static ProviderList getFullProviderList() {159ProviderList list;160synchronized (Providers.class) {161list = getThreadProviderList();162if (list != null) {163ProviderList newList = list.removeInvalid();164if (newList != list) {165changeThreadProviderList(newList);166list = newList;167}168return list;169}170}171list = getSystemProviderList();172ProviderList newList = list.removeInvalid();173if (newList != list) {174setSystemProviderList(newList);175list = newList;176}177return list;178}179180private static ProviderList getSystemProviderList() {181return providerList;182}183184private static void setSystemProviderList(ProviderList list) {185providerList = list;186}187188public static ProviderList getThreadProviderList() {189// avoid accessing the threadlocal if none are currently in use190// (first use of ThreadLocal.get() for a Thread allocates a Map)191if (threadListsUsed == 0) {192return null;193}194return threadLists.get();195}196197// Change the thread local provider list. Use only if the current thread198// is already using a thread local list and you want to change it in place.199// In other cases, use the begin/endThreadProviderList() methods.200private static void changeThreadProviderList(ProviderList list) {201threadLists.set(list);202}203204/**205* Methods to manipulate the thread local provider list. It is for use by206* JAR verification (see above) and the SunJSSE FIPS mode only.207*208* It should be used as follows:209*210* ProviderList list = ...;211* ProviderList oldList = Providers.beginThreadProviderList(list);212* try {213* // code that needs thread local provider list214* } finally {215* Providers.endThreadProviderList(oldList);216* }217*218*/219220public static synchronized ProviderList beginThreadProviderList(ProviderList list) {221if (ProviderList.debug != null) {222ProviderList.debug.println("ThreadLocal providers: " + list);223}224ProviderList oldList = threadLists.get();225threadListsUsed++;226threadLists.set(list);227return oldList;228}229230public static synchronized void endThreadProviderList(ProviderList list) {231if (list == null) {232if (ProviderList.debug != null) {233ProviderList.debug.println("Disabling ThreadLocal providers");234}235threadLists.remove();236} else {237if (ProviderList.debug != null) {238ProviderList.debug.println239("Restoring previous ThreadLocal providers: " + list);240}241threadLists.set(list);242}243threadListsUsed--;244}245246}247248249