Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java
38922 views
/*1* Copyright (c) 2000, 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*/2425/*26* NOTE: this file was copied from javax.net.ssl.SSLSecurity,27* but was heavily modified to allow com.sun.* users to28* access providers written using the javax.sun.* APIs.29*/3031package com.sun.net.ssl;3233import java.util.*;34import java.io.*;35import java.security.*;36import java.security.Provider.Service;37import java.net.Socket;3839import sun.security.jca.*;4041/**42* This class instantiates implementations of JSSE engine classes from43* providers registered with the java.security.Security object.44*45* @author Jan Luehe46* @author Jeff Nisewanger47* @author Brad Wetmore48*/4950final class SSLSecurity {5152/*53* Don't let anyone instantiate this.54*/55private SSLSecurity() {56}575859// ProviderList.getService() is not accessible now, implement our own loop60private static Service getService(String type, String alg) {61ProviderList list = Providers.getProviderList();62for (Provider p : list.providers()) {63Service s = p.getService(type, alg);64if (s != null) {65return s;66}67}68return null;69}7071/**72* The body of the driver for the getImpl method.73*/74private static Object[] getImpl1(String algName, String engineType,75Service service) throws NoSuchAlgorithmException76{77Provider provider = service.getProvider();78String className = service.getClassName();79Class<?> implClass;80try {81ClassLoader cl = provider.getClass().getClassLoader();82if (cl == null) {83// system class84implClass = Class.forName(className);85} else {86implClass = cl.loadClass(className);87}88} catch (ClassNotFoundException e) {89throw new NoSuchAlgorithmException("Class " + className +90" configured for " +91engineType +92" not found: " +93e.getMessage());94} catch (SecurityException e) {95throw new NoSuchAlgorithmException("Class " + className +96" configured for " +97engineType +98" cannot be accessed: " +99e.getMessage());100}101102/*103* JSSE 1.0, 1.0.1, and 1.0.2 used the com.sun.net.ssl API as the104* API was being developed. As JSSE was folded into the main105* release, it was decided to promote the com.sun.net.ssl API to106* be javax.net.ssl. It is desired to keep binary compatibility107* with vendors of JSSE implementation written using the108* com.sun.net.sll API, so we do this magic to handle everything.109*110* API used Implementation used Supported?111* ======== =================== ==========112* com.sun javax Yes113* com.sun com.sun Yes114* javax javax Yes115* javax com.sun Not Currently116*117* Make sure the implementation class is a subclass of the118* corresponding engine class.119*120* In wrapping these classes, there's no way to know how to121* wrap all possible classes that extend the TrustManager/KeyManager.122* We only wrap the x509 variants.123*/124125try { // catch instantiation errors126127/*128* (The following Class.forName()s should alway work, because129* this class and all the SPI classes in javax.crypto are130* loaded by the same class loader.) That is, unless they131* give us a SPI class that doesn't exist, say SSLFoo,132* or someone has removed classes from the jsse.jar file.133*/134135Class<?> typeClassJavax;136Class<?> typeClassCom;137Object obj = null;138139/*140* Odds are more likely that we have a javax variant, try this141* first.142*/143if (((typeClassJavax = Class.forName("javax.net.ssl." +144engineType + "Spi")) != null) &&145(checkSuperclass(implClass, typeClassJavax))) {146147if (engineType.equals("SSLContext")) {148obj = new SSLContextSpiWrapper(algName, provider);149} else if (engineType.equals("TrustManagerFactory")) {150obj = new TrustManagerFactorySpiWrapper(algName, provider);151} else if (engineType.equals("KeyManagerFactory")) {152obj = new KeyManagerFactorySpiWrapper(algName, provider);153} else {154/*155* We should throw an error if we get156* something totally unexpected. Don't ever157* expect to see this one...158*/159throw new IllegalStateException(160"Class " + implClass.getName() +161" unknown engineType wrapper:" + engineType);162}163164} else if (((typeClassCom = Class.forName("com.sun.net.ssl." +165engineType + "Spi")) != null) &&166(checkSuperclass(implClass, typeClassCom))) {167obj = service.newInstance(null);168}169170if (obj != null) {171return new Object[] { obj, provider };172} else {173throw new NoSuchAlgorithmException(174"Couldn't locate correct object or wrapper: " +175engineType + " " + algName);176}177178} catch (ClassNotFoundException e) {179IllegalStateException exc = new IllegalStateException(180"Engine Class Not Found for " + engineType);181exc.initCause(e);182throw exc;183}184}185186/**187* Returns an array of objects: the first object in the array is188* an instance of an implementation of the requested algorithm189* and type, and the second object in the array identifies the provider190* of that implementation.191* The <code>provName</code> argument can be null, in which case all192* configured providers will be searched in order of preference.193*/194static Object[] getImpl(String algName, String engineType, String provName)195throws NoSuchAlgorithmException, NoSuchProviderException196{197Service service;198if (provName != null) {199ProviderList list = Providers.getProviderList();200Provider prov = list.getProvider(provName);201if (prov == null) {202throw new NoSuchProviderException("No such provider: " +203provName);204}205service = prov.getService(engineType, algName);206} else {207service = getService(engineType, algName);208}209if (service == null) {210throw new NoSuchAlgorithmException("Algorithm " + algName211+ " not available");212}213return getImpl1(algName, engineType, service);214}215216217/**218* Returns an array of objects: the first object in the array is219* an instance of an implementation of the requested algorithm220* and type, and the second object in the array identifies the provider221* of that implementation.222* The <code>prov</code> argument can be null, in which case all223* configured providers will be searched in order of preference.224*/225static Object[] getImpl(String algName, String engineType, Provider prov)226throws NoSuchAlgorithmException227{228Service service = prov.getService(engineType, algName);229if (service == null) {230throw new NoSuchAlgorithmException("No such algorithm: " +231algName);232}233return getImpl1(algName, engineType, service);234}235236/*237* Checks whether one class is the superclass of another238*/239private static boolean checkSuperclass(Class<?> subclass, Class<?> superclass) {240if ((subclass == null) || (superclass == null))241return false;242243while (!subclass.equals(superclass)) {244subclass = subclass.getSuperclass();245if (subclass == null) {246return false;247}248}249return true;250}251252/*253* Return at most the first "resize" elements of an array.254*255* Didn't want to use java.util.Arrays, as PJava may not have it.256*/257static Object[] truncateArray(Object[] oldArray, Object[] newArray) {258259for (int i = 0; i < newArray.length; i++) {260newArray[i] = oldArray[i];261}262263return newArray;264}265266}267268269/*270* =================================================================271* The remainder of this file is for the wrapper and wrapper-support272* classes. When SSLSecurity finds something which extends the273* javax.net.ssl.*Spi, we need to go grab a real instance of the274* thing that the Spi supports, and wrap into a com.sun.net.ssl.*Spi275* object. This also mean that anything going down into the SPI276* needs to be wrapped, as well as anything coming back up.277*/278final class SSLContextSpiWrapper extends SSLContextSpi {279280private javax.net.ssl.SSLContext theSSLContext;281282SSLContextSpiWrapper(String algName, Provider prov) throws283NoSuchAlgorithmException {284theSSLContext = javax.net.ssl.SSLContext.getInstance(algName, prov);285}286287protected void engineInit(KeyManager[] kma, TrustManager[] tma,288SecureRandom sr) throws KeyManagementException {289290// Keep track of the actual number of array elements copied291int dst;292int src;293javax.net.ssl.KeyManager[] kmaw;294javax.net.ssl.TrustManager[] tmaw;295296// Convert com.sun.net.ssl.kma to a javax.net.ssl.kma297// wrapper if need be.298if (kma != null) {299kmaw = new javax.net.ssl.KeyManager[kma.length];300for (src = 0, dst = 0; src < kma.length; ) {301/*302* These key managers may implement both javax303* and com.sun interfaces, so if they do304* javax, there's no need to wrap them.305*/306if (!(kma[src] instanceof javax.net.ssl.KeyManager)) {307/*308* Do we know how to convert them? If not, oh well...309* We'll have to drop them on the floor in this310* case, cause we don't know how to handle them.311* This will be pretty rare, but put here for312* completeness.313*/314if (kma[src] instanceof X509KeyManager) {315kmaw[dst] = (javax.net.ssl.KeyManager)316new X509KeyManagerJavaxWrapper(317(X509KeyManager)kma[src]);318dst++;319}320} else {321// We can convert directly, since they implement.322kmaw[dst] = (javax.net.ssl.KeyManager)kma[src];323dst++;324}325src++;326}327328/*329* If dst != src, there were more items in the original array330* than in the new array. Compress the new elements to avoid331* any problems down the road.332*/333if (dst != src) {334kmaw = (javax.net.ssl.KeyManager [])335SSLSecurity.truncateArray(kmaw,336new javax.net.ssl.KeyManager [dst]);337}338} else {339kmaw = null;340}341342// Now do the same thing with the TrustManagers.343if (tma != null) {344tmaw = new javax.net.ssl.TrustManager[tma.length];345346for (src = 0, dst = 0; src < tma.length; ) {347/*348* These key managers may implement both...see above...349*/350if (!(tma[src] instanceof javax.net.ssl.TrustManager)) {351// Do we know how to convert them?352if (tma[src] instanceof X509TrustManager) {353tmaw[dst] = (javax.net.ssl.TrustManager)354new X509TrustManagerJavaxWrapper(355(X509TrustManager)tma[src]);356dst++;357}358} else {359tmaw[dst] = (javax.net.ssl.TrustManager)tma[src];360dst++;361}362src++;363}364365if (dst != src) {366tmaw = (javax.net.ssl.TrustManager [])367SSLSecurity.truncateArray(tmaw,368new javax.net.ssl.TrustManager [dst]);369}370} else {371tmaw = null;372}373374theSSLContext.init(kmaw, tmaw, sr);375}376377protected javax.net.ssl.SSLSocketFactory378engineGetSocketFactory() {379return theSSLContext.getSocketFactory();380}381382protected javax.net.ssl.SSLServerSocketFactory383engineGetServerSocketFactory() {384return theSSLContext.getServerSocketFactory();385}386387}388389final class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {390391private javax.net.ssl.TrustManagerFactory theTrustManagerFactory;392393TrustManagerFactorySpiWrapper(String algName, Provider prov) throws394NoSuchAlgorithmException {395theTrustManagerFactory =396javax.net.ssl.TrustManagerFactory.getInstance(algName, prov);397}398399protected void engineInit(KeyStore ks) throws KeyStoreException {400theTrustManagerFactory.init(ks);401}402403protected TrustManager[] engineGetTrustManagers() {404405int dst;406int src;407408javax.net.ssl.TrustManager[] tma =409theTrustManagerFactory.getTrustManagers();410411TrustManager[] tmaw = new TrustManager[tma.length];412413for (src = 0, dst = 0; src < tma.length; ) {414if (!(tma[src] instanceof com.sun.net.ssl.TrustManager)) {415// We only know how to wrap X509TrustManagers, as416// TrustManagers don't have any methods to wrap.417if (tma[src] instanceof javax.net.ssl.X509TrustManager) {418tmaw[dst] = (TrustManager)419new X509TrustManagerComSunWrapper(420(javax.net.ssl.X509TrustManager)tma[src]);421dst++;422}423} else {424tmaw[dst] = (TrustManager)tma[src];425dst++;426}427src++;428}429430if (dst != src) {431tmaw = (TrustManager [])432SSLSecurity.truncateArray(tmaw, new TrustManager [dst]);433}434435return tmaw;436}437438}439440final class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {441442private javax.net.ssl.KeyManagerFactory theKeyManagerFactory;443444KeyManagerFactorySpiWrapper(String algName, Provider prov) throws445NoSuchAlgorithmException {446theKeyManagerFactory =447javax.net.ssl.KeyManagerFactory.getInstance(algName, prov);448}449450protected void engineInit(KeyStore ks, char[] password)451throws KeyStoreException, NoSuchAlgorithmException,452UnrecoverableKeyException {453theKeyManagerFactory.init(ks, password);454}455456protected KeyManager[] engineGetKeyManagers() {457458int dst;459int src;460461javax.net.ssl.KeyManager[] kma =462theKeyManagerFactory.getKeyManagers();463464KeyManager[] kmaw = new KeyManager[kma.length];465466for (src = 0, dst = 0; src < kma.length; ) {467if (!(kma[src] instanceof com.sun.net.ssl.KeyManager)) {468// We only know how to wrap X509KeyManagers, as469// KeyManagers don't have any methods to wrap.470if (kma[src] instanceof javax.net.ssl.X509KeyManager) {471kmaw[dst] = (KeyManager)472new X509KeyManagerComSunWrapper(473(javax.net.ssl.X509KeyManager)kma[src]);474dst++;475}476} else {477kmaw[dst] = (KeyManager)kma[src];478dst++;479}480src++;481}482483if (dst != src) {484kmaw = (KeyManager [])485SSLSecurity.truncateArray(kmaw, new KeyManager [dst]);486}487488return kmaw;489}490491}492493// =================================494495final class X509KeyManagerJavaxWrapper implements496javax.net.ssl.X509KeyManager {497498private X509KeyManager theX509KeyManager;499500X509KeyManagerJavaxWrapper(X509KeyManager obj) {501theX509KeyManager = obj;502}503504public String[] getClientAliases(String keyType, Principal[] issuers) {505return theX509KeyManager.getClientAliases(keyType, issuers);506}507508public String chooseClientAlias(String[] keyTypes, Principal[] issuers,509Socket socket) {510String retval;511512if (keyTypes == null) {513return null;514}515516/*517* Scan the list, look for something we can pass back.518*/519for (int i = 0; i < keyTypes.length; i++) {520if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],521issuers)) != null)522return retval;523}524return null;525526}527528/*529* JSSE 1.0.x was only socket based, but it's possible someone might530* want to install a really old provider. We should at least531* try to be nice.532*/533public String chooseEngineClientAlias(534String[] keyTypes, Principal[] issuers,535javax.net.ssl.SSLEngine engine) {536String retval;537538if (keyTypes == null) {539return null;540}541542/*543* Scan the list, look for something we can pass back.544*/545for (int i = 0; i < keyTypes.length; i++) {546if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],547issuers)) != null)548return retval;549}550551return null;552}553554public String[] getServerAliases(String keyType, Principal[] issuers) {555return theX509KeyManager.getServerAliases(keyType, issuers);556}557558public String chooseServerAlias(String keyType, Principal[] issuers,559Socket socket) {560561if (keyType == null) {562return null;563}564return theX509KeyManager.chooseServerAlias(keyType, issuers);565}566567/*568* JSSE 1.0.x was only socket based, but it's possible someone might569* want to install a really old provider. We should at least570* try to be nice.571*/572public String chooseEngineServerAlias(573String keyType, Principal[] issuers,574javax.net.ssl.SSLEngine engine) {575576if (keyType == null) {577return null;578}579return theX509KeyManager.chooseServerAlias(keyType, issuers);580}581582public java.security.cert.X509Certificate[]583getCertificateChain(String alias) {584return theX509KeyManager.getCertificateChain(alias);585}586587public PrivateKey getPrivateKey(String alias) {588return theX509KeyManager.getPrivateKey(alias);589}590}591592final class X509TrustManagerJavaxWrapper implements593javax.net.ssl.X509TrustManager {594595private X509TrustManager theX509TrustManager;596597X509TrustManagerJavaxWrapper(X509TrustManager obj) {598theX509TrustManager = obj;599}600601public void checkClientTrusted(602java.security.cert.X509Certificate[] chain, String authType)603throws java.security.cert.CertificateException {604if (!theX509TrustManager.isClientTrusted(chain)) {605throw new java.security.cert.CertificateException(606"Untrusted Client Certificate Chain");607}608}609610public void checkServerTrusted(611java.security.cert.X509Certificate[] chain, String authType)612throws java.security.cert.CertificateException {613if (!theX509TrustManager.isServerTrusted(chain)) {614throw new java.security.cert.CertificateException(615"Untrusted Server Certificate Chain");616}617}618619public java.security.cert.X509Certificate[] getAcceptedIssuers() {620return theX509TrustManager.getAcceptedIssuers();621}622}623624final class X509KeyManagerComSunWrapper implements X509KeyManager {625626private javax.net.ssl.X509KeyManager theX509KeyManager;627628X509KeyManagerComSunWrapper(javax.net.ssl.X509KeyManager obj) {629theX509KeyManager = obj;630}631632public String[] getClientAliases(String keyType, Principal[] issuers) {633return theX509KeyManager.getClientAliases(keyType, issuers);634}635636public String chooseClientAlias(String keyType, Principal[] issuers) {637String [] keyTypes = new String [] { keyType };638return theX509KeyManager.chooseClientAlias(keyTypes, issuers, null);639}640641public String[] getServerAliases(String keyType, Principal[] issuers) {642return theX509KeyManager.getServerAliases(keyType, issuers);643}644645public String chooseServerAlias(String keyType, Principal[] issuers) {646return theX509KeyManager.chooseServerAlias(keyType, issuers, null);647}648649public java.security.cert.X509Certificate[]650getCertificateChain(String alias) {651return theX509KeyManager.getCertificateChain(alias);652}653654public PrivateKey getPrivateKey(String alias) {655return theX509KeyManager.getPrivateKey(alias);656}657}658659final class X509TrustManagerComSunWrapper implements X509TrustManager {660661private javax.net.ssl.X509TrustManager theX509TrustManager;662663X509TrustManagerComSunWrapper(javax.net.ssl.X509TrustManager obj) {664theX509TrustManager = obj;665}666667public boolean isClientTrusted(668java.security.cert.X509Certificate[] chain) {669try {670theX509TrustManager.checkClientTrusted(chain, "UNKNOWN");671return true;672} catch (java.security.cert.CertificateException e) {673return false;674}675}676677public boolean isServerTrusted(678java.security.cert.X509Certificate[] chain) {679try {680theX509TrustManager.checkServerTrusted(chain, "UNKNOWN");681return true;682} catch (java.security.cert.CertificateException e) {683return false;684}685}686687public java.security.cert.X509Certificate[] getAcceptedIssuers() {688return theX509TrustManager.getAcceptedIssuers();689}690}691692693