001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.util;
028    
029    
030    
031    import java.net.Socket;
032    import java.security.Principal;
033    import java.security.PrivateKey;
034    import java.security.cert.X509Certificate;
035    import javax.net.ssl.KeyManager;
036    import javax.net.ssl.SSLEngine;
037    import javax.net.ssl.X509ExtendedKeyManager;
038    import javax.net.ssl.X509KeyManager;
039    
040    
041    
042    /**
043     * This class implements an X.509 key manager that will be used to wrap an
044     * existing key manager and makes it possible to configure which certificate(s)
045     * should be used for client and/or server operations.  The certificate
046     * selection will be based on the alias (also called the nickname) of the
047     * certificate.
048     */
049    @org.opends.server.types.PublicAPI(
050         stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
051         mayInstantiate=true,
052         mayExtend=false,
053         mayInvoke=true)
054    public final class SelectableCertificateKeyManager
055           extends X509ExtendedKeyManager
056    {
057      // The alias of the certificate that should be selected from the key manager.
058      private String alias;
059    
060      // The key manager that is wrapped by this key manager.
061      private X509KeyManager keyManager;
062    
063    
064    
065      /**
066       * Creates a new instance of this key manager that will wrap the provided key
067       * manager and use the certificate with the specified alias.
068       *
069       * @param  keyManager  The key manager to be wrapped by this key manager.
070       * @param  alias       The nickname of the certificate that should be
071       *                     selected for operations involving this key manager.
072       */
073      public SelectableCertificateKeyManager(X509KeyManager keyManager,
074                                             String alias)
075      {
076        super();
077    
078        this.keyManager = keyManager;
079        this.alias      = alias;
080      }
081    
082    
083    
084      /**
085       * Chooses the alias of the client certificate that should be used based on
086       * the provided critieria.  This will either return the preferred alias
087       * configured for this key manager, or {@code null} if no client certificate
088       * with that alias is configured in the underlying key manager.
089       *
090       * @param  keyType  The set of key algorithm names, ordered with the most
091       *                  preferred key type first.
092       * @param  issuers  The list of acceptable issuer subject names, or
093       *                  {@code null} if any issuer may be used.
094       * @param  socket   The socket to be used for this connection.
095       *
096       * @return  The alias configured for this key manager, or {@code null} if no
097       *          such client certificate is available with that alias.
098       */
099      public String chooseClientAlias(String[] keyType, Principal[] issuers,
100                                      Socket socket)
101      {
102        for (String type : keyType)
103        {
104          String[] clientAliases = keyManager.getClientAliases(type, issuers);
105          if (clientAliases != null)
106          {
107            for (String clientAlias : clientAliases)
108            {
109              if (clientAlias.equals(alias))
110              {
111                return alias;
112              }
113            }
114          }
115        }
116    
117        return null;
118      }
119    
120    
121    
122      /**
123       * Chooses the alias of the client certificate that should be used based on
124       * the provided critieria.  This will either return the preferred alias
125       * configured for this key manager, or {@code null} if no client certificate
126       * with that alias is configured in the underlying key manager.
127       *
128       * @param  keyType  The set of key algorithm names, ordered with the most
129       *                  preferred key type first.
130       * @param  issuers  The list of acceptable issuer subject names, or
131       *                  {@code null} if any issuer may be used.
132       * @param  engine   The SSL engine to be used for this connection.
133       *
134       * @return  The alias configured for this key manager, or {@code null} if no
135       *          such client certificate is available with that alias.
136       */
137      public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
138                                            SSLEngine engine)
139      {
140        for (String type : keyType)
141        {
142          String[] clientAliases = keyManager.getClientAliases(type, issuers);
143          if (clientAliases != null)
144          {
145            for (String clientAlias : clientAliases)
146            {
147              if (clientAlias.equals(alias))
148              {
149                return alias;
150              }
151            }
152          }
153        }
154    
155        return null;
156      }
157    
158    
159    
160      /**
161       * Chooses the alias of the server certificate that should be used based on
162       * the provided critieria.  This will either return the preferred alias
163       * configured for this key manager, or {@code null} if no server certificate
164       * with that alias is configured in the underlying key manager.
165       *
166       * @param  keyType  The public key type for the certificate.
167       * @param  issuers  The list of acceptable issuer subject names, or
168       *                  {@code null} if any issuer may be used.
169       * @param  socket   The socket to be used for this connection.
170       *
171       * @return  The alias configured for this key manager, or {@code null} if no
172       *          such server certificate is available with that alias.
173       */
174      public String chooseServerAlias(String keyType, Principal[] issuers,
175                                      Socket socket)
176      {
177        String[] serverAliases = keyManager.getServerAliases(keyType, issuers);
178        if (serverAliases != null)
179        {
180          for (String serverAlias : serverAliases)
181          {
182            if (serverAlias.equals(alias))
183            {
184              return alias;
185            }
186          }
187        }
188    
189        return null;
190      }
191    
192    
193    
194      /**
195       * Chooses the alias of the server certificate that should be used based on
196       * the provided critieria.  This will either return the preferred alias
197       * configured for this key manager, or {@code null} if no server certificate
198       * with that alias is configured in the underlying key manager.
199       *
200       * @param  keyType  The public key type for the certificate.
201       * @param  issuers  The list of acceptable issuer subject names, or
202       *                  {@code null} if any issuer may be used.
203       * @param  engine   The SSL engine to be used for this connection.
204       *
205       * @return  The alias configured for this key manager, or {@code null} if no
206       *          such server certificate is available with that alias.
207       */
208      public String chooseEngineServerAlias(String keyType, Principal[] issuers,
209                                            SSLEngine engine)
210      {
211        String[] serverAliases = keyManager.getServerAliases(keyType, issuers);
212        if (serverAliases != null)
213        {
214          for (String serverAlias : serverAliases)
215          {
216            if (serverAlias.equals(alias))
217            {
218              return alias;
219            }
220          }
221        }
222    
223        return null;
224      }
225    
226    
227    
228      /**
229       * Retrieves the certificate chain for the provided alias.
230       *
231       * @param  alias  The alias for the certificate chain to retrieve.
232       *
233       * @return  The certificate chain for the provided alias, or {@code null} if
234       *          no certificate is associated with the provided alias.
235       */
236      public X509Certificate[] getCertificateChain(String alias)
237      {
238        return keyManager.getCertificateChain(alias);
239      }
240    
241    
242    
243      /**
244       * Retrieves the set of certificate aliases that may be used for client
245       * authentication with the given public key type and set of issuers.
246       *
247       * @param  keyType  The public key type for the aliases to retrieve.
248       * @param  issuers  The list of acceptable issuer subject names, or
249       *                  {@code null} if any issuer may be used.
250       *
251       * @return  The set of certificate aliases that may be used for client
252       *          authentication with the given public key type and set of issuers,
253       *          or {@code null} if there were none.
254       */
255      public String[] getClientAliases(String keyType, Principal[] issuers)
256      {
257        return keyManager.getClientAliases(keyType, issuers);
258      }
259    
260    
261    
262      /**
263       * Retrieves the private key for the provided alias.
264       *
265       * @param  alias  The alias for the private key to return.
266       *
267       * @return  The private key for the provided alias, or {@code null} if no
268       *          private key is available for the provided alias.
269       */
270      public PrivateKey getPrivateKey(String alias)
271      {
272        return keyManager.getPrivateKey(alias);
273      }
274    
275    
276    
277      /**
278       * Retrieves the set of certificate aliases that may be used for server
279       * authentication with the given public key type and set of issuers.
280       *
281       * @param  keyType  The public key type for the aliases to retrieve.
282       * @param  issuers  The list of acceptable issuer subject names, or
283       *                  {@code null} if any issuer may be used.
284       *
285       * @return  The set of certificate aliases that may be used for server
286       *          authentication with the given public key type and set of issuers,
287       *          or {@code null} if there were none.
288       */
289      public String[] getServerAliases(String keyType, Principal[] issuers)
290      {
291        return keyManager.getServerAliases(keyType, issuers);
292      }
293    
294    
295    
296      /**
297       * Wraps the provided set of key managers in selectable certificate key
298       * managers using the provided alias.
299       *
300       * @param  keyManagers  The set of key managers to be wrapped.
301       * @param  alias        The alias to use for selecting the desired
302       *                      certificate.
303       *
304       * @return  A key manager array
305       */
306      public static X509ExtendedKeyManager[] wrap(KeyManager[] keyManagers,
307                                                  String alias)
308      {
309        X509ExtendedKeyManager[] newKeyManagers =
310             new X509ExtendedKeyManager[keyManagers.length];
311        for (int i=0; i < keyManagers.length; i++)
312        {
313          newKeyManagers[i] = new SelectableCertificateKeyManager(
314                                       (X509KeyManager) keyManagers[i], alias);
315        }
316    
317        return newKeyManagers;
318      }
319    }
320