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.net.Socket;
026 import java.security.Principal;
027 import java.security.PrivateKey;
028 import java.security.cert.X509Certificate;
029 import java.util.Arrays;
030 import java.util.LinkedHashSet;
031 import javax.net.ssl.KeyManager;
032 import javax.net.ssl.SSLEngine;
033 import javax.net.ssl.X509ExtendedKeyManager;
034 import javax.net.ssl.X509KeyManager;
035
036 import com.unboundid.util.NotExtensible;
037 import com.unboundid.util.ThreadSafety;
038 import com.unboundid.util.ThreadSafetyLevel;
039
040
041
042 /**
043 * This class provides an SSL key manager that may be used to wrap a provided
044 * set of key managers. It provides the ability to select the desired
045 * certificate based on a given nickname.
046 */
047 @NotExtensible()
048 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
049 public abstract class WrapperKeyManager
050 extends X509ExtendedKeyManager
051 {
052 // The nickname of the certificate that should be selected.
053 private final String certificateAlias;
054
055 // The set of key managers that will be used to perform the processing.
056 private final X509KeyManager[] keyManagers;
057
058
059
060 /**
061 * Creates a new instance of this wrapper key manager with the provided
062 * information.
063 *
064 * @param keyManagers The set of key managers to be wrapped. It must
065 * not be {@code null} or empty, and it must contain
066 * only X509KeyManager instances.
067 * @param certificateAlias The nickname of the certificate that should be
068 * selected. It may be {@code null} if any
069 * acceptable certificate found may be used.
070 */
071 protected WrapperKeyManager(final KeyManager[] keyManagers,
072 final String certificateAlias)
073 {
074 this.certificateAlias = certificateAlias;
075
076 this.keyManagers = new X509KeyManager[keyManagers.length];
077 for (int i=0; i < keyManagers.length; i++)
078 {
079 this.keyManagers[i] = (X509KeyManager) keyManagers[i];
080 }
081 }
082
083
084
085 /**
086 * Creates a new instance of this wrapper key manager with the provided
087 * information.
088 *
089 * @param keyManagers The set of key managers to be wrapped. It must
090 * not be {@code null} or empty.
091 * @param certificateAlias The nickname of the certificate that should be
092 * selected. It may be {@code null} if any
093 * acceptable certificate found may be used.
094 */
095 protected WrapperKeyManager(final X509KeyManager[] keyManagers,
096 final String certificateAlias)
097 {
098 this.keyManagers = keyManagers;
099 this.certificateAlias = certificateAlias;
100 }
101
102
103
104 /**
105 * Retrieves the nickname of the certificate that should be selected.
106 *
107 * @return The nickname of the certificate that should be selected, or
108 * {@code null} if any acceptable certificate found in the key store
109 * may be used.
110 */
111 public String getCertificateAlias()
112 {
113 return certificateAlias;
114 }
115
116
117
118 /**
119 * Retrieves the nicknames of the client certificates of the specified type
120 * contained in the key store.
121 *
122 * @param keyType The key algorithm name for which to retrieve the available
123 * certificate nicknames.
124 * @param issuers The list of acceptable issuer certificate subjects. It
125 * may be {@code null} if any issuer may be used.
126 *
127 * @return The nicknames of the client certificates, or {@code null} if none
128 * were found in the key store.
129 */
130 public final synchronized String[] getClientAliases(final String keyType,
131 final Principal[] issuers)
132 {
133 final LinkedHashSet<String> clientAliases = new LinkedHashSet<String>();
134
135 for (final X509KeyManager m : keyManagers)
136 {
137 final String[] aliases = m.getClientAliases(keyType, issuers);
138 if (aliases != null)
139 {
140 clientAliases.addAll(Arrays.asList(aliases));
141 }
142 }
143
144 if (clientAliases.isEmpty())
145 {
146 return null;
147 }
148 else
149 {
150 final String[] aliases = new String[clientAliases.size()];
151 return clientAliases.toArray(aliases);
152 }
153 }
154
155
156
157 /**
158 * Retrieves the nickname of the certificate that a client should use to
159 * authenticate to a server.
160 *
161 * @param keyType The list of key algorithm names that may be used.
162 * @param issuers The list of acceptable issuer certificate subjects. It
163 * may be {@code null} if any issuer may be used.
164 * @param socket The socket to be used. It may be {@code null} if the
165 * certificate may be for any socket.
166 *
167 * @return The nickname of the certificate to use, or {@code null} if no
168 * appropriate certificate is found.
169 */
170 public final synchronized String chooseClientAlias(final String[] keyType,
171 final Principal[] issuers,
172 final Socket socket)
173 {
174 if (certificateAlias == null)
175 {
176 for (final X509KeyManager m : keyManagers)
177 {
178 final String alias = m.chooseClientAlias(keyType, issuers, socket);
179 if (alias != null)
180 {
181 return alias;
182 }
183 }
184
185 return null;
186 }
187 else
188 {
189 for (final String s : keyType)
190 {
191 for (final X509KeyManager m : keyManagers)
192 {
193 final String[] aliases = m.getClientAliases(s, issuers);
194 if (aliases != null)
195 {
196 for (final String alias : aliases)
197 {
198 if (alias.equals(certificateAlias))
199 {
200 return certificateAlias;
201 }
202 }
203 }
204 }
205 }
206
207 return null;
208 }
209 }
210
211
212
213 /**
214 * Retrieves the nickname of the certificate that a client should use to
215 * authenticate to a server.
216 *
217 * @param keyType The list of key algorithm names that may be used.
218 * @param issuers The list of acceptable issuer certificate subjects. It
219 * may be {@code null} if any issuer may be used.
220 * @param engine The SSL engine to be used. It may be {@code null} if the
221 * certificate may be for any engine.
222 *
223 * @return The nickname of the certificate to use, or {@code null} if no
224 * appropriate certificate is found.
225 */
226 @Override()
227 public final synchronized String chooseEngineClientAlias(
228 final String[] keyType,
229 final Principal[] issuers,
230 final SSLEngine engine)
231 {
232 if (certificateAlias == null)
233 {
234 for (final X509KeyManager m : keyManagers)
235 {
236 if (m instanceof X509ExtendedKeyManager)
237 {
238 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m;
239 final String alias =
240 em.chooseEngineClientAlias(keyType, issuers, engine);
241 if (alias != null)
242 {
243 return alias;
244 }
245 }
246 else
247 {
248 final String alias = m.chooseClientAlias(keyType, issuers, null);
249 if (alias != null)
250 {
251 return alias;
252 }
253 }
254 }
255
256 return null;
257 }
258 else
259 {
260 for (final String s : keyType)
261 {
262 for (final X509KeyManager m : keyManagers)
263 {
264 final String[] aliases = m.getClientAliases(s, issuers);
265 if (aliases != null)
266 {
267 for (final String alias : aliases)
268 {
269 if (alias.equals(certificateAlias))
270 {
271 return certificateAlias;
272 }
273 }
274 }
275 }
276 }
277
278 return null;
279 }
280 }
281
282
283
284 /**
285 * Retrieves the nicknames of the server certificates of the specified type
286 * contained in the key store.
287 *
288 * @param keyType The key algorithm name for which to retrieve the available
289 * certificate nicknames.
290 * @param issuers The list of acceptable issuer certificate subjects. It
291 * may be {@code null} if any issuer may be used.
292 *
293 * @return The nicknames of the server certificates, or {@code null} if none
294 * were found in the key store.
295 */
296 public final synchronized String[] getServerAliases(final String keyType,
297 final Principal[] issuers)
298 {
299 final LinkedHashSet<String> serverAliases = new LinkedHashSet<String>();
300
301 for (final X509KeyManager m : keyManagers)
302 {
303 final String[] aliases = m.getServerAliases(keyType, issuers);
304 if (aliases != null)
305 {
306 serverAliases.addAll(Arrays.asList(aliases));
307 }
308 }
309
310 if (serverAliases.isEmpty())
311 {
312 return null;
313 }
314 else
315 {
316 final String[] aliases = new String[serverAliases.size()];
317 return serverAliases.toArray(aliases);
318 }
319 }
320
321
322
323 /**
324 * Retrieves the nickname of the certificate that a server should use to
325 * authenticate to a client.
326 *
327 * @param keyType The key algorithm name that may be used.
328 * @param issuers The list of acceptable issuer certificate subjects. It
329 * may be {@code null} if any issuer may be used.
330 * @param socket The socket to be used. It may be {@code null} if the
331 * certificate may be for any socket.
332 *
333 * @return The nickname of the certificate to use, or {@code null} if no
334 * appropriate certificate is found.
335 */
336 public final synchronized String chooseServerAlias(final String keyType,
337 final Principal[] issuers,
338 final Socket socket)
339 {
340 if (certificateAlias == null)
341 {
342 for (final X509KeyManager m : keyManagers)
343 {
344 final String alias = m.chooseServerAlias(keyType, issuers, socket);
345 if (alias != null)
346 {
347 return alias;
348 }
349 }
350
351 return null;
352 }
353 else
354 {
355 for (final X509KeyManager m : keyManagers)
356 {
357 final String[] aliases = m.getServerAliases(keyType, issuers);
358 if (aliases != null)
359 {
360 for (final String alias : aliases)
361 {
362 if (alias.equals(certificateAlias))
363 {
364 return certificateAlias;
365 }
366 }
367 }
368 }
369
370 return null;
371 }
372 }
373
374
375
376 /**
377 * Retrieves the nickname of the certificate that a server should use to
378 * authenticate to a client.
379 *
380 * @param keyType The key algorithm name that may be used.
381 * @param issuers The list of acceptable issuer certificate subjects. It
382 * may be {@code null} if any issuer may be used.
383 * @param engine The SSL engine to be used. It may be {@code null} if the
384 * certificate may be for any engine.
385 *
386 * @return The nickname of the certificate to use, or {@code null} if no
387 * appropriate certificate is found.
388 */
389 @Override()
390 public final synchronized String chooseEngineServerAlias(final String keyType,
391 final Principal[] issuers,
392 final SSLEngine engine)
393 {
394 if (certificateAlias == null)
395 {
396 for (final X509KeyManager m : keyManagers)
397 {
398 if (m instanceof X509ExtendedKeyManager)
399 {
400 final X509ExtendedKeyManager em = (X509ExtendedKeyManager) m;
401 final String alias =
402 em.chooseEngineServerAlias(keyType, issuers, engine);
403 if (alias != null)
404 {
405 return alias;
406 }
407 }
408 else
409 {
410 final String alias = m.chooseServerAlias(keyType, issuers, null);
411 if (alias != null)
412 {
413 return alias;
414 }
415 }
416 }
417
418 return null;
419 }
420 else
421 {
422 for (final X509KeyManager m : keyManagers)
423 {
424 final String[] aliases = m.getServerAliases(keyType, issuers);
425 if (aliases != null)
426 {
427 for (final String alias : aliases)
428 {
429 if (alias.equals(certificateAlias))
430 {
431 return certificateAlias;
432 }
433 }
434 }
435 }
436
437 return null;
438 }
439 }
440
441
442
443 /**
444 * Retrieves the certificate chain for the certificate with the given
445 * nickname.
446 *
447 * @param alias The nickname of the certificate for which to retrieve the
448 * certificate chain.
449 *
450 * @return The certificate chain for the certificate with the given nickname,
451 * or {@code null} if the requested certificate cannot be found.
452 */
453 public final synchronized X509Certificate[] getCertificateChain(
454 final String alias)
455 {
456 for (final X509KeyManager m : keyManagers)
457 {
458 final X509Certificate[] chain = m.getCertificateChain(alias);
459 if (chain != null)
460 {
461 return chain;
462 }
463 }
464
465 return null;
466 }
467
468
469
470 /**
471 * Retrieves the private key for the specified certificate.
472 *
473 * @param alias The nickname of the certificate for which to retrieve the
474 * private key.
475 *
476 * @return The private key for the requested certificate, or {@code null} if
477 * the requested certificate cannot be found.
478 */
479 public final synchronized PrivateKey getPrivateKey(final String alias)
480 {
481 for (final X509KeyManager m : keyManagers)
482 {
483 final PrivateKey key = m.getPrivateKey(alias);
484 if (key != null)
485 {
486 return key;
487 }
488 }
489
490 return null;
491 }
492 }