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