001    /*
002     * Copyright 2008-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2015 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    }