Path: blob/master/src/java.base/share/classes/sun/security/jca/Providers.java
67848 views
/*1* Copyright (c) 2003, 2021, 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;28import sun.security.x509.AlgorithmId;2930/**31* Collection of methods to get and set provider list. Also includes32* special code for the provider list during JAR verification.33*34* @author Andreas Sterbenz35* @since 1.536*/37public class Providers {3839private static final ThreadLocal<ProviderList> threadLists =40new ThreadLocal<>();4142// number of threads currently using thread-local provider lists43// tracked to allow an optimization if == 044private static volatile int threadListsUsed;4546// current system-wide provider list47// Note volatile immutable object, so no synchronization needed.48private static volatile ProviderList providerList;4950static {51// set providerList to empty list first in case initialization somehow52// triggers a getInstance() call (although that should not happen)53providerList = ProviderList.EMPTY;54providerList = ProviderList.fromSecurityProperties();55}5657private Providers() {58// empty59}6061// After the switch to modules, JDK providers are all in modules and JDK62// no longer needs to load signed jars during start up.63//64// However, for earlier releases, it need special handling to resolve65// circularities when loading signed JAR files during startup. The code66// below is part of that.67//68// Basically, before we load data from a signed JAR file, we parse69// the PKCS#7 file and verify the signature. We need a70// CertificateFactory, Signatures, etc. to do that. We have to make71// sure that we do not try to load the implementation from the JAR72// file we are just verifying.73//74// To avoid that, we use different provider settings during JAR75// verification. However, we do not want those provider settings to76// interfere with other parts of the system. Therefore, we make them local77// to the Thread executing the JAR verification code.78//79// The code here is used by sun.security.util.SignatureFileVerifier.80// See there for details.8182// Hardcoded names of providers to use for JAR verification.83// MUST NOT be on the bootclasspath and not in signed JAR files.84private static final String[] jarVerificationProviders = {85"SUN",86"SunRsaSign",87// Note: when SunEC is in a signed JAR file, it's not signed88// by EC algorithms. So it's still safe to be listed here.89"SunEC",90"SunJCE",91};9293// Return Sun provider.94// This method should only be called by95// sun.security.util.ManifestEntryVerifier and java.security.SecureRandom.96public static Provider getSunProvider() {97return new sun.security.provider.Sun();98}99100/**101* Start JAR verification. This sets a special provider list for102* the current thread. You MUST save the return value from this103* method and you MUST call stopJarVerification() with that object104* once you are done.105*/106public static Object startJarVerification() {107ProviderList currentList = getProviderList();108ProviderList jarList = currentList.getJarList(jarVerificationProviders);109if (jarList.getProvider("SUN") == null) {110// add backup provider111Provider p;112try {113p = new sun.security.provider.VerificationProvider();114} catch (Exception e) {115throw new RuntimeException("Missing provider for jar verification", e);116}117ProviderList.add(jarList, p);118}119// return the old thread-local provider list, usually null120return beginThreadProviderList(jarList);121}122123/**124* Stop JAR verification. Call once you have completed JAR verification.125*/126public static void stopJarVerification(Object obj) {127// restore old thread-local provider list128endThreadProviderList((ProviderList)obj);129}130131/**132* Return the current ProviderList. If the thread-local list is set,133* it is returned. Otherwise, the system wide list is returned.134*/135public static ProviderList getProviderList() {136ProviderList list = getThreadProviderList();137if (list == null) {138list = getSystemProviderList();139}140return list;141}142143/**144* Set the current ProviderList. Affects the thread-local list if set,145* otherwise the system wide list.146*/147public static void setProviderList(ProviderList newList) {148if (getThreadProviderList() == null) {149setSystemProviderList(newList);150} else {151changeThreadProviderList(newList);152}153clearCachedValues();154}155156/**157* Clears the cached provider-list-specific values. These values need to158* be re-generated whenever provider list is changed. The logic for159* generating them is in the respective classes.160*/161private static void clearCachedValues() {162JCAUtil.clearDefSecureRandom();163AlgorithmId.clearAliasOidsTable();164}165166/**167* Get the full provider list with invalid providers (those that168* could not be loaded) removed. This is the list we need to169* present to applications.170*/171public static ProviderList getFullProviderList() {172ProviderList list;173synchronized (Providers.class) {174list = getThreadProviderList();175if (list != null) {176ProviderList newList = list.removeInvalid();177if (newList != list) {178changeThreadProviderList(newList);179list = newList;180}181return list;182}183}184list = getSystemProviderList();185ProviderList newList = list.removeInvalid();186if (newList != list) {187setSystemProviderList(newList);188list = newList;189}190return list;191}192193private static ProviderList getSystemProviderList() {194return providerList;195}196197private static void setSystemProviderList(ProviderList list) {198providerList = list;199}200201public static ProviderList getThreadProviderList() {202// avoid accessing the threadlocal if none are currently in use203// (first use of ThreadLocal.get() for a Thread allocates a Map)204if (threadListsUsed == 0) {205return null;206}207return threadLists.get();208}209210// Change the thread local provider list. Use only if the current thread211// is already using a thread local list and you want to change it in place.212// In other cases, use the begin/endThreadProviderList() methods.213private static void changeThreadProviderList(ProviderList list) {214threadLists.set(list);215}216217/**218* Methods to manipulate the thread local provider list. It is for use by219* JAR verification (see above).220*221* It should be used as follows:222*223* ProviderList list = ...;224* ProviderList oldList = Providers.beginThreadProviderList(list);225* try {226* // code that needs thread local provider list227* } finally {228* Providers.endThreadProviderList(oldList);229* }230*231*/232233public static synchronized ProviderList beginThreadProviderList(ProviderList list) {234if (ProviderList.debug != null) {235ProviderList.debug.println("ThreadLocal providers: " + list);236}237ProviderList oldList = threadLists.get();238threadListsUsed++;239threadLists.set(list);240return oldList;241}242243public static synchronized void endThreadProviderList(ProviderList list) {244if (list == null) {245if (ProviderList.debug != null) {246ProviderList.debug.println("Disabling ThreadLocal providers");247}248threadLists.remove();249} else {250if (ProviderList.debug != null) {251ProviderList.debug.println252("Restoring previous ThreadLocal providers: " + list);253}254threadLists.set(list);255}256threadListsUsed--;257}258259}260261262