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