Path: blob/master/src/java.base/share/classes/sun/security/jca/Providers.java
41159 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;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 ThreadLocal<>();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// After the switch to modules, JDK providers are all in modules and JDK61// no longer needs to load signed jars during start up.62//63// However, for earlier releases, it need special handling to resolve64// circularities when loading signed JAR files during startup. The code65// below is part of that.66//67// Basically, before we load data from a signed JAR file, we parse68// the PKCS#7 file and verify the signature. We need a69// CertificateFactory, Signatures, etc. to do that. We have to make70// sure that we do not try to load the implementation from the JAR71// file we are just verifying.72//73// To avoid that, we use different provider settings during JAR74// verification. However, we do not want those provider settings to75// interfere with other parts of the system. Therefore, we make them local76// to the Thread executing the JAR verification code.77//78// The code here is used by sun.security.util.SignatureFileVerifier.79// See there for details.8081// Hardcoded names of providers to use for JAR verification.82// MUST NOT be on the bootclasspath and not in signed JAR files.83private static final String[] jarVerificationProviders = {84"SUN",85"SunRsaSign",86// Note: when SunEC is in a signed JAR file, it's not signed87// by EC algorithms. So it's still safe to be listed here.88"SunEC",89"SunJCE",90};9192// Return Sun provider.93// This method should only be called by94// sun.security.util.ManifestEntryVerifier and java.security.SecureRandom.95public static Provider getSunProvider() {96return new sun.security.provider.Sun();97}9899/**100* Start JAR verification. This sets a special provider list for101* the current thread. You MUST save the return value from this102* method and you MUST call stopJarVerification() with that object103* once you are done.104*/105public static Object startJarVerification() {106ProviderList currentList = getProviderList();107ProviderList jarList = currentList.getJarList(jarVerificationProviders);108if (jarList.getProvider("SUN") == null) {109// add backup provider110Provider p;111try {112p = new sun.security.provider.VerificationProvider();113} catch (Exception e) {114throw new RuntimeException("Missing provider for jar verification", e);115}116ProviderList.add(jarList, p);117}118// return the old thread-local provider list, usually null119return beginThreadProviderList(jarList);120}121122/**123* Stop JAR verification. Call once you have completed JAR verification.124*/125public static void stopJarVerification(Object obj) {126// restore old thread-local provider list127endThreadProviderList((ProviderList)obj);128}129130/**131* Return the current ProviderList. If the thread-local list is set,132* it is returned. Otherwise, the system wide list is returned.133*/134public static ProviderList getProviderList() {135ProviderList list = getThreadProviderList();136if (list == null) {137list = getSystemProviderList();138}139return list;140}141142/**143* Set the current ProviderList. Affects the thread-local list if set,144* otherwise the system wide list.145*/146public static void setProviderList(ProviderList newList) {147if (getThreadProviderList() == null) {148setSystemProviderList(newList);149} else {150changeThreadProviderList(newList);151}152JCAUtil.clearDefSecureRandom();153}154155/**156* Get the full provider list with invalid providers (those that157* could not be loaded) removed. This is the list we need to158* present to applications.159*/160public static ProviderList getFullProviderList() {161ProviderList list;162synchronized (Providers.class) {163list = getThreadProviderList();164if (list != null) {165ProviderList newList = list.removeInvalid();166if (newList != list) {167changeThreadProviderList(newList);168list = newList;169}170return list;171}172}173list = getSystemProviderList();174ProviderList newList = list.removeInvalid();175if (newList != list) {176setSystemProviderList(newList);177list = newList;178}179return list;180}181182private static ProviderList getSystemProviderList() {183return providerList;184}185186private static void setSystemProviderList(ProviderList list) {187providerList = list;188}189190public static ProviderList getThreadProviderList() {191// avoid accessing the threadlocal if none are currently in use192// (first use of ThreadLocal.get() for a Thread allocates a Map)193if (threadListsUsed == 0) {194return null;195}196return threadLists.get();197}198199// Change the thread local provider list. Use only if the current thread200// is already using a thread local list and you want to change it in place.201// In other cases, use the begin/endThreadProviderList() methods.202private static void changeThreadProviderList(ProviderList list) {203threadLists.set(list);204}205206/**207* Methods to manipulate the thread local provider list. It is for use by208* JAR verification (see above).209*210* It should be used as follows:211*212* ProviderList list = ...;213* ProviderList oldList = Providers.beginThreadProviderList(list);214* try {215* // code that needs thread local provider list216* } finally {217* Providers.endThreadProviderList(oldList);218* }219*220*/221222public static synchronized ProviderList beginThreadProviderList(ProviderList list) {223if (ProviderList.debug != null) {224ProviderList.debug.println("ThreadLocal providers: " + list);225}226ProviderList oldList = threadLists.get();227threadListsUsed++;228threadLists.set(list);229return oldList;230}231232public static synchronized void endThreadProviderList(ProviderList list) {233if (list == null) {234if (ProviderList.debug != null) {235ProviderList.debug.println("Disabling ThreadLocal providers");236}237threadLists.remove();238} else {239if (ProviderList.debug != null) {240ProviderList.debug.println241("Restoring previous ThreadLocal providers: " + list);242}243threadLists.set(list);244}245threadListsUsed--;246}247248}249250251