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 */
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 import com.unboundid.util.NotMutable;
034 import com.unboundid.util.ThreadSafety;
035 import com.unboundid.util.ThreadSafetyLevel;
036
037 import static com.unboundid.util.Debug.*;
038 import static com.unboundid.util.Validator.*;
039 import 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)
051 public 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 }