1 /*
   2  * Copyright (c) 2000, 2014, 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      */
  56     private SSLSecurity() {
  57     }
  58 
  59 
  60     // ProviderList.getService() is not accessible now, implement our own loop
  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      */
  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 java.base module.
 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      */
 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      */
 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      */
 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      */
 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 @SuppressWarnings("deprecation")
 280 final class SSLContextSpiWrapper extends SSLContextSpi {
 281 
 282     private javax.net.ssl.SSLContext theSSLContext;
 283 
 284     SSLContextSpiWrapper(String algName, Provider prov) throws
 285             NoSuchAlgorithmException {
 286         theSSLContext = javax.net.ssl.SSLContext.getInstance(algName, prov);
 287     }
 288 
 289     @SuppressWarnings("deprecation")
 290     protected void engineInit(KeyManager[] kma, TrustManager[] tma,
 291             SecureRandom sr) throws KeyManagementException {
 292 
 293         // Keep track of the actual number of array elements copied
 294         int dst;
 295         int src;
 296         javax.net.ssl.KeyManager[] kmaw;
 297         javax.net.ssl.TrustManager[] tmaw;
 298 
 299         // Convert com.sun.net.ssl.kma to a javax.net.ssl.kma
 300         // wrapper if need be.
 301         if (kma != null) {
 302             kmaw = new javax.net.ssl.KeyManager[kma.length];
 303             for (src = 0, dst = 0; src < kma.length; ) {
 304                 /*
 305                  * These key managers may implement both javax
 306                  * and com.sun interfaces, so if they do
 307                  * javax, there's no need to wrap them.
 308                  */
 309                 if (!(kma[src] instanceof javax.net.ssl.KeyManager)) {
 310                     /*
 311                      * Do we know how to convert them?  If not, oh well...
 312                      * We'll have to drop them on the floor in this
 313                      * case, cause we don't know how to handle them.
 314                      * This will be pretty rare, but put here for
 315                      * completeness.
 316                      */
 317                     if (kma[src] instanceof X509KeyManager) {
 318                         kmaw[dst] = (javax.net.ssl.KeyManager)
 319                             new X509KeyManagerJavaxWrapper(
 320                             (X509KeyManager)kma[src]);
 321                         dst++;
 322                     }
 323                 } else {
 324                     // We can convert directly, since they implement.
 325                     kmaw[dst] = (javax.net.ssl.KeyManager)kma[src];
 326                     dst++;
 327                 }
 328                 src++;
 329             }
 330 
 331             /*
 332              * If dst != src, there were more items in the original array
 333              * than in the new array.  Compress the new elements to avoid
 334              * any problems down the road.
 335              */
 336             if (dst != src) {
 337                     kmaw = (javax.net.ssl.KeyManager [])
 338                         SSLSecurity.truncateArray(kmaw,
 339                             new javax.net.ssl.KeyManager [dst]);
 340             }
 341         } else {
 342             kmaw = null;
 343         }
 344 
 345         // Now do the same thing with the TrustManagers.
 346         if (tma != null) {
 347             tmaw = new javax.net.ssl.TrustManager[tma.length];
 348 
 349             for (src = 0, dst = 0; src < tma.length; ) {
 350                 /*
 351                  * These key managers may implement both...see above...
 352                  */
 353                 if (!(tma[src] instanceof javax.net.ssl.TrustManager)) {
 354                     // Do we know how to convert them?
 355                     if (tma[src] instanceof X509TrustManager) {
 356                         tmaw[dst] = (javax.net.ssl.TrustManager)
 357                             new X509TrustManagerJavaxWrapper(
 358                             (X509TrustManager)tma[src]);
 359                         dst++;
 360                     }
 361                 } else {
 362                     tmaw[dst] = (javax.net.ssl.TrustManager)tma[src];
 363                     dst++;
 364                 }
 365                 src++;
 366             }
 367 
 368             if (dst != src) {
 369                 tmaw = (javax.net.ssl.TrustManager [])
 370                     SSLSecurity.truncateArray(tmaw,
 371                         new javax.net.ssl.TrustManager [dst]);
 372             }
 373         } else {
 374             tmaw = null;
 375         }
 376 
 377         theSSLContext.init(kmaw, tmaw, sr);
 378     }
 379 
 380     protected javax.net.ssl.SSLSocketFactory
 381             engineGetSocketFactory() {
 382         return theSSLContext.getSocketFactory();
 383     }
 384 
 385     protected javax.net.ssl.SSLServerSocketFactory
 386             engineGetServerSocketFactory() {
 387         return theSSLContext.getServerSocketFactory();
 388     }
 389 
 390 }
 391 
 392 @SuppressWarnings("deprecation")
 393 final class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {
 394 
 395     private javax.net.ssl.TrustManagerFactory theTrustManagerFactory;
 396 
 397     TrustManagerFactorySpiWrapper(String algName, Provider prov) throws
 398             NoSuchAlgorithmException {
 399         theTrustManagerFactory =
 400             javax.net.ssl.TrustManagerFactory.getInstance(algName, prov);
 401     }
 402 
 403     protected void engineInit(KeyStore ks) throws KeyStoreException {
 404         theTrustManagerFactory.init(ks);
 405     }
 406 
 407     protected TrustManager[] engineGetTrustManagers() {
 408 
 409         int dst;
 410         int src;
 411 
 412         javax.net.ssl.TrustManager[] tma =
 413             theTrustManagerFactory.getTrustManagers();
 414 
 415         TrustManager[] tmaw = new TrustManager[tma.length];
 416 
 417         for (src = 0, dst = 0; src < tma.length; ) {
 418             if (!(tma[src] instanceof com.sun.net.ssl.TrustManager)) {
 419                 // We only know how to wrap X509TrustManagers, as
 420                 // TrustManagers don't have any methods to wrap.
 421                 if (tma[src] instanceof javax.net.ssl.X509TrustManager) {
 422                     tmaw[dst] = (TrustManager)
 423                         new X509TrustManagerComSunWrapper(
 424                         (javax.net.ssl.X509TrustManager)tma[src]);
 425                     dst++;
 426                 }
 427             } else {
 428                 tmaw[dst] = (TrustManager)tma[src];
 429                 dst++;
 430             }
 431             src++;
 432         }
 433 
 434         if (dst != src) {
 435             tmaw = (TrustManager [])
 436                 SSLSecurity.truncateArray(tmaw, new TrustManager [dst]);
 437         }
 438 
 439         return tmaw;
 440     }
 441 
 442 }
 443 
 444 @SuppressWarnings("deprecation")
 445 final class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {
 446 
 447     private javax.net.ssl.KeyManagerFactory theKeyManagerFactory;
 448 
 449     KeyManagerFactorySpiWrapper(String algName, Provider prov) throws
 450             NoSuchAlgorithmException {
 451         theKeyManagerFactory =
 452             javax.net.ssl.KeyManagerFactory.getInstance(algName, prov);
 453     }
 454 
 455     protected void engineInit(KeyStore ks, char[] password)
 456             throws KeyStoreException, NoSuchAlgorithmException,
 457             UnrecoverableKeyException {
 458         theKeyManagerFactory.init(ks, password);
 459     }
 460 
 461     protected KeyManager[] engineGetKeyManagers() {
 462 
 463         int dst;
 464         int src;
 465 
 466         javax.net.ssl.KeyManager[] kma =
 467             theKeyManagerFactory.getKeyManagers();
 468 
 469         KeyManager[] kmaw = new KeyManager[kma.length];
 470 
 471         for (src = 0, dst = 0; src < kma.length; ) {
 472             if (!(kma[src] instanceof com.sun.net.ssl.KeyManager)) {
 473                 // We only know how to wrap X509KeyManagers, as
 474                 // KeyManagers don't have any methods to wrap.
 475                 if (kma[src] instanceof javax.net.ssl.X509KeyManager) {
 476                     kmaw[dst] = (KeyManager)
 477                         new X509KeyManagerComSunWrapper(
 478                         (javax.net.ssl.X509KeyManager)kma[src]);
 479                     dst++;
 480                 }
 481             } else {
 482                 kmaw[dst] = (KeyManager)kma[src];
 483                 dst++;
 484             }
 485             src++;
 486         }
 487 
 488         if (dst != src) {
 489             kmaw = (KeyManager [])
 490                 SSLSecurity.truncateArray(kmaw, new KeyManager [dst]);
 491         }
 492 
 493         return kmaw;
 494     }
 495 
 496 }
 497 
 498 // =================================
 499 
 500 @SuppressWarnings("deprecation")
 501 final class X509KeyManagerJavaxWrapper implements
 502         javax.net.ssl.X509KeyManager {
 503 
 504     private X509KeyManager theX509KeyManager;
 505 
 506     X509KeyManagerJavaxWrapper(X509KeyManager obj) {
 507         theX509KeyManager = obj;
 508     }
 509 
 510     public String[] getClientAliases(String keyType, Principal[] issuers) {
 511         return theX509KeyManager.getClientAliases(keyType, issuers);
 512     }
 513 
 514     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
 515             Socket socket) {
 516         String retval;
 517 
 518         if (keyTypes == null) {
 519             return null;
 520         }
 521 
 522         /*
 523          * Scan the list, look for something we can pass back.
 524          */
 525         for (int i = 0; i < keyTypes.length; i++) {
 526             if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],
 527                     issuers)) != null)
 528                 return retval;
 529         }
 530         return null;
 531 
 532     }
 533 
 534     /*
 535      * JSSE 1.0.x was only socket based, but it's possible someone might
 536      * want to install a really old provider.  We should at least
 537      * try to be nice.
 538      */
 539     public String chooseEngineClientAlias(
 540             String[] keyTypes, Principal[] issuers,
 541             javax.net.ssl.SSLEngine engine) {
 542         String retval;
 543 
 544         if (keyTypes == null) {
 545             return null;
 546         }
 547 
 548         /*
 549          * Scan the list, look for something we can pass back.
 550          */
 551         for (int i = 0; i < keyTypes.length; i++) {
 552             if ((retval = theX509KeyManager.chooseClientAlias(keyTypes[i],
 553                     issuers)) != null)
 554                 return retval;
 555         }
 556 
 557         return null;
 558     }
 559 
 560     public String[] getServerAliases(String keyType, Principal[] issuers) {
 561         return theX509KeyManager.getServerAliases(keyType, issuers);
 562     }
 563 
 564     public String chooseServerAlias(String keyType, Principal[] issuers,
 565             Socket socket) {
 566 
 567         if (keyType == null) {
 568             return null;
 569         }
 570         return theX509KeyManager.chooseServerAlias(keyType, issuers);
 571     }
 572 
 573     /*
 574      * JSSE 1.0.x was only socket based, but it's possible someone might
 575      * want to install a really old provider.  We should at least
 576      * try to be nice.
 577      */
 578     public String chooseEngineServerAlias(
 579             String keyType, Principal[] issuers,
 580             javax.net.ssl.SSLEngine engine) {
 581 
 582         if (keyType == null) {
 583             return null;
 584         }
 585         return theX509KeyManager.chooseServerAlias(keyType, issuers);
 586     }
 587 
 588     public java.security.cert.X509Certificate[]
 589             getCertificateChain(String alias) {
 590         return theX509KeyManager.getCertificateChain(alias);
 591     }
 592 
 593     public PrivateKey getPrivateKey(String alias) {
 594         return theX509KeyManager.getPrivateKey(alias);
 595     }
 596 }
 597 
 598 @SuppressWarnings("deprecation")
 599 final class X509TrustManagerJavaxWrapper implements
 600         javax.net.ssl.X509TrustManager {
 601 
 602     private X509TrustManager theX509TrustManager;
 603 
 604     X509TrustManagerJavaxWrapper(X509TrustManager obj) {
 605         theX509TrustManager = obj;
 606     }
 607 
 608     public void checkClientTrusted(
 609             java.security.cert.X509Certificate[] chain, String authType)
 610         throws java.security.cert.CertificateException {
 611         if (!theX509TrustManager.isClientTrusted(chain)) {
 612             throw new java.security.cert.CertificateException(
 613                 "Untrusted Client Certificate Chain");
 614         }
 615     }
 616 
 617     public void checkServerTrusted(
 618             java.security.cert.X509Certificate[] chain, String authType)
 619         throws java.security.cert.CertificateException {
 620         if (!theX509TrustManager.isServerTrusted(chain)) {
 621             throw new java.security.cert.CertificateException(
 622                 "Untrusted Server Certificate Chain");
 623         }
 624     }
 625 
 626     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
 627         return theX509TrustManager.getAcceptedIssuers();
 628     }
 629 }
 630 
 631 @SuppressWarnings("deprecation")
 632 final class X509KeyManagerComSunWrapper implements X509KeyManager {
 633 
 634     private javax.net.ssl.X509KeyManager theX509KeyManager;
 635 
 636     X509KeyManagerComSunWrapper(javax.net.ssl.X509KeyManager obj) {
 637         theX509KeyManager = obj;
 638     }
 639 
 640     public String[] getClientAliases(String keyType, Principal[] issuers) {
 641         return theX509KeyManager.getClientAliases(keyType, issuers);
 642     }
 643 
 644     public String chooseClientAlias(String keyType, Principal[] issuers) {
 645         String [] keyTypes = new String [] { keyType };
 646         return theX509KeyManager.chooseClientAlias(keyTypes, issuers, null);
 647     }
 648 
 649     public String[] getServerAliases(String keyType, Principal[] issuers) {
 650         return theX509KeyManager.getServerAliases(keyType, issuers);
 651     }
 652 
 653     public String chooseServerAlias(String keyType, Principal[] issuers) {
 654         return theX509KeyManager.chooseServerAlias(keyType, issuers, null);
 655     }
 656 
 657     public java.security.cert.X509Certificate[]
 658             getCertificateChain(String alias) {
 659         return theX509KeyManager.getCertificateChain(alias);
 660     }
 661 
 662     public PrivateKey getPrivateKey(String alias) {
 663         return theX509KeyManager.getPrivateKey(alias);
 664     }
 665 }
 666 
 667 @SuppressWarnings("deprecation")
 668 final class X509TrustManagerComSunWrapper implements X509TrustManager {
 669 
 670     private javax.net.ssl.X509TrustManager theX509TrustManager;
 671 
 672     X509TrustManagerComSunWrapper(javax.net.ssl.X509TrustManager obj) {
 673         theX509TrustManager = obj;
 674     }
 675 
 676     public boolean isClientTrusted(
 677             java.security.cert.X509Certificate[] chain) {
 678         try {
 679             theX509TrustManager.checkClientTrusted(chain, "UNKNOWN");
 680             return true;
 681         } catch (java.security.cert.CertificateException e) {
 682             return false;
 683         }
 684     }
 685 
 686     public boolean isServerTrusted(
 687             java.security.cert.X509Certificate[] chain) {
 688         try {
 689             theX509TrustManager.checkServerTrusted(chain, "UNKNOWN");
 690             return true;
 691         } catch (java.security.cert.CertificateException e) {
 692             return false;
 693         }
 694     }
 695 
 696     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
 697         return theX509TrustManager.getAcceptedIssuers();
 698     }
 699 }