001 /* 002 * Copyright 2008-2016 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2016 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021 package com.unboundid.util.ssl; 022 023 024 025 import java.io.File; 026 import java.io.FileInputStream; 027 import java.io.Serializable; 028 import java.security.KeyStore; 029 import java.security.KeyStoreException; 030 import javax.net.ssl.KeyManager; 031 import javax.net.ssl.KeyManagerFactory; 032 033 034 import static com.unboundid.util.Debug.*; 035 import static com.unboundid.util.Validator.*; 036 import static com.unboundid.util.ssl.SSLMessages.*; 037 038 039 040 /** 041 * This class provides an SSL key manager that may be used to retrieve 042 * certificates from a key store file. By default it will use the default key 043 * store format for the JVM (e.g., "JKS" for Sun-provided Java implementations), 044 * but alternate formats like PKCS12 may be used. 045 */ 046 public final class KeyStoreKeyManager 047 extends WrapperKeyManager 048 implements Serializable 049 { 050 /** 051 * The serial version UID for this serializable class. 052 */ 053 private static final long serialVersionUID = -5202641256733094253L; 054 055 056 057 // The path to the key store file. 058 private final String keyStoreFile; 059 060 // The format to use for the key store file. 061 private final String keyStoreFormat; 062 063 064 065 /** 066 * Creates a new instance of this key store key manager that provides the 067 * ability to retrieve certificates from the specified key store file. It 068 * will use the default key store format. 069 * 070 * @param keyStoreFile The path to the key store file to use. It must not 071 * be {@code null}. 072 * @param keyStorePIN The PIN to use to access the contents of the key 073 * store. It may be {@code null} if no PIN is required. 074 * 075 * @throws KeyStoreException If a problem occurs while initializing this key 076 * manager. 077 */ 078 public KeyStoreKeyManager(final File keyStoreFile, final char[] keyStorePIN) 079 throws KeyStoreException 080 { 081 this(keyStoreFile.getAbsolutePath(), keyStorePIN, null, null); 082 } 083 084 085 086 /** 087 * Creates a new instance of this key store key manager that provides the 088 * ability to retrieve certificates from the specified key store file. It 089 * will use the default key store format. 090 * 091 * @param keyStoreFile The path to the key store file to use. It must not 092 * be {@code null}. 093 * @param keyStorePIN The PIN to use to access the contents of the key 094 * store. It may be {@code null} if no PIN is required. 095 * 096 * @throws KeyStoreException If a problem occurs while initializing this key 097 * manager. 098 */ 099 public KeyStoreKeyManager(final String keyStoreFile, final char[] keyStorePIN) 100 throws KeyStoreException 101 { 102 this(keyStoreFile, keyStorePIN, null, null); 103 } 104 105 106 107 /** 108 * Creates a new instance of this key store key manager that provides the 109 * ability to retrieve certificates from the specified key store file. 110 * 111 * @param keyStoreFile The path to the key store file to use. It must 112 * not be {@code null}. 113 * @param keyStorePIN The PIN to use to access the contents of the key 114 * store. It may be {@code null} if no PIN is 115 * required. 116 * @param keyStoreFormat The format to use for the key store. It may be 117 * {@code null} if the default format should be 118 * used. 119 * @param certificateAlias The nickname of the certificate that should be 120 * selected. It may be {@code null} if any 121 * acceptable certificate found in the keystore may 122 * be used. 123 * 124 * @throws KeyStoreException If a problem occurs while initializing this key 125 * manager. 126 */ 127 public KeyStoreKeyManager(final File keyStoreFile, final char[] keyStorePIN, 128 final String keyStoreFormat, 129 final String certificateAlias) 130 throws KeyStoreException 131 { 132 this(keyStoreFile.getAbsolutePath(), keyStorePIN, keyStoreFormat, 133 certificateAlias); 134 } 135 136 137 138 /** 139 * Creates a new instance of this key store key manager that provides the 140 * ability to retrieve certificates from the specified key store file. 141 * 142 * @param keyStoreFile The path to the key store file to use. It must 143 * not be {@code null}. 144 * @param keyStorePIN The PIN to use to access the contents of the key 145 * store. It may be {@code null} if no PIN is 146 * required. 147 * @param keyStoreFormat The format to use for the key store. It may be 148 * {@code null} if the default format should be 149 * used. 150 * @param certificateAlias The nickname of the certificate that should be 151 * selected. It may be {@code null} if any 152 * acceptable certificate found in the keystore may 153 * be used. 154 * 155 * @throws KeyStoreException If a problem occurs while initializing this key 156 * manager. 157 */ 158 public KeyStoreKeyManager(final String keyStoreFile, final char[] keyStorePIN, 159 final String keyStoreFormat, 160 final String certificateAlias) 161 throws KeyStoreException 162 { 163 super(getKeyManagers(keyStoreFile, keyStorePIN, keyStoreFormat), 164 certificateAlias); 165 166 this.keyStoreFile = keyStoreFile; 167 168 if (keyStoreFormat == null) 169 { 170 this.keyStoreFormat = KeyStore.getDefaultType(); 171 } 172 else 173 { 174 this.keyStoreFormat = keyStoreFormat; 175 } 176 } 177 178 179 180 /** 181 * Retrieves the set of key managers that will be wrapped by this key manager. 182 * 183 * @param keyStoreFile The path to the key store file to use. It must 184 * not be {@code null}. 185 * @param keyStorePIN The PIN to use to access the contents of the key 186 * store. It may be {@code null} if no PIN is 187 * required. 188 * @param keyStoreFormat The format to use for the key store. It may be 189 * {@code null} if the default format should be 190 * used. 191 * 192 * @return The set of key managers that will be wrapped by this key manager. 193 * 194 * @throws KeyStoreException If a problem occurs while initializing this key 195 * manager. 196 */ 197 private static KeyManager[] getKeyManagers(final String keyStoreFile, 198 final char[] keyStorePIN, 199 final String keyStoreFormat) 200 throws KeyStoreException 201 { 202 ensureNotNull(keyStoreFile); 203 204 String type = keyStoreFormat; 205 if (type == null) 206 { 207 type = KeyStore.getDefaultType(); 208 } 209 210 final File f = new File(keyStoreFile); 211 if (! f.exists()) 212 { 213 throw new KeyStoreException(ERR_KEYSTORE_NO_SUCH_FILE.get(keyStoreFile)); 214 } 215 216 final KeyStore ks = KeyStore.getInstance(type); 217 FileInputStream inputStream = null; 218 try 219 { 220 inputStream = new FileInputStream(f); 221 ks.load(inputStream, keyStorePIN); 222 } 223 catch (Exception e) 224 { 225 debugException(e); 226 227 throw new KeyStoreException( 228 ERR_KEYSTORE_CANNOT_LOAD.get(keyStoreFile, type, String.valueOf(e)), 229 e); 230 } 231 finally 232 { 233 if (inputStream != null) 234 { 235 try 236 { 237 inputStream.close(); 238 } 239 catch (Exception e) 240 { 241 debugException(e); 242 } 243 } 244 } 245 246 try 247 { 248 final KeyManagerFactory factory = KeyManagerFactory.getInstance( 249 KeyManagerFactory.getDefaultAlgorithm()); 250 factory.init(ks, keyStorePIN); 251 return factory.getKeyManagers(); 252 } 253 catch (Exception e) 254 { 255 debugException(e); 256 257 throw new KeyStoreException(ERR_KEYSTORE_CANNOT_GET_KEY_MANAGERS.get( 258 keyStoreFile, keyStoreFormat, String.valueOf(e)), e); 259 } 260 } 261 262 263 264 /** 265 * Retrieves the path to the key store file to use. 266 * 267 * @return The path to the key store file to use. 268 */ 269 public String getKeyStoreFile() 270 { 271 return keyStoreFile; 272 } 273 274 275 276 /** 277 * Retrieves the name of the key store file format. 278 * 279 * @return The name of the key store file format. 280 */ 281 public String getKeyStoreFormat() 282 { 283 return keyStoreFormat; 284 } 285 }