1 /*
2  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * NOTE:  this file was copied from javax.net.ssl.SSLSecurity,
28  * but was heavily modified to allow com.sun.* users to
29  * access providers written using the javax.sun.* APIs.
30  */
31 
32 package com.sun.net.ssl;
33 
34 import java.util.*;
35 import java.io.*;
36 import java.security.*;
37 import java.security.Provider.Service;
38 import java.net.Socket;
39 
40 import sun.security.jca.*;
41 
42 /**
43  * This class instantiates implementations of JSSE engine classes from
44  * providers registered with the java.security.Security object.
45  *
46  * @author Jan Luehe
47  * @author Jeff Nisewanger
48  * @author Brad Wetmore
49  */
50 
51 final class SSLSecurity {
52 
53     /*
54      * Don't let anyone instantiate this.
55      */
SSLSecurity()56     private SSLSecurity() {
57     }
58 
59 
60     // ProviderList.getService() is not accessible now, implement our own loop
getService(String type, String alg)61     private static Service getService(String type, String alg) {
62         ProviderList list = Providers.getProviderList();
63         for (Provider p : list.providers()) {
64             Service s = p.getService(type, alg);
65             if (s != null) {
66                 return s;
67             }
68         }
69         return null;
70     }
71 
72     /**
73      * The body of the driver for the getImpl method.
74      */
getImpl1(String algName, String engineType, Service service)75     private static Object[] getImpl1(String algName, String engineType,
76             Service service) throws NoSuchAlgorithmException
77     {
78         Provider provider = service.getProvider();
79         String className = service.getClassName();
80         Class<?> implClass;
81         try {
82             ClassLoader cl = provider.getClass().getClassLoader();
83             if (cl == null) {
84                 // system class
85                 implClass = Class.forName(className);
86             } else {
87                 implClass = cl.loadClass(className);
88             }
89         } catch (ClassNotFoundException e) {
90             throw new NoSuchAlgorithmException("Class " + className +
91                                                 " configured for " +
92                                                 engineType +
93                                                 " not found: " +
94                                                 e.getMessage());
95         } catch (SecurityException e) {
96             throw new NoSuchAlgorithmException("Class " + className +
97                                                 " configured for " +
98                                                 engineType +
99                                                 " cannot be accessed: " +
100                                                 e.getMessage());
101         }
102 
103         /*
104          * JSSE 1.0, 1.0.1, and 1.0.2 used the com.sun.net.ssl API as the
105          * API was being developed.  As JSSE was folded into the main
106          * release, it was decided to promote the com.sun.net.ssl API to
107          * be javax.net.ssl.  It is desired to keep binary compatibility
108          * with vendors of JSSE implementation written using the
109          * com.sun.net.sll API, so we do this magic to handle everything.
110          *
111          * API used     Implementation used     Supported?
112          * ========     ===================     ==========
113          * com.sun      javax                   Yes
114          * com.sun      com.sun                 Yes
115          * javax        javax                   Yes
116          * javax        com.sun                 Not Currently
117          *
118          * Make sure the implementation class is a subclass of the
119          * corresponding engine class.
120          *
121          * In wrapping these classes, there's no way to know how to
122          * wrap all possible classes that extend the TrustManager/KeyManager.
123          * We only wrap the x509 variants.
124          */
125 
126         try {   // catch instantiation errors
127 
128             /*
129              * (The following Class.forName()s should alway work, because
130              * this class and all the SPI classes in javax.crypto are
131              * loaded by the same class loader.)  That is, unless they
132              * give us a SPI class that doesn't exist, say SSLFoo,
133              * or someone has removed classes from the jsse.jar file.
134              */
135 
136             Class<?> typeClassJavax;
137             Class<?> typeClassCom;
138             Object obj = null;
139 
140             /*
141              * Odds are more likely that we have a javax variant, try this
142              * first.
143              */
144             if (((typeClassJavax = Class.forName("javax.net.ssl." +
145                     engineType + "Spi")) != null) &&
146                     (checkSuperclass(implClass, typeClassJavax))) {
147 
148                 if (engineType.equals("SSLContext")) {
149                     obj = new SSLContextSpiWrapper(algName, provider);
150                 } else if (engineType.equals("TrustManagerFactory")) {
151                     obj = new TrustManagerFactorySpiWrapper(algName, provider);
152                 } else if (engineType.equals("KeyManagerFactory")) {
153                     obj = new KeyManagerFactorySpiWrapper(algName, provider);
154                 } else {
155                     /*
156                      * We should throw an error if we get
157                      * something totally unexpected.  Don't ever
158                      * expect to see this one...
159                      */
160                     throw new IllegalStateException(
161                         "Class " + implClass.getName() +
162                         " unknown engineType wrapper:" + engineType);
163                 }
164 
165             } else if (((typeClassCom = Class.forName("com.sun.net.ssl." +
166                         engineType + "Spi")) != null) &&
167                         (checkSuperclass(implClass, typeClassCom))) {
168                 obj = service.newInstance(null);
169             }
170 
171             if (obj != null) {
172                 return new Object[] { obj, provider };
173             } else {
174                 throw new NoSuchAlgorithmException(
175                     "Couldn't locate correct object or wrapper: " +
176                     engineType + " " + algName);
177             }
178 
179         } catch (ClassNotFoundException e) {
180             IllegalStateException exc = new IllegalStateException(
181                 "Engine Class Not Found for " + engineType);
182             exc.initCause(e);
183             throw exc;
184         }
185     }
186 
187     /**
188      * Returns an array of objects: the first object in the array is
189      * an instance of an implementation of the requested algorithm
190      * and type, and the second object in the array identifies the provider
191      * of that implementation.
192      * The <code>provName</code> argument can be null, in which case all
193      * configured providers will be searched in order of preference.
194      */
getImpl(String algName, String engineType, String provName)195     static Object[] getImpl(String algName, String engineType, String provName)
196         throws NoSuchAlgorithmException, NoSuchProviderException
197     {
198         Service service;
199         if (provName != null) {
200             ProviderList list = Providers.getProviderList();
201             Provider prov = list.getProvider(provName);
202             if (prov == null) {
203                 throw new NoSuchProviderException("No such provider: " +
204                                                   provName);
205             }
206             service = prov.getService(engineType, algName);
207         } else {
208             service = getService(engineType, algName);
209         }
210         if (service == null) {
211             throw new NoSuchAlgorithmException("Algorithm " + algName
212                                                + " not available");
213         }
214         return getImpl1(algName, engineType, service);
215     }
216 
217 
218     /**
219      * Returns an array of objects: the first object in the array is
220      * an instance of an implementation of the requested algorithm
221      * and type, and the second object in the array identifies the provider
222      * of that implementation.
223      * The <code>prov</code> argument can be null, in which case all
224      * configured providers will be searched in order of preference.
225      */
getImpl(String algName, String engineType, Provider prov)226     static Object[] getImpl(String algName, String engineType, Provider prov)
227         throws NoSuchAlgorithmException
228     {
229         Service service = prov.getService(engineType, algName);
230         if (service == null) {
231             throw new NoSuchAlgorithmException("No such algorithm: " +
232                                                algName);
233         }
234         return getImpl1(algName, engineType, service);
235     }
236 
237     /*
238      * Checks whether one class is the superclass of another
239      */
checkSuperclass(Class<?> subclass, Class<?> superclass)240     private static boolean checkSuperclass(Class<?> subclass, Class<?> superclass) {
241         if ((subclass == null) || (superclass == null))
242                 return false;
243 
244         while (!subclass.equals(superclass)) {
245             subclass = subclass.getSuperclass();
246             if (subclass == null) {
247                 return false;
248             }
249         }
250         return true;
251     }
252 
253     /*
254      * Return at most the first "resize" elements of an array.
255      *
256      * Didn't want to use java.util.Arrays, as PJava may not have it.
257      */
truncateArray(Object[] oldArray, Object[] newArray)258     static Object[] truncateArray(Object[] oldArray, Object[] newArray) {
259 
260         for (int i = 0; i < newArray.length; i++) {
261             newArray[i] = oldArray[i];
262         }
263 
264         return newArray;
265     }
266 
267 }
268 
269 
270 /*
271  * =================================================================
272  * The remainder of this file is for the wrapper and wrapper-support
273  * classes.  When SSLSecurity finds something which extends the
274  * javax.net.ssl.*Spi, we need to go grab a real instance of the
275  * thing that the Spi supports, and wrap into a com.sun.net.ssl.*Spi
276  * object.  This also mean that anything going down into the SPI
277  * needs to be wrapped, as well as anything coming back up.
278  */
279 final class SSLContextSpiWrapper extends SSLContextSpi {
280 
281     private javax.net.ssl.SSLContext theSSLContext;
282 
SSLContextSpiWrapper(String algName, Provider prov)283     SSLContextSpiWrapper(String algName, Provider prov) throws
284             NoSuchAlgorithmException {
285         theSSLContext = javax.net.ssl.SSLContext.getInstance(algName, prov);
286     }
287 
engineInit(KeyManager[] kma, TrustManager[] tma, SecureRandom sr)288     protected void engineInit(KeyManager[] kma, TrustManager[] tma,
289             SecureRandom sr) throws KeyManagementException {
290 
291         // Keep track of the actual number of array elements copied
292         int dst;
293         int src;
294         javax.net.ssl.KeyManager[] kmaw;
295         javax.net.ssl.TrustManager[] tmaw;
296 
297         // Convert com.sun.net.ssl.kma to a javax.net.ssl.kma
298         // wrapper if need be.
299         if (kma != null) {
300             kmaw = new javax.net.ssl.KeyManager[kma.length];
301             for (src = 0, dst = 0; src < kma.length; ) {
302                 /*
303                  * These key managers may implement both javax
304                  * and com.sun interfaces, so if they do
305                  * javax, there's no need to wrap them.
306                  */
307                 if (!(kma[src] instanceof javax.net.ssl.KeyManager)) {
308                     /*
309                      * Do we know how to convert them?  If not, oh well...
310                      * We'll have to drop them on the floor in this
311                      * case, cause we don't know how to handle them.
312                      * This will be pretty rare, but put here for
313                      * completeness.
314                      */
315                     if (kma[src] instanceof X509KeyManager) {
316                         kmaw[dst] = (javax.net.ssl.KeyManager)
317                             new X509KeyManagerJavaxWrapper(
318                             (X509KeyManager)kma[src]);
319                         dst++;
320                     }
321                 } else {
322                     // We can convert directly, since they implement.
323                     kmaw[dst] = (javax.net.ssl.KeyManager)kma[src];
324                     dst++;
325                 }
326                 src++;
327             }
328 
329             /*
330              * If dst != src, there were more items in the original array
331              * than in the new array.  Compress the new elements to avoid
332              * any problems down the road.
333              */
334             if (dst != src) {
335                     kmaw = (javax.net.ssl.KeyManager [])
336                         SSLSecurity.truncateArray(kmaw,
337                             new javax.net.ssl.KeyManager [dst]);
338             }
339         } else {
340             kmaw = null;
341         }
342 
343         // Now do the same thing with the TrustManagers.
344         if (tma != null) {
345             tmaw = new javax.net.ssl.TrustManager[tma.length];
346 
347             for (src = 0, dst = 0; src < tma.length; ) {
348                 /*
349                  * These key managers may implement both...see above...
350                  */
351                 if (!(tma[src] instanceof javax.net.ssl.TrustManager)) {
352                     // Do we know how to convert them?
353                     if (tma[src] instanceof X509TrustManager) {
354                         tmaw[dst] = (javax.net.ssl.TrustManager)
355                             new X509TrustManagerJavaxWrapper(
356                             (X509TrustManager)tma[src]);
357                         dst++;
358                     }
359                 } else {
360                     tmaw[dst] = (javax.net.ssl.TrustManager)tma[src];
361                     dst++;
362                 }
363                 src++;
364             }
365 
366             if (dst != src) {
367                 tmaw = (javax.net.ssl.TrustManager [])
368                     SSLSecurity.truncateArray(tmaw,
369                         new javax.net.ssl.TrustManager [dst]);
370             }
371         } else {
372             tmaw = null;
373         }
374 
375         theSSLContext.init(kmaw, tmaw, sr);
376     }
377 
378     protected javax.net.ssl.SSLSocketFactory
engineGetSocketFactory()379             engineGetSocketFactory() {
380         return theSSLContext.getSocketFactory();
381     }
382 
383     protected javax.net.ssl.SSLServerSocketFactory
engineGetServerSocketFactory()384             engineGetServerSocketFactory() {
385         return theSSLContext.getServerSocketFactory();
386     }
387 
388 }
389 
390 final class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {
391 
392     private javax.net.ssl.TrustManagerFactory theTrustManagerFactory;
393 
TrustManagerFactorySpiWrapper(String algName, Provider prov)394     TrustManagerFactorySpiWrapper(String algName, Provider prov) throws
395             NoSuchAlgorithmException {
396         theTrustManagerFactory =
397             javax.net.ssl.TrustManagerFactory.getInstance(algName, prov);
398     }
399 
engineInit(KeyStore ks)400     protected void engineInit(KeyStore ks) throws KeyStoreException {
401         theTrustManagerFactory.init(ks);
402     }
403 
engineGetTrustManagers()404     protected TrustManager[] engineGetTrustManagers() {
405 
406         int dst;
407         int src;
408 
409         javax.net.ssl.TrustManager[] tma =
410             theTrustManagerFactory.getTrustManagers();
411 
412         TrustManager[] tmaw = new TrustManager[tma.length];
413 
414         for (src = 0, dst = 0; src < tma.length; ) {
415             if (!(tma[src] instanceof com.sun.net.ssl.TrustManager)) {
416                 // We only know how to wrap X509TrustManagers, as
417                 // TrustManagers don't have any methods to wrap.
418                 if (tma[src] instanceof javax.net.ssl.X509TrustManager) {
419                     tmaw[dst] = (TrustManager)
420                         new X509TrustManagerComSunWrapper(
421                         (javax.net.ssl.X509TrustManager)tma[src]);
422                     dst++;
423                 }
424             } else {
425                 tmaw[dst] = (TrustManager)tma[src];
426                 dst++;
427             }
428             src++;
429         }
430 
431         if (dst != src) {
432             tmaw = (TrustManager [])
433                 SSLSecurity.truncateArray(tmaw, new TrustManager [dst]);
434         }
435 
436         return tmaw;
437     }
438 
439 }
440 
441 final class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {
442 
443     private javax.net.ssl.KeyManagerFactory theKeyManagerFactory;
444 
KeyManagerFactorySpiWrapper(String algName, Provider prov)445     KeyManagerFactorySpiWrapper(String algName, Provider prov) throws
446             NoSuchAlgorithmException {
447         theKeyManagerFactory =
448             javax.net.ssl.KeyManagerFactory.getInstance(algName, prov);
449     }
450 
engineInit(KeyStore ks, char[] password)451     protected void engineInit(KeyStore ks, char[] password)
452             throws KeyStoreException, NoSuchAlgorithmException,
453             UnrecoverableKeyException {
454         theKeyManagerFactory.init(ks, password);
455     }
456 
engineGetKeyManagers()457     protected KeyManager[] engineGetKeyManagers() {
458 
459         int dst;
460         int src;
461 
462         javax.net.ssl.KeyManager[] kma =
463             theKeyManagerFactory.getKeyManagers();
464 
465         KeyManager[] kmaw = new KeyManager[kma.length];
466 
467         for (src = 0, dst = 0; src < kma.length; ) {
468             if (!(kma[src] instanceof com.sun.net.ssl.KeyManager)) {
469                 // We only know how to wrap X509KeyManagers, as
470                 // KeyManagers don't have any methods to wrap.
471                 if (kma[src] instanceof javax.net.ssl.X509KeyManager) {
472                     kmaw[dst] = (KeyManager)
473                         new X509KeyManagerComSunWrapper(
474                         (javax.net.ssl.X509KeyManager)kma[src]);
475                     dst++;
476                 }
477             } else {
478                 kmaw[dst] = (KeyManager)kma[src];
479                 dst++;
480             }
481             src++;
482         }
483 
484         if (dst != src) {
485             kmaw = (KeyManager [])
486                 SSLSecurity.truncateArray(kmaw, new KeyManager [dst]);
487         }
488 
489         return kmaw;
490     }
491 
492 }
493 
494 // =================================
495 
496 final class X509KeyManagerJavaxWrapper implements
497         javax.net.ssl.X509KeyManager {
498 
499     private X509KeyManager theX509KeyManager;
500 
X509KeyManagerJavaxWrapper(X509KeyManager obj)501     X509KeyManagerJavaxWrapper(X509KeyManager obj) {
502         theX509KeyManager = obj;
503     }
504 
getClientAliases(String keyType, Principal[] issuers)505     public String[] getClientAliases(String keyType, Principal[] issuers) {
506         return theX509KeyManager.getClientAliases(keyType, issuers);
507     }
508 
chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket)509     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
510             Socket socket) {
511         String retval;
512 
513         if (keyTypes == null) {
514             return null;
515         }
516 
517         /*
518          * Scan the list, look for something we can pass back.
519          */
520         for (int i = 0; i < keyTypes.length; i++) {
521             if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],
522                     issuers)) != null)
523                 return retval;
524         }
525         return null;
526 
527     }
528 
529     /*
530      * JSSE 1.0.x was only socket based, but it's possible someone might
531      * want to install a really old provider.  We should at least
532      * try to be nice.
533      */
chooseEngineClientAlias( String[] keyTypes, Principal[] issuers, javax.net.ssl.SSLEngine engine)534     public String chooseEngineClientAlias(
535             String[] keyTypes, Principal[] issuers,
536             javax.net.ssl.SSLEngine engine) {
537         String retval;
538 
539         if (keyTypes == null) {
540             return null;
541         }
542 
543         /*
544          * Scan the list, look for something we can pass back.
545          */
546         for (int i = 0; i < keyTypes.length; i++) {
547             if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],
548                     issuers)) != null)
549                 return retval;
550         }
551 
552         return null;
553     }
554 
getServerAliases(String keyType, Principal[] issuers)555     public String[] getServerAliases(String keyType, Principal[] issuers) {
556         return theX509KeyManager.getServerAliases(keyType, issuers);
557     }
558 
chooseServerAlias(String keyType, Principal[] issuers, Socket socket)559     public String chooseServerAlias(String keyType, Principal[] issuers,
560             Socket socket) {
561 
562         if (keyType == null) {
563             return null;
564         }
565         return theX509KeyManager.chooseServerAlias(keyType, issuers);
566     }
567 
568     /*
569      * JSSE 1.0.x was only socket based, but it's possible someone might
570      * want to install a really old provider.  We should at least
571      * try to be nice.
572      */
chooseEngineServerAlias( String keyType, Principal[] issuers, javax.net.ssl.SSLEngine engine)573     public String chooseEngineServerAlias(
574             String keyType, Principal[] issuers,
575             javax.net.ssl.SSLEngine engine) {
576 
577         if (keyType == null) {
578             return null;
579         }
580         return theX509KeyManager.chooseServerAlias(keyType, issuers);
581     }
582 
583     public java.security.cert.X509Certificate[]
getCertificateChain(String alias)584             getCertificateChain(String alias) {
585         return theX509KeyManager.getCertificateChain(alias);
586     }
587 
getPrivateKey(String alias)588     public PrivateKey getPrivateKey(String alias) {
589         return theX509KeyManager.getPrivateKey(alias);
590     }
591 }
592 
593 final class X509TrustManagerJavaxWrapper implements
594         javax.net.ssl.X509TrustManager {
595 
596     private X509TrustManager theX509TrustManager;
597 
X509TrustManagerJavaxWrapper(X509TrustManager obj)598     X509TrustManagerJavaxWrapper(X509TrustManager obj) {
599         theX509TrustManager = obj;
600     }
601 
checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType)602     public void checkClientTrusted(
603             java.security.cert.X509Certificate[] chain, String authType)
604         throws java.security.cert.CertificateException {
605         if (!theX509TrustManager.isClientTrusted(chain)) {
606             throw new java.security.cert.CertificateException(
607                 "Untrusted Client Certificate Chain");
608         }
609     }
610 
checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType)611     public void checkServerTrusted(
612             java.security.cert.X509Certificate[] chain, String authType)
613         throws java.security.cert.CertificateException {
614         if (!theX509TrustManager.isServerTrusted(chain)) {
615             throw new java.security.cert.CertificateException(
616                 "Untrusted Server Certificate Chain");
617         }
618     }
619 
getAcceptedIssuers()620     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
621         return theX509TrustManager.getAcceptedIssuers();
622     }
623 }
624 
625 final class X509KeyManagerComSunWrapper implements X509KeyManager {
626 
627     private javax.net.ssl.X509KeyManager theX509KeyManager;
628 
X509KeyManagerComSunWrapper(javax.net.ssl.X509KeyManager obj)629     X509KeyManagerComSunWrapper(javax.net.ssl.X509KeyManager obj) {
630         theX509KeyManager = obj;
631     }
632 
getClientAliases(String keyType, Principal[] issuers)633     public String[] getClientAliases(String keyType, Principal[] issuers) {
634         return theX509KeyManager.getClientAliases(keyType, issuers);
635     }
636 
chooseClientAlias(String keyType, Principal[] issuers)637     public String chooseClientAlias(String keyType, Principal[] issuers) {
638         String [] keyTypes = new String [] { keyType };
639         return theX509KeyManager.chooseClientAlias(keyTypes, issuers, null);
640     }
641 
getServerAliases(String keyType, Principal[] issuers)642     public String[] getServerAliases(String keyType, Principal[] issuers) {
643         return theX509KeyManager.getServerAliases(keyType, issuers);
644     }
645 
chooseServerAlias(String keyType, Principal[] issuers)646     public String chooseServerAlias(String keyType, Principal[] issuers) {
647         return theX509KeyManager.chooseServerAlias(keyType, issuers, null);
648     }
649 
650     public java.security.cert.X509Certificate[]
getCertificateChain(String alias)651             getCertificateChain(String alias) {
652         return theX509KeyManager.getCertificateChain(alias);
653     }
654 
getPrivateKey(String alias)655     public PrivateKey getPrivateKey(String alias) {
656         return theX509KeyManager.getPrivateKey(alias);
657     }
658 }
659 
660 final class X509TrustManagerComSunWrapper implements X509TrustManager {
661 
662     private javax.net.ssl.X509TrustManager theX509TrustManager;
663 
X509TrustManagerComSunWrapper(javax.net.ssl.X509TrustManager obj)664     X509TrustManagerComSunWrapper(javax.net.ssl.X509TrustManager obj) {
665         theX509TrustManager = obj;
666     }
667 
isClientTrusted( java.security.cert.X509Certificate[] chain)668     public boolean isClientTrusted(
669             java.security.cert.X509Certificate[] chain) {
670         try {
671             theX509TrustManager.checkClientTrusted(chain, "UNKNOWN");
672             return true;
673         } catch (java.security.cert.CertificateException e) {
674             return false;
675         }
676     }
677 
isServerTrusted( java.security.cert.X509Certificate[] chain)678     public boolean isServerTrusted(
679             java.security.cert.X509Certificate[] chain) {
680         try {
681             theX509TrustManager.checkServerTrusted(chain, "UNKNOWN");
682             return true;
683         } catch (java.security.cert.CertificateException e) {
684             return false;
685         }
686     }
687 
getAcceptedIssuers()688     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
689         return theX509TrustManager.getAcceptedIssuers();
690     }
691 }
692