1 /*
   2  * Copyright (c) 1999, 2012, 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 package sun.security.ssl;
  27 
  28 import java.util.*;
  29 import java.io.*;
  30 import java.security.*;
  31 import java.security.cert.*;
  32 import javax.net.ssl.*;
  33 import sun.security.action.GetPropertyAction;
  34 import sun.security.action.OpenFileInputStreamAction;
  35 import sun.security.validator.Validator;
  36 
  37 abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
  38 
  39     private static final Debug debug = Debug.getInstance("ssl");
  40     private X509TrustManager trustManager = null;
  41     private boolean isInitialized = false;
  42 
  43     TrustManagerFactoryImpl() {
  44         // empty
  45     }
  46 
  47     @Override
  48     protected void engineInit(KeyStore ks) throws KeyStoreException {
  49         if (ks == null) {
  50             try {
  51                 ks = getCacertsKeyStore("trustmanager");
  52             } catch (SecurityException se) {
  53                 // eat security exceptions but report other throwables
  54                 if (debug != null && Debug.isOn("trustmanager")) {
  55                     System.out.println(
  56                         "SunX509: skip default keystore: " + se);
  57                 }
  58             } catch (Error err) {
  59                 if (debug != null && Debug.isOn("trustmanager")) {
  60                     System.out.println(
  61                         "SunX509: skip default keystore: " + err);
  62                 }
  63                 throw err;
  64             } catch (RuntimeException re) {
  65                 if (debug != null && Debug.isOn("trustmanager")) {
  66                     System.out.println(
  67                         "SunX509: skip default keystore: " + re);
  68                 }
  69                 throw re;
  70             } catch (Exception e) {
  71                 if (debug != null && Debug.isOn("trustmanager")) {
  72                     System.out.println(
  73                         "SunX509: skip default keystore: " + e);
  74                 }
  75                 throw new KeyStoreException(
  76                     "problem accessing trust store" + e);
  77             }
  78         }
  79         trustManager = getInstance(ks);
  80         isInitialized = true;
  81     }
  82 
  83     abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
  84 
  85     abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
  86             throws InvalidAlgorithmParameterException;
  87 
  88     @Override
  89     protected void engineInit(ManagerFactoryParameters spec) throws
  90             InvalidAlgorithmParameterException {
  91         trustManager = getInstance(spec);
  92         isInitialized = true;
  93     }
  94 
  95     /**
  96      * Returns one trust manager for each type of trust material.
  97      */
  98     @Override
  99     protected TrustManager[] engineGetTrustManagers() {
 100         if (!isInitialized) {
 101             throw new IllegalStateException(
 102                         "TrustManagerFactoryImpl is not initialized");
 103         }
 104         return new TrustManager[] { trustManager };
 105     }
 106 
 107     /*
 108      * Try to get an InputStream based on the file we pass in.
 109      */
 110     private static FileInputStream getFileInputStream(final File file)
 111             throws Exception {
 112         return AccessController.doPrivileged(
 113                 new OpenFileInputStreamAction(file, true));
 114     }
 115 
 116     /**
 117      * Returns the keystore with the configured CA certificates.
 118      */
 119     static KeyStore getCacertsKeyStore(String dbgname) throws Exception {
 120         FileInputStream fis = null;
 121         final String sep = File.separator;
 122         KeyStore ks = null;
 123 
 124         final Properties props = GetPropertyAction.getProperties();
 125 
 126         /*
 127          * Try:
 128          *      javax.net.ssl.trustStore  (if this variable exists, stop)
 129          *      jssecacerts
 130          *      cacerts
 131          *
 132          * If none exists, we use an empty keystore.
 133          */
 134 
 135         try {
 136             File storeFile;
 137             String storeFileName = props
 138                     .getProperty("javax.net.ssl.trustStore");
 139             if (!"NONE".equals(storeFileName)) {
 140                 if (storeFileName != null) {
 141                     storeFile = new File(storeFileName);
 142                     fis = getFileInputStream(storeFile);
 143                 } else {
 144                     String javaHome = props.getProperty("java.home");
 145                     storeFile = new File(javaHome + sep + "lib" + sep
 146                                                     + "security" + sep +
 147                                                     "jssecacerts");
 148                     if ((fis = getFileInputStream(storeFile)) == null) {
 149                         storeFile = new File(javaHome + sep + "lib" + sep
 150                                                     + "security" + sep +
 151                                                     "cacerts");
 152                         fis = getFileInputStream(storeFile);
 153                     }
 154                 }
 155 
 156                 if (fis != null) {
 157                     storeFileName = storeFile.getPath();
 158                 } else {
 159                     storeFileName = "No File Available, using empty keystore.";
 160                 }
 161             }
 162 
 163             String defaultTrustStoreType = props.getProperty(
 164                     "javax.net.ssl.trustStoreType",
 165                     KeyStore.getDefaultType());
 166             String defaultTrustStoreProvider = props.getProperty(
 167                                 "javax.net.ssl.trustStoreProvider", "");
 168             if (debug != null && Debug.isOn(dbgname)) {
 169                 System.out.println("trustStore is: " + storeFileName);
 170                 System.out.println("trustStore type is : " +
 171                                     defaultTrustStoreType);
 172                 System.out.println("trustStore provider is : " +
 173                                     defaultTrustStoreProvider);
 174             }
 175 
 176             /*
 177              * Try to initialize trust store.
 178              */
 179             if (defaultTrustStoreType.length() != 0) {
 180                 if (debug != null && Debug.isOn(dbgname)) {
 181                     System.out.println("init truststore");
 182                 }
 183                 if (defaultTrustStoreProvider.length() == 0) {
 184                     ks = KeyStore.getInstance(defaultTrustStoreType);
 185                 } else {
 186                     ks = KeyStore.getInstance(defaultTrustStoreType,
 187                                             defaultTrustStoreProvider);
 188                 }
 189                 char[] passwd = null;
 190                 String defaultTrustStorePassword = props
 191                         .getProperty("javax.net.ssl.trustStorePassword", "");
 192                 if (defaultTrustStorePassword.length() != 0)
 193                     passwd = defaultTrustStorePassword.toCharArray();
 194 
 195                 // if trustStore is NONE, fis will be null
 196                 ks.load(fis, passwd);
 197 
 198                 // Zero out the temporary password storage
 199                 if (passwd != null) {
 200                     for (int i = 0; i < passwd.length; i++) {
 201                         passwd[i] = (char)0;
 202                     }
 203                 }
 204             }
 205         } finally {
 206             if (fis != null) {
 207                 fis.close();
 208             }
 209         }
 210 
 211         return ks;
 212     }
 213 
 214     public static final class SimpleFactory extends TrustManagerFactoryImpl {
 215         @Override
 216         X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
 217             return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
 218         }
 219         @Override
 220         X509TrustManager getInstance(ManagerFactoryParameters spec)
 221                 throws InvalidAlgorithmParameterException {
 222             throw new InvalidAlgorithmParameterException
 223                 ("SunX509 TrustManagerFactory does not use "
 224                 + "ManagerFactoryParameters");
 225         }
 226     }
 227 
 228     public static final class PKIXFactory extends TrustManagerFactoryImpl {
 229         @Override
 230         X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
 231             return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
 232         }
 233         @Override
 234         X509TrustManager getInstance(ManagerFactoryParameters spec)
 235                 throws InvalidAlgorithmParameterException {
 236             if (spec instanceof CertPathTrustManagerParameters == false) {
 237                 throw new InvalidAlgorithmParameterException
 238                     ("Parameters must be CertPathTrustManagerParameters");
 239             }
 240             CertPathParameters params =
 241                 ((CertPathTrustManagerParameters)spec).getParameters();
 242             if (params instanceof PKIXBuilderParameters == false) {
 243                 throw new InvalidAlgorithmParameterException
 244                     ("Encapsulated parameters must be PKIXBuilderParameters");
 245             }
 246             PKIXBuilderParameters pkixParams = (PKIXBuilderParameters)params;
 247             return new X509TrustManagerImpl(Validator.TYPE_PKIX, pkixParams);
 248         }
 249     }
 250 }