1 /*
   2  * Copyright (c) 2004, 2006, 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.util;
  27 
  28 import java.io.*;
  29 import java.net.*;
  30 import java.security.*;
  31 import java.util.Arrays;
  32 
  33 import sun.net.www.ParseUtil;
  34 
  35 
  36 /**
  37  * A utility class for getting a KeyStore instance from policy information.
  38  * In addition, a supporting getInputStream method.
  39  *
  40  */
  41 public class PolicyUtil {
  42 
  43     // standard PKCS11 KeyStore type
  44     private static final String P11KEYSTORE = "PKCS11";
  45 
  46     // reserved word
  47     private static final String NONE = "NONE";
  48 
  49     /*
  50      * Fast path reading from file urls in order to avoid calling
  51      * FileURLConnection.connect() which can be quite slow the first time
  52      * it is called. We really should clean up FileURLConnection so that
  53      * this is not a problem but in the meantime this fix helps reduce
  54      * start up time noticeably for the new launcher. -- DAC
  55      */
  56     public static InputStream getInputStream(URL url) throws IOException {
  57         if ("file".equals(url.getProtocol())) {
  58             String path = url.getFile().replace('/', File.separatorChar);
  59             path = ParseUtil.decode(path);
  60             return new FileInputStream(path);
  61         } else {
  62             return url.openStream();
  63         }
  64     }
  65 
  66     /**
  67      * this is intended for use by the policy parser to
  68      * instantiate a KeyStore from the information in the GUI/policy file
  69      */
  70     public static KeyStore getKeyStore
  71                 (URL policyUrl,                 // URL of policy file
  72                 String keyStoreName,            // input: keyStore URL
  73                 String keyStoreType,            // input: keyStore type
  74                 String keyStoreProvider,        // input: keyStore provider
  75                 String storePassURL,            // input: keyStore password
  76                 Debug debug)
  77         throws KeyStoreException, MalformedURLException, IOException,
  78                 NoSuchProviderException, NoSuchAlgorithmException,
  79                 java.security.cert.CertificateException {
  80 
  81         if (keyStoreName == null) {
  82             throw new IllegalArgumentException("null KeyStore name");
  83         }
  84 
  85         char[] keyStorePassword = null;
  86         try {
  87             KeyStore ks;
  88             if (keyStoreType == null) {
  89                 keyStoreType = KeyStore.getDefaultType();
  90             }
  91 
  92             if (P11KEYSTORE.equalsIgnoreCase(keyStoreType) &&
  93                 !NONE.equals(keyStoreName)) {
  94                 throw new IllegalArgumentException
  95                         ("Invalid value (" +
  96                         keyStoreName +
  97                         ") for keystore URL.  If the keystore type is \"" +
  98                         P11KEYSTORE +
  99                         "\", the keystore url must be \"" +
 100                         NONE +
 101                         "\"");
 102             }
 103 
 104             if (keyStoreProvider != null) {
 105                 ks = KeyStore.getInstance(keyStoreType, keyStoreProvider);
 106             } else {
 107                 ks = KeyStore.getInstance(keyStoreType);
 108             }
 109 
 110             if (storePassURL != null) {
 111                 URL passURL;
 112                 try {
 113                     passURL = new URL(storePassURL);
 114                     // absolute URL
 115                 } catch (MalformedURLException e) {
 116                     // relative URL
 117                     if (policyUrl == null) {
 118                         throw e;
 119                     }
 120                     passURL = new URL(policyUrl, storePassURL);
 121                 }
 122 
 123                 if (debug != null) {
 124                     debug.println("reading password"+passURL);
 125                 }
 126 
 127                 InputStream in = null;
 128                 try {
 129                     in = passURL.openStream();
 130                     keyStorePassword = Password.readPassword(in);
 131                 } finally {
 132                     if (in != null) {
 133                         in.close();
 134                     }
 135                 }
 136             }
 137 
 138             if (NONE.equals(keyStoreName)) {
 139                 ks.load(null, keyStorePassword);
 140                 return ks;
 141             } else {
 142                 /*
 143                  * location of keystore is specified as absolute URL in policy
 144                  * file, or is relative to URL of policy file
 145                  */
 146                 URL keyStoreUrl = null;
 147                 try {
 148                     keyStoreUrl = new URL(keyStoreName);
 149                     // absolute URL
 150                 } catch (MalformedURLException e) {
 151                     // relative URL
 152                     if (policyUrl == null) {
 153                         throw e;
 154                     }
 155                     keyStoreUrl = new URL(policyUrl, keyStoreName);
 156                 }
 157 
 158                 if (debug != null) {
 159                     debug.println("reading keystore"+keyStoreUrl);
 160                 }
 161 
 162                 InputStream inStream = null;
 163                 try {
 164                     inStream =
 165                         new BufferedInputStream(getInputStream(keyStoreUrl));
 166                     ks.load(inStream, keyStorePassword);
 167                 } finally {
 168                     inStream.close();
 169                 }
 170                 return ks;
 171             }
 172         } finally {
 173             if (keyStorePassword != null) {
 174                 Arrays.fill(keyStorePassword, ' ');
 175             }
 176         }
 177     }
 178 }